Compare commits

...

489 Commits

Author SHA1 Message Date
Keith Burzinski
ec3162282c Merge pull request #6132 from esphome/bump-2023.12.9
2023.12.9
2024-01-22 19:54:22 -06:00
Keith Burzinski
f3997d0f77 Bump version to 2023.12.9 2024-01-22 19:28:12 -06:00
aschmitz
4e5534850c fix: negative temperatures on PMS5003T sensors (#6100) 2024-01-22 19:28:12 -06:00
Samuel Sieb
354314dbf3 fix negative temperature for pmsx003 (#6083)
* fix negative temperature for pmsx003

* Update esphome/components/pmsx003/pmsx003.cpp
2024-01-22 19:28:11 -06:00
Samuel Sieb
2cda6462f3 negative values for all DHT22 variants (#6074)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2024-01-22 19:28:11 -06:00
Samuel Sieb
a6f864a4a3 fix sen5x negative temperature (#6082) 2024-01-22 19:28:11 -06:00
Jesse Hills
1821ddd996 Merge pull request #6122 from esphome/bump-2023.12.8
2023.12.8
2024-01-20 04:22:36 +13:00
Jesse Hills
aee702f84f Bump version to 2023.12.8 2024-01-19 23:40:26 +09:00
Jesse Hills
d5fe5b0899 Fix some Voice Assistant bugs (#6121) 2024-01-19 23:40:25 +09:00
guillempages
bd7fe1227c Let show_*_page actions depend on "Display" (#6092)
Instead of forcing a DisplayBuffer, let the display page actions use Displays without buffer.
2024-01-19 23:40:25 +09:00
Jesse Hills
7dced7f55d Merge pull request #6104 from esphome/bump-2023.12.7
2023.12.7
2024-01-17 13:24:00 +13:00
Jesse Hills
36de644065 Bump version to 2023.12.7 2024-01-17 08:27:03 +09:00
Clyde Stubbs
95292dbba1 Inkplate6: Fix crash with initial set of greyscale (#6038) 2024-01-17 08:27:03 +09:00
Jesse Hills
86c9546362 Create RingBuffer for VoiceAssistant (#6102) 2024-01-17 08:27:03 +09:00
Piotr Majkrzak
f37a812e59 Fix RMT timing clock base (#6101) 2024-01-17 08:27:03 +09:00
Jesse Hills
78a6509fb1 Merge pull request #6097 from esphome/bump-2023.12.6
2023.12.6
2024-01-15 13:06:58 +13:00
Jesse Hills
534c14e313 Bump version to 2023.12.6 2024-01-15 08:25:48 +09:00
J. Nick Koston
3fec8f9b53 Fallback to pure-python loader for better error when YAML loading fails (#6081) 2024-01-15 08:25:41 +09:00
tomaszduda23
b8b6462844 add STATE_CLASS_TOTAL_INCREASING to bl0940 and bl0942 (#6090) 2024-01-15 08:23:56 +09:00
Keith Burzinski
59e7c52341 Improv Serial -- don't wait for incoming bytes (#6089) 2024-01-15 08:23:55 +09:00
Keith Burzinski
ff7de4c971 ESP32-C3 USB_CDC fixes (#6069) 2024-01-15 08:23:55 +09:00
Robert Paskowitz
978a676c7c Support full (>460 char) dumps of Pronto IR commands (#6040)
Co-authored-by: Rob Paskowitz <rob@paskowitz.ca>
2024-01-15 08:23:55 +09:00
functionpointer
33051906bd pylontech: Fix parsing error with US2000 (#6061) 2024-01-15 08:23:55 +09:00
tomaszduda23
da56d333dc fix compilation error for libretiny (#6064) 2024-01-15 08:23:55 +09:00
J. Nick Koston
48a4e6bae9 Fix device not requesting Home Assistant time at the update interval (#6022) 2024-01-15 08:23:55 +09:00
Jesse Hills
41dc73d228 Merge pull request #6017 from esphome/bump-2023.12.5
2023.12.5
2023-12-26 02:44:59 +13:00
Jesse Hills
6ceefe08ab Bump version to 2023.12.5 2023-12-25 22:24:13 +09:00
J. Nick Koston
21e5806a73 Fix docker builds (#6012) 2023-12-25 22:24:13 +09:00
Jesse Hills
4fd79fee2c Merge pull request #6016 from esphome/bump-2023.12.4
2023.12.4
2023-12-26 01:45:41 +13:00
Jesse Hills
4c8c4a2579 Bump version to 2023.12.4 2023-12-25 21:14:55 +09:00
NP v/d Spek
b68420b2cc Display: fix class inherence in Python script (#6009) 2023-12-25 21:14:55 +09:00
J. Nick Koston
7bce999bba dashboard: Fix file writes on Windows (#6013) 2023-12-25 21:14:55 +09:00
NP v/d Spek
dc0cc0b431 tt21100: restore init read (#6008) 2023-12-25 21:14:55 +09:00
J. Nick Koston
0990d0812e dashboard: Only ping when polling is active (#6001)
fixes https://github.com/esphome/issues/issues/5257
2023-12-25 21:14:55 +09:00
Jesse Hills
35388cf2a2 Merge pull request #5994 from esphome/bump-2023.12.3
2023.12.3
2023-12-22 21:42:41 +13:00
Jesse Hills
417e37d291 Bump version to 2023.12.3 2023-12-22 17:12:42 +09:00
Jesse Hills
7dc35a1029 Fix broken configs with non-existent components (#5993) 2023-12-22 17:12:42 +09:00
J. Nick Koston
9202a30dc7 Fix dashboard logs when api is disabled and using MQTT (#5992) 2023-12-22 17:12:42 +09:00
matzman666
45f9f3d972 Improved sensor readings in htu21d component. (#5839) 2023-12-22 17:12:42 +09:00
Jesse Hills
46310ff223 Regenerate api_pb2 after manual changes were added incorrectly in #5732 (#5990) 2023-12-22 17:12:42 +09:00
J. Nick Koston
f5c99d1647 Fix unexpected disconnects when outgoing buffer is full during keepalive (#5988) 2023-12-22 17:12:42 +09:00
Jesse Hills
9b72a3a584 Merge pull request #5989 from esphome/bump-2023.12.2
2023.12.2
2023-12-22 15:57:09 +13:00
Jesse Hills
19e5a4a81a Bump version to 2023.12.2 2023-12-22 11:04:00 +09:00
Jessica Hamilton
8e13c3e1b0 web_server.py: return empty content when file doesn't exist (#5980)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-22 11:04:00 +09:00
Keith Burzinski
4f8e3211bf Add workaround for crash in Arduino 2.0.9 when CDC is configured (#5987) 2023-12-22 11:04:00 +09:00
davidmonro
872519f7f6 Override GPIOs 12 and 13 on the airm2m (LuatOS) board (#5982)
Co-authored-by: David Monro <david.monro@anu.edu.au>
2023-12-22 11:04:00 +09:00
CVan
2a69a49061 Update libtiff6 (#5985) 2023-12-22 11:04:00 +09:00
Clyde Stubbs
1a8e7854c7 ESP32-S3 and ESP-IDF don't play well with USB_CDC and need USB_SERIAL_JTAG (#5929)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2023-12-22 11:04:00 +09:00
Jesse Hills
6d3c7f035d Merge pull request #5984 from esphome/bump-2023.12.1
2023.12.1
2023-12-22 04:02:39 +13:00
Jesse Hills
00ab17cb8e Bump version to 2023.12.1 2023-12-21 23:33:35 +09:00
Jesse Hills
2ee01e22cd Fix replaced - in allowed characters during object_id sanitizing (#5983) 2023-12-21 23:33:35 +09:00
Jesse Hills
cfa5e5c5a9 Merge pull request #5977 from esphome/bump-2023.12.0
2023.12.0
2023-12-21 08:47:53 +09:00
Jesse Hills
8675955614 Bump version to 2023.12.0 2023-12-21 08:09:10 +09:00
Jesse Hills
816dcdf24f Merge pull request #5975 from esphome/bump-2023.12.0b6
2023.12.0b6
2023-12-21 07:56:11 +09:00
Jesse Hills
bec1ad9396 Bump version to 2023.12.0b6 2023-12-20 20:59:46 +09:00
Jesse Hills
6a9e85438f Fix pin reuse error with pin expanders (#5973)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2023-12-20 20:59:46 +09:00
Kamil Trzciński
ab25e32509 image: allow the image to by auto-loaded by animation (#5139) 2023-12-20 20:59:46 +09:00
Jesse Hills
2ccf985de5 Merge pull request #5972 from esphome/bump-2023.12.0b5
2023.12.0b5
2023-12-20 14:17:31 +09:00
Jesse Hills
a64e96e7ad Bump version to 2023.12.0b5 2023-12-20 13:43:43 +09:00
NP v/d Spek
fbf3d03a33 rename set_raw_touch_position_ to add_raw_touch_position_ (#5962) 2023-12-20 13:43:43 +09:00
Jesse Hills
7b2b6aaeb1 Merge pull request #5971 from esphome/bump-2023.12.0b4
2023.12.0b4
2023-12-20 10:49:42 +09:00
Jesse Hills
e2a00f66b8 Bump version to 2023.12.0b4 2023-12-20 09:59:58 +09:00
J. Nick Koston
1b3068a409 Bump aioesphomeapi to 21.0.1 (#5969) 2023-12-20 09:59:52 +09:00
J. Nick Koston
e5414d70f5 Speed up writing protobuf strings/bytes (#5828) 2023-12-20 09:57:37 +09:00
mathieu-mp
977e0184a7 Add deep sleep between updates for waveshare epaper 1.54in and 1.54inv2 (#5961) 2023-12-20 09:57:37 +09:00
Jean Louis-Guerin
820f328248 Fix I2CBus::write() bug and add i2c documentation (#5947) 2023-12-20 09:57:37 +09:00
Keith Burzinski
7807f0d892 Fix build issue with UART component when building with Arduino and CDC (#5964) 2023-12-20 09:57:37 +09:00
Jesse Hills
b59666c512 Merge pull request #5958 from esphome/bump-2023.12.0b3
2023.12.0b3
2023-12-18 17:32:02 +09:00
Jesse Hills
dbfa77cb4b Bump version to 2023.12.0b3 2023-12-18 16:51:11 +09:00
Keith Burzinski
ab22a3da34 Use the correct UART/Serial when CDC is enabled (#5957) 2023-12-18 16:51:11 +09:00
Jean Louis-Guerin
eefa1cd3ab Revert pure virtual functions in UART component from #5920 (#5932)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-18 16:51:10 +09:00
dentra
d0df73769d web_server_idf: fix call with hardcoded http code (#5942) 2023-12-18 16:51:10 +09:00
Alex Hermann
e8ce780482 esp32_camera: Set framebuffer task prio to 1 (#5943) 2023-12-18 16:51:10 +09:00
Alex Hermann
168e704130 i2s_audio: Set player_task's prio to 1 (#5945) 2023-12-18 16:51:10 +09:00
Grant Le Roux
2309f15ce0 Fix - Tuya Fan - Allow integer speed datapoint (#5948)
Co-authored-by: Cram42 <5396871+cram42@users.noreply.github.com>
2023-12-18 16:51:10 +09:00
Edward Firmo
917e0f93ed UARTComponent inline doc (#5930) 2023-12-18 16:51:10 +09:00
dependabot[bot]
70dac54113 Bump zeroconf from 0.128.4 to 0.130.0 (#5950)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 16:51:10 +09:00
Jesse Hills
2270c3050e Merge pull request #5940 from esphome/bump-2023.12.0b2
2023.12.0b2
2023-12-15 15:26:30 +09:00
Jesse Hills
514db8b26e Bump version to 2023.12.0b2 2023-12-15 15:02:47 +09:00
mrtoy-me
e030c0fc45 Update ENS160 TVOC device_class and AQI units to match required by HA (#5939) 2023-12-15 15:02:46 +09:00
Jesse Hills
6b5eb7e656 Fix SplitDefault with variants (#5928) 2023-12-15 15:02:46 +09:00
jochenvg
f28cf9348e Support toggle action for template cover (#5917) 2023-12-15 15:02:46 +09:00
Fabian
3e475c21ff [Logger] ESP32 S3 serial logger (#4853)
* Add support for ESP32 S3 logger.

* fix default

* Remove cpp & h changes to combine with PR #4658

* Not enough attention to details.

* Add build flag

* Validation fix

* Fix validation for real this time

---------

Co-authored-by: Your Name <you@example.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2023-12-15 15:02:46 +09:00
Jesse Hills
3c3ac92038 Allow use of CDC/JTAG loggers on esp32 variants with Arduino (#4658)
* Allow use of CDC/JTAG loggers on esp32 variants with Arduino

* Only on s2/s3

* Separate C3 from S2/S3

* C code builds & runs correctly, still needs work though

* Works on S2

* It works!

* Remove unnecessary header

---------

Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2023-12-15 15:02:46 +09:00
Jesse Hills
cc5611bd89 Merge pull request #5923 from esphome/bump-2023.12.0b1
2023.12.0b1
2023-12-14 09:00:48 +09:00
Jesse Hills
8cc44766e6 Bump version to 2023.12.0b1 2023-12-14 08:30:45 +09:00
Jesse Hills
5ab2c74519 Merge branch 'dev' into bump-2023.12.0b1 2023-12-14 08:30:45 +09:00
Keith Burzinski
76a6e288b6 Add support for PN7150 (#5487)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-14 08:27:35 +09:00
Keith Burzinski
6fd239362d Add support for PN7160 (#5486) 2023-12-14 07:54:55 +09:00
Edward Firmo
81aa48a5f3 Exposes load_settings to UARTComponent class (#5920) 2023-12-14 07:45:08 +09:00
Jacob Masen-Smith
9a8bc9484d Fix the initial run of lambda light effects (#5921)
The timer used for `millis()` is a monotonic timer based on the last
start time of the device. If, for some reason, you pick a long
`update_interval` and try to apply it as soon as you start the device,
nothing happens because the device hasn't been on for longer than the
`update_interval`
2023-12-13 14:33:24 -06:00
dependabot[bot]
f355972c9d Bump aioesphomeapi from 20.1.0 to 21.0.0 (#5922)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-13 09:57:50 -10:00
Edward Firmo
9daaadb3b6 UART change at runtime (#5909)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-13 20:29:05 +13:00
Jesse Hills
058c43e953 Copy esp32 custom partition files to build folder (#5919) 2023-12-13 02:51:07 +00:00
Jesse Hills
f1f8689462 Fix typo added in esp32 post_build filename (#5918) 2023-12-13 02:47:46 +00:00
Jesse Hills
2fcc5b3ef2 Remove lingering note (#5916) 2023-12-13 10:46:11 +09:00
Stefan Rado
6c7a133faa Add humidity support to climate (#5732)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-13 10:23:02 +09:00
Cossid
a72725f4b4 BP1658CJ - Fix timing for all platforms, now consistent with other drivers (#5799) 2023-12-13 09:04:17 +09:00
Nicolas Gilles
d0bcba3b3f ir_transmitter: add support for repeated commands in NEC protocol (#4995)
Co-authored-by: Nicolas Gilles <nicolas.gilles@aiven.io>
2023-12-13 08:55:20 +09:00
Mathias Pihl
69026f7599 Remove setpoint-change from error when calculating derivative in pid controller (#4737)
Co-authored-by: Mathias Pihl <mapih@frode-laursen.com>
2023-12-13 08:50:55 +09:00
J. Nick Koston
8789925fe8 Bump aioesphomeapi to 20.1.0 (#5914) 2023-12-13 08:48:14 +09:00
Clyde Stubbs
29002c8f45 Fix crash when handling pin_check error (#5915) 2023-12-13 08:38:37 +09:00
Theo Hussey
03baaa94a8 Fix AHT10 / AHT20 communication (#5198)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-13 08:28:59 +09:00
Thomas Bræmer
259a6d52e1 A02yyuw (#5729) 2023-12-13 08:26:08 +09:00
NP v/d Spek
c6dc336c4a Updating the touchscreen interface structure (#4596)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: NP v/d Spek <github_mail@lumensoft.nl>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Gustavo Ambrozio <gustavo@gustavo.eng.br>
2023-12-12 22:56:01 +00:00
dependabot[bot]
8e92bb7958 Bump black from 23.11.0 to 23.12.0 (#5912)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2023-12-12 21:59:10 +00:00
dependabot[bot]
04720b8440 Bump aioesphomeapi from 19.3.0 to 20.0.0 (#5911)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 09:39:29 -10:00
Çetin Koca
cc7d167e8b Fix uninitialized climate target temperature (#5795) 2023-12-12 14:17:56 +09:00
Tucker Kern
ad79e4fe24 Add support for fan preset modes (#5694)
Co-authored-by: J. Nick Koston <nick@koston.org>
2023-12-12 14:13:26 +09:00
dependabot[bot]
47665164e8 Bump dessant/lock-threads from 4.0.1 to 5.0.1 (#5820)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 13:52:05 +09:00
dependabot[bot]
d0dd0e38db Bump frenck/action-yamllint from 1.4.1 to 1.4.2 (#5716)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 13:51:36 +09:00
dependabot[bot]
0117de5b78 Bump pylint from 3.0.2 to 3.0.3 (#5905)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 13:51:22 +09:00
dependabot[bot]
7fb10547ed Bump actions/stale from 8.0.0 to 9.0.0 (#5899)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 13:51:07 +09:00
Evgeny
39d026299e Added on_image callback to ESP32 Cam (#4860) 2023-12-12 13:48:21 +09:00
Michael Davidson
b30430b0bd Add graphical display menu (#4105)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Alex Hermann <gaaf@gmx.net>
2023-12-12 12:15:59 +09:00
Clemens
86e6a8a503 fix RGBW Mode on RP2040 (#5907) 2023-12-12 12:28:16 +13:00
Clyde Stubbs
b62c099d54 Fix 18 bit displays. (#5908) 2023-12-12 12:22:41 +13:00
dependabot[bot]
0906559afe Bump zeroconf from 0.128.0 to 0.128.4 (#5906)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-11 19:38:55 +00:00
dependabot[bot]
a6f1701902 Bump actions/setup-python from 4.7.1 to 5.0.0 (#5896)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-07 01:08:50 +00:00
mtl010957
51428dcbc2 Handle case where using enetity level name: None with MQTT (#5897)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-12-07 09:31:27 +09:00
Edward Firmo
049a7a0113 Add framework info to Nextion log tags (#5864) 2023-12-07 08:57:06 +09:00
dependabot[bot]
c53874788a Bump aioesphomeapi from 19.2.1 to 19.3.0 (#5895)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-06 11:04:20 -10:00
Edward Firmo
f026f49415 Nextion exit reparse mode on startup (#5868)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2023-12-06 00:55:07 -06:00
J. Nick Koston
be07463fbd dashboard: Add some basic tests for the dashboard (#5870) 2023-12-06 10:06:05 +09:00
Subhash Chandra
8f70ef24a2 feat(packages): support removing components (#5821) 2023-12-06 10:04:17 +09:00
Keith Burzinski
89d7cdf86b RC522 - Fix error counter error (#5873) 2023-12-05 17:21:12 +09:00
Fabio Pugliese Ornellas
7fd08fb816 Fix template text component length check (#5881)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2023-12-04 22:17:43 -06:00
Keith Burzinski
1d0fb59208 Fix test4.yaml after #5666 (#5890) 2023-12-05 02:50:40 +00:00
Edward Firmo
4d3730b50e Nextion support to idf with cinttypes (#5876) 2023-12-04 19:09:44 -06:00
Clyde Stubbs
d9792b0d92 Checks for pins used in multiple places (#5666) 2023-12-05 08:56:53 +09:00
Clyde Stubbs
df5394d51c Suppress full config output of "esphome config" when -q option is used. (#5852) 2023-12-05 08:52:02 +09:00
Fabio Pugliese Ornellas
b8fe4f8d56 Security improvement: Support wifi ap_timeout=0s (disable) (#5887) 2023-12-05 08:50:01 +09:00
dependabot[bot]
657a7070cb Bump voluptuous from 0.13.1 to 0.14.1 (#5784)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 08:43:07 +09:00
dependabot[bot]
2a740963ba Bump pylint from 2.17.6 to 3.0.2 (#5592)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 08:42:37 +09:00
dependabot[bot]
c2183eb7f0 Bump zeroconf from 0.127.0 to 0.128.0 (#5889)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 08:42:19 +09:00
dependabot[bot]
0c71685d55 Bump pytest-asyncio from 0.21.1 to 0.23.2 (#5888)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 08:42:02 +09:00
Samuel Sieb
29dcc4031f fix a01nyub data reading (#5882)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-12-05 08:41:33 +09:00
Mike La Spina
e271faa544 Fix un-initialized version string (#5865) 2023-12-04 17:15:01 -06:00
Samuel Sieb
788f1b60e2 add missing ifdef to pvvx_mithermometer (#5880) 2023-12-02 22:58:25 -08:00
dependabot[bot]
782854ab36 Bump tornado from 6.3.3 to 6.4 (#5862)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-30 20:51:14 -10:00
dependabot[bot]
6cf4412e7b Bump aioesphomeapi from 19.1.7 to 19.2.1 (#5863)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-30 20:49:42 -10:00
Clyde Stubbs
391eff8fd5 Add Chamberlain/HomEntry HE60R garage door opener (#5834)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-29 10:42:35 +13:00
Alexander Dimitrov
6424f831e2 Pn532 non blocking scan (#5191) 2023-11-29 10:17:16 +13:00
dependabot[bot]
087733c2fd Bump aioesphomeapi from 19.1.2 to 19.1.7 (#5859)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-28 19:23:55 +00:00
Sean Brogan
af8258168b Add Pro Check Universal sensor support. (#5798)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-28 20:00:48 +13:00
Edward Firmo
3940c6ac4e Improve reliability of Nextion TFT uploads (Arduino) (#5683)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2023-11-27 23:25:20 -06:00
J. Nick Koston
ad5f6b5687 dashboard: fix supervisor auth doing I/O in the event loop (#5807) 2023-11-27 23:11:17 -06:00
Edward Firmo
2f888ff7c5 Nextion colors parameters (#5699)
* Add `foreground` color

- Adds `set_component_foreground_color` and `set_component_pressed_foreground_color` which does the same as `set_component_font_color` and `set_component_pressed_font_color` but with a more intuitive name, as this can be used for any component and not only the ones with a text (font).
- I've also reviewed some docstring when related to colors.

* Add numeric color to drawing methods

Should I've used uint32_t instead? In order to keep consistency?

* component color support to uint6_t

This is the right format and is now consistent with colors on drawings.
I'm keeping uint32_t also to avoid breaking changes.

* Enforces uint16_t for colors

uint32_t is incorrect for Nextion display colors.

* Fix clang-format
2023-11-27 22:50:14 -06:00
Edward Firmo
d1be686c54 Nextion on_touch trigger (#5833) 2023-11-28 17:14:59 +13:00
Clyde Stubbs
a8bc5ef46f Pass through additional arguments to create number (#5849) 2023-11-28 16:50:02 +13:00
Jesse Hills
1e77271858 Fix regex for 'byte' custom CI check (#5851) 2023-11-28 16:07:29 +13:00
Clyde Stubbs
993cd55b1d Speed up (and fix) ili9xxx display component. (#5406) 2023-11-28 13:42:03 +13:00
Edward Firmo
ab1cc0ed6e Nextion - Align strings on dump_config (#5824) 2023-11-27 18:24:43 -06:00
Clyde Stubbs
496c29aa04 Fix ESP-IDF uart initialisation sequence to match Espressif docs. (#5838) 2023-11-28 12:42:22 +13:00
Lucas Prim
a66dec738d Implement deep sleep and clear screen on Waveshare 7.5in B V3 (#5239) 2023-11-28 12:40:39 +13:00
Jesse Hills
ddff92c88b Merge pull request #5848 from esphome/bump-2023.11.6
2023.11.6
2023-11-28 12:37:13 +13:00
Jesse Hills
ed9fd173a9 Bump version to 2023.11.6 2023-11-28 12:31:55 +13:00
Jesse Hills
175f00f41b Fix write_speaker without speaker in config (#5847) 2023-11-28 12:31:54 +13:00
Jesse Hills
b8ee0dedec Fix write_speaker without speaker in config (#5847) 2023-11-28 12:28:24 +13:00
Jesse Hills
676b37e6b0 Merge pull request #5846 from esphome/bump-2023.11.5
2023.11.5
2023-11-28 11:54:33 +13:00
functionpointer
4b6fbd5db0 Pylontech integration (solar battery bank) (#4688)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-28 11:43:03 +13:00
J. Nick Koston
4e6d3729e1 dashboard: Small cleanups to dashboard (#5841) 2023-11-28 11:39:24 +13:00
Jesse Hills
28a3cddde3 Bump version to 2023.11.5 2023-11-28 11:14:26 +13:00
Jesse Hills
687f5ca633 Add 'voice_assistant.connected' condition (#5845) 2023-11-28 11:14:26 +13:00
Jesse Hills
ff97639f79 Fix missing include in remote_base (#5843) 2023-11-28 11:14:26 +13:00
Jesse Hills
8e4b9c3c1e Voice Assistant improvements (#5827) 2023-11-28 11:14:26 +13:00
Edward Firmo
460362b11f Nextion - Standardizing log messages (#5837) 2023-11-27 21:09:57 +00:00
dependabot[bot]
019315afa0 Bump aioesphomeapi from 18.5.9 to 19.1.2 (#5844)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2023-11-27 21:07:48 +00:00
Jesse Hills
3b77f05cc9 Add 'voice_assistant.connected' condition (#5845) 2023-11-27 14:57:40 -06:00
Jesse Hills
f63f722afb Create GT911 Touchscreen component (#4027)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2023-11-28 09:44:09 +13:00
Jesse Hills
a15a812466 Fix missing include in remote_base (#5843) 2023-11-28 09:43:41 +13:00
Jesse Hills
15180ee1e2 mcp3008: Tidy up and fix auto load bug (#5842) 2023-11-27 20:35:31 +00:00
Jesse Hills
1324d9e39a Voice Assistant improvements (#5827) 2023-11-27 13:45:26 +13:00
Clyde Stubbs
0a7d3c367b Add 'enable_at_startup' feature to power_supply (#5826) 2023-11-27 10:36:52 +13:00
Clyde Stubbs
2e6d01ddff Implement variable length single word SPI writes. (#5678) 2023-11-27 09:54:12 +13:00
Clyde Stubbs
dbdcb39af9 Pull PollingComponent up from individual display drivers to Display. (#5444) 2023-11-27 09:48:38 +13:00
Edward Firmo
ccd7f0661c Add is_detected() for Nextion displays (#5825) 2023-11-25 02:38:45 -06:00
Clyde Stubbs
c43518c391 Allow split uart pin inversion for ESP-IDF (#5831) 2023-11-24 21:56:32 -06:00
dependabot[bot]
636ee2b597 Bump aioesphomeapi from 18.5.7 to 18.5.9 (#5830)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-24 18:06:57 -06:00
Fabian
91f1aa05ad Run all tests when local testing. (#5717) 2023-11-25 10:18:36 +11:00
dependabot[bot]
9f84b6390d Bump actions/github-script from 6.4.1 to 7.0.1 (#5803)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-24 09:27:56 +01:00
Vincent Schmandt
f456603c1b Add ENS160 Sensor (#4243)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
Co-authored-by: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com>
2023-11-23 22:31:07 -06:00
J. Nick Koston
5c31bec8c2 Ensure names containing characters other than a-z A-Z 0-9 or _ are unique (#5810) 2023-11-23 17:29:08 -06:00
dependabot[bot]
9f8a896e13 Bump aioesphomeapi from 18.5.5 to 18.5.7 (#5822)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-23 17:02:44 -06:00
Jesse Hills
c571abeea8 Merge branch 'release' into dev 2023-11-24 11:53:04 +13:00
J. Nick Koston
1762204b00 dashboard: set nodelay on the websocket to avoid a delay seeing log messages (#5802) 2023-11-24 11:49:55 +13:00
Jesse Hills
1aa49c8956 Merge pull request #5823 from esphome/bump-2023.11.4
2023.11.4
2023-11-24 11:02:15 +13:00
Jesse Hills
711faab329 Bump version to 2023.11.4 2023-11-24 10:24:25 +13:00
Landon Rohatensky
1204b4f1bd Allow images to be downloaded from URLs (#5214)
Co-authored-by: guillempages <guillempages@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-24 10:24:16 +13:00
Ilia Sotnikov
2076db1ccd Pillow: bump to 10.1.0 (#5815) 2023-11-24 08:15:58 +13:00
Landon Rohatensky
49c09afb87 Allow images to be downloaded from URLs (#5214)
Co-authored-by: guillempages <guillempages@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-24 08:10:33 +13:00
Clyde Stubbs
3ac59180ab Add startup_delay to interval. (#5327) 2023-11-23 20:31:23 +13:00
matt7aylor
8738cef5a3 sen5x fix temperature compensation and gas tuning (#4901) 2023-11-23 08:48:38 +13:00
Jesse Hills
cadbf7463e Merge pull request #5816 from esphome/bump-2023.11.3
2023.11.3
2023-11-22 13:37:10 +13:00
Jesse Hills
3f40e32eba Bump version to 2023.11.3 2023-11-22 11:08:47 +13:00
Keith Burzinski
b421fccc08 Add some additional VA triggers, part 2 (#5811) 2023-11-22 11:08:47 +13:00
Jesse Hills
10ca05b686 Early return when there are no wifi scan results (#5797) 2023-11-22 11:08:46 +13:00
CVan
d0ac202a3f fix: compile errors with fonts (#5808) 2023-11-22 11:08:46 +13:00
Cody Cutrer
1c4b06700f include payload_open when a lock supports OPEN (#5809) 2023-11-22 11:08:21 +13:00
Keith Burzinski
b809d02846 Add some additional VA triggers, part 2 (#5811) 2023-11-22 10:09:14 +13:00
Jesse Hills
e7038d077a Early return when there are no wifi scan results (#5797) 2023-11-21 14:24:47 +13:00
Pavlo Dudnytskyi
cf6b56c1ac Haier component updated to support new protocol variations (#5713)
Co-authored-by: Pavlo Dudnytskyi <pdudnytskyi@astrata.eu>
2023-11-21 14:12:36 +13:00
CVan
55f13dc347 fix: compile errors with fonts (#5808) 2023-11-21 13:19:36 +13:00
J. Nick Koston
7d5ebeda52 dashboard: Fix online status when api is disabled (#5792) 2023-11-21 13:16:06 +13:00
J. Nick Koston
47d42afda3 dashboard: Fix online status when api is disabled (#5791) 2023-11-21 13:15:32 +13:00
Cody Cutrer
d5d97c4558 include payload_open when a lock supports OPEN (#5809) 2023-11-21 12:59:38 +13:00
dependabot[bot]
5744490f2f Bump aioesphomeapi from 18.5.3 to 18.5.5 (#5804)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-20 23:18:00 +01:00
Christian Schmitt
d462beea6e ssd1306: handle V_COM differently for SH1106 (#5796) 2023-11-20 16:34:26 +13:00
Kevin P. Fleming
e367ab26e1 wifi: Don't build SoftAP/DHCPS support unless 'ap' is in config. (#5649) 2023-11-20 16:32:46 +13:00
J. Nick Koston
2aaee81313 Refactor StorageJSON to keep loaded_integrations a set until its converted to JSON (#5793)
* Refactor StorageJSON to keep loaded_integrations a set until its converted to a dict

after #5792 we will be checking loaded_integrations often. ESPHome
core keep uses a set, but it would get converted to a list when
passed through StorageJSON. Keep it a set until its needed to
be read/write to JSON so we do not have to linear searches on it
since they have a time complexity of O(n) vs O(1)

* legacy
2023-11-19 22:31:00 -05:00
J. Nick Koston
cd9bf29df1 dashboard: Add lookup by name to entries (#5790)
* Add lookup by name to entries

* adj

* tweak

* tweak

* tweak

* tweak

* tweak

* tweak

* preen
2023-11-19 22:29:40 -05:00
J. Nick Koston
4e4fe3c26d dashboard: Ensure disk I/O happens in the executor (#5789)
* Ensure I/O executor

* safe file writer

* fixes

* more io

* more io
2023-11-19 22:28:35 -05:00
Jesse Hills
1a9f66e630 Merge pull request #5787 from esphome/bump-2023.11.2
2023.11.2
2023-11-18 22:25:00 +13:00
Jesse Hills
8fb6b8f1a2 Bump version to 2023.11.2 2023-11-18 21:15:56 +13:00
Keith Burzinski
22eef036c7 Add 2MB option for partitions.csv generation and restore use of user-defined partitions (#5779) 2023-11-18 21:15:56 +13:00
Samuel Sieb
625ce2b8eb fix 32-bit arm (#5781) 2023-11-18 21:15:56 +13:00
dependabot[bot]
e5e3b253bc Bump aioesphomeapi from 18.4.1 to 18.5.2 (#5780)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-18 21:15:51 +13:00
dependabot[bot]
c369443263 Bump aioesphomeapi from 18.4.0 to 18.4.1 (#5767)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-18 21:14:50 +13:00
Keith Burzinski
8fbb4e27d1 Add 2MB option for partitions.csv generation and restore use of user-defined partitions (#5779) 2023-11-18 21:00:59 +13:00
J. Nick Koston
3c243e663f dashboard: Add support for firing events (#5775)
* dashboard: fire events when entry is updated or state changes

* dashboard: fire events when entry is updated or state changes

* dashboard: fire events when entry is updated or state changes

* tweaks

* fixes

* remove typing_extensions

* rename for asyncio

* rename for asyncio

* rename for asyncio

* preen

* lint

* lint

* move dict converter

* lint
2023-11-17 19:33:10 -05:00
J. Nick Koston
288af1f4d2 Refactor log api client to let aioesphomeapi manage zeroconf (#5783)
aioesphomeapi is now smart enough to avoid creating a zeroconf instance
until its needed after https://github.com/esphome/aioesphomeapi/pull/643

This avoids the needs to have a background zeroconf instance running that
is processing incoming records but will never do anything
2023-11-17 18:50:40 -05:00
J. Nick Koston
6f8d7c6acd Bump aioesphomeapi to 18.5.3 (#5785)
- Avoids creating a zeroconf instance when we do not need one

supports https://github.com/esphome/esphome/pull/5783

changelog: https://github.com/esphome/aioesphomeapi/compare/v18.5.2...v18.5.3
2023-11-17 18:48:53 -05:00
Samuel Sieb
32e3f26239 fix 32-bit arm (#5781) 2023-11-17 09:16:03 +00:00
dependabot[bot]
5464368c08 Bump aioesphomeapi from 18.4.1 to 18.5.2 (#5780)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-16 23:35:42 -06:00
Jesse Hills
1e061582d3 Merge pull request #5776 from esphome/bump-2023.11.1
2023.11.1
2023-11-16 21:19:39 +13:00
Jesse Hills
208edf89dc Split release workflow jobs per system arch (#5723) 2023-11-16 21:06:16 +13:00
Nikita Kuklev
fefdb80fdc Add proper support for SH1107 to SSD1306 component (#5166) 2023-11-16 21:06:03 +13:00
Jesse Hills
445b13dbc6 Bump version to 2023.11.1 2023-11-16 20:55:28 +13:00
Mat931
255483de63 Fix MY9231 flicker (#5765) 2023-11-16 20:55:28 +13:00
Keith Burzinski
4ac49907ca Add more VA triggers (#5762) 2023-11-16 20:55:28 +13:00
Mat931
754bd5b7be Fix MY9231 flicker (#5765) 2023-11-16 20:45:08 +13:00
J. Nick Koston
10a9129b7b Pass the name to the log runner when available (#5759) 2023-11-16 20:41:49 +13:00
Keith Burzinski
ef945d298c Add more VA triggers (#5762) 2023-11-15 21:29:50 -06:00
J. Nick Koston
149d814fab dashboard: Centralize dashboard entries into DashboardEntries class (#5774)
* Centralize dashboard entries into DashboardEntries class

* preen

* preen

* preen

* preen

* preen
2023-11-15 21:49:56 -05:00
J. Nick Koston
5f1d8dfa5b dashboard: use fastest available yaml loader in the dashboard (#5771)
* dashboard: use fastest available yaml loader in the dashboard

* remove unrelated change
2023-11-15 19:08:17 -05:00
J. Nick Koston
3644853d38 dashboard: fix subprocesses blocking the event loop (#5772)
* dashboard: fix subprocesses blocking the event loop

- break apart the util module
- adds a new util to run subprocesses with asyncio

* take a list
2023-11-15 19:07:51 -05:00
dependabot[bot]
4e3170dc95 Bump zeroconf from 0.126.0 to 0.127.0 (#5768)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 21:48:59 +00:00
J. Nick Koston
c795dbde26 dashboard: split dashboard web server code into its own module (#5770) 2023-11-15 21:34:09 +00:00
dependabot[bot]
4ce627b4ee Bump aioesphomeapi from 18.4.0 to 18.4.1 (#5767)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 15:28:04 -06:00
J. Nick Koston
86b4fdc139 dashboard: Break apart dashboard into separate modules (#5764)
* Break apart dashboard into seperate modules

* reduce code change

* late imports

* late imports

* preen

* remove accidental changes

* save the file
2023-11-15 13:00:28 -05:00
J. Nick Koston
20ea8bf06e dashboard: convert ping thread to use asyncio (#5749) 2023-11-14 22:55:33 -06:00
J. Nick Koston
642db6d92b Speed up OTAs (#5720) 2023-11-14 22:14:37 -06:00
Jesse Hills
4aac5a23cd Merge branch 'release' into dev 2023-11-15 16:13:43 +13:00
Jesse Hills
c536c976b7 Merge pull request #5758 from esphome/bump-2023.11.0
2023.11.0
2023-11-15 16:11:18 +13:00
J. Nick Koston
214b419db2 dashboard: Use mdns cache when available if device connection is OTA (#5724)
* Use mdns or freshen cache when device connection is OTA

Since we already have a service browser running, we likely
already know the IP of the deivce we want to connect to so
we can replace OTA with the address to avoid the esphome
app having to look it up again

* isort

* Fix zeroconf name resolution refactoring error

HostResolver should get the type as the first arg instead
of the name

* no i/o

* tornado support native coros

* lint

* use new tornado start methods

* use new tornado start methods

* use new tornado start methods

* break

* lint

* lint

* typing, missing awaits

* io in executor

* missed one

* fix: missing if

* stale comment

* rename run_command to build_device_command since it does not actually run anything
2023-11-14 21:21:44 -05:00
Jesse Hills
0c18872888 Bump version to 2023.11.0 2023-11-15 14:13:39 +13:00
Jesse Hills
197b6b4275 Merge pull request #5756 from esphome/bump-2023.11.0b7
2023.11.0b7
2023-11-15 13:19:48 +13:00
Jesse Hills
4e8bdc2155 Bump version to 2023.11.0b7 2023-11-15 12:45:03 +13:00
Jesse Hills
f1e8622187 Dont dump wifi info when disabled (#5755) 2023-11-15 12:45:02 +13:00
Jesse Hills
e0c7a02fbc Allow setup to continue past mqtt if network/wifi is disabled (#5754) 2023-11-15 12:45:02 +13:00
Jimmy Hedman
cdcb25be8e Make precommit checks happy (#5751) 2023-11-15 12:38:36 +13:00
Jesse Hills
aecc6655db Dont dump wifi info when disabled (#5755) 2023-11-14 21:57:25 +00:00
Jesse Hills
2754ddec1b Allow setup to continue past mqtt if network/wifi is disabled (#5754) 2023-11-15 10:51:45 +13:00
Jesse Hills
2a20a5fc11 Merge pull request #5750 from esphome/bump-2023.11.0b6
2023.11.0b6
2023-11-14 16:16:11 +13:00
Jesse Hills
7100d073f8 Bump version to 2023.11.0b6 2023-11-14 14:32:41 +13:00
Keith Burzinski
1ac6cf2ff9 Generate partitions.csv based on flash size (#5697) 2023-11-14 14:32:41 +13:00
J. Nick Koston
2ee089c9d5 dashboard: Run get_serial_ports in the executor (#5740) 2023-11-14 14:32:41 +13:00
J. Nick Koston
bd568eecf5 dashboard: remove usage of codecs module (#5741) 2023-11-14 14:32:40 +13:00
Keith Burzinski
ae0e481cff Generate partitions.csv based on flash size (#5697) 2023-11-14 13:47:29 +13:00
J. Nick Koston
f198be39d7 dashboard: Run get_serial_ports in the executor (#5740) 2023-11-14 13:46:51 +13:00
J. Nick Koston
08fc96b890 dashboard: remove usage of codecs module (#5741) 2023-11-14 13:44:49 +13:00
dependabot[bot]
8c28bea5b1 Bump zeroconf from 0.123.0 to 0.126.0 (#5748)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 16:19:15 -06:00
Sergey Dudanov
00eedeb8b3 remote_base: added helper class and schemas (#5169)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-14 06:55:36 +13:00
Jimmy Hedman
0a4853ba7b Correct url for Arduino platform (#5744) 2023-11-14 06:38:08 +13:00
Jesse Hills
3e2b83acb0 Merge pull request #5742 from esphome/bump-2023.11.0b5
2023.11.0b5
2023-11-13 16:37:28 +13:00
Jesse Hills
c1eb5bd675 Bump version to 2023.11.0b5 2023-11-13 15:26:04 +13:00
Jesse Hills
a9772ebf3f Handle wake word not set up internally (#5738) 2023-11-13 15:26:04 +13:00
Jesse Hills
45276cc244 Handle wake word not set up internally (#5738) 2023-11-13 11:48:26 +13:00
Jesse Hills
a9a17ee89d Merge pull request #5737 from esphome/bump-2023.11.0b4
2023.11.0b4
2023-11-13 11:25:42 +13:00
Jesse Hills
f094702a16 Bump version to 2023.11.0b4 2023-11-13 10:23:28 +13:00
J. Nick Koston
908f56ff46 Bump zeroconf to 0.123.0 (#5736) 2023-11-13 10:23:28 +13:00
J. Nick Koston
bd5905c59a Migrate to using aioesphomeapi for the log runner to fix multiple issues (#5733) 2023-11-13 10:23:28 +13:00
dependabot[bot]
91299f05f7 Bump aioesphomeapi from 18.2.7 to 18.4.0 (#5735)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 10:23:27 +13:00
Mike La Spina
30e5ff9fff Missed ifdefs (#5727) 2023-11-13 10:23:27 +13:00
J. Nick Koston
163b38e153 Fix zeroconf name resolution refactoring error (#5725) 2023-11-13 10:23:27 +13:00
Jesse Hills
3b486084c8 Add resistance_sampler interface for config validation (#5718) 2023-11-13 10:23:27 +13:00
Jimmy Hedman
684cf10230 Bump Arduino Pico Framework to 3.6.0 and Platform to 1.10.0 (#5731) 2023-11-13 07:28:02 +13:00
J. Nick Koston
63a277ba80 Bump zeroconf to 0.123.0 (#5736) 2023-11-13 07:20:34 +13:00
J. Nick Koston
53f3385c49 Migrate to using aioesphomeapi for the log runner to fix multiple issues (#5733) 2023-11-12 14:36:56 +13:00
dependabot[bot]
51930a0243 Bump aioesphomeapi from 18.2.7 to 18.4.0 (#5735)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-11 21:59:36 +00:00
Mike La Spina
6a5cea171e Missed ifdefs (#5727) 2023-11-10 18:37:39 -06:00
J. Nick Koston
3363c8f434 Fix zeroconf name resolution refactoring error (#5725) 2023-11-10 22:55:21 +13:00
J. Nick Koston
3b891bc146 Speed up YAML by using YAML C loader when available (#5721) 2023-11-10 22:17:40 +13:00
dependabot[bot]
0f19450ab4 Bump black from 23.10.1 to 23.11.0 (#5702)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2023-11-09 21:18:22 -06:00
Samuel Sieb
98ec798bfc fix pin range for xl9535 (#5722)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-11-10 01:53:35 +00:00
Jesse Hills
01d28ce3fc Add resistance_sampler interface for config validation (#5718) 2023-11-10 11:40:07 +13:00
Jesse Hills
9d453f0ba2 Merge pull request #5714 from esphome/bump-2023.11.0b3
2023.11.0b3
2023-11-10 08:16:33 +13:00
dependabot[bot]
799851a83a Bump zeroconf from 0.120.0 to 0.122.3 (#5715) 2023-11-10 07:29:44 +13:00
dependabot[bot]
bc7519f645 Bump zeroconf from 0.120.0 to 0.122.3 (#5715) 2023-11-09 12:26:05 -06:00
Jesse Hills
7a9866f1b6 Bump version to 2023.11.0b3 2023-11-09 22:14:22 +13:00
J. Nick Koston
3d30f1f733 Update Dockerfile to use piwheels for armv7 (#5709) 2023-11-09 22:14:22 +13:00
J. Nick Koston
1e55764d52 Bump aioesphomeapi to 18.2.7 (#5706) 2023-11-09 22:14:22 +13:00
J. Nick Koston
28513a0502 Update Dockerfile to use piwheels for armv7 (#5709) 2023-11-09 21:04:39 +13:00
J. Nick Koston
3e3266fa74 Bump aioesphomeapi to 18.2.7 (#5706) 2023-11-09 15:52:08 +13:00
Jesse Hills
020da89b6a Merge pull request #5707 from esphome/bump-2023.11.0b2
2023.11.0b2
2023-11-09 14:16:27 +13:00
Jesse Hills
6932422104 Bump version to 2023.11.0b2 2023-11-09 12:46:57 +13:00
Rodrigo Martín
29aa15b253 fix: Fix broken bluetooth_proxy and ble_clients after BLE enable/disable (#5704) 2023-11-09 12:46:57 +13:00
J. Nick Koston
c40519ec6f Use piwheels for armv7 docker image builds (#5703) 2023-11-09 12:46:57 +13:00
J. Nick Koston
6c62c00963 Fix static assets cache logic (#5700) 2023-11-09 12:46:57 +13:00
Jesse Hills
1bd2e558d6 Fix esp32_rmt_led_strip custom timing units (#5696) 2023-11-09 12:46:57 +13:00
Jesse Hills
dbb1263a36 Handle nanoseconds in config (#5695) 2023-11-09 12:46:57 +13:00
Rodrigo Martín
ce020b1f9f fix: Fix broken bluetooth_proxy and ble_clients after BLE enable/disable (#5704) 2023-11-08 23:35:37 +00:00
J. Nick Koston
d394b957d1 Use piwheels for armv7 docker image builds (#5703) 2023-11-09 11:50:08 +13:00
J. Nick Koston
cf22c55430 Fix static assets cache logic (#5700) 2023-11-08 21:04:01 +00:00
Jesse Hills
511348974e Fix esp32_rmt_led_strip custom timing units (#5696) 2023-11-08 09:01:26 +00:00
Jesse Hills
972598a698 Handle nanoseconds in config (#5695) 2023-11-08 21:34:44 +13:00
Jesse Hills
966c6a4531 Merge pull request #5693 from esphome/bump-2023.11.0b1
2023.11.0b1
2023-11-08 16:21:35 +13:00
Edward Firmo
d81bec860b Nextion support to esp-idf (#5667)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-07 19:50:45 -06:00
Jesse Hills
fff2d01420 Bump version to 2023.11.0b1 2023-11-08 13:13:56 +13:00
Jesse Hills
fde7a04ee7 Bump version to 2023.12.0-dev 2023-11-08 13:13:56 +13:00
Jesse Hills
bf217ce252 Merge branch 'dev' into bump-2023.11.0b1 2023-11-08 13:13:54 +13:00
dependabot[bot]
0101ae768c Bump aioesphomeapi from 18.2.1 to 18.2.4 (#5692)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 15:44:33 -06:00
Keith Burzinski
9bd4b229e3 Handle on_disconnect when Wi-Fi is disabled (#5691) 2023-11-08 07:00:36 +13:00
Angel Nunez Mencias
ccffbfd3ae support spi for sn74hc595 (#5491)
Co-authored-by: Jimmy Hedman <jimmy.hedman@gmail.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-07 03:15:13 -06:00
J. Nick Koston
78e3ce7718 Implement a memory cache for dashboard entries to avoid frequent disk reads (#5687) 2023-11-07 19:04:55 +13:00
Charles Johnson
31fec2d692 add wifi.on_connect and wifi.on_disconnect triggers (#3639)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-06 23:17:13 -06:00
Jesse Hills
888c298d7e Update esphome-dashboard to version 20231107.0 (#5686) 2023-11-07 13:59:26 +13:00
Daniel Baulig
708ed8f38a [web_server] Adds the ability to handle Private Network Access preflight requests (#5669) 2023-11-07 13:59:03 +13:00
Edward Firmo
a8a9c6192d Remove page jump on Nextion startup (#5673) 2023-11-06 18:48:15 -06:00
Angel Nunez Mencias
defe8ac97b Add spi support for ade7953 (#5439)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-07 13:17:29 +13:00
dependabot[bot]
7ac9caa169 Bump zeroconf from 0.119.0 to 0.120.0 (#5682)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 12:48:37 +13:00
Greg Cormier
972c18a7ca Add differential pressure sensor support for CFSensor XGZP68xxD devices (#5562)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-07 12:46:30 +13:00
Jesse Hills
dd0270207f Allow pulse light effect to have separate on and off transition lengths (#5659) 2023-11-07 12:39:47 +13:00
Jesse Hills
d141e1cd67 Remove extra code in old sgp40 (#5685) 2023-11-07 12:38:52 +13:00
Jesse Hills
43b36ac3c7 Allow static assets to be cached if not in debug mode (#5684) 2023-11-07 12:38:38 +13:00
J. Nick Koston
fce59819f5 Refactor dashboard zeroconf support (#5681) 2023-11-07 11:07:59 +13:00
marshn
b978985aa1 Add Byron Doorbell RF protocol (#4718) 2023-11-07 08:30:23 +13:00
Jesse Hills
84bbf02bde ble_client rssi sensor fix when not connected (#5632) 2023-11-06 16:41:45 +13:00
Rodrigo Martín
d5aeb32ca6 feat: Add ESP32 BLE enable/disable automations (#5616)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-06 15:54:39 +13:00
kahrendt
ff8b904097 Null topic_prefix disables MQTT publishing/subscription unless topic is explicitly configured (#5644) 2023-11-06 14:19:03 +13:00
DAVe3283
e0cee472c3 Fix compile with latest esp-idf on esp32c6 (#5677)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-05 23:13:01 +00:00
micw
3ee85d7516 Add callback for raw sml messages (#5668) 2023-11-06 10:27:11 +13:00
Pavlo Dudnytskyi
4ca9aefc43 Fixed int variables for user defined service in case of ESP32-C3 (#5675) 2023-11-06 09:28:50 +13:00
Patrick ZAJDA
4ef2e28496 Add basic shell autocompletion using argcomplete (#5618) 2023-11-06 09:27:14 +13:00
Joris S
13994d9bd1 Add Micronova component (#4760)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Graham Brown <grahambrown11@gmail.com>
2023-11-03 19:54:47 +13:00
Mike La Spina
22cdb8dfc3 Add HLK-LD2420 mmWave Radar module component (#4847)
Co-authored-by: descipher <120155735+GelidusResearch@users.noreply.github.com>
2023-11-02 18:02:23 -05:00
Jesse Hills
a7ad4482f0 Merge pull request #5664 from esphome/bump-2023.10.6
2023.10.6
2023-11-03 08:49:48 +13:00
Jesse Hills
aa17661002 Bump version to 2023.10.6 2023-11-03 08:11:58 +13:00
Jesse Hills
4e65aac7ae Revert "Ensure that all uses of strncpy in wifi component are safe." (#5662) 2023-11-03 08:11:58 +13:00
Jesse Hills
d74a8abf9a Revert "Ensure that all uses of strncpy in wifi component are safe." (#5662) 2023-11-03 08:09:17 +13:00
Jc Miñarro
d809c80286 Add Healthcheck to Dockerfile (#5651) 2023-11-03 07:19:43 +13:00
dependabot[bot]
6ca14331e5 Bump black from 23.10.0 to 23.10.1 (#5593)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-02 17:15:28 +13:00
dependabot[bot]
d5f010ee52 Bump tzlocal from 5.1 to 5.2 (#5594)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 17:15:20 +13:00
dependabot[bot]
4837e114e4 Bump pytest from 7.4.2 to 7.4.3 (#5599)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 17:15:05 +13:00
Jesse Hills
77b530cf9e Bump flake8 version in pre-commit to match requirements file (#5658) 2023-11-02 17:14:39 +13:00
NP v/d Spek
453600f18e Update RTTTL component to allow I2S (#5177)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-11-02 17:14:05 +13:00
Jesse Hills
4edf3efdf3 Fix return value of run_external_command (#5657) 2023-11-02 17:06:09 +13:00
Jimmy Hedman
f70d651a39 Update mDNS component to 1.2.2 (#5654) 2023-11-02 16:56:02 +13:00
Clyde Stubbs
b0a400d82b Update PCA9554 pin checks to new facility (#5656) 2023-11-02 03:46:47 +00:00
Jesse Hills
29b1233609 Validate sn74hc595 pin number are within range (#5655) 2023-11-02 16:45:00 +13:00
dependabot[bot]
c3f7cae2b0 Bump aioesphomeapi from 18.2.0 to 18.2.1 (#5653)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 15:49:16 +13:00
Jesse Hills
9eea52ea85 Allow validation of pins based on hub config (#5647) 2023-11-02 15:32:00 +13:00
Gustavo Ambrozio
40c001bdc2 Fix nextion waveform sending for multiple waveforms (#4408) 2023-11-01 20:09:12 -05:00
Jesse Hills
229ba18e6c Merge pull request #5645 from esphome/bump-2023.10.5
2023.10.5
2023-11-01 14:07:42 +13:00
Clyde Stubbs
1fd9d67e2b Add support for PCA9535 16 bit I/O expander (#5634) 2023-11-01 12:22:04 +13:00
Jesse Hills
b99be250a0 Bump version to 2023.10.5 2023-11-01 12:19:16 +13:00
Jimmy Hedman
b9d4e2e501 Remove some explicit IPAddress casts (#5639) 2023-11-01 12:19:16 +13:00
Kevin P. Fleming
ef2531edf3 Ensure that all uses of strncpy in wifi component are safe. (#5636) 2023-11-01 12:19:16 +13:00
Jesse Hills
eae3089201 Add on_client_connected and disconnected to voice assistant (#5629) 2023-11-01 12:19:16 +13:00
Jesse Hills
0ea4de5f4c Add connection triggers to api (#5628) 2023-11-01 12:19:16 +13:00
Jesse Hills
8eae882d93 Add needs-docs workflow to fail CI (#5643) 2023-11-01 11:12:16 +13:00
Jimmy Hedman
9adda8085a Remove some explicit IPAddress casts (#5639) 2023-11-01 10:32:29 +13:00
Kevin P. Fleming
b03eb5ea0a Ensure that all uses of strncpy in wifi component are safe. (#5636) 2023-11-01 10:30:42 +13:00
Jesse Hills
193bac94f4 Add on_client_connected and disconnected to voice assistant (#5629) 2023-10-30 17:16:42 -05:00
dependabot[bot]
69ec647f7e Bump aioesphomeapi from 18.0.12 to 18.2.0 (#5606) 2023-10-30 14:57:41 -07:00
J. Nick Koston
9dfcf801a3 Fix armv7 docker builds (#5630) 2023-10-30 14:07:25 -05:00
Jesse Hills
1e0daefa16 Merge pull request #5627 from esphome/bump-2023.10.4
2023.10.4
2023-10-30 16:33:36 +13:00
Jesse Hills
27b593ba85 Add connection triggers to api (#5628) 2023-10-29 21:02:49 -05:00
Jesse Hills
6d991a1fc8 Bump version to 2023.10.4 2023-10-30 13:59:58 +13:00
Jesse Hills
a1845e1e72 Handle enum type in tuya text_sensor (#5626) 2023-10-30 13:59:58 +13:00
Dewet Diener
f96a839bcf Fix bug when requesting italic gfonts (#5623) 2023-10-30 13:59:58 +13:00
Jimmy Hedman
1282a15b14 Fixes ip include on arduino 2.7.4 (#5620) 2023-10-30 13:59:58 +13:00
Roger Busser
35039b45e4 Update current_based_cover bugfix (#5587) 2023-10-30 13:59:58 +13:00
Jesse Hills
0c46403eaf Handle enum type in tuya text_sensor (#5626) 2023-10-29 22:00:47 +00:00
Dewet Diener
f36ec7c726 Fix bug when requesting italic gfonts (#5623) 2023-10-30 08:05:18 +13:00
Jimmy Hedman
01a16141f1 Fixes ip include on arduino 2.7.4 (#5620) 2023-10-30 07:35:33 +13:00
Keith Burzinski
7cf056e828 IDF 5 fixes for various components from test2.yaml (#5621) 2023-10-29 18:50:26 +13:00
Keith Burzinski
f7f63c9da1 IDF 5 fixes for various components from test4.yaml (#5622) 2023-10-29 18:49:19 +13:00
Keith Burzinski
d4cb29a380 Fix xpt2046 for IDF 5 (#5614) 2023-10-27 22:36:43 +00:00
H. Árkosi Róbert
563e15e8a7 Fix HA error related to incorrect state class (#5605) 2023-10-27 07:39:23 +00:00
Samuel Sieb
c83cb30935 refactor mcp4728 component (#5609)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-10-27 18:01:18 +13:00
niklasweber
907d43827c Add dfrobot_sen0395 mmwave radar component (#4203)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-27 17:56:33 +13:00
Jesse Hills
0c5d5cd623 timeout filter: return value (#5612) 2023-10-27 16:36:54 +13:00
Jesse Hills
535568e065 Minor defines.h updates (#5610) 2023-10-27 16:16:44 +13:00
Jesse Hills
2adda3a994 Validate test files before compiling (#5611)
* Validate test files before compiling

* Dont restrict parallel
2023-10-27 01:59:10 +00:00
Jesse Hills
a9f4922824 Devcontainer: allow pip install and dont warn about root user (#5608) 2023-10-27 11:56:16 +13:00
Cossid
bcfbcd9578 Add area (zone) to esphome core config to be suggested through API and MQTT. (#5602)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-27 11:38:52 +13:00
dentra
cfbf3681f3 Fallback to main secrets.yaml for packages (#5604) 2023-10-27 10:16:43 +13:00
dentra
f6e8d97981 Add details when error loading package (#5603) 2023-10-27 09:27:42 +13:00
tracestep
6b8a75d3b8 SX1509 output debounce fix (resolves esphome/issues#4402) (#4672) 2023-10-26 15:36:58 +13:00
Jesse Hills
8b9a7608f0 Correctly allow mqtt topics to be none so ESPHome does not sub/pub to them (#5213) 2023-10-26 13:37:50 +13:00
Jesse Hills
4774200f6b Print text mqtt command topic (#5601) 2023-10-26 13:37:06 +13:00
kahrendt
93056dead9 Add ignore out of range option for clamp filter (#5455)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-26 09:30:23 +13:00
kahrendt
841b24f744 Add support for Qwiic PIR binary sensor (#5194) 2023-10-26 08:29:21 +13:00
kahrendt
258b0fbff3 Fix: Incorporate unique serial number in preference's hash for multiple Sensirion sensors (#5479) 2023-10-26 08:23:55 +13:00
Roger Busser
fdef6c6d46 Update current_based_cover bugfix (#5587) 2023-10-26 07:31:39 +13:00
Eduard Llull
28aedae8d7 Add Emc2101 (#4491)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-26 07:30:11 +13:00
jpfaff
2895cc6c57 Add support for honeywellabp2 pressure sensor (#5422) 2023-10-26 07:28:07 +13:00
dentra
ec835c0b05 Fix exception handling when loading packages (#5569) 2023-10-26 07:15:25 +13:00
Daniel Dunn
e80bd8ed3d Add text component (#5336)
Co-authored-by: Maurits <maurits@vloop.nl>
Co-authored-by: mauritskorse <mauritskorse@gmail.com>
Co-authored-by: Daniel Dunn <dannydunn@eternityforest.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-25 22:00:32 +13:00
dependabot[bot]
cf7df9e360 Bump aioesphomeapi from 18.0.7 to 18.0.12 (#5597)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 12:08:00 -05:00
Alejandro Galfrascoli
e01ba894ed Add IR Noblex climate component (#4913)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-24 16:28:53 +13:00
Jesse Hills
390766eb67 Merge pull request #5596 from esphome/bump-2023.10.3
2023.10.3
2023-10-24 13:40:13 +13:00
Jesse Hills
899d280ac7 Bump version to 2023.10.3 2023-10-24 12:56:25 +13:00
Keith Burzinski
96dc7f0259 Set IP address type only when IPv4 and IPv6 are both enabled (#5595) 2023-10-24 12:56:25 +13:00
Keith Burzinski
cb2f5eb781 Set IP address type only when IPv4 and IPv6 are both enabled (#5595) 2023-10-23 23:43:54 +00:00
Jevgeni Kiski
34dce0acbf AMS iAQ Core CO2 sensor component (#5192)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-24 12:35:51 +13:00
Piu Piuson
96822aaa3a Feat: Add GREE climateir component (#4464)
Co-authored-by: orestismers <33354671+orestismers@users.noreply.github.com>
Co-authored-by: Orestes Mersinias <orestis.mers@gmail.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-24 11:34:46 +13:00
Chris Feenstra
b4765fb5fb Add ZH/LT-01 climate component with IR receiver option (#4333)
Co-authored-by: Chris Feenstra <chris@cfeenstra.nl>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-24 11:33:47 +13:00
dependabot[bot]
da9c2f2256 Bump pyupgrade from 3.13.0 to 3.15.0 (#5570)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-23 21:35:55 +00:00
Jesse Hills
0104bf3fc8 Merge pull request #5590 from esphome/bump-2023.10.2
2023.10.2
2023-10-24 10:15:07 +13:00
dependabot[bot]
cf8fb7888a Bump pytest-mock from 3.11.1 to 3.12.0 (#5571)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 08:43:51 +13:00
Jesse Hills
9b1e1bf56c Bump version to 2023.10.2 2023-10-24 08:32:26 +13:00
dentra
33e0f16b3b Allow set climate preset to NONE (#5588) 2023-10-24 08:32:26 +13:00
Samuel Sieb
0807d60c6a fix canbus send config (#5585)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-10-24 08:32:03 +13:00
Jimmy Hedman
f018fde369 Set addr type when copy from ip4_addr_t (#5583) 2023-10-24 08:30:47 +13:00
Jimmy Hedman
c47f8fc02c Remove explicit cast for IPAddress (#5574)
* Remove explicit cast for IPAddress

* Make linter happy
2023-10-24 08:30:47 +13:00
Trent Houliston
76ab923780 Publish the pulse_meter total when setting the total (#5475) 2023-10-24 08:30:47 +13:00
Keith Burzinski
11dba3147d Improv Serial support via USB CDC and JTAG (#5559) 2023-10-24 08:30:47 +13:00
Jesse Hills
8c2d9101d5 Fix XOR condition (#5567) 2023-10-24 08:30:47 +13:00
Jimmy Hedman
5347c9aafe Add LibreTiny hardwares to PR Template (#5575) 2023-10-24 08:06:23 +13:00
Simone Rossetto
e7d51f9c16 Add address text sensor to WireGuard (#5576) 2023-10-24 08:05:57 +13:00
Edward Firmo
7e27e98bff set Nextion protocol reparse mode (#5484) 2023-10-24 08:02:57 +13:00
Guillermo Ruffino
eead33b6f2 update storage version from mdns (#5584) 2023-10-24 08:02:29 +13:00
dentra
b898f75631 Allow set climate preset to NONE (#5588) 2023-10-24 07:29:32 +13:00
Samuel Sieb
84c00a5867 fix canbus send config (#5585)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-10-24 07:26:23 +13:00
Jimmy Hedman
e3fbf54a1a Set addr type when copy from ip4_addr_t (#5583) 2023-10-23 01:41:16 -05:00
Edward Firmo
3d7d0d4f73 Remove unnecessary checks in Nextion component (#5578) 2023-10-21 14:38:22 -05:00
Jimmy Hedman
05a95f8ee9 Remove explicit cast for IPAddress (#5574)
* Remove explicit cast for IPAddress

* Make linter happy
2023-10-21 17:04:07 +13:00
dependabot[bot]
76417103c7 Bump aioesphomeapi from 18.0.6 to 18.0.7 (#5573)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 16:48:56 -10:00
Trent Houliston
d82471942f Publish the pulse_meter total when setting the total (#5475) 2023-10-19 14:28:05 -07:00
Jordan W. Cobb
9f033bce3b Fan no off cycle action (#5564)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-19 20:02:27 +13:00
Keith Burzinski
b632ae49d4 Improv Serial support via USB CDC and JTAG (#5559) 2023-10-19 19:53:09 +13:00
Jesse Hills
b9d72231b0 Fix XOR condition (#5567) 2023-10-18 21:36:01 -05:00
Jesse Hills
61b8004536 Merge pull request #5566 from esphome/bump-2023.10.1
2023.10.1
2023-10-19 14:27:10 +13:00
dependabot[bot]
e99b8aaf96 Bump black from 23.9.1 to 23.10.0 (#5561)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-19 00:50:09 +00:00
Jesse Hills
db02c4ea21 Bump version to 2023.10.1 2023-10-19 13:30:13 +13:00
Mike La Spina
f077a5962d Incorrect ESP32 Strapping PIN Defined (#5563)
Co-authored-by: descipher <120155735+GelidusResearch@users.noreply.github.com>
2023-10-19 13:30:12 +13:00
Jesse Hills
fa4ba43eb9 Create IPv4 sockets if ipv6 is not enabled (#5565) 2023-10-19 13:30:12 +13:00
Jesse Hills
9579423b24 esp32_improv add timeout (#5556) 2023-10-19 13:30:12 +13:00
Jesse Hills
02449f24c9 Fix voice_assistant without a speaker (#5558) 2023-10-19 13:30:12 +13:00
dependabot[bot]
960d6a1431 Bump tzlocal from 5.0.1 to 5.1 (#5480)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-19 13:09:04 +13:00
dependabot[bot]
53572dcb8a Bump pyupgrade from 3.10.1 to 3.13.0 (#5428)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-19 13:08:44 +13:00
dependabot[bot]
9a087c0767 Bump actions/checkout from 4.1.0 to 4.1.1 (#5551)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-19 13:08:15 +13:00
jj-uk
a7d817656e Hydreon updates (#5424) 2023-10-19 13:06:28 +13:00
Clyde Stubbs
a794836ebe Add config to allow suppression of warnings about use of strapping pins (#5287)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-19 13:04:53 +13:00
Mike La Spina
799c3cf439 Incorrect ESP32 Strapping PIN Defined (#5563)
Co-authored-by: descipher <120155735+GelidusResearch@users.noreply.github.com>
2023-10-19 13:00:15 +13:00
Jesse Hills
b7402ee6ff Create IPv4 sockets if ipv6 is not enabled (#5565) 2023-10-19 12:25:43 +13:00
Jesse Hills
a8667b680e esp32_improv add timeout (#5556) 2023-10-19 11:42:52 +13:00
dependabot[bot]
10c89771e3 Bump zeroconf from 0.115.1 to 0.119.0 (#5560) 2023-10-18 10:21:19 -10:00
dependabot[bot]
b735fc475e Bump aioesphomeapi from 15.0.0 to 18.0.6 (#5557)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-18 08:28:52 -10:00
Jesse Hills
19736f6e53 Fix voice_assistant without a speaker (#5558) 2023-10-18 09:12:35 +00:00
Keith Burzinski
cdc4f7f59b IDF 5 fixes for various components from test1.yaml (#5451) 2023-10-18 19:33:36 +13:00
J. Nick Koston
8ef743f25e Update docker base and packages + docker python 3.11 (#5473)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-18 19:33:19 +13:00
Jesse Hills
b973238323 Merge pull request #5555 from esphome/bump-2023.10.0
2023.10.0
2023-10-18 17:38:50 +13:00
Jesse Hills
582b8383d2 Bump version to 2023.10.0 2023-10-18 16:47:03 +13:00
Jesse Hills
e1c9418aee Merge pull request #5554 from esphome/bump-2023.10.0b4
2023.10.0b4
2023-10-18 15:44:37 +13:00
Jesse Hills
2aa787f5f0 Bump version to 2023.10.0b4 2023-10-18 14:28:03 +13:00
Jesse Hills
2189a40a39 esp32_improv advertise capabilities and state in ble service data (#5553) 2023-10-18 14:28:03 +13:00
Fabian Bläse
51688d4078 SML: fix incomplete sign extension for abbreviated transmissions (#5544) 2023-10-18 14:28:03 +13:00
Jesse Hills
cc4c0e3e0b Fix default libretiny manufacturer reported to HA (#5549) 2023-10-18 14:28:02 +13:00
Jesse Hills
14aa27f5e2 esp32_improv advertise capabilities and state in ble service data (#5553) 2023-10-18 14:26:47 +13:00
Samuel Sieb
c19dbdb02d add on/off options for uart switch (#5539)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-10-18 08:07:29 +13:00
Fabian Bläse
b0ac729a8e SML: fix incomplete sign extension for abbreviated transmissions (#5544) 2023-10-18 07:39:05 +13:00
Samuel Sieb
6839de69c1 add uart button (#5540)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-10-18 07:30:32 +13:00
Jesse Hills
b12dc98150 Fix default libretiny manufacturer reported to HA (#5549) 2023-10-18 07:23:34 +13:00
Jesse Hills
1a44c6487e Merge pull request #5548 from esphome/bump-2023.10.0b3
2023.10.0b3
2023-10-17 20:49:16 +13:00
Jesse Hills
5e7ce610a0 Bump version to 2023.10.0b3 2023-10-17 20:15:14 +13:00
Jesse Hills
1f02096edb More voice assistant fixes (#5547) 2023-10-17 20:15:14 +13:00
Jesse Hills
fd7d3c4332 Fix esp32_improv authorizer with no binary sensors in config (#5546) 2023-10-17 20:15:14 +13:00
Jesse Hills
61cf566560 Add stream start and end events (#5545) 2023-10-17 20:15:14 +13:00
Christian
97d624114d Add change i2c address and allow multi conf for TB6612FNG (#5492) 2023-10-17 20:15:14 +13:00
raineth
52e8a2e9e4 Make IPAddress's operator!= compare values, not memory addresses. (#5537)
Co-authored-by: Ben Winslow <rain@bluecherry.net>
2023-10-17 20:15:14 +13:00
Jesse Hills
261c271d60 Prometheus fix for esp-idf and fix newlines (#5536) 2023-10-17 20:15:14 +13:00
Jesse Hills
a960c8008e More voice assistant fixes (#5547) 2023-10-17 20:11:37 +13:00
Jesse Hills
fb90e19713 Fix esp32_improv authorizer with no binary sensors in config (#5546) 2023-10-17 20:03:39 +13:00
Jesse Hills
4913b3cc35 Add stream start and end events (#5545) 2023-10-17 17:18:05 +13:00
Christian
e42c51a222 Add change i2c address and allow multi conf for TB6612FNG (#5492) 2023-10-17 08:47:35 +13:00
raineth
26f12cd3bb Make IPAddress's operator!= compare values, not memory addresses. (#5537)
Co-authored-by: Ben Winslow <rain@bluecherry.net>
2023-10-16 19:42:18 +13:00
Jesse Hills
06eff72065 Prometheus fix for esp-idf and fix newlines (#5536) 2023-10-16 19:41:59 +13:00
leoshusar
357ba1ab0f Change UART source clock to UART_SCLK_DEFAULT when IDF >=v5 (#5533) 2023-10-16 11:29:13 +13:00
ghsensdev
6143099f60 Add Support for Sensirion SFA30 sensor (#5519)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-16 07:49:57 +13:00
Jesse Hills
7ddcdab351 Add round sensor filter (#5532) 2023-10-14 13:07:23 +13:00
Cossid
da3e3903dd BP1658CJ - Clear all channels before sleeping. (#5525) 2023-10-13 12:51:28 +13:00
Cossid
f5c12b50ce SM10BIT_BASE - Add delays and ACKs, clear all channels before sleeping. (#5526) 2023-10-13 12:51:19 +13:00
Jesse Hills
33ebfd221e Update Improv BLE component (#5518) 2023-10-13 12:46:46 +13:00
Cossid
7c890d8ebc BD5758D - Add delays and ACKs (#5524) 2023-10-12 19:09:07 +00:00
NP v/d Spek
04b708c336 Splits FastLed test scripts out of test1.yaml (#5522) 2023-10-13 07:20:31 +13:00
Nippey
2910eb2ef7 Update htu21d.cpp, fix publishing of heater level (#5520) 2023-10-12 10:56:30 -07:00
750 changed files with 31205 additions and 6357 deletions

View File

@@ -1,17 +1,13 @@
{
"name": "ESPHome Dev",
"image": "ghcr.io/esphome/esphome-lint:dev",
"postCreateCommand": [
"script/devcontainer-post-create"
],
"postCreateCommand": ["script/devcontainer-post-create"],
"containerEnv": {
"DEVCONTAINER": "1"
"DEVCONTAINER": "1",
"PIP_BREAK_SYSTEM_PACKAGES": "1",
"PIP_ROOT_USER_ACTION": "ignore"
},
"runArgs": [
"--privileged",
"-e",
"ESPHOME_DASHBOARD_USE_PING=1"
],
"runArgs": ["--privileged", "-e", "ESPHOME_DASHBOARD_USE_PING=1"],
"appPort": 6052,
"customizations": {
"vscode": {
@@ -24,7 +20,7 @@
// cpp
"ms-vscode.cpptools",
// editorconfig
"editorconfig.editorconfig",
"editorconfig.editorconfig"
],
"settings": {
"python.languageServer": "Pylance",
@@ -41,6 +37,7 @@
"!secret scalar",
"!lambda scalar",
"!extend scalar",
"!remove scalar",
"!include_dir_named scalar",
"!include_dir_list scalar",
"!include_dir_merge_list scalar",

View File

@@ -19,6 +19,8 @@
- [ ] ESP32 IDF
- [ ] ESP8266
- [ ] RP2040
- [ ] BK72xx
- [ ] RTL87xx
## Example entry for `config.yaml`:
<!--

97
.github/actions/build-image/action.yaml vendored Normal file
View File

@@ -0,0 +1,97 @@
name: Build Image
inputs:
platform:
description: "Platform to build for"
required: true
example: "linux/amd64"
target:
description: "Target to build"
required: true
example: "docker"
baseimg:
description: "Base image type"
required: true
example: "docker"
suffix:
description: "Suffix to add to tags"
required: true
version:
description: "Version to build"
required: true
example: "2023.12.0"
runs:
using: "composite"
steps:
- name: Generate short tags
id: tags
shell: bash
run: |
output=$(docker/generate_tags.py \
--tag "${{ inputs.version }}" \
--suffix "${{ inputs.suffix }}")
echo $output
for l in $output; do
echo $l >> $GITHUB_OUTPUT
done
- name: Build and push to ghcr by digest
id: build-ghcr
uses: docker/build-push-action@v5.0.0
with:
context: .
file: ./docker/Dockerfile
platforms: ${{ inputs.platform }}
target: ${{ inputs.target }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BASEIMGTYPE=${{ inputs.baseimg }}
BUILD_VERSION=${{ inputs.version }}
outputs: |
type=image,name=ghcr.io/${{ steps.tags.outputs.image_name }},push-by-digest=true,name-canonical=true,push=true
- name: Export ghcr digests
shell: bash
run: |
mkdir -p /tmp/digests/${{ inputs.target }}/ghcr
digest="${{ steps.build-ghcr.outputs.digest }}"
touch "/tmp/digests/${{ inputs.target }}/ghcr/${digest#sha256:}"
- name: Upload ghcr digest
uses: actions/upload-artifact@v3.1.3
with:
name: digests-${{ inputs.target }}-ghcr
path: /tmp/digests/${{ inputs.target }}/ghcr/*
if-no-files-found: error
retention-days: 1
- name: Build and push to dockerhub by digest
id: build-dockerhub
uses: docker/build-push-action@v5.0.0
with:
context: .
file: ./docker/Dockerfile
platforms: ${{ inputs.platform }}
target: ${{ inputs.target }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BASEIMGTYPE=${{ inputs.baseimg }}
BUILD_VERSION=${{ inputs.version }}
outputs: |
type=image,name=docker.io/${{ steps.tags.outputs.image_name }},push-by-digest=true,name-canonical=true,push=true
- name: Export dockerhub digests
shell: bash
run: |
mkdir -p /tmp/digests/${{ inputs.target }}/dockerhub
digest="${{ steps.build-dockerhub.outputs.digest }}"
touch "/tmp/digests/${{ inputs.target }}/dockerhub/${digest#sha256:}"
- name: Upload dockerhub digest
uses: actions/upload-artifact@v3.1.3
with:
name: digests-${{ inputs.target }}-dockerhub
path: /tmp/digests/${{ inputs.target }}/dockerhub/*
if-no-files-found: error
retention-days: 1

View File

@@ -17,7 +17,7 @@ runs:
steps:
- name: Set up Python ${{ inputs.python-version }}
id: python
uses: actions/setup-python@v4.7.0
uses: actions/setup-python@v5.0.0
with:
python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment

View File

@@ -40,9 +40,9 @@ jobs:
arch: [amd64, armv7, aarch64]
build_type: ["ha-addon", "docker", "lint"]
steps:
- uses: actions/checkout@v4.1.0
- uses: actions/checkout@v4.1.1
- name: Set up Python
uses: actions/setup-python@v4.7.1
uses: actions/setup-python@v5.0.0
with:
python-version: "3.9"
- name: Set up Docker Buildx

View File

@@ -34,13 +34,13 @@ jobs:
cache-key: ${{ steps.cache-key.outputs.key }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Generate cache-key
id: cache-key
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@v4.7.1
uses: actions/setup-python@v5.0.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
@@ -66,7 +66,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -87,7 +87,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -108,7 +108,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -129,7 +129,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -150,7 +150,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -171,7 +171,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -191,7 +191,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -216,11 +216,34 @@ jobs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Find all YAML test files
id: set-matrix
run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
validate-tests:
name: Validate YAML test ${{ matrix.file }}
runs-on: ubuntu-latest
needs:
- common
- compile-tests-list
strategy:
fail-fast: false
matrix:
file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Run esphome config ${{ matrix.file }}
run: |
. venv/bin/activate
esphome config ${{ matrix.file }}
compile-tests:
name: Run YAML test ${{ matrix.file }}
runs-on: ubuntu-latest
@@ -234,6 +257,7 @@ jobs:
- pytest
- pyupgrade
- compile-tests-list
- validate-tests
strategy:
fail-fast: false
max-parallel: 2
@@ -241,7 +265,7 @@ jobs:
file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -296,7 +320,7 @@ jobs:
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Restore Python
uses: ./.github/actions/restore-python
with:

View File

@@ -18,7 +18,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v4.0.1
- uses: dessant/lock-threads@v5.0.1
with:
pr-inactive-days: "1"
pr-lock-reason: ""

24
.github/workflows/needs-docs.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Needs Docs
on:
pull_request:
types: [labeled, unlabeled]
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Check for needs-docs label
uses: actions/github-script@v7.0.1
with:
script: |
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const needsDocs = labels.find(label => label.name === 'needs-docs');
if (needsDocs) {
core.setFailed('Pull request needs docs');
}

View File

@@ -19,7 +19,7 @@ jobs:
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- uses: actions/checkout@v4.1.0
- uses: actions/checkout@v4.1.1
- name: Get tag
id: tag
# yamllint disable rule:line-length
@@ -43,9 +43,9 @@ jobs:
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.0
- uses: actions/checkout@v4.1.1
- name: Set up Python
uses: actions/setup-python@v4.7.1
uses: actions/setup-python@v5.0.0
with:
python-version: "3.x"
- name: Set up python environment
@@ -63,40 +63,31 @@ jobs:
run: twine upload dist/*
deploy-docker:
name: Build and publish ESPHome ${{ matrix.image.title}}
name: Build ESPHome ${{ matrix.platform }}
if: github.repository == 'esphome/esphome'
permissions:
contents: read
packages: write
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.image.title == 'lint' }}
needs: [init]
strategy:
fail-fast: false
matrix:
image:
- title: "ha-addon"
suffix: "hassio"
target: "hassio"
baseimg: "hassio"
- title: "docker"
suffix: ""
target: "docker"
baseimg: "docker"
- title: "lint"
suffix: "lint"
target: "lint"
baseimg: "docker"
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
steps:
- uses: actions/checkout@v4.1.0
- uses: actions/checkout@v4.1.1
- name: Set up Python
uses: actions/setup-python@v4.7.1
uses: actions/setup-python@v5.0.0
with:
python-version: "3.9"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0
- name: Set up QEMU
if: matrix.platform != 'linux/amd64'
uses: docker/setup-qemu-action@v3.0.0
- name: Log in to docker hub
@@ -111,37 +102,108 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build docker
uses: ./.github/actions/build-image
with:
platform: ${{ matrix.platform }}
target: docker
baseimg: docker
suffix: ""
version: ${{ needs.init.outputs.tag }}
- name: Build ha-addon
uses: ./.github/actions/build-image
with:
platform: ${{ matrix.platform }}
target: hassio
baseimg: hassio
suffix: "hassio"
version: ${{ needs.init.outputs.tag }}
- name: Build lint
uses: ./.github/actions/build-image
with:
platform: ${{ matrix.platform }}
target: lint
baseimg: docker
suffix: lint
version: ${{ needs.init.outputs.tag }}
deploy-manifest:
name: Publish ESPHome ${{ matrix.image.title }} to ${{ matrix.registry }}
runs-on: ubuntu-latest
needs:
- init
- deploy-docker
if: github.repository == 'esphome/esphome'
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
image:
- title: "ha-addon"
target: "hassio"
suffix: "hassio"
- title: "docker"
target: "docker"
suffix: ""
- title: "lint"
target: "lint"
suffix: "lint"
registry:
- ghcr
- dockerhub
steps:
- uses: actions/checkout@v4.1.1
- name: Download digests
uses: actions/download-artifact@v3.0.2
with:
name: digests-${{ matrix.image.target }}-${{ matrix.registry }}
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0
- name: Log in to docker hub
if: matrix.registry == 'dockerhub'
uses: docker/login-action@v3.0.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.0.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate short tags
id: tags
run: |
docker/generate_tags.py \
output=$(docker/generate_tags.py \
--tag "${{ needs.init.outputs.tag }}" \
--suffix "${{ matrix.image.suffix }}"
--suffix "${{ matrix.image.suffix }}" \
--registry "${{ matrix.registry }}")
echo $output
for l in $output; do
echo $l >> $GITHUB_OUTPUT
done
- name: Build and push
uses: docker/build-push-action@v5.0.0
with:
context: .
file: ./docker/Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64
target: ${{ matrix.image.target }}
push: true
# yamllint disable rule:line-length
cache-from: type=registry,ref=ghcr.io/${{ steps.tags.outputs.image }}:cache-${{ steps.tags.outputs.channel }}
cache-to: type=registry,ref=ghcr.io/${{ steps.tags.outputs.image }}:cache-${{ steps.tags.outputs.channel }},mode=max
# yamllint enable rule:line-length
tags: ${{ steps.tags.outputs.tags }}
build-args: |
BASEIMGTYPE=${{ matrix.image.baseimg }}
BUILD_VERSION=${{ needs.init.outputs.tag }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -Rcnr 'inputs | . / "," | map("-t " + .) | join(" ")' <<< "${{ steps.tags.outputs.tags}}") \
$(printf '${{ steps.tags.outputs.image }}@sha256:%s ' *)
deploy-ha-addon-repo:
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
runs-on: ubuntu-latest
needs: [deploy-docker]
needs: [deploy-manifest]
steps:
- name: Trigger Workflow
uses: actions/github-script@v6.4.1
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
script: |

View File

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

View File

@@ -13,16 +13,16 @@ jobs:
if: github.repository == 'esphome/esphome'
steps:
- name: Checkout
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Checkout Home Assistant
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
with:
repository: home-assistant/core
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@v4.7.1
uses: actions/setup-python@v5.0.0
with:
python-version: 3.11

View File

@@ -17,6 +17,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.0
uses: actions/checkout@v4.1.1
- name: Run yamllint
uses: frenck/action-yamllint@v1.4.1
uses: frenck/action-yamllint@v1.4.2

View File

@@ -3,7 +3,7 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.9.1
rev: 23.12.0
hooks:
- id: black
args:
@@ -11,7 +11,7 @@ repos:
- --quiet
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
rev: 6.1.0
hooks:
- id: flake8
additional_dependencies:
@@ -27,7 +27,7 @@ repos:
- --branch=release
- --branch=beta
- repo: https://github.com/asottile/pyupgrade
rev: v3.10.1
rev: v3.15.0
hooks:
- id: pyupgrade
args: [--py39-plus]

View File

@@ -12,11 +12,15 @@ esphome/core/* @esphome/core
# Integrations
esphome/components/a01nyub/* @MrSuicideParrot
esphome/components/a02yyuw/* @TH-Braemer
esphome/components/absolute_humidity/* @DAVe3283
esphome/components/ac_dimmer/* @glmnet
esphome/components/adc/* @esphome/core
esphome/components/adc128s102/* @DeerMaximum
esphome/components/addressable_light/* @justfalter
esphome/components/ade7953/* @angelnu
esphome/components/ade7953_i2c/* @angelnu
esphome/components/ade7953_spi/* @angelnu
esphome/components/airthings_ble/* @jeromelaban
esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau
esphome/components/airthings_wave_mini/* @ncareau
@@ -77,6 +81,7 @@ esphome/components/dashboard_import/* @esphome/core
esphome/components/debug/* @OttoWinter
esphome/components/delonghi/* @grob6000
esphome/components/dfplayer/* @glmnet
esphome/components/dfrobot_sen0395/* @niklasweber
esphome/components/dht/* @OttoWinter
esphome/components/display_menu_base/* @numo68
esphome/components/dps310/* @kbx81
@@ -84,12 +89,14 @@ esphome/components/ds1307/* @badbadc0ffee
esphome/components/dsmr/* @glmnet @zuidwijk
esphome/components/duty_time/* @dudanov
esphome/components/ee895/* @Stock-M
esphome/components/ektf2232/* @jesserockz
esphome/components/ektf2232/touchscreen/* @jesserockz
esphome/components/emc2101/* @ellull
esphome/components/ens160/* @vincentscode
esphome/components/ens210/* @itn3rd77
esphome/components/esp32/* @esphome/core
esphome/components/esp32_ble/* @jesserockz
esphome/components/esp32_ble/* @Rapsssito @jesserockz
esphome/components/esp32_ble_client/* @jesserockz
esphome/components/esp32_ble_server/* @clydebarrow @jesserockz
esphome/components/esp32_ble_server/* @Rapsssito @clydebarrow @jesserockz
esphome/components/esp32_camera_web_server/* @ayufan
esphome/components/esp32_can/* @Sympatron
esphome/components/esp32_improv/* @jesserockz
@@ -104,23 +111,30 @@ esphome/components/fastled_base/* @OttoWinter
esphome/components/feedback/* @ianchi
esphome/components/fingerprint_grow/* @OnFreund @loongyh
esphome/components/fs3000/* @kahrendt
esphome/components/ft5x06/* @clydebarrow
esphome/components/ft63x6/* @gpambrozio
esphome/components/gcja5/* @gcormier
esphome/components/globals/* @esphome/core
esphome/components/gp8403/* @jesserockz
esphome/components/gpio/* @esphome/core
esphome/components/gps/* @coogle
esphome/components/graph/* @synco
esphome/components/graphical_display_menu/* @MrMDavidson
esphome/components/gree/* @orestismers
esphome/components/grove_tb6612fng/* @max246
esphome/components/growatt_solar/* @leeuwte
esphome/components/gt911/* @clydebarrow @jesserockz
esphome/components/haier/* @paveldn
esphome/components/havells_solar/* @sourabhjaiswal
esphome/components/hbridge/fan/* @WeekendWarrior
esphome/components/hbridge/light/* @DotNetDann
esphome/components/he60r/* @clydebarrow
esphome/components/heatpumpir/* @rob-deutsch
esphome/components/hitachi_ac424/* @sourabhjaiswal
esphome/components/hm3301/* @freekode
esphome/components/homeassistant/* @OttoWinter
esphome/components/honeywellabp/* @RubyBailey
esphome/components/honeywellabp2_i2c/* @jpfaff
esphome/components/host/* @esphome/core
esphome/components/hrxl_maxsonar_wr/* @netmikey
esphome/components/hte501/* @Stock-M
@@ -131,6 +145,7 @@ esphome/components/i2s_audio/* @jesserockz
esphome/components/i2s_audio/media_player/* @jesserockz
esphome/components/i2s_audio/microphone/* @jesserockz
esphome/components/i2s_audio/speaker/* @jesserockz
esphome/components/iaqcore/* @yozik04
esphome/components/ili9xxx/* @clydebarrow @nielsnl68
esphome/components/improv_base/* @esphome/core
esphome/components/improv_serial/* @esphome/core
@@ -147,6 +162,7 @@ esphome/components/key_provider/* @ssieb
esphome/components/kuntze/* @ssieb
esphome/components/lcd_menu/* @numo68
esphome/components/ld2410/* @regevbr @sebcaps
esphome/components/ld2420/* @descipher
esphome/components/ledc/* @OttoWinter
esphome/components/libretiny/* @kuba2k2
esphome/components/libretiny_pwm/* @kuba2k2
@@ -178,6 +194,7 @@ esphome/components/mcp9808/* @k7hpn
esphome/components/md5/* @esphome/core
esphome/components/mdns/* @esphome/core
esphome/components/media_player/* @jesserockz
esphome/components/micronova/* @jorre05
esphome/components/microphone/* @jesserockz
esphome/components/mics_4514/* @jesserockz
esphome/components/midea/* @dudanov
@@ -207,11 +224,12 @@ esphome/components/nextion/sensor/* @senexcrenshaw
esphome/components/nextion/switch/* @senexcrenshaw
esphome/components/nextion/text_sensor/* @senexcrenshaw
esphome/components/nfc/* @jesserockz
esphome/components/noblex/* @AGalfra
esphome/components/number/* @esphome/core
esphome/components/ota/* @esphome/core
esphome/components/output/* @esphome/core
esphome/components/pca6416a/* @Mat931
esphome/components/pca9554/* @hwstar
esphome/components/pca9554/* @clydebarrow @hwstar
esphome/components/pcf85063/* @brogon
esphome/components/pcf8563/* @KoenBreeman
esphome/components/pid/* @OttoWinter
@@ -222,18 +240,26 @@ esphome/components/pmwcs3/* @SeByDocKy
esphome/components/pn532/* @OttoWinter @jesserockz
esphome/components/pn532_i2c/* @OttoWinter @jesserockz
esphome/components/pn532_spi/* @OttoWinter @jesserockz
esphome/components/pn7150/* @jesserockz @kbx81
esphome/components/pn7150_i2c/* @jesserockz @kbx81
esphome/components/pn7160/* @jesserockz @kbx81
esphome/components/pn7160_i2c/* @jesserockz @kbx81
esphome/components/pn7160_spi/* @jesserockz @kbx81
esphome/components/power_supply/* @esphome/core
esphome/components/preferences/* @esphome/core
esphome/components/psram/* @esphome/core
esphome/components/pulse_meter/* @cstaahl @stevebaxter
esphome/components/pulse_meter/* @TrentHouliston @cstaahl @stevebaxter
esphome/components/pvvx_mithermometer/* @pasiz
esphome/components/pylontech/* @functionpointer
esphome/components/qmp6988/* @andrewpc
esphome/components/qr_code/* @wjtje
esphome/components/qwiic_pir/* @kahrendt
esphome/components/radon_eye_ble/* @jeffeb3
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/restart/* @esphome/core
esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz
@@ -254,6 +280,7 @@ esphome/components/sen21231/* @shreyaskarnik
esphome/components/sen5x/* @martgras
esphome/components/sensirion_common/* @martgras
esphome/components/sensor/* @esphome/core
esphome/components/sfa30/* @ghsensdev
esphome/components/sgp40/* @SenexCrenshaw
esphome/components/sgp4x/* @SenexCrenshaw @martgras
esphome/components/shelly_dimmer/* @edge90 @rnauber
@@ -299,6 +326,7 @@ esphome/components/tcl112/* @glmnet
esphome/components/tee501/* @Stock-M
esphome/components/teleinfo/* @0hax
esphome/components/template/alarm_control_panel/* @grahambrown11
esphome/components/text/* @mauritskorse
esphome/components/thermostat/* @kbx81
esphome/components/time/* @OttoWinter
esphome/components/tlc5947/* @rnauber
@@ -311,7 +339,7 @@ esphome/components/tmp1075/* @sybrenstuvel
esphome/components/tmp117/* @Azimath
esphome/components/tof10120/* @wstrzalka
esphome/components/toshiba/* @kbx81
esphome/components/touchscreen/* @jesserockz
esphome/components/touchscreen/* @jesserockz @nielsnl68
esphome/components/tsl2591/* @wjcarpenter
esphome/components/tt21100/* @kroimon
esphome/components/tuya/binary_sensor/* @jesserockz
@@ -322,6 +350,7 @@ esphome/components/tuya/sensor/* @jesserockz
esphome/components/tuya/switch/* @jesserockz
esphome/components/tuya/text_sensor/* @dentra
esphome/components/uart/* @esphome/core
esphome/components/uart/button/* @ssieb
esphome/components/ufire_ec/* @pvizeli
esphome/components/ufire_ise/* @pvizeli
esphome/components/ultrasonic/* @OttoWinter
@@ -337,10 +366,12 @@ esphome/components/wiegand/* @ssieb
esphome/components/wireguard/* @droscy @lhoracek @thomas0bernard
esphome/components/wl_134/* @hobbypunk90
esphome/components/x9c/* @EtienneMD
esphome/components/xgzp68xx/* @gcormier
esphome/components/xiaomi_lywsd03mmc/* @ahpohl
esphome/components/xiaomi_mhoc303/* @drug123
esphome/components/xiaomi_mhoc401/* @vevsvevs
esphome/components/xiaomi_rtcgq02lm/* @jesserockz
esphome/components/xl9535/* @mreditor97
esphome/components/xpt2046/* @nielsnl68 @numo68
esphome/components/xpt2046/touchscreen/* @nielsnl68 @numo68
esphome/components/zhlt01/* @cfeenstra1024
esphome/components/zio_ultrasonic/* @kahrendt

View File

@@ -10,5 +10,3 @@ Things to note when contributing:
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.
- Sometimes I will let pull requests linger because I'm not 100% sure about them. Please feel free to ping
me after some time.

View File

@@ -5,39 +5,55 @@
# One of "docker", "hassio"
ARG BASEIMGTYPE=docker
# https://github.com/hassio-addons/addon-debian-base/releases
FROM ghcr.io/hassio-addons/debian-base:6.2.3 AS base-hassio
# https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye
FROM debian:bullseye-20230208-slim AS base-docker
FROM ghcr.io/hassio-addons/debian-base:7.2.0 AS base-hassio
# https://hub.docker.com/_/debian?tab=tags&page=1&name=bookworm
FROM debian:12.2-slim AS base-docker
FROM base-${BASEIMGTYPE} AS base
ARG TARGETARCH
ARG TARGETVARIANT
# Note that --break-system-packages is used below because
# https://peps.python.org/pep-0668/ added a safety check that prevents
# installing packages with the same name as a system package. This is
# not a problem for us because we are not concerned about overwriting
# system packages because we are running in an isolated container.
RUN \
apt-get update \
# Use pinned versions so that we get updates with build caching
&& apt-get install -y --no-install-recommends \
python3=3.9.2-3 \
python3-pip=20.3.4-4+deb11u1 \
python3-setuptools=52.0.0-4 \
python3-cryptography=3.3.2-1 \
python3-venv=3.9.2-3 \
iputils-ping=3:20210202-1 \
git=1:2.30.2-1+deb11u2 \
curl=7.74.0-1.3+deb11u10 \
openssh-client=1:8.4p1-5+deb11u2 \
python3-cffi=1.14.5-1 \
libcairo2=1.16.0-5 \
python3-pip=23.0.1+dfsg-1 \
python3-setuptools=66.1.1-1 \
python3-venv=3.11.2-1+b1 \
python3-wheel=0.38.4-2 \
iputils-ping=3:20221126-1 \
git=1:2.39.2-1.1 \
curl=7.88.1-10+deb12u5 \
openssh-client=1:9.2p1-2+deb12u1 \
python3-cffi=1.15.1-5 \
libcairo2=1.16.0-7 \
libmagic1=1:5.44-3 \
patch=2.7.6-7; \
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
apt-get install -y --no-install-recommends \
build-essential=12.9 \
python3-dev=3.9.2-3 \
zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \
libjpeg-dev=1:2.0.6-4 \
libfreetype-dev=2.10.4+dfsg-1+deb11u1; \
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 \
libssl-dev=3.0.11-1~deb12u2 \
libffi-dev=3.4.4-1 \
libopenjp2-7=2.5.0-2 \
libtiff6=4.5.0-6+deb12u1 \
cargo=0.66.0+ds1-1 \
pkg-config=1.8.1-1 \
gcc-arm-linux-gnueabihf=4:12.2.0-3; \
fi; \
rm -rf \
/tmp/* \
@@ -55,14 +71,17 @@ ENV \
# 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.so.3 /lib/ld-linux.so.3; \
ln -s /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 /lib/ld-linux.so.3; \
fi
RUN \
# Ubuntu python3-pip is missing wheel
pip3 install --no-cache-dir \
wheel==0.37.1 \
platformio==6.1.11 \
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir \
platformio==6.1.11 \
# Change some platformio settings
&& platformio settings set enable_telemetry No \
&& platformio settings set check_platformio_interval 1000000 \
@@ -70,9 +89,15 @@ RUN \
# First install requirements to leverage caching when requirements don't change
# tmpfs is for https://github.com/rust-lang/cargo/issues/8719
COPY requirements.txt requirements_optional.txt script/platformio_install_deps.py platformio.ini /
RUN \
pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
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 \
&& /platformio_install_deps.py /platformio.ini --libraries
@@ -81,7 +106,11 @@ FROM base AS docker
# Copy esphome and install
COPY . /esphome
RUN pip3 install --no-cache-dir --no-use-pep517 -e /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 --no-use-pep517 -e /esphome
# Settings for dashboard
ENV USERNAME="" PASSWORD=""
@@ -89,6 +118,10 @@ ENV USERNAME="" PASSWORD=""
# Expose the dashboard to Docker
EXPOSE 6052
# Run healthcheck (heartbeat)
HEALTHCHECK --interval=30s --timeout=30s \
CMD curl --fail http://localhost:6052/version -A "HealthCheck" || exit 1
COPY docker/docker_entrypoint.sh /entrypoint.sh
# The directory the user should mount their configuration files to
@@ -110,7 +143,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.18.0-6.1+deb11u3 \
nginx-light=1.22.1-9 \
&& rm -rf \
/tmp/* \
/var/{cache,log}/* \
@@ -123,7 +156,11 @@ COPY docker/ha-addon-rootfs/ /
# Copy esphome and install
COPY . /esphome
RUN pip3 install --no-cache-dir --no-use-pep517 -e /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 --no-use-pep517 -e /esphome
# Labels
LABEL \
@@ -146,20 +183,24 @@ RUN \
apt-get update \
# Use pinned versions so that we get updates with build caching
&& apt-get install -y --no-install-recommends \
clang-format-13=1:13.0.1-6~deb11u1 \
clang-tidy-11=1:11.0.1-2 \
clang-format-13=1:13.0.1-11+b2 \
clang-tidy-14=1:14.0.6-12 \
patch=2.7.6-7 \
software-properties-common=0.96.20.2-2.1 \
nano=5.4-2+deb11u2 \
software-properties-common=0.99.30-4 \
nano=7.2-1 \
build-essential=12.9 \
python3-dev=3.9.2-3 \
python3-dev=3.11.2-1+b1 \
&& rm -rf \
/tmp/* \
/var/{cache,log}/* \
/var/lib/apt/lists/*
COPY requirements_test.txt /
RUN pip3 install --no-cache-dir -r /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
VOLUME ["/esphome"]
WORKDIR /esphome

View File

@@ -1,13 +1,14 @@
#!/usr/bin/env python3
import re
import os
import argparse
import json
CHANNEL_DEV = "dev"
CHANNEL_BETA = "beta"
CHANNEL_RELEASE = "release"
GHCR = "ghcr"
DOCKERHUB = "dockerhub"
parser = argparse.ArgumentParser()
parser.add_argument(
"--tag",
@@ -21,21 +22,31 @@ parser.add_argument(
required=True,
help="The suffix of the tag.",
)
parser.add_argument(
"--registry",
type=str,
choices=[GHCR, DOCKERHUB],
required=False,
action="append",
help="The registry to build tags for.",
)
def main():
args = parser.parse_args()
# detect channel from tag
match = re.match(r"^(\d+\.\d+)(?:\.\d+)?(b\d+)?$", args.tag)
match = re.match(r"^(\d+\.\d+)(?:\.\d+)(?:(b\d+)|(-dev\d+))?$", args.tag)
major_minor_version = None
if match is None:
if match is None: # eg 2023.12.0-dev20231109-testbranch
channel = None # Ran with custom tag for a branch etc
elif match.group(3) is not None: # eg 2023.12.0-dev20231109
channel = CHANNEL_DEV
elif match.group(2) is None:
elif match.group(2) is not None: # eg 2023.12.0b1
channel = CHANNEL_BETA
else: # eg 2023.12.0
major_minor_version = match.group(1)
channel = CHANNEL_RELEASE
else:
channel = CHANNEL_BETA
tags_to_push = [args.tag]
if channel == CHANNEL_DEV:
@@ -53,15 +64,28 @@ def main():
suffix = f"-{args.suffix}" if args.suffix else ""
with open(os.environ["GITHUB_OUTPUT"], "w") as f:
print(f"channel={channel}", file=f)
print(f"image=esphome/esphome{suffix}", file=f)
full_tags = []
image_name = f"esphome/esphome{suffix}"
for tag in tags_to_push:
full_tags += [f"ghcr.io/esphome/esphome{suffix}:{tag}"]
full_tags += [f"esphome/esphome{suffix}:{tag}"]
print(f"tags={','.join(full_tags)}", file=f)
print(f"channel={channel}")
if args.registry is None:
args.registry = [GHCR, DOCKERHUB]
elif len(args.registry) == 1:
if GHCR in args.registry:
print(f"image=ghcr.io/{image_name}")
if DOCKERHUB in args.registry:
print(f"image=docker.io/{image_name}")
print(f"image_name={image_name}")
full_tags = []
for tag in tags_to_push:
if GHCR in args.registry:
full_tags += [f"ghcr.io/{image_name}:{tag}"]
if DOCKERHUB in args.registry:
full_tags += [f"docker.io/{image_name}:{tag}"]
print(f"tags={','.join(full_tags)}")
if __name__ == "__main__":

View File

@@ -1,3 +1,4 @@
# PYTHON_ARGCOMPLETE_OK
import argparse
import functools
import logging
@@ -7,9 +8,11 @@ import sys
import time
from datetime import datetime
import argcomplete
from esphome import const, writer, yaml_util
import esphome.codegen as cg
from esphome.config import iter_components, read_config, strip_default_ids
from esphome.config import iter_component_configs, read_config, strip_default_ids
from esphome.const import (
ALLOWED_NAME_CHARS,
CONF_BAUD_RATE,
@@ -193,7 +196,7 @@ def write_cpp(config):
def generate_cpp_contents(config):
_LOGGER.info("Generating C++ source...")
for name, component, conf in iter_components(CORE.config):
for name, component, conf in iter_component_configs(CORE.config):
if component.to_code is not None:
coro = wrap_to_code(name, component)
CORE.add_job(coro, conf)
@@ -386,7 +389,8 @@ def command_config(args, config):
output = re.sub(
r"(password|key|psk|ssid)\: (.+)", r"\1: \\033[5m\2\\033[6m", output
)
safe_print(output)
if not CORE.quiet:
safe_print(output)
_LOGGER.info("Configuration is valid!")
return 0
@@ -511,7 +515,7 @@ def command_clean(args, config):
def command_dashboard(args):
from esphome.dashboard import dashboard
return dashboard.start_web_server(args)
return dashboard.start_dashboard(args)
def command_update_all(args):
@@ -966,6 +970,7 @@ def parse_args(argv):
# Finally, run the new-style parser again with the possibly swapped arguments,
# and let it error out if the command is unparsable.
parser.set_defaults(deprecated_argv_suggestion=deprecated_argv_suggestion)
argcomplete.autocomplete(parser)
return parser.parse_args(arguments)

View File

@@ -8,50 +8,37 @@ namespace esphome {
namespace a01nyub {
static const char *const TAG = "a01nyub.sensor";
static const uint8_t MAX_DATA_LENGTH_BYTES = 4;
void A01nyubComponent::loop() {
uint8_t data;
while (this->available() > 0) {
if (this->read_byte(&data)) {
buffer_.push_back(data);
this->read_byte(&data);
if (this->buffer_.empty() && (data != 0xff))
continue;
buffer_.push_back(data);
if (this->buffer_.size() == 4)
this->check_buffer_();
}
}
}
void A01nyubComponent::check_buffer_() {
if (this->buffer_.size() >= MAX_DATA_LENGTH_BYTES) {
size_t i;
for (i = 0; i < this->buffer_.size(); i++) {
// Look for the first packet
if (this->buffer_[i] == 0xFF) {
if (i + 1 + 3 < this->buffer_.size()) { // Packet is not complete
return; // Wait for completion
}
uint8_t checksum = (this->buffer_[i] + this->buffer_[i + 1] + this->buffer_[i + 2]) & 0xFF;
if (this->buffer_[i + 3] == checksum) {
float distance = (this->buffer_[i + 1] << 8) + this->buffer_[i + 2];
if (distance > 280) {
float meters = distance / 1000.0;
ESP_LOGV(TAG, "Distance from sensor: %f mm, %f m", distance, meters);
this->publish_state(meters);
} else {
ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str());
}
}
break;
}
uint8_t checksum = this->buffer_[0] + this->buffer_[1] + this->buffer_[2];
if (this->buffer_[3] == checksum) {
float distance = (this->buffer_[1] << 8) + this->buffer_[2];
if (distance > 280) {
float meters = distance / 1000.0;
ESP_LOGV(TAG, "Distance from sensor: %f mm, %f m", distance, meters);
this->publish_state(meters);
} else {
ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str());
}
this->buffer_.clear();
} else {
ESP_LOGW(TAG, "checksum failed: %02x != %02x", checksum, this->buffer_[3]);
}
this->buffer_.clear();
}
void A01nyubComponent::dump_config() {
ESP_LOGCONFIG(TAG, "A01nyub Sensor:");
LOG_SENSOR(" ", "Distance", this);
}
void A01nyubComponent::dump_config() { LOG_SENSOR("", "A01nyub Sensor", this); }
} // namespace a01nyub
} // namespace esphome

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@TH-Braemer"]

View File

@@ -0,0 +1,43 @@
// Datasheet https://wiki.dfrobot.com/_A02YYUW_Waterproof_Ultrasonic_Sensor_SKU_SEN0311
#include "a02yyuw.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace a02yyuw {
static const char *const TAG = "a02yyuw.sensor";
void A02yyuwComponent::loop() {
uint8_t data;
while (this->available() > 0) {
this->read_byte(&data);
if (this->buffer_.empty() && (data != 0xff))
continue;
buffer_.push_back(data);
if (this->buffer_.size() == 4)
this->check_buffer_();
}
}
void A02yyuwComponent::check_buffer_() {
uint8_t checksum = this->buffer_[0] + this->buffer_[1] + this->buffer_[2];
if (this->buffer_[3] == checksum) {
float distance = (this->buffer_[1] << 8) + this->buffer_[2];
if (distance > 30) {
ESP_LOGV(TAG, "Distance from sensor: %f mm", distance);
this->publish_state(distance);
} else {
ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str());
}
} else {
ESP_LOGW(TAG, "checksum failed: %02x != %02x", checksum, this->buffer_[3]);
}
this->buffer_.clear();
}
void A02yyuwComponent::dump_config() { LOG_SENSOR("", "A02yyuw Sensor", this); }
} // namespace a02yyuw
} // namespace esphome

View File

@@ -0,0 +1,27 @@
#pragma once
#include <vector>
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/uart/uart.h"
namespace esphome {
namespace a02yyuw {
class A02yyuwComponent : public sensor::Sensor, public Component, public uart::UARTDevice {
public:
// Nothing really public.
// ========== INTERNAL METHODS ==========
void loop() override;
void dump_config() override;
protected:
void check_buffer_();
std::vector<uint8_t> buffer_;
};
} // namespace a02yyuw
} // namespace esphome

View File

@@ -0,0 +1,41 @@
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,
)
CODEOWNERS = ["@TH-Braemer"]
DEPENDENCIES = ["uart"]
UNIT_MILLIMETERS = "mm"
a02yyuw_ns = cg.esphome_ns.namespace("a02yyuw")
A02yyuwComponent = a02yyuw_ns.class_(
"A02yyuwComponent", sensor.Sensor, cg.Component, uart.UARTDevice
)
CONFIG_SCHEMA = sensor.sensor_schema(
A02yyuwComponent,
unit_of_measurement=UNIT_MILLIMETERS,
icon=ICON_ARROW_EXPAND_VERTICAL,
accuracy_decimals=0,
state_class=STATE_CLASS_MEASUREMENT,
device_class=DEVICE_CLASS_DISTANCE,
).extend(uart.UART_DEVICE_SCHEMA)
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
"a02yyuw",
baud_rate=9600,
require_tx=False,
require_rx=True,
data_bits=8,
parity=None,
stop_bits=1,
)
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
await uart.register_uart_device(var, config)

View File

@@ -1,7 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
from esphome.const import CONF_ANALOG, CONF_INPUT
from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER
from esphome.core import CORE
from esphome.components.esp32 import get_esp32_variant
@@ -152,7 +152,8 @@ def validate_adc_pin(value):
return cv.only_on_rp2040("TEMPERATURE")
if CORE.is_esp32:
value = pins.internal_gpio_input_pin_number(value)
conf = pins.internal_gpio_input_pin_schema(value)
value = conf[CONF_NUMBER]
variant = get_esp32_variant()
if (
variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL
@@ -166,24 +167,23 @@ def validate_adc_pin(value):
):
raise cv.Invalid(f"{variant} doesn't support ADC on this pin")
return pins.internal_gpio_input_pin_schema(value)
return conf
if CORE.is_esp8266:
value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})(
value
)
if value != 17: # A0
raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC")
return pins.gpio_pin_schema(
conf = pins.gpio_pin_schema(
{CONF_ANALOG: True, CONF_INPUT: True}, internal=True
)(value)
if conf[CONF_NUMBER] != 17: # A0
raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC")
return conf
if CORE.is_rp2040:
value = pins.internal_gpio_input_pin_number(value)
if value not in (26, 27, 28, 29):
conf = pins.internal_gpio_input_pin_schema(value)
number = conf[CONF_NUMBER]
if number not in (26, 27, 28, 29):
raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC")
return pins.internal_gpio_input_pin_schema(value)
return conf
if CORE.is_libretiny:
return pins.gpio_pin_schema(

View File

@@ -10,7 +10,7 @@
namespace esphome {
namespace addressable_light {
class AddressableLightDisplay : public display::DisplayBuffer, public PollingComponent {
class AddressableLightDisplay : public display::DisplayBuffer {
public:
light::AddressableLight *get_light() const { return this->light_; }

View File

@@ -45,7 +45,6 @@ async def to_code(config):
cg.add(var.set_height(config[CONF_HEIGHT]))
cg.add(var.set_light(wrapped_light))
await cg.register_component(var, config)
await display.register_display(var, config)
if pixel_mapper := config.get(CONF_PIXEL_MAPPER):

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@angelnu"]

View File

@@ -1,53 +0,0 @@
#include "ade7953.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ade7953 {
static const char *const TAG = "ade7953";
void ADE7953::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7953:");
LOG_PIN(" IRQ Pin: ", irq_pin_);
LOG_I2C_DEVICE(this);
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Voltage Sensor", this->voltage_sensor_);
LOG_SENSOR(" ", "Current A Sensor", this->current_a_sensor_);
LOG_SENSOR(" ", "Current B Sensor", this->current_b_sensor_);
LOG_SENSOR(" ", "Active Power A Sensor", this->active_power_a_sensor_);
LOG_SENSOR(" ", "Active Power B Sensor", this->active_power_b_sensor_);
}
#define ADE_PUBLISH_(name, val, factor) \
if (err == i2c::ERROR_OK && this->name##_sensor_) { \
float value = (val) / (factor); \
this->name##_sensor_->publish_state(value); \
}
#define ADE_PUBLISH(name, val, factor) ADE_PUBLISH_(name, val, factor)
void ADE7953::update() {
if (!this->is_setup_)
return;
uint32_t val;
i2c::ErrorCode err = ade_read_32_(0x0312, &val);
ADE_PUBLISH(active_power_a, (int32_t) val, 154.0f);
err = ade_read_32_(0x0313, &val);
ADE_PUBLISH(active_power_b, (int32_t) val, 154.0f);
err = ade_read_32_(0x031A, &val);
ADE_PUBLISH(current_a, (uint32_t) val, 100000.0f);
err = ade_read_32_(0x031B, &val);
ADE_PUBLISH(current_b, (uint32_t) val, 100000.0f);
err = ade_read_32_(0x031C, &val);
ADE_PUBLISH(voltage, (uint32_t) val, 26000.0f);
// auto apparent_power_a = this->ade_read_<int32_t>(0x0310);
// auto apparent_power_b = this->ade_read_<int32_t>(0x0311);
// auto reactive_power_a = this->ade_read_<int32_t>(0x0314);
// auto reactive_power_b = this->ade_read_<int32_t>(0x0315);
// auto power_factor_a = this->ade_read_<int16_t>(0x010A);
// auto power_factor_b = this->ade_read_<int16_t>(0x010B);
}
} // namespace ade7953
} // namespace esphome

View File

@@ -1,97 +0,0 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensor/sensor.h"
#include <vector>
namespace esphome {
namespace ade7953 {
class ADE7953 : public i2c::I2CDevice, public PollingComponent {
public:
void set_irq_pin(InternalGPIOPin *irq_pin) { irq_pin_ = irq_pin; }
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
void set_current_a_sensor(sensor::Sensor *current_a_sensor) { current_a_sensor_ = current_a_sensor; }
void set_current_b_sensor(sensor::Sensor *current_b_sensor) { current_b_sensor_ = current_b_sensor; }
void set_active_power_a_sensor(sensor::Sensor *active_power_a_sensor) {
active_power_a_sensor_ = active_power_a_sensor;
}
void set_active_power_b_sensor(sensor::Sensor *active_power_b_sensor) {
active_power_b_sensor_ = active_power_b_sensor;
}
void setup() override {
if (this->irq_pin_ != nullptr) {
this->irq_pin_->setup();
}
this->set_timeout(100, [this]() {
this->ade_write_8_(0x0010, 0x04);
this->ade_write_8_(0x00FE, 0xAD);
this->ade_write_16_(0x0120, 0x0030);
this->is_setup_ = true;
});
}
void dump_config() override;
void update() override;
protected:
i2c::ErrorCode ade_write_8_(uint16_t reg, uint8_t value) {
std::vector<uint8_t> data;
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value);
return write(data.data(), data.size());
}
i2c::ErrorCode ade_write_16_(uint16_t reg, uint16_t value) {
std::vector<uint8_t> data;
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value >> 8);
data.push_back(value >> 0);
return write(data.data(), data.size());
}
i2c::ErrorCode ade_write_32_(uint16_t reg, uint32_t value) {
std::vector<uint8_t> data;
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value >> 24);
data.push_back(value >> 16);
data.push_back(value >> 8);
data.push_back(value >> 0);
return write(data.data(), data.size());
}
i2c::ErrorCode ade_read_32_(uint16_t reg, uint32_t *value) {
uint8_t reg_data[2];
reg_data[0] = reg >> 8;
reg_data[1] = reg >> 0;
i2c::ErrorCode err = write(reg_data, 2);
if (err != i2c::ERROR_OK)
return err;
uint8_t recv[4];
err = read(recv, 4);
if (err != i2c::ERROR_OK)
return err;
*value = 0;
*value |= ((uint32_t) recv[0]) << 24;
*value |= ((uint32_t) recv[1]) << 16;
*value |= ((uint32_t) recv[2]) << 8;
*value |= ((uint32_t) recv[3]);
return i2c::ERROR_OK;
}
InternalGPIOPin *irq_pin_{nullptr};
bool is_setup_{false};
sensor::Sensor *voltage_sensor_{nullptr};
sensor::Sensor *current_a_sensor_{nullptr};
sensor::Sensor *current_b_sensor_{nullptr};
sensor::Sensor *active_power_a_sensor_{nullptr};
sensor::Sensor *active_power_b_sensor_{nullptr};
};
} // namespace ade7953
} // namespace esphome

View File

@@ -1,90 +1,5 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, i2c
from esphome import pins
from esphome.const import (
CONF_ID,
CONF_IRQ_PIN,
CONF_VOLTAGE,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_POWER,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
UNIT_AMPERE,
UNIT_VOLT,
UNIT_WATT,
CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid(
"The ade7953 sensor component has been renamed to ade7953_i2c."
)
DEPENDENCIES = ["i2c"]
ade7953_ns = cg.esphome_ns.namespace("ade7953")
ADE7953 = ade7953_ns.class_("ADE7953", cg.PollingComponent, i2c.I2CDevice)
CONF_CURRENT_A = "current_a"
CONF_CURRENT_B = "current_b"
CONF_ACTIVE_POWER_A = "active_power_a"
CONF_ACTIVE_POWER_B = "active_power_b"
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(ADE7953),
cv.Optional(CONF_IRQ_PIN): pins.internal_gpio_input_pin_schema,
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT,
accuracy_decimals=1,
device_class=DEVICE_CLASS_VOLTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_CURRENT_A): sensor.sensor_schema(
unit_of_measurement=UNIT_AMPERE,
accuracy_decimals=2,
device_class=DEVICE_CLASS_CURRENT,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_CURRENT_B): sensor.sensor_schema(
unit_of_measurement=UNIT_AMPERE,
accuracy_decimals=2,
device_class=DEVICE_CLASS_CURRENT,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema(
unit_of_measurement=UNIT_WATT,
accuracy_decimals=1,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema(
unit_of_measurement=UNIT_WATT,
accuracy_decimals=1,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x38))
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)
if irq_pin_config := config.get(CONF_IRQ_PIN):
irq_pin = await cg.gpio_pin_expression(irq_pin_config)
cg.add(var.set_irq_pin(irq_pin))
for key in [
CONF_VOLTAGE,
CONF_CURRENT_A,
CONF_CURRENT_B,
CONF_ACTIVE_POWER_A,
CONF_ACTIVE_POWER_B,
]:
if key not in config:
continue
conf = config[key]
sens = await sensor.new_sensor(conf)
cg.add(getattr(var, f"set_{key}_sensor")(sens))

View File

@@ -0,0 +1,196 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome import pins
from esphome.const import (
CONF_IRQ_PIN,
CONF_VOLTAGE,
CONF_FREQUENCY,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_APPARENT_POWER,
DEVICE_CLASS_POWER,
DEVICE_CLASS_REACTIVE_POWER,
DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_FREQUENCY,
STATE_CLASS_MEASUREMENT,
UNIT_VOLT,
UNIT_HERTZ,
UNIT_AMPERE,
UNIT_VOLT_AMPS,
UNIT_WATT,
UNIT_VOLT_AMPS_REACTIVE,
UNIT_PERCENT,
)
CONF_CURRENT_A = "current_a"
CONF_CURRENT_B = "current_b"
CONF_ACTIVE_POWER_A = "active_power_a"
CONF_ACTIVE_POWER_B = "active_power_b"
CONF_APPARENT_POWER_A = "apparent_power_a"
CONF_APPARENT_POWER_B = "apparent_power_b"
CONF_REACTIVE_POWER_A = "reactive_power_a"
CONF_REACTIVE_POWER_B = "reactive_power_b"
CONF_POWER_FACTOR_A = "power_factor_a"
CONF_POWER_FACTOR_B = "power_factor_b"
CONF_VOLTAGE_PGA_GAIN = "voltage_pga_gain"
CONF_CURRENT_PGA_GAIN_A = "current_pga_gain_a"
CONF_CURRENT_PGA_GAIN_B = "current_pga_gain_b"
CONF_VOLTAGE_GAIN = "voltage_gain"
CONF_CURRENT_GAIN_A = "current_gain_a"
CONF_CURRENT_GAIN_B = "current_gain_b"
CONF_ACTIVE_POWER_GAIN_A = "active_power_gain_a"
CONF_ACTIVE_POWER_GAIN_B = "active_power_gain_b"
PGA_GAINS = {
"1x": 0b000,
"2x": 0b001,
"4x": 0b010,
"8x": 0b011,
"16x": 0b100,
"22x": 0b101,
}
ade7953_base_ns = cg.esphome_ns.namespace("ade7953_base")
ADE7953 = ade7953_base_ns.class_("ADE7953", cg.PollingComponent)
ADE7953_CONFIG_SCHEMA = cv.Schema(
{
cv.Optional(CONF_IRQ_PIN): pins.internal_gpio_input_pin_schema,
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT,
accuracy_decimals=1,
device_class=DEVICE_CLASS_VOLTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
unit_of_measurement=UNIT_HERTZ,
accuracy_decimals=2,
device_class=DEVICE_CLASS_FREQUENCY,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_CURRENT_A): sensor.sensor_schema(
unit_of_measurement=UNIT_AMPERE,
accuracy_decimals=2,
device_class=DEVICE_CLASS_CURRENT,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_CURRENT_B): sensor.sensor_schema(
unit_of_measurement=UNIT_AMPERE,
accuracy_decimals=2,
device_class=DEVICE_CLASS_CURRENT,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema(
unit_of_measurement=UNIT_WATT,
accuracy_decimals=1,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema(
unit_of_measurement=UNIT_WATT,
accuracy_decimals=1,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_APPARENT_POWER_A): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT_AMPS,
accuracy_decimals=1,
device_class=DEVICE_CLASS_APPARENT_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_APPARENT_POWER_B): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT_AMPS,
accuracy_decimals=1,
device_class=DEVICE_CLASS_APPARENT_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_REACTIVE_POWER_A): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
accuracy_decimals=1,
device_class=DEVICE_CLASS_REACTIVE_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_REACTIVE_POWER_B): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
accuracy_decimals=1,
device_class=DEVICE_CLASS_REACTIVE_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_POWER_FACTOR_A): sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
accuracy_decimals=2,
device_class=DEVICE_CLASS_POWER_FACTOR,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_POWER_FACTOR_B): sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
accuracy_decimals=2,
device_class=DEVICE_CLASS_POWER_FACTOR,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(
CONF_VOLTAGE_PGA_GAIN,
default="1x",
): cv.one_of(*PGA_GAINS, lower=True),
cv.Optional(
CONF_CURRENT_PGA_GAIN_A,
default="1x",
): cv.one_of(*PGA_GAINS, lower=True),
cv.Optional(
CONF_CURRENT_PGA_GAIN_B,
default="1x",
): cv.one_of(*PGA_GAINS, lower=True),
cv.Optional(CONF_VOLTAGE_GAIN, default=0x400000): cv.hex_int_range(
min=0x100000, max=0x800000
),
cv.Optional(CONF_CURRENT_GAIN_A, default=0x400000): cv.hex_int_range(
min=0x100000, max=0x800000
),
cv.Optional(CONF_CURRENT_GAIN_B, default=0x400000): cv.hex_int_range(
min=0x100000, max=0x800000
),
cv.Optional(CONF_ACTIVE_POWER_GAIN_A, default=0x400000): cv.hex_int_range(
min=0x100000, max=0x800000
),
cv.Optional(CONF_ACTIVE_POWER_GAIN_B, default=0x400000): cv.hex_int_range(
min=0x100000, max=0x800000
),
}
).extend(cv.polling_component_schema("60s"))
async def register_ade7953(var, config):
await cg.register_component(var, config)
if irq_pin_config := config.get(CONF_IRQ_PIN):
irq_pin = await cg.gpio_pin_expression(irq_pin_config)
cg.add(var.set_irq_pin(irq_pin))
cg.add(var.set_pga_v(PGA_GAINS[config.get(CONF_VOLTAGE_PGA_GAIN)]))
cg.add(var.set_pga_ia(PGA_GAINS[config.get(CONF_CURRENT_PGA_GAIN_A)]))
cg.add(var.set_pga_ib(PGA_GAINS[config.get(CONF_CURRENT_PGA_GAIN_B)]))
cg.add(var.set_vgain(config.get(CONF_VOLTAGE_GAIN)))
cg.add(var.set_aigain(config.get(CONF_CURRENT_GAIN_A)))
cg.add(var.set_bigain(config.get(CONF_CURRENT_GAIN_B)))
cg.add(var.set_awgain(config.get(CONF_ACTIVE_POWER_GAIN_A)))
cg.add(var.set_bwgain(config.get(CONF_ACTIVE_POWER_GAIN_B)))
for key in [
CONF_VOLTAGE,
CONF_FREQUENCY,
CONF_CURRENT_A,
CONF_CURRENT_B,
CONF_POWER_FACTOR_A,
CONF_POWER_FACTOR_B,
CONF_APPARENT_POWER_A,
CONF_APPARENT_POWER_B,
CONF_ACTIVE_POWER_A,
CONF_ACTIVE_POWER_B,
CONF_REACTIVE_POWER_A,
CONF_REACTIVE_POWER_B,
]:
if key not in config:
continue
conf = config[key]
sens = await sensor.new_sensor(conf)
cg.add(getattr(var, f"set_{key}_sensor")(sens))

View File

@@ -0,0 +1,129 @@
#include "ade7953_base.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ade7953_base {
static const char *const TAG = "ade7953";
void ADE7953::setup() {
if (this->irq_pin_ != nullptr) {
this->irq_pin_->setup();
}
// The chip might take up to 100ms to initialise
this->set_timeout(100, [this]() {
// this->ade_write_8(0x0010, 0x04);
this->ade_write_8(0x00FE, 0xAD);
this->ade_write_16(0x0120, 0x0030);
// Set gains
this->ade_write_8(PGA_V_8, pga_v_);
this->ade_write_8(PGA_IA_8, pga_ia_);
this->ade_write_8(PGA_IB_8, pga_ib_);
this->ade_write_32(AVGAIN_32, vgain_);
this->ade_write_32(AIGAIN_32, aigain_);
this->ade_write_32(BIGAIN_32, bigain_);
this->ade_write_32(AWGAIN_32, awgain_);
this->ade_write_32(BWGAIN_32, bwgain_);
// Read back gains for debugging
this->ade_read_8(PGA_V_8, &pga_v_);
this->ade_read_8(PGA_IA_8, &pga_ia_);
this->ade_read_8(PGA_IB_8, &pga_ib_);
this->ade_read_32(AVGAIN_32, &vgain_);
this->ade_read_32(AIGAIN_32, &aigain_);
this->ade_read_32(BIGAIN_32, &bigain_);
this->ade_read_32(AWGAIN_32, &awgain_);
this->ade_read_32(BWGAIN_32, &bwgain_);
this->is_setup_ = true;
});
}
void ADE7953::dump_config() {
LOG_PIN(" IRQ Pin: ", irq_pin_);
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Voltage Sensor", this->voltage_sensor_);
LOG_SENSOR(" ", "Current A Sensor", this->current_a_sensor_);
LOG_SENSOR(" ", "Current B Sensor", this->current_b_sensor_);
LOG_SENSOR(" ", "Power Factor A Sensor", this->power_factor_a_sensor_);
LOG_SENSOR(" ", "Power Factor B Sensor", this->power_factor_b_sensor_);
LOG_SENSOR(" ", "Apparent Power A Sensor", this->apparent_power_a_sensor_);
LOG_SENSOR(" ", "Apparent Power B Sensor", this->apparent_power_b_sensor_);
LOG_SENSOR(" ", "Active Power A Sensor", this->active_power_a_sensor_);
LOG_SENSOR(" ", "Active Power B Sensor", this->active_power_b_sensor_);
LOG_SENSOR(" ", "Rective Power A Sensor", this->reactive_power_a_sensor_);
LOG_SENSOR(" ", "Reactive Power B Sensor", this->reactive_power_b_sensor_);
ESP_LOGCONFIG(TAG, " PGA_V_8: 0x%X", pga_v_);
ESP_LOGCONFIG(TAG, " PGA_IA_8: 0x%X", pga_ia_);
ESP_LOGCONFIG(TAG, " PGA_IB_8: 0x%X", pga_ib_);
ESP_LOGCONFIG(TAG, " VGAIN_32: 0x%08jX", (uintmax_t) vgain_);
ESP_LOGCONFIG(TAG, " AIGAIN_32: 0x%08jX", (uintmax_t) aigain_);
ESP_LOGCONFIG(TAG, " BIGAIN_32: 0x%08jX", (uintmax_t) bigain_);
ESP_LOGCONFIG(TAG, " AWGAIN_32: 0x%08jX", (uintmax_t) awgain_);
ESP_LOGCONFIG(TAG, " BWGAIN_32: 0x%08jX", (uintmax_t) bwgain_);
}
#define ADE_PUBLISH_(name, val, factor) \
if (err == 0 && this->name##_sensor_) { \
float value = (val) / (factor); \
this->name##_sensor_->publish_state(value); \
}
#define ADE_PUBLISH(name, val, factor) ADE_PUBLISH_(name, val, factor)
void ADE7953::update() {
if (!this->is_setup_)
return;
bool err;
uint32_t interrupts_a = 0;
uint32_t interrupts_b = 0;
if (this->irq_pin_ != nullptr) {
// Read and reset interrupts
this->ade_read_32(0x032E, &interrupts_a);
this->ade_read_32(0x0331, &interrupts_b);
}
uint32_t val;
uint16_t val_16;
// Power factor
err = this->ade_read_16(0x010A, &val_16);
ADE_PUBLISH(power_factor_a, (int16_t) val_16, (0x7FFF / 100.0f));
err = this->ade_read_16(0x010B, &val_16);
ADE_PUBLISH(power_factor_b, (int16_t) val_16, (0x7FFF / 100.0f));
// Apparent power
err = this->ade_read_32(0x0310, &val);
ADE_PUBLISH(apparent_power_a, (int32_t) val, 154.0f);
err = this->ade_read_32(0x0311, &val);
ADE_PUBLISH(apparent_power_b, (int32_t) val, 154.0f);
// Active power
err = this->ade_read_32(0x0312, &val);
ADE_PUBLISH(active_power_a, (int32_t) val, 154.0f);
err = this->ade_read_32(0x0313, &val);
ADE_PUBLISH(active_power_b, (int32_t) val, 154.0f);
// Reactive power
err = this->ade_read_32(0x0314, &val);
ADE_PUBLISH(reactive_power_a, (int32_t) val, 154.0f);
err = this->ade_read_32(0x0315, &val);
ADE_PUBLISH(reactive_power_b, (int32_t) val, 154.0f);
// Current
err = this->ade_read_32(0x031A, &val);
ADE_PUBLISH(current_a, (uint32_t) val, 100000.0f);
err = this->ade_read_32(0x031B, &val);
ADE_PUBLISH(current_b, (uint32_t) val, 100000.0f);
// Voltage
err = this->ade_read_32(0x031C, &val);
ADE_PUBLISH(voltage, (uint32_t) val, 26000.0f);
// Frequency
err = this->ade_read_16(0x010E, &val_16);
ADE_PUBLISH(frequency, 223750.0f, 1 + val_16);
}
} // namespace ade7953_base
} // namespace esphome

View File

@@ -0,0 +1,121 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/sensor/sensor.h"
#include <vector>
namespace esphome {
namespace ade7953_base {
static const uint8_t PGA_V_8 =
0x007; // PGA_V, (R/W) Default: 0x00, Unsigned, Voltage channel gain configuration (Bits[2:0])
static const uint8_t PGA_IA_8 =
0x008; // PGA_IA, (R/W) Default: 0x00, Unsigned, Current Channel A gain configuration (Bits[2:0])
static const uint8_t PGA_IB_8 =
0x009; // PGA_IB, (R/W) Default: 0x00, Unsigned, Current Channel B gain configuration (Bits[2:0])
static const uint32_t AIGAIN_32 =
0x380; // AIGAIN, (R/W) Default: 0x400000, Unsigned,Current channel gain (Current Channel A)(32 bit)
static const uint32_t AVGAIN_32 = 0x381; // AVGAIN, (R/W) Default: 0x400000, Unsigned,Voltage channel gain(32 bit)
static const uint32_t AWGAIN_32 =
0x382; // AWGAIN, (R/W) Default: 0x400000, Unsigned,Active power gain (Current Channel A)(32 bit)
static const uint32_t AVARGAIN_32 =
0x383; // AVARGAIN, (R/W) Default: 0x400000, Unsigned, Reactive power gain (Current Channel A)(32 bit)
static const uint32_t AVAGAIN_32 =
0x384; // AVAGAIN, (R/W) Default: 0x400000, Unsigned,Apparent power gain (Current Channel A)(32 bit)
static const uint32_t BIGAIN_32 =
0x38C; // BIGAIN, (R/W) Default: 0x400000, Unsigned,Current channel gain (Current Channel B)(32 bit)
static const uint32_t BVGAIN_32 = 0x38D; // BVGAIN, (R/W) Default: 0x400000, Unsigned,Voltage channel gain(32 bit)
static const uint32_t BWGAIN_32 =
0x38E; // BWGAIN, (R/W) Default: 0x400000, Unsigned,Active power gain (Current Channel B)(32 bit)
static const uint32_t BVARGAIN_32 =
0x38F; // BVARGAIN, (R/W) Default: 0x400000, Unsigned, Reactive power gain (Current Channel B)(32 bit)
static const uint32_t BVAGAIN_32 =
0x390; // BVAGAIN, (R/W) Default: 0x400000, Unsigned,Apparent power gain (Current Channel B)(32 bit)
class ADE7953 : public PollingComponent, public sensor::Sensor {
public:
void set_irq_pin(InternalGPIOPin *irq_pin) { irq_pin_ = irq_pin; }
// Set PGA input gains: 0 1x, 1 2x, 0b10 4x
void set_pga_v(uint8_t pga_v) { pga_v_ = pga_v; }
void set_pga_ia(uint8_t pga_ia) { pga_ia_ = pga_ia; }
void set_pga_ib(uint8_t pga_ib) { pga_ib_ = pga_ib; }
// Set input gains
void set_vgain(uint32_t vgain) { vgain_ = vgain; }
void set_aigain(uint32_t aigain) { aigain_ = aigain; }
void set_bigain(uint32_t bigain) { bigain_ = bigain; }
void set_awgain(uint32_t awgain) { awgain_ = awgain; }
void set_bwgain(uint32_t bwgain) { bwgain_ = bwgain; }
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; }
void set_power_factor_a_sensor(sensor::Sensor *power_factor_a) { power_factor_a_sensor_ = power_factor_a; }
void set_power_factor_b_sensor(sensor::Sensor *power_factor_b) { power_factor_b_sensor_ = power_factor_b; }
void set_current_a_sensor(sensor::Sensor *current_a_sensor) { current_a_sensor_ = current_a_sensor; }
void set_current_b_sensor(sensor::Sensor *current_b_sensor) { current_b_sensor_ = current_b_sensor; }
void set_apparent_power_a_sensor(sensor::Sensor *apparent_power_a) { apparent_power_a_sensor_ = apparent_power_a; }
void set_apparent_power_b_sensor(sensor::Sensor *apparent_power_b) { apparent_power_b_sensor_ = apparent_power_b; }
void set_active_power_a_sensor(sensor::Sensor *active_power_a_sensor) {
active_power_a_sensor_ = active_power_a_sensor;
}
void set_active_power_b_sensor(sensor::Sensor *active_power_b_sensor) {
active_power_b_sensor_ = active_power_b_sensor;
}
void set_reactive_power_a_sensor(sensor::Sensor *reactive_power_a) { reactive_power_a_sensor_ = reactive_power_a; }
void set_reactive_power_b_sensor(sensor::Sensor *reactive_power_b) { reactive_power_b_sensor_ = reactive_power_b; }
void setup() override;
void dump_config() override;
void update() override;
protected:
InternalGPIOPin *irq_pin_{nullptr};
bool is_setup_{false};
sensor::Sensor *voltage_sensor_{nullptr};
sensor::Sensor *frequency_sensor_{nullptr};
sensor::Sensor *current_a_sensor_{nullptr};
sensor::Sensor *current_b_sensor_{nullptr};
sensor::Sensor *apparent_power_a_sensor_{nullptr};
sensor::Sensor *apparent_power_b_sensor_{nullptr};
sensor::Sensor *active_power_a_sensor_{nullptr};
sensor::Sensor *active_power_b_sensor_{nullptr};
sensor::Sensor *reactive_power_a_sensor_{nullptr};
sensor::Sensor *reactive_power_b_sensor_{nullptr};
sensor::Sensor *power_factor_a_sensor_{nullptr};
sensor::Sensor *power_factor_b_sensor_{nullptr};
uint8_t pga_v_;
uint8_t pga_ia_;
uint8_t pga_ib_;
uint32_t vgain_;
uint32_t aigain_;
uint32_t bigain_;
uint32_t awgain_;
uint32_t bwgain_;
virtual bool ade_write_8(uint16_t reg, uint8_t value) = 0;
virtual bool ade_write_16(uint16_t reg, uint16_t value) = 0;
virtual bool ade_write_32(uint16_t reg, uint32_t value) = 0;
virtual bool ade_read_8(uint16_t reg, uint8_t *value) = 0;
virtual bool ade_read_16(uint16_t reg, uint16_t *value) = 0;
virtual bool ade_read_32(uint16_t reg, uint32_t *value) = 0;
};
} // namespace ade7953_base
} // namespace esphome

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@angelnu"]

View File

@@ -0,0 +1,80 @@
#include "ade7953_i2c.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace ade7953_i2c {
static const char *const TAG = "ade7953";
void AdE7953I2c::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7953_i2c:");
LOG_I2C_DEVICE(this);
ade7953_base::ADE7953::dump_config();
}
bool AdE7953I2c::ade_write_8(uint16_t reg, uint8_t value) {
std::vector<uint8_t> data(3);
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value);
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
}
bool AdE7953I2c::ade_write_16(uint16_t reg, uint16_t value) {
std::vector<uint8_t> data(4);
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value >> 8);
data.push_back(value >> 0);
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
}
bool AdE7953I2c::ade_write_32(uint16_t reg, uint32_t value) {
std::vector<uint8_t> data(6);
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value >> 24);
data.push_back(value >> 16);
data.push_back(value >> 8);
data.push_back(value >> 0);
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
}
bool AdE7953I2c::ade_read_8(uint16_t reg, uint8_t *value) {
uint8_t reg_data[2];
reg_data[0] = reg >> 8;
reg_data[1] = reg >> 0;
i2c::ErrorCode err = this->write(reg_data, 2);
if (err != i2c::ERROR_OK)
return true;
err = this->read(value, 1);
return (err != i2c::ERROR_OK);
}
bool AdE7953I2c::ade_read_16(uint16_t reg, uint16_t *value) {
uint8_t reg_data[2];
reg_data[0] = reg >> 8;
reg_data[1] = reg >> 0;
i2c::ErrorCode err = this->write(reg_data, 2);
if (err != i2c::ERROR_OK)
return true;
uint8_t recv[2];
err = this->read(recv, 2);
if (err != i2c::ERROR_OK)
return true;
*value = encode_uint16(recv[0], recv[1]);
return false;
}
bool AdE7953I2c::ade_read_32(uint16_t reg, uint32_t *value) {
uint8_t reg_data[2];
reg_data[0] = reg >> 8;
reg_data[1] = reg >> 0;
i2c::ErrorCode err = this->write(reg_data, 2);
if (err != i2c::ERROR_OK)
return true;
uint8_t recv[4];
err = this->read(recv, 4);
if (err != i2c::ERROR_OK)
return true;
*value = encode_uint32(recv[0], recv[1], recv[2], recv[3]);
return false;
}
} // namespace ade7953_i2c
} // namespace esphome

View File

@@ -0,0 +1,28 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/ade7953_base/ade7953_base.h"
#include <vector>
namespace esphome {
namespace ade7953_i2c {
class AdE7953I2c : public ade7953_base::ADE7953, public i2c::I2CDevice {
public:
void dump_config() override;
protected:
bool ade_write_8(uint16_t reg, uint8_t value) override;
bool ade_write_16(uint16_t reg, uint16_t value) override;
bool ade_write_32(uint16_t reg, uint32_t value) override;
bool ade_read_8(uint16_t reg, uint8_t *value) override;
bool ade_read_16(uint16_t reg, uint16_t *value) override;
bool ade_read_32(uint16_t reg, uint32_t *value) override;
};
} // namespace ade7953_i2c
} // namespace esphome

View File

@@ -0,0 +1,27 @@
import esphome.codegen as cg
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"]
ade7953_ns = cg.esphome_ns.namespace("ade7953_i2c")
ADE7953 = ade7953_ns.class_("AdE7953I2c", ade7953_base.ADE7953, i2c.I2CDevice)
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(ADE7953),
}
)
.extend(ade7953_base.ADE7953_CONFIG_SCHEMA)
.extend(i2c.i2c_device_schema(0x38))
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await i2c.register_i2c_device(var, config)
await ade7953_base.register_ade7953(var, config)

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@angelnu"]

View File

@@ -0,0 +1,81 @@
#include "ade7953_spi.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace ade7953_spi {
static const char *const TAG = "ade7953";
void AdE7953Spi::setup() {
this->spi_setup();
ade7953_base::ADE7953::setup();
}
void AdE7953Spi::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7953_spi:");
LOG_PIN(" CS Pin: ", this->cs_);
ade7953_base::ADE7953::dump_config();
}
bool AdE7953Spi::ade_write_8(uint16_t reg, uint8_t value) {
this->enable();
this->write_byte16(reg);
this->transfer_byte(0);
this->transfer_byte(value);
this->disable();
return false;
}
bool AdE7953Spi::ade_write_16(uint16_t reg, uint16_t value) {
this->enable();
this->write_byte16(reg);
this->transfer_byte(0);
this->write_byte16(value);
this->disable();
return false;
}
bool AdE7953Spi::ade_write_32(uint16_t reg, uint32_t value) {
this->enable();
this->write_byte16(reg);
this->transfer_byte(0);
this->write_byte16(value >> 16);
this->write_byte16(value & 0xFFFF);
this->disable();
return false;
}
bool AdE7953Spi::ade_read_8(uint16_t reg, uint8_t *value) {
this->enable();
this->write_byte16(reg);
this->transfer_byte(0x80);
*value = this->read_byte();
this->disable();
return false;
}
bool AdE7953Spi::ade_read_16(uint16_t reg, uint16_t *value) {
this->enable();
this->write_byte16(reg);
this->transfer_byte(0x80);
uint8_t recv[2];
this->read_array(recv, 4);
*value = encode_uint16(recv[0], recv[1]);
this->disable();
return false;
}
bool AdE7953Spi::ade_read_32(uint16_t reg, uint32_t *value) {
this->enable();
this->write_byte16(reg);
this->transfer_byte(0x80);
uint8_t recv[4];
this->read_array(recv, 4);
*value = encode_uint32(recv[0], recv[1], recv[2], recv[3]);
this->disable();
return false;
}
} // namespace ade7953_spi
} // namespace esphome

View File

@@ -0,0 +1,32 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/spi/spi.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/ade7953_base/ade7953_base.h"
#include <vector>
namespace esphome {
namespace ade7953_spi {
class AdE7953Spi : public ade7953_base::ADE7953,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, spi::CLOCK_PHASE_LEADING,
spi::DATA_RATE_1MHZ> {
public:
void setup() override;
void dump_config() override;
protected:
bool ade_write_8(uint16_t reg, uint8_t value) override;
bool ade_write_16(uint16_t reg, uint16_t value) override;
bool ade_write_32(uint16_t reg, uint32_t value) override;
bool ade_read_8(uint16_t reg, uint8_t *value) override;
bool ade_read_16(uint16_t reg, uint16_t *value) override;
bool ade_read_32(uint16_t reg, uint32_t *value) override;
};
} // namespace ade7953_spi
} // namespace esphome

View File

@@ -0,0 +1,27 @@
import esphome.codegen as cg
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"]
ade7953_ns = cg.esphome_ns.namespace("ade7953_spi")
ADE7953 = ade7953_ns.class_("AdE7953Spi", ade7953_base.ADE7953, spi.SPIDevice)
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(ADE7953),
}
)
.extend(ade7953_base.ADE7953_CONFIG_SCHEMA)
.extend(spi.spi_device_schema())
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await spi.register_spi_device(var, config)
await ade7953_base.register_ade7953(var, config)

View File

@@ -15,41 +15,55 @@
#include "aht10.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include <cinttypes>
namespace esphome {
namespace aht10 {
static const char *const TAG = "aht10";
static const uint8_t AHT10_CALIBRATE_CMD[] = {0xE1};
static const size_t SIZE_CALIBRATE_CMD = 3;
static const uint8_t AHT10_CALIBRATE_CMD[] = {0xE1, 0x08, 0x00};
static const uint8_t AHT20_CALIBRATE_CMD[] = {0xBE, 0x08, 0x00};
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
static const uint8_t AHT10_DEFAULT_DELAY = 5; // ms, for calibration and temperature measurement
static const uint8_t AHT10_HUMIDITY_DELAY = 30; // ms
static const uint8_t AHT10_ATTEMPTS = 3; // safety margin, normally 3 attempts are enough: 3*30=90ms
static const uint8_t AHT10_CAL_ATTEMPTS = 10;
static const uint8_t AHT10_STATUS_BUSY = 0x80;
void AHT10Component::setup() {
ESP_LOGCONFIG(TAG, "Setting up AHT10...");
const uint8_t *calibrate_cmd;
switch (this->variant_) {
case AHT10Variant::AHT20:
calibrate_cmd = AHT20_CALIBRATE_CMD;
ESP_LOGCONFIG(TAG, "Setting up AHT20");
break;
case AHT10Variant::AHT10:
default:
calibrate_cmd = AHT10_CALIBRATE_CMD;
ESP_LOGCONFIG(TAG, "Setting up AHT10");
}
if (!this->write_bytes(0, AHT10_CALIBRATE_CMD, sizeof(AHT10_CALIBRATE_CMD))) {
if (this->write(calibrate_cmd, SIZE_CALIBRATE_CMD) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->mark_failed();
return;
}
uint8_t data = 0;
if (this->write(&data, 1) != i2c::ERROR_OK) {
ESP_LOGD(TAG, "Communication with AHT10 failed!");
this->mark_failed();
return;
}
delay(AHT10_DEFAULT_DELAY);
if (this->read(&data, 1) != i2c::ERROR_OK) {
ESP_LOGD(TAG, "Communication with AHT10 failed!");
this->mark_failed();
return;
}
if (this->read(&data, 1) != i2c::ERROR_OK) {
ESP_LOGD(TAG, "Communication with AHT10 failed!");
this->mark_failed();
return;
uint8_t data = AHT10_STATUS_BUSY;
int cal_attempts = 0;
while (data & AHT10_STATUS_BUSY) {
delay(AHT10_DEFAULT_DELAY);
if (this->read(&data, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->mark_failed();
return;
}
++cal_attempts;
if (cal_attempts > AHT10_CAL_ATTEMPTS) {
ESP_LOGE(TAG, "AHT10 calibration timed out!");
this->mark_failed();
return;
}
}
if ((data & 0x68) != 0x08) { // Bit[6:5] = 0b00, NORMAL mode and Bit[3] = 0b1, CALIBRATED
ESP_LOGE(TAG, "AHT10 calibration failed!");
@@ -61,7 +75,7 @@ void AHT10Component::setup() {
}
void AHT10Component::update() {
if (!this->write_bytes(0, AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD))) {
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->status_set_warning();
return;
@@ -72,7 +86,7 @@ void AHT10Component::update() {
delay_ms = AHT10_HUMIDITY_DELAY;
bool success = false;
for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
ESP_LOGVV(TAG, "Attempt %d at %6u", i, millis());
ESP_LOGVV(TAG, "Attempt %d at %6" PRIu32, i, millis());
delay(delay_ms);
if (this->read(data, 6) != i2c::ERROR_OK) {
ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
@@ -88,7 +102,7 @@ void AHT10Component::update() {
break;
} else {
ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying...");
if (!this->write_bytes(0, AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD))) {
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->status_set_warning();
return;
@@ -96,7 +110,7 @@ void AHT10Component::update() {
}
} else {
// data is valid, we can break the loop
ESP_LOGVV(TAG, "Answer at %6u", millis());
ESP_LOGVV(TAG, "Answer at %6" PRIu32, millis());
success = true;
break;
}

View File

@@ -1,5 +1,7 @@
#pragma once
#include <utility>
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
@@ -7,12 +9,15 @@
namespace esphome {
namespace aht10 {
enum AHT10Variant { AHT10, AHT20 };
class AHT10Component : public PollingComponent, public i2c::I2CDevice {
public:
void setup() override;
void update() override;
void dump_config() override;
float get_setup_priority() const override;
void set_variant(AHT10Variant variant) { this->variant_ = variant; }
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
@@ -20,6 +25,7 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice {
protected:
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr};
AHT10Variant variant_{};
};
} // namespace aht10

View File

@@ -10,6 +10,7 @@ from esphome.const import (
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
UNIT_PERCENT,
CONF_VARIANT,
)
DEPENDENCIES = ["i2c"]
@@ -17,6 +18,12 @@ DEPENDENCIES = ["i2c"]
aht10_ns = cg.esphome_ns.namespace("aht10")
AHT10Component = aht10_ns.class_("AHT10Component", cg.PollingComponent, i2c.I2CDevice)
AHT10Variant = aht10_ns.enum("AHT10Variant")
AHT10_VARIANTS = {
"AHT10": AHT10Variant.AHT10,
"AHT20": AHT10Variant.AHT20,
}
CONFIG_SCHEMA = (
cv.Schema(
{
@@ -33,6 +40,9 @@ CONFIG_SCHEMA = (
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_VARIANT, default="AHT10"): cv.enum(
AHT10_VARIANTS, upper=True
),
}
)
.extend(cv.polling_component_schema("60s"))
@@ -44,6 +54,7 @@ async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)
cg.add(var.set_variant(config[CONF_VARIANT]))
if temperature := config.get(CONF_TEMPERATURE):
sens = await sensor.new_sensor(temperature)

View File

@@ -18,6 +18,8 @@ from esphome.const import (
CONF_TRIGGER_ID,
CONF_EVENT,
CONF_TAG,
CONF_ON_CLIENT_CONNECTED,
CONF_ON_CLIENT_DISCONNECTED,
)
from esphome.core import coroutine_with_priority
@@ -87,6 +89,12 @@ CONFIG_SCHEMA = cv.Schema(
cv.Required(CONF_KEY): validate_encryption_key,
}
),
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
single=True
),
cv.Optional(CONF_ON_CLIENT_DISCONNECTED): automation.validate_automation(
single=True
),
}
).extend(cv.COMPONENT_SCHEMA)
@@ -116,6 +124,20 @@ async def to_code(config):
cg.add(var.register_user_service(trigger))
await automation.build_automation(trigger, func_args, conf)
if CONF_ON_CLIENT_CONNECTED in config:
await automation.build_automation(
var.get_client_connected_trigger(),
[(cg.std_string, "client_info"), (cg.std_string, "client_address")],
config[CONF_ON_CLIENT_CONNECTED],
)
if CONF_ON_CLIENT_DISCONNECTED in config:
await automation.build_automation(
var.get_client_disconnected_trigger(),
[(cg.std_string, "client_info"), (cg.std_string, "client_address")],
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)))

View File

@@ -39,6 +39,7 @@ service APIConnection {
rpc camera_image (CameraImageRequest) returns (void) {}
rpc climate_command (ClimateCommandRequest) returns (void) {}
rpc number_command (NumberCommandRequest) returns (void) {}
rpc text_command (TextCommandRequest) returns (void) {}
rpc select_command (SelectCommandRequest) returns (void) {}
rpc button_command (ButtonCommandRequest) returns (void) {}
rpc lock_command (LockCommandRequest) returns (void) {}
@@ -216,6 +217,8 @@ message DeviceInfoResponse {
string friendly_name = 13;
uint32 voice_assistant_version = 14;
string suggested_area = 16;
}
message ListEntitiesRequest {
@@ -362,6 +365,7 @@ message ListEntitiesFanResponse {
bool disabled_by_default = 9;
string icon = 10;
EntityCategory entity_category = 11;
repeated string supported_preset_modes = 12;
}
enum FanSpeed {
FAN_SPEED_LOW = 0;
@@ -384,6 +388,7 @@ message FanStateResponse {
FanSpeed speed = 4 [deprecated = true];
FanDirection direction = 5;
int32 speed_level = 6;
string preset_mode = 7;
}
message FanCommandRequest {
option (id) = 31;
@@ -402,6 +407,8 @@ message FanCommandRequest {
FanDirection direction = 9;
bool has_speed_level = 10;
int32 speed_level = 11;
bool has_preset_mode = 12;
string preset_mode = 13;
}
// ==================== LIGHT ====================
@@ -852,6 +859,10 @@ message ListEntitiesClimateResponse {
string icon = 19;
EntityCategory entity_category = 20;
float visual_current_temperature_step = 21;
bool supports_current_humidity = 22;
bool supports_target_humidity = 23;
float visual_min_humidity = 24;
float visual_max_humidity = 25;
}
message ClimateStateResponse {
option (id) = 47;
@@ -872,6 +883,8 @@ message ClimateStateResponse {
string custom_fan_mode = 11;
ClimatePreset preset = 12;
string custom_preset = 13;
float current_humidity = 14;
float target_humidity = 15;
}
message ClimateCommandRequest {
option (id) = 48;
@@ -900,6 +913,8 @@ message ClimateCommandRequest {
ClimatePreset preset = 19;
bool has_custom_preset = 20;
string custom_preset = 21;
bool has_target_humidity = 22;
float target_humidity = 23;
}
// ==================== NUMBER ====================
@@ -1459,6 +1474,8 @@ enum VoiceAssistantEvent {
VOICE_ASSISTANT_WAKE_WORD_END = 10;
VOICE_ASSISTANT_STT_VAD_START = 11;
VOICE_ASSISTANT_STT_VAD_END = 12;
VOICE_ASSISTANT_TTS_STREAM_START = 98;
VOICE_ASSISTANT_TTS_STREAM_END = 99;
}
message VoiceAssistantEventData {
@@ -1534,3 +1551,48 @@ message AlarmControlPanelCommandRequest {
AlarmControlPanelStateCommand command = 2;
string code = 3;
}
// ===================== TEXT =====================
enum TextMode {
TEXT_MODE_TEXT = 0;
TEXT_MODE_PASSWORD = 1;
}
message ListEntitiesTextResponse {
option (id) = 97;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_TEXT";
string object_id = 1;
fixed32 key = 2;
string name = 3;
string unique_id = 4;
string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 min_length = 8;
uint32 max_length = 9;
string pattern = 10;
TextMode mode = 11;
}
message TextStateResponse {
option (id) = 98;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_TEXT";
option (no_delay) = true;
fixed32 key = 1;
string state = 2;
// If the Text does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
}
message TextCommandRequest {
option (id) = 99;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_TEXT";
option (no_delay) = true;
fixed32 key = 1;
string state = 2;
}

View File

@@ -1,6 +1,7 @@
#include "api_connection.h"
#include <cerrno>
#include <cinttypes>
#include <utility>
#include "esphome/components/network/util.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/hal.h"
@@ -31,9 +32,9 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa
this->proto_write_buffer_.reserve(64);
#if defined(USE_API_PLAINTEXT)
helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
#elif defined(USE_API_NOISE)
helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())};
this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())};
#else
#error "No frame helper defined"
#endif
@@ -41,14 +42,16 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa
void APIConnection::start() {
this->last_traffic_ = millis();
APIError err = helper_->init();
APIError err = this->helper_->init();
if (err != APIError::OK) {
on_fatal_error();
ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", client_info_.c_str(), api_error_to_str(err), errno);
ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
errno);
return;
}
client_info_ = helper_->getpeername();
helper_->set_log_info(client_info_);
this->client_info_ = helper_->getpeername();
this->client_peername_ = this->client_info_;
this->helper_->set_log_info(this->client_info_);
}
APIConnection::~APIConnection() {
@@ -57,6 +60,11 @@ APIConnection::~APIConnection() {
bluetooth_proxy::global_bluetooth_proxy->unsubscribe_api_connection(this);
}
#endif
#ifdef USE_VOICE_ASSISTANT
if (voice_assistant::global_voice_assistant->get_api_connection() == this) {
voice_assistant::global_voice_assistant->client_subscription(this, false);
}
#endif
}
void APIConnection::loop() {
@@ -67,7 +75,7 @@ void APIConnection::loop() {
// when network is disconnected force disconnect immediately
// don't wait for timeout
this->on_fatal_error();
ESP_LOGW(TAG, "%s: Network unavailable, disconnecting", client_info_.c_str());
ESP_LOGW(TAG, "%s: Network unavailable, disconnecting", this->client_combined_info_.c_str());
return;
}
if (this->next_close_) {
@@ -77,24 +85,26 @@ void APIConnection::loop() {
return;
}
APIError err = helper_->loop();
APIError err = this->helper_->loop();
if (err != APIError::OK) {
on_fatal_error();
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", client_info_.c_str(), api_error_to_str(err), errno);
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
api_error_to_str(err), errno);
return;
}
ReadPacketBuffer buffer;
err = helper_->read_packet(&buffer);
err = this->helper_->read_packet(&buffer);
if (err == APIError::WOULD_BLOCK) {
// pass
} else if (err != APIError::OK) {
on_fatal_error();
if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
ESP_LOGW(TAG, "%s: Connection reset", client_info_.c_str());
ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
} else if (err == APIError::CONNECTION_CLOSED) {
ESP_LOGW(TAG, "%s: Connection closed", client_info_.c_str());
ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str());
} else {
ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", client_info_.c_str(), api_error_to_str(err), errno);
ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
errno);
}
return;
} else {
@@ -108,18 +118,34 @@ void APIConnection::loop() {
this->list_entities_iterator_.advance();
this->initial_state_iterator_.advance();
const uint32_t keepalive = 60000;
static uint32_t keepalive = 60000;
static uint8_t max_ping_retries = 60;
static uint16_t ping_retry_interval = 1000;
const uint32_t now = millis();
if (this->sent_ping_) {
// Disconnect if not responded within 2.5*keepalive
if (now - this->last_traffic_ > (keepalive * 5) / 2) {
on_fatal_error();
ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_info_.c_str());
ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
}
} else if (now - this->last_traffic_ > keepalive) {
} else if (now - this->last_traffic_ > keepalive && now > this->next_ping_retry_) {
ESP_LOGVV(TAG, "Sending keepalive PING...");
this->sent_ping_ = true;
this->send_ping_request(PingRequest());
this->sent_ping_ = this->send_ping_request(PingRequest());
if (!this->sent_ping_) {
this->next_ping_retry_ = now + ping_retry_interval;
this->ping_retries_++;
if (this->ping_retries_ >= max_ping_retries) {
on_fatal_error();
ESP_LOGE(TAG, "%s: Sending keepalive failed %d time(s). Disconnecting...", this->client_combined_info_.c_str(),
this->ping_retries_);
} else if (this->ping_retries_ >= 10) {
ESP_LOGW(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
} else {
ESP_LOGD(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
}
}
}
#ifdef USE_ESP32_CAMERA
@@ -168,7 +194,7 @@ DisconnectResponse APIConnection::disconnect(const DisconnectRequest &msg) {
// remote initiated disconnect_client
// don't close yet, we still need to send the disconnect response
// close will happen on next loop
ESP_LOGD(TAG, "%s requested disconnected", client_info_.c_str());
ESP_LOGD(TAG, "%s requested disconnected", this->client_combined_info_.c_str());
this->next_close_ = true;
DisconnectResponse resp;
return resp;
@@ -283,6 +309,8 @@ bool APIConnection::send_fan_state(fan::Fan *fan) {
}
if (traits.supports_direction())
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);
}
bool APIConnection::send_fan_info(fan::Fan *fan) {
@@ -297,6 +325,8 @@ bool APIConnection::send_fan_info(fan::Fan *fan) {
msg.supports_speed = traits.supports_speed();
msg.supports_direction = traits.supports_direction();
msg.supported_speed_count = traits.supported_speed_count();
for (auto const &preset : traits.supported_preset_modes())
msg.supported_preset_modes.push_back(preset);
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());
@@ -318,6 +348,8 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
}
if (msg.has_direction)
call.set_direction(static_cast<fan::FanDirection>(msg.direction));
if (msg.has_preset_mode)
call.set_preset_mode(msg.preset_mode);
call.perform();
}
#endif
@@ -544,6 +576,10 @@ bool APIConnection::send_climate_state(climate::Climate *climate) {
resp.custom_preset = climate->custom_preset.value();
if (traits.get_supports_swing_modes())
resp.swing_mode = static_cast<enums::ClimateSwingMode>(climate->swing_mode);
if (traits.get_supports_current_humidity())
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);
}
bool APIConnection::send_climate_info(climate::Climate *climate) {
@@ -560,7 +596,9 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
msg.entity_category = static_cast<enums::EntityCategory>(climate->get_entity_category());
msg.supports_current_temperature = traits.get_supports_current_temperature();
msg.supports_current_humidity = traits.get_supports_current_humidity();
msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
msg.supports_target_humidity = traits.get_supports_target_humidity();
for (auto mode : traits.get_supported_modes())
msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
@@ -569,6 +607,8 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
msg.visual_max_temperature = traits.get_visual_max_temperature();
msg.visual_target_temperature_step = traits.get_visual_target_temperature_step();
msg.visual_current_temperature_step = traits.get_visual_current_temperature_step();
msg.visual_min_humidity = traits.get_visual_min_humidity();
msg.visual_max_humidity = traits.get_visual_max_humidity();
msg.legacy_supports_away = traits.supports_preset(climate::CLIMATE_PRESET_AWAY);
msg.supports_action = traits.get_supports_action();
@@ -599,6 +639,8 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) {
call.set_target_temperature_low(msg.target_temperature_low);
if (msg.has_target_temperature_high)
call.set_target_temperature_high(msg.target_temperature_high);
if (msg.has_target_humidity)
call.set_target_humidity(msg.target_humidity);
if (msg.has_fan_mode)
call.set_fan_mode(static_cast<climate::ClimateFanMode>(msg.fan_mode));
if (msg.has_custom_fan_mode)
@@ -655,6 +697,44 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
}
#endif
#ifdef USE_TEXT
bool APIConnection::send_text_state(text::Text *text, std::string state) {
if (!this->state_subscription_)
return false;
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);
}
bool APIConnection::send_text_info(text::Text *text) {
ListEntitiesTextResponse msg;
msg.key = text->get_object_id_hash();
msg.object_id = text->get_object_id();
msg.name = text->get_name();
msg.icon = text->get_icon();
msg.disabled_by_default = text->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(text->get_entity_category());
msg.mode = static_cast<enums::TextMode>(text->traits.get_mode());
msg.min_length = text->traits.get_min_length();
msg.max_length = text->traits.get_max_length();
msg.pattern = text->traits.get_pattern();
return this->send_list_entities_text_response(msg);
}
void APIConnection::text_command(const TextCommandRequest &msg) {
text::Text *text = App.get_text_by_key(msg.key);
if (text == nullptr)
return;
auto call = text->make_call();
call.set_value(msg.state);
call.perform();
}
#endif
#ifdef USE_SELECT
bool APIConnection::send_select_state(select::Select *select, std::string state) {
if (!this->state_subscription_)
@@ -907,14 +987,17 @@ BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_
#endif
#ifdef USE_VOICE_ASSISTANT
bool APIConnection::request_voice_assistant(const VoiceAssistantRequest &msg) {
if (!this->voice_assistant_subscription_)
return false;
return this->send_voice_assistant_request(msg);
void APIConnection::subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) {
if (voice_assistant::global_voice_assistant != nullptr) {
voice_assistant::global_voice_assistant->client_subscription(this, msg.subscribe);
}
}
void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) {
if (voice_assistant::global_voice_assistant != nullptr) {
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
return;
}
if (msg.error) {
voice_assistant::global_voice_assistant->failed_to_start();
return;
@@ -927,6 +1010,10 @@ void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &ms
};
void APIConnection::on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) {
if (voice_assistant::global_voice_assistant != nullptr) {
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
return;
}
voice_assistant::global_voice_assistant->on_event(msg);
}
}
@@ -1006,12 +1093,14 @@ bool APIConnection::send_log_message(int level, const char *tag, const char *lin
}
HelloResponse APIConnection::hello(const HelloRequest &msg) {
this->client_info_ = msg.client_info + " (" + this->helper_->getpeername() + ")";
this->helper_->set_log_info(client_info_);
this->client_info_ = msg.client_info;
this->client_peername_ = this->helper_->getpeername();
this->client_combined_info_ = this->client_info_ + " (" + this->client_peername_ + ")";
this->helper_->set_log_info(this->client_combined_info_);
this->client_api_version_major_ = msg.api_version_major;
this->client_api_version_minor_ = msg.api_version_minor;
ESP_LOGV(TAG, "Hello from client: '%s' | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
this->client_api_version_major_, this->client_api_version_minor_);
ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
this->client_peername_.c_str(), this->client_api_version_major_, this->client_api_version_minor_);
HelloResponse resp;
resp.api_version_major = 1;
@@ -1029,9 +1118,9 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) {
// bool invalid_password = 1;
resp.invalid_password = !correct;
if (correct) {
ESP_LOGD(TAG, "%s: Connected successfully", this->client_info_.c_str());
ESP_LOGD(TAG, "%s: Connected successfully", this->client_combined_info_.c_str());
this->connection_state_ = ConnectionState::AUTHENTICATED;
this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
#ifdef USE_HOMEASSISTANT_TIME
if (homeassistant::global_homeassistant_time != nullptr) {
this->send_time_request();
@@ -1045,6 +1134,7 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
resp.uses_password = this->parent_->uses_password();
resp.name = App.get_name();
resp.friendly_name = App.get_friendly_name();
resp.suggested_area = App.get_area();
resp.mac_address = get_mac_address_pretty();
resp.esphome_version = ESPHOME_VERSION;
resp.compilation_time = App.get_compilation_time();
@@ -1105,10 +1195,11 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type)
return false;
if (!this->helper_->can_write_without_blocking()) {
delay(0);
APIError err = helper_->loop();
APIError err = this->helper_->loop();
if (err != APIError::OK) {
on_fatal_error();
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", client_info_.c_str(), api_error_to_str(err), errno);
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
api_error_to_str(err), errno);
return false;
}
if (!this->helper_->can_write_without_blocking()) {
@@ -1127,9 +1218,10 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type)
if (err != APIError::OK) {
on_fatal_error();
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
ESP_LOGW(TAG, "%s: Connection reset", client_info_.c_str());
ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
} else {
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", client_info_.c_str(), api_error_to_str(err), errno);
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
errno);
}
return false;
}
@@ -1138,11 +1230,11 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type)
}
void APIConnection::on_unauthenticated_access() {
this->on_fatal_error();
ESP_LOGD(TAG, "%s: tried to access without authentication.", this->client_info_.c_str());
ESP_LOGD(TAG, "%s: tried to access without authentication.", this->client_combined_info_.c_str());
}
void APIConnection::on_no_setup_connection() {
this->on_fatal_error();
ESP_LOGD(TAG, "%s: tried to access without full connection.", this->client_info_.c_str());
ESP_LOGD(TAG, "%s: tried to access without full connection.", this->client_combined_info_.c_str());
}
void APIConnection::on_fatal_error() {
this->helper_->close();

View File

@@ -72,6 +72,11 @@ class APIConnection : public APIServerConnection {
bool send_number_info(number::Number *number);
void number_command(const NumberCommandRequest &msg) override;
#endif
#ifdef USE_TEXT
bool send_text_state(text::Text *text, std::string state);
bool send_text_info(text::Text *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);
@@ -121,10 +126,7 @@ class APIConnection : public APIServerConnection {
#endif
#ifdef USE_VOICE_ASSISTANT
void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override {
this->voice_assistant_subscription_ = msg.subscribe;
}
bool request_voice_assistant(const VoiceAssistantRequest &msg);
void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override;
void on_voice_assistant_response(const VoiceAssistantResponse &msg) override;
void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override;
#endif
@@ -138,6 +140,7 @@ class APIConnection : public APIServerConnection {
void on_disconnect_response(const DisconnectResponse &value) override;
void on_ping_response(const PingResponse &value) override {
// we initiated ping
this->ping_retries_ = 0;
this->sent_ping_ = false;
}
void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override;
@@ -183,6 +186,8 @@ class APIConnection : public APIServerConnection {
}
bool send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) override;
std::string get_client_combined_info() const { return this->client_combined_info_; }
protected:
friend APIServer;
@@ -202,6 +207,8 @@ class APIConnection : public APIServerConnection {
std::unique_ptr<APIFrameHelper> helper_;
std::string client_info_;
std::string client_peername_;
std::string client_combined_info_;
uint32_t client_api_version_major_{0};
uint32_t client_api_version_minor_{0};
#ifdef USE_ESP32_CAMERA
@@ -211,11 +218,10 @@ class APIConnection : public APIServerConnection {
bool state_subscription_{false};
int log_subscription_{ESPHOME_LOG_LEVEL_NONE};
uint32_t last_traffic_;
uint32_t next_ping_retry_{0};
uint8_t ping_retries_{0};
bool sent_ping_{false};
bool service_call_subscription_{false};
#ifdef USE_VOICE_ASSISTANT
bool voice_assistant_subscription_{false};
#endif
bool next_close_ = false;
APIServer *parent_;
InitialStateIterator initial_state_iterator_;

View File

@@ -452,6 +452,10 @@ template<> const char *proto_enum_to_string<enums::VoiceAssistantEvent>(enums::V
return "VOICE_ASSISTANT_STT_VAD_START";
case enums::VOICE_ASSISTANT_STT_VAD_END:
return "VOICE_ASSISTANT_STT_VAD_END";
case enums::VOICE_ASSISTANT_TTS_STREAM_START:
return "VOICE_ASSISTANT_TTS_STREAM_START";
case enums::VOICE_ASSISTANT_TTS_STREAM_END:
return "VOICE_ASSISTANT_TTS_STREAM_END";
default:
return "UNKNOWN";
}
@@ -508,6 +512,18 @@ const char *proto_enum_to_string<enums::AlarmControlPanelStateCommand>(enums::Al
}
}
#endif
#ifdef HAS_PROTO_MESSAGE_DUMP
template<> const char *proto_enum_to_string<enums::TextMode>(enums::TextMode value) {
switch (value) {
case enums::TEXT_MODE_TEXT:
return "TEXT_MODE_TEXT";
case enums::TEXT_MODE_PASSWORD:
return "TEXT_MODE_PASSWORD";
default:
return "UNKNOWN";
}
}
#endif
bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 2: {
@@ -745,6 +761,10 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v
this->friendly_name = value.as_string();
return true;
}
case 16: {
this->suggested_area = value.as_string();
return true;
}
default:
return false;
}
@@ -765,6 +785,7 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(12, this->manufacturer);
buffer.encode_string(13, this->friendly_name);
buffer.encode_uint32(14, this->voice_assistant_version);
buffer.encode_string(16, this->suggested_area);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void DeviceInfoResponse::dump_to(std::string &out) const {
@@ -833,6 +854,10 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
sprintf(buffer, "%" PRIu32, this->voice_assistant_version);
out.append(buffer);
out.append("\n");
out.append(" suggested_area: ");
out.append("'").append(this->suggested_area).append("'");
out.append("\n");
out.append("}");
}
#endif
@@ -1350,6 +1375,10 @@ bool ListEntitiesFanResponse::decode_length(uint32_t field_id, ProtoLengthDelimi
this->icon = value.as_string();
return true;
}
case 12: {
this->supported_preset_modes.push_back(value.as_string());
return true;
}
default:
return false;
}
@@ -1376,6 +1405,9 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(9, this->disabled_by_default);
buffer.encode_string(10, this->icon);
buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
for (auto &it : this->supported_preset_modes) {
buffer.encode_string(12, it, true);
}
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesFanResponse::dump_to(std::string &out) const {
@@ -1426,6 +1458,12 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
for (const auto &it : this->supported_preset_modes) {
out.append(" supported_preset_modes: ");
out.append("'").append(it).append("'");
out.append("\n");
}
out.append("}");
}
#endif
@@ -1455,6 +1493,16 @@ bool FanStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
return false;
}
}
bool FanStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 7: {
this->preset_mode = value.as_string();
return true;
}
default:
return false;
}
}
bool FanStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
switch (field_id) {
case 1: {
@@ -1472,6 +1520,7 @@ void FanStateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_enum<enums::FanSpeed>(4, this->speed);
buffer.encode_enum<enums::FanDirection>(5, this->direction);
buffer.encode_int32(6, this->speed_level);
buffer.encode_string(7, this->preset_mode);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void FanStateResponse::dump_to(std::string &out) const {
@@ -1502,6 +1551,10 @@ void FanStateResponse::dump_to(std::string &out) const {
sprintf(buffer, "%" PRId32, this->speed_level);
out.append(buffer);
out.append("\n");
out.append(" preset_mode: ");
out.append("'").append(this->preset_mode).append("'");
out.append("\n");
out.append("}");
}
#endif
@@ -1547,6 +1600,20 @@ bool FanCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
this->speed_level = value.as_int32();
return true;
}
case 12: {
this->has_preset_mode = value.as_bool();
return true;
}
default:
return false;
}
}
bool FanCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 13: {
this->preset_mode = value.as_string();
return true;
}
default:
return false;
}
@@ -1573,6 +1640,8 @@ void FanCommandRequest::encode(ProtoWriteBuffer buffer) const {
buffer.encode_enum<enums::FanDirection>(9, this->direction);
buffer.encode_bool(10, this->has_speed_level);
buffer.encode_int32(11, this->speed_level);
buffer.encode_bool(12, this->has_preset_mode);
buffer.encode_string(13, this->preset_mode);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void FanCommandRequest::dump_to(std::string &out) const {
@@ -1623,6 +1692,14 @@ void FanCommandRequest::dump_to(std::string &out) const {
sprintf(buffer, "%" PRId32, this->speed_level);
out.append(buffer);
out.append("\n");
out.append(" has_preset_mode: ");
out.append(YESNO(this->has_preset_mode));
out.append("\n");
out.append(" preset_mode: ");
out.append("'").append(this->preset_mode).append("'");
out.append("\n");
out.append("}");
}
#endif
@@ -3534,6 +3611,14 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 22: {
this->supports_current_humidity = value.as_bool();
return true;
}
case 23: {
this->supports_target_humidity = value.as_bool();
return true;
}
default:
return false;
}
@@ -3590,6 +3675,14 @@ bool ListEntitiesClimateResponse::decode_32bit(uint32_t field_id, Proto32Bit val
this->visual_current_temperature_step = value.as_float();
return true;
}
case 24: {
this->visual_min_humidity = value.as_float();
return true;
}
case 25: {
this->visual_max_humidity = value.as_float();
return true;
}
default:
return false;
}
@@ -3628,6 +3721,10 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(19, this->icon);
buffer.encode_enum<enums::EntityCategory>(20, this->entity_category);
buffer.encode_float(21, this->visual_current_temperature_step);
buffer.encode_bool(22, this->supports_current_humidity);
buffer.encode_bool(23, this->supports_target_humidity);
buffer.encode_float(24, this->visual_min_humidity);
buffer.encode_float(25, this->visual_max_humidity);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesClimateResponse::dump_to(std::string &out) const {
@@ -3733,6 +3830,24 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
sprintf(buffer, "%g", this->visual_current_temperature_step);
out.append(buffer);
out.append("\n");
out.append(" supports_current_humidity: ");
out.append(YESNO(this->supports_current_humidity));
out.append("\n");
out.append(" supports_target_humidity: ");
out.append(YESNO(this->supports_target_humidity));
out.append("\n");
out.append(" visual_min_humidity: ");
sprintf(buffer, "%g", this->visual_min_humidity);
out.append(buffer);
out.append("\n");
out.append(" visual_max_humidity: ");
sprintf(buffer, "%g", this->visual_max_humidity);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -3802,6 +3917,14 @@ bool ClimateStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
this->target_temperature_high = value.as_float();
return true;
}
case 14: {
this->current_humidity = value.as_float();
return true;
}
case 15: {
this->target_humidity = value.as_float();
return true;
}
default:
return false;
}
@@ -3820,6 +3943,8 @@ void ClimateStateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(11, this->custom_fan_mode);
buffer.encode_enum<enums::ClimatePreset>(12, this->preset);
buffer.encode_string(13, this->custom_preset);
buffer.encode_float(14, this->current_humidity);
buffer.encode_float(15, this->target_humidity);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ClimateStateResponse::dump_to(std::string &out) const {
@@ -3881,6 +4006,16 @@ void ClimateStateResponse::dump_to(std::string &out) const {
out.append(" custom_preset: ");
out.append("'").append(this->custom_preset).append("'");
out.append("\n");
out.append(" current_humidity: ");
sprintf(buffer, "%g", this->current_humidity);
out.append(buffer);
out.append("\n");
out.append(" target_humidity: ");
sprintf(buffer, "%g", this->target_humidity);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -3946,6 +4081,10 @@ bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value)
this->has_custom_preset = value.as_bool();
return true;
}
case 22: {
this->has_target_humidity = value.as_bool();
return true;
}
default:
return false;
}
@@ -3982,6 +4121,10 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) {
this->target_temperature_high = value.as_float();
return true;
}
case 23: {
this->target_humidity = value.as_float();
return true;
}
default:
return false;
}
@@ -4008,6 +4151,8 @@ void ClimateCommandRequest::encode(ProtoWriteBuffer buffer) const {
buffer.encode_enum<enums::ClimatePreset>(19, this->preset);
buffer.encode_bool(20, this->has_custom_preset);
buffer.encode_string(21, this->custom_preset);
buffer.encode_bool(22, this->has_target_humidity);
buffer.encode_float(23, this->target_humidity);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ClimateCommandRequest::dump_to(std::string &out) const {
@@ -4100,6 +4245,15 @@ void ClimateCommandRequest::dump_to(std::string &out) const {
out.append(" custom_preset: ");
out.append("'").append(this->custom_preset).append("'");
out.append("\n");
out.append(" has_target_humidity: ");
out.append(YESNO(this->has_target_humidity));
out.append("\n");
out.append(" target_humidity: ");
sprintf(buffer, "%g", this->target_humidity);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -6791,6 +6945,227 @@ void AlarmControlPanelCommandRequest::dump_to(std::string &out) const {
out.append("}");
}
#endif
bool ListEntitiesTextResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 6: {
this->disabled_by_default = value.as_bool();
return true;
}
case 7: {
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 8: {
this->min_length = value.as_uint32();
return true;
}
case 9: {
this->max_length = value.as_uint32();
return true;
}
case 11: {
this->mode = value.as_enum<enums::TextMode>();
return true;
}
default:
return false;
}
}
bool ListEntitiesTextResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 1: {
this->object_id = value.as_string();
return true;
}
case 3: {
this->name = value.as_string();
return true;
}
case 4: {
this->unique_id = value.as_string();
return true;
}
case 5: {
this->icon = value.as_string();
return true;
}
case 10: {
this->pattern = value.as_string();
return true;
}
default:
return false;
}
}
bool ListEntitiesTextResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
switch (field_id) {
case 2: {
this->key = value.as_fixed32();
return true;
}
default:
return false;
}
}
void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(1, this->object_id);
buffer.encode_fixed32(2, this->key);
buffer.encode_string(3, this->name);
buffer.encode_string(4, this->unique_id);
buffer.encode_string(5, this->icon);
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_uint32(8, this->min_length);
buffer.encode_uint32(9, this->max_length);
buffer.encode_string(10, this->pattern);
buffer.encode_enum<enums::TextMode>(11, this->mode);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesTextResponse::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("ListEntitiesTextResponse {\n");
out.append(" object_id: ");
out.append("'").append(this->object_id).append("'");
out.append("\n");
out.append(" key: ");
sprintf(buffer, "%" PRIu32, this->key);
out.append(buffer);
out.append("\n");
out.append(" name: ");
out.append("'").append(this->name).append("'");
out.append("\n");
out.append(" unique_id: ");
out.append("'").append(this->unique_id).append("'");
out.append("\n");
out.append(" icon: ");
out.append("'").append(this->icon).append("'");
out.append("\n");
out.append(" disabled_by_default: ");
out.append(YESNO(this->disabled_by_default));
out.append("\n");
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" min_length: ");
sprintf(buffer, "%" PRIu32, this->min_length);
out.append(buffer);
out.append("\n");
out.append(" max_length: ");
sprintf(buffer, "%" PRIu32, this->max_length);
out.append(buffer);
out.append("\n");
out.append(" pattern: ");
out.append("'").append(this->pattern).append("'");
out.append("\n");
out.append(" mode: ");
out.append(proto_enum_to_string<enums::TextMode>(this->mode));
out.append("\n");
out.append("}");
}
#endif
bool TextStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 3: {
this->missing_state = value.as_bool();
return true;
}
default:
return false;
}
}
bool TextStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 2: {
this->state = value.as_string();
return true;
}
default:
return false;
}
}
bool TextStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
switch (field_id) {
case 1: {
this->key = value.as_fixed32();
return true;
}
default:
return false;
}
}
void TextStateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_fixed32(1, this->key);
buffer.encode_string(2, this->state);
buffer.encode_bool(3, this->missing_state);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void TextStateResponse::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("TextStateResponse {\n");
out.append(" key: ");
sprintf(buffer, "%" PRIu32, this->key);
out.append(buffer);
out.append("\n");
out.append(" state: ");
out.append("'").append(this->state).append("'");
out.append("\n");
out.append(" missing_state: ");
out.append(YESNO(this->missing_state));
out.append("\n");
out.append("}");
}
#endif
bool TextCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 2: {
this->state = value.as_string();
return true;
}
default:
return false;
}
}
bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) {
switch (field_id) {
case 1: {
this->key = value.as_fixed32();
return true;
}
default:
return false;
}
}
void TextCommandRequest::encode(ProtoWriteBuffer buffer) const {
buffer.encode_fixed32(1, this->key);
buffer.encode_string(2, this->state);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void TextCommandRequest::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("TextCommandRequest {\n");
out.append(" key: ");
sprintf(buffer, "%" PRIu32, this->key);
out.append(buffer);
out.append("\n");
out.append(" state: ");
out.append("'").append(this->state).append("'");
out.append("\n");
out.append("}");
}
#endif
} // namespace api
} // namespace esphome

View File

@@ -184,6 +184,8 @@ enum VoiceAssistantEvent : uint32_t {
VOICE_ASSISTANT_WAKE_WORD_END = 10,
VOICE_ASSISTANT_STT_VAD_START = 11,
VOICE_ASSISTANT_STT_VAD_END = 12,
VOICE_ASSISTANT_TTS_STREAM_START = 98,
VOICE_ASSISTANT_TTS_STREAM_END = 99,
};
enum AlarmControlPanelState : uint32_t {
ALARM_STATE_DISARMED = 0,
@@ -206,6 +208,10 @@ enum AlarmControlPanelStateCommand : uint32_t {
ALARM_CONTROL_PANEL_ARM_CUSTOM_BYPASS = 5,
ALARM_CONTROL_PANEL_TRIGGER = 6,
};
enum TextMode : uint32_t {
TEXT_MODE_TEXT = 0,
TEXT_MODE_PASSWORD = 1,
};
} // namespace enums
@@ -322,6 +328,7 @@ class DeviceInfoResponse : public ProtoMessage {
std::string manufacturer{};
std::string friendly_name{};
uint32_t voice_assistant_version{0};
std::string suggested_area{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -465,6 +472,7 @@ class ListEntitiesFanResponse : public ProtoMessage {
bool disabled_by_default{false};
std::string icon{};
enums::EntityCategory entity_category{};
std::vector<std::string> supported_preset_modes{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -483,6 +491,7 @@ class FanStateResponse : public ProtoMessage {
enums::FanSpeed speed{};
enums::FanDirection direction{};
int32_t speed_level{0};
std::string preset_mode{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -490,6 +499,7 @@ class FanStateResponse : public ProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class FanCommandRequest : public ProtoMessage {
@@ -505,6 +515,8 @@ class FanCommandRequest : public ProtoMessage {
enums::FanDirection direction{};
bool has_speed_level{false};
int32_t speed_level{0};
bool has_preset_mode{false};
std::string preset_mode{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -512,6 +524,7 @@ class FanCommandRequest : public ProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class ListEntitiesLightResponse : public ProtoMessage {
@@ -972,6 +985,10 @@ class ListEntitiesClimateResponse : public ProtoMessage {
std::string icon{};
enums::EntityCategory entity_category{};
float visual_current_temperature_step{0.0f};
bool supports_current_humidity{false};
bool supports_target_humidity{false};
float visual_min_humidity{0.0f};
float visual_max_humidity{0.0f};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -997,6 +1014,8 @@ class ClimateStateResponse : public ProtoMessage {
std::string custom_fan_mode{};
enums::ClimatePreset preset{};
std::string custom_preset{};
float current_humidity{0.0f};
float target_humidity{0.0f};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -1030,6 +1049,8 @@ class ClimateCommandRequest : public ProtoMessage {
enums::ClimatePreset preset{};
bool has_custom_preset{false};
std::string custom_preset{};
bool has_target_humidity{false};
float target_humidity{0.0f};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -1776,6 +1797,57 @@ class AlarmControlPanelCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class ListEntitiesTextResponse : public ProtoMessage {
public:
std::string object_id{};
uint32_t key{0};
std::string name{};
std::string unique_id{};
std::string icon{};
bool disabled_by_default{false};
enums::EntityCategory entity_category{};
uint32_t min_length{0};
uint32_t max_length{0};
std::string pattern{};
enums::TextMode mode{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class TextStateResponse : public ProtoMessage {
public:
uint32_t key{0};
std::string state{};
bool missing_state{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class TextCommandRequest : public ProtoMessage {
public:
uint32_t key{0};
std::string state{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
} // namespace api
} // namespace esphome

View File

@@ -495,6 +495,24 @@ bool APIServerConnectionBase::send_alarm_control_panel_state_response(const Alar
#endif
#ifdef USE_ALARM_CONTROL_PANEL
#endif
#ifdef USE_TEXT
bool APIServerConnectionBase::send_list_entities_text_response(const ListEntitiesTextResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_list_entities_text_response: %s", msg.dump().c_str());
#endif
return this->send_message_<ListEntitiesTextResponse>(msg, 97);
}
#endif
#ifdef USE_TEXT
bool APIServerConnectionBase::send_text_state_response(const TextStateResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_text_state_response: %s", msg.dump().c_str());
#endif
return this->send_message_<TextStateResponse>(msg, 98);
}
#endif
#ifdef USE_TEXT
#endif
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
switch (msg_type) {
case 1: {
@@ -913,6 +931,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ESP_LOGVV(TAG, "on_alarm_control_panel_command_request: %s", msg.dump().c_str());
#endif
this->on_alarm_control_panel_command_request(msg);
#endif
break;
}
case 99: {
#ifdef USE_TEXT
TextCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_text_command_request: %s", msg.dump().c_str());
#endif
this->on_text_command_request(msg);
#endif
break;
}
@@ -1124,6 +1153,19 @@ void APIServerConnection::on_number_command_request(const NumberCommandRequest &
this->number_command(msg);
}
#endif
#ifdef USE_TEXT
void APIServerConnection::on_text_command_request(const TextCommandRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->text_command(msg);
}
#endif
#ifdef USE_SELECT
void APIServerConnection::on_select_command_request(const SelectCommandRequest &msg) {
if (!this->is_connection_setup()) {

View File

@@ -248,6 +248,15 @@ class APIServerConnectionBase : public ProtoService {
#endif
#ifdef USE_ALARM_CONTROL_PANEL
virtual void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &value){};
#endif
#ifdef USE_TEXT
bool send_list_entities_text_response(const ListEntitiesTextResponse &msg);
#endif
#ifdef USE_TEXT
bool send_text_state_response(const TextStateResponse &msg);
#endif
#ifdef USE_TEXT
virtual void on_text_command_request(const TextCommandRequest &value){};
#endif
protected:
bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
@@ -288,6 +297,9 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_NUMBER
virtual void number_command(const NumberCommandRequest &msg) = 0;
#endif
#ifdef USE_TEXT
virtual void text_command(const TextCommandRequest &msg) = 0;
#endif
#ifdef USE_SELECT
virtual void select_command(const SelectCommandRequest &msg) = 0;
#endif
@@ -371,6 +383,9 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_NUMBER
void on_number_command_request(const NumberCommandRequest &msg) override;
#endif
#ifdef USE_TEXT
void on_text_command_request(const TextCommandRequest &msg) override;
#endif
#ifdef USE_SELECT
void on_select_command_request(const SelectCommandRequest &msg) override;
#endif

View File

@@ -111,6 +111,7 @@ void APIServer::loop() {
[](const std::unique_ptr<APIConnection> &conn) { return !conn->remove_; });
// print disconnection messages
for (auto it = new_end; it != this->clients_.end(); ++it) {
this->client_disconnected_trigger_->trigger((*it)->client_info_, (*it)->client_peername_);
ESP_LOGV(TAG, "Removing connection to %s", (*it)->client_info_.c_str());
}
// resize vector
@@ -254,6 +255,15 @@ void APIServer::on_number_update(number::Number *obj, float state) {
}
#endif
#ifdef USE_TEXT
void APIServer::on_text_update(text::Text *obj, const std::string &state) {
if (obj->is_internal())
return;
for (auto &c : this->clients_)
c->send_text_state(obj, state);
}
#endif
#ifdef USE_SELECT
void APIServer::on_select_update(select::Select *obj, const std::string &state, size_t index) {
if (obj->is_internal())
@@ -309,7 +319,7 @@ void APIServer::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeo
#ifdef USE_HOMEASSISTANT_TIME
void APIServer::request_time() {
for (auto &client : this->clients_) {
if (!client->remove_ && client->connection_state_ == APIConnection::ConnectionState::CONNECTED)
if (!client->remove_ && client->is_authenticated())
client->send_time_request();
}
}
@@ -322,30 +332,6 @@ void APIServer::on_shutdown() {
delay(10);
}
#ifdef USE_VOICE_ASSISTANT
bool APIServer::start_voice_assistant(const std::string &conversation_id, uint32_t flags,
const api::VoiceAssistantAudioSettings &audio_settings) {
VoiceAssistantRequest msg;
msg.start = true;
msg.conversation_id = conversation_id;
msg.flags = flags;
msg.audio_settings = audio_settings;
for (auto &c : this->clients_) {
if (c->request_voice_assistant(msg))
return true;
}
return false;
}
void APIServer::stop_voice_assistant() {
VoiceAssistantRequest msg;
msg.start = false;
for (auto &c : this->clients_) {
if (c->request_voice_assistant(msg))
return;
}
}
#endif
#ifdef USE_ALARM_CONTROL_PANEL
void APIServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) {
if (obj->is_internal())

View File

@@ -4,6 +4,7 @@
#include "api_pb2.h"
#include "api_pb2_service.h"
#include "esphome/components/socket/socket.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/controller.h"
#include "esphome/core/defines.h"
@@ -65,6 +66,9 @@ class APIServer : public Component, public Controller {
#ifdef USE_NUMBER
void on_number_update(number::Number *obj, float state) override;
#endif
#ifdef USE_TEXT
void on_text_update(text::Text *obj, const std::string &state) override;
#endif
#ifdef USE_SELECT
void on_select_update(select::Select *obj, const std::string &state, size_t index) override;
#endif
@@ -80,12 +84,6 @@ class APIServer : public Component, public Controller {
void request_time();
#endif
#ifdef USE_VOICE_ASSISTANT
bool start_voice_assistant(const std::string &conversation_id, uint32_t flags,
const api::VoiceAssistantAudioSettings &audio_settings);
void stop_voice_assistant();
#endif
#ifdef USE_ALARM_CONTROL_PANEL
void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override;
#endif
@@ -103,6 +101,11 @@ class APIServer : public Component, public Controller {
const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; }
Trigger<std::string, std::string> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
Trigger<std::string, std::string> *get_client_disconnected_trigger() const {
return this->client_disconnected_trigger_;
}
protected:
std::unique_ptr<socket::Socket> socket_ = nullptr;
uint16_t port_{6053};
@@ -112,6 +115,8 @@ class APIServer : public Component, public Controller {
std::string password_;
std::vector<HomeAssistantStateSubscription> state_subs_;
std::vector<UserServiceDescriptor *> user_services_;
Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>();
Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>();
#ifdef USE_API_NOISE
std::shared_ptr<APINoiseContext> noise_ctx_ = std::make_shared<APINoiseContext>();

View File

@@ -1,23 +1,29 @@
from __future__ import annotations
import asyncio
import logging
from datetime import datetime
from typing import Optional
from typing import Any
from aioesphomeapi import APIClient, ReconnectLogic, APIConnectionError, LogLevel
import zeroconf
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__
from esphome.core import CORE
from esphome.const import CONF_KEY, CONF_PORT, CONF_PASSWORD, __version__
from esphome.util import safe_print
from . import CONF_ENCRYPTION
_LOGGER = logging.getLogger(__name__)
async def async_run_logs(config, address):
async def async_run_logs(config: dict[str, Any], address: str) -> None:
"""Run the logs command in the event loop."""
conf = config["api"]
name = config["esphome"]["name"]
port: int = int(conf[CONF_PORT])
password: str = conf[CONF_PASSWORD]
noise_psk: Optional[str] = None
noise_psk: str | None = None
if CONF_ENCRYPTION in conf:
noise_psk = conf[CONF_ENCRYPTION][CONF_KEY]
_LOGGER.info("Starting log output from %s using esphome API", address)
@@ -28,44 +34,27 @@ async def async_run_logs(config, address):
client_info=f"ESPHome Logs {__version__}",
noise_psk=noise_psk,
)
first_connect = True
dashboard = CORE.dashboard
def on_log(msg):
time_ = datetime.now().time().strftime("[%H:%M:%S]")
text = msg.message.decode("utf8", "backslashreplace")
safe_print(time_ + text)
async def on_connect():
nonlocal first_connect
try:
await cli.subscribe_logs(
on_log,
log_level=LogLevel.LOG_LEVEL_VERY_VERBOSE,
dump_config=first_connect,
)
first_connect = False
except APIConnectionError:
cli.disconnect()
async def on_disconnect(expected_disconnect: bool) -> None:
_LOGGER.warning("Disconnected from API")
zc = zeroconf.Zeroconf()
reconnect = ReconnectLogic(
client=cli,
on_connect=on_connect,
on_disconnect=on_disconnect,
zeroconf_instance=zc,
)
await reconnect.start()
def on_log(msg: SubscribeLogsResponse) -> None:
"""Handle a new log message."""
time_ = datetime.now()
message: bytes = msg.message
text = message.decode("utf8", "backslashreplace")
if dashboard:
text = text.replace("\033", "\\033")
print(f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}]{text}")
stop = await async_run(cli, on_log, name=name)
try:
while True:
await asyncio.sleep(60)
await asyncio.Event().wait()
finally:
await stop()
def run_logs(config: dict[str, Any], address: str) -> None:
"""Run the logs command."""
try:
asyncio.run(async_run_logs(config, address))
except KeyboardInterrupt:
await reconnect.stop()
zc.close()
def run_logs(config, address):
asyncio.run(async_run_logs(config, address))
pass

View File

@@ -60,6 +60,10 @@ bool ListEntitiesIterator::on_climate(climate::Climate *climate) { return this->
bool ListEntitiesIterator::on_number(number::Number *number) { return this->client_->send_number_info(number); }
#endif
#ifdef USE_TEXT
bool ListEntitiesIterator::on_text(text::Text *text) { return this->client_->send_text_info(text); }
#endif
#ifdef USE_SELECT
bool ListEntitiesIterator::on_select(select::Select *select) { return this->client_->send_select_info(select); }
#endif

View File

@@ -46,6 +46,9 @@ class ListEntitiesIterator : public ComponentIterator {
#ifdef USE_NUMBER
bool on_number(number::Number *number) override;
#endif
#ifdef USE_TEXT
bool on_text(text::Text *text) override;
#endif
#ifdef USE_SELECT
bool on_select(select::Select *select) override;
#endif

View File

@@ -160,8 +160,7 @@ class ProtoWriteBuffer {
this->encode_field_raw(field_id, 2);
this->encode_varint_raw(len);
auto *data = reinterpret_cast<const uint8_t *>(string);
for (size_t i = 0; i < len; i++)
this->write(data[i]);
this->buffer_->insert(this->buffer_->end(), data, data + len);
}
void encode_string(uint32_t field_id, const std::string &value, bool force = false) {
this->encode_string(field_id, value.data(), value.size());

View File

@@ -42,6 +42,9 @@ bool InitialStateIterator::on_number(number::Number *number) {
return this->client_->send_number_state(number, number->state);
}
#endif
#ifdef USE_TEXT
bool InitialStateIterator::on_text(text::Text *text) { return this->client_->send_text_state(text, text->state); }
#endif
#ifdef USE_SELECT
bool InitialStateIterator::on_select(select::Select *select) {
return this->client_->send_select_state(select, select->state);

View File

@@ -43,6 +43,9 @@ class InitialStateIterator : public ComponentIterator {
#ifdef USE_NUMBER
bool on_number(number::Number *number) override;
#endif
#ifdef USE_TEXT
bool on_text(text::Text *text) override;
#endif
#ifdef USE_SELECT
bool on_select(select::Select *select) override;
#endif

View File

@@ -5,7 +5,7 @@ namespace esphome {
namespace api {
template<> bool get_execute_arg_value<bool>(const ExecuteServiceArgument &arg) { return arg.bool_; }
template<> int get_execute_arg_value<int>(const ExecuteServiceArgument &arg) {
template<> int32_t get_execute_arg_value<int32_t>(const ExecuteServiceArgument &arg) {
if (arg.legacy_int != 0)
return arg.legacy_int;
return arg.int_;
@@ -26,11 +26,13 @@ template<> std::vector<std::string> get_execute_arg_value<std::vector<std::strin
}
template<> enums::ServiceArgType to_service_arg_type<bool>() { return enums::SERVICE_ARG_TYPE_BOOL; }
template<> enums::ServiceArgType to_service_arg_type<int>() { return enums::SERVICE_ARG_TYPE_INT; }
template<> enums::ServiceArgType to_service_arg_type<int32_t>() { return enums::SERVICE_ARG_TYPE_INT; }
template<> enums::ServiceArgType to_service_arg_type<float>() { return enums::SERVICE_ARG_TYPE_FLOAT; }
template<> enums::ServiceArgType to_service_arg_type<std::string>() { return enums::SERVICE_ARG_TYPE_STRING; }
template<> enums::ServiceArgType to_service_arg_type<std::vector<bool>>() { return enums::SERVICE_ARG_TYPE_BOOL_ARRAY; }
template<> enums::ServiceArgType to_service_arg_type<std::vector<int>>() { return enums::SERVICE_ARG_TYPE_INT_ARRAY; }
template<> enums::ServiceArgType to_service_arg_type<std::vector<int32_t>>() {
return enums::SERVICE_ARG_TYPE_INT_ARRAY;
}
template<> enums::ServiceArgType to_service_arg_type<std::vector<float>>() {
return enums::SERVICE_ARG_TYPE_FLOAT_ARRAY;
}

View File

@@ -1,6 +1,7 @@
#include "atm90e32.h"
#include "atm90e32_reg.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace atm90e32 {
@@ -173,7 +174,7 @@ uint16_t ATM90E32Component::read16_(uint16_t a_register) {
this->disable();
output = (uint16_t(data[0] & 0xFF) << 8) | (data[1] & 0xFF);
ESP_LOGVV(TAG, "read16_ 0x%04X output 0x%04X", a_register, output);
ESP_LOGVV(TAG, "read16_ 0x%04" PRIX16 " output 0x%04" PRIX16, a_register, output);
return output;
}
@@ -182,8 +183,10 @@ int ATM90E32Component::read32_(uint16_t addr_h, uint16_t addr_l) {
uint16_t val_l = this->read16_(addr_l);
int32_t val = (val_h << 16) | val_l;
ESP_LOGVV(TAG, "read32_ addr_h 0x%04X val_h 0x%04X addr_l 0x%04X val_l 0x%04X = %d", addr_h, val_h, addr_l, val_l,
val);
ESP_LOGVV(TAG,
"read32_ addr_h 0x%04" PRIX16 " val_h 0x%04" PRIX16 " addr_l 0x%04" PRIX16 " val_l 0x%04" PRIX16
" = %" PRId32,
addr_h, val_h, addr_l, val_l, val);
return val;
}
@@ -192,7 +195,7 @@ void ATM90E32Component::write16_(uint16_t a_register, uint16_t val) {
uint8_t addrh = (a_register >> 8) & 0x03;
uint8_t addrl = (a_register & 0xFF);
ESP_LOGVV(TAG, "write16_ 0x%04X val 0x%04X", a_register, val);
ESP_LOGVV(TAG, "write16_ 0x%04" PRIX16 " val 0x%04" PRIX16, a_register, val);
this->enable();
delayMicroseconds(10);
this->write_byte(addrh);

View File

@@ -15,6 +15,16 @@ void BangBangClimate::setup() {
this->publish_state();
});
this->current_temperature = this->sensor_->state;
// register for humidity values and get initial state
if (this->humidity_sensor_ != nullptr) {
this->humidity_sensor_->add_on_state_callback([this](float state) {
this->current_humidity = state;
this->publish_state();
});
this->current_humidity = this->humidity_sensor_->state;
}
// restore set points
auto restore = this->restore_state_();
if (restore.has_value()) {
@@ -47,6 +57,8 @@ void BangBangClimate::control(const climate::ClimateCall &call) {
climate::ClimateTraits BangBangClimate::traits() {
auto traits = climate::ClimateTraits();
traits.set_supports_current_temperature(true);
if (this->humidity_sensor_ != nullptr)
traits.set_supports_current_humidity(true);
traits.set_supported_modes({
climate::CLIMATE_MODE_OFF,
});
@@ -171,6 +183,7 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa
BangBangClimate::BangBangClimate()
: idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {}
void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
void BangBangClimate::set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; }
Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; }
void BangBangClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }

View File

@@ -24,6 +24,7 @@ class BangBangClimate : public climate::Climate, public Component {
void dump_config() override;
void set_sensor(sensor::Sensor *sensor);
void set_humidity_sensor(sensor::Sensor *humidity_sensor);
Trigger<> *get_idle_trigger() const;
Trigger<> *get_cool_trigger() const;
void set_supports_cool(bool supports_cool);
@@ -48,6 +49,9 @@ class BangBangClimate : public climate::Climate, public Component {
/// The sensor used for getting the current temperature
sensor::Sensor *sensor_{nullptr};
/// The sensor used for getting the current humidity
sensor::Sensor *humidity_sensor_{nullptr};
/** The trigger to call when the controller should switch to idle mode.
*
* In idle mode, the controller is assumed to have both heating and cooling disabled.

View File

@@ -8,6 +8,7 @@ from esphome.const import (
CONF_DEFAULT_TARGET_TEMPERATURE_HIGH,
CONF_DEFAULT_TARGET_TEMPERATURE_LOW,
CONF_HEAT_ACTION,
CONF_HUMIDITY_SENSOR,
CONF_ID,
CONF_IDLE_ACTION,
CONF_SENSOR,
@@ -22,6 +23,7 @@ CONFIG_SCHEMA = cv.All(
{
cv.GenerateID(): cv.declare_id(BangBangClimate),
cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
cv.Optional(CONF_HUMIDITY_SENSOR): cv.use_id(sensor.Sensor),
cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature,
cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True),
@@ -47,6 +49,10 @@ async def to_code(config):
sens = await cg.get_variable(config[CONF_SENSOR])
cg.add(var.set_sensor(sens))
if CONF_HUMIDITY_SENSOR in config:
sens = await cg.get_variable(config[CONF_HUMIDITY_SENSOR])
cg.add(var.set_humidity_sensor(sens))
normal_config = BangBangClimateTargetTempConfig(
config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW],
config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH],

View File

@@ -22,7 +22,7 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) {
// Start matching
MultiClickTriggerEvent evt = this->timing_[0];
if (evt.state == state) {
ESP_LOGV(TAG, "START min=%u max=%u", evt.min_length, evt.max_length);
ESP_LOGV(TAG, "START min=%" PRIu32 " max=%" PRIu32, evt.min_length, evt.max_length);
ESP_LOGV(TAG, "Multi Click: Starting multi click action!");
this->at_index_ = 1;
if (this->timing_.size() == 1 && evt.max_length == 4294967294UL) {
@@ -51,15 +51,15 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) {
MultiClickTriggerEvent evt = this->timing_[*this->at_index_];
if (evt.max_length != 4294967294UL) {
ESP_LOGV(TAG, "A i=%u min=%u max=%u", *this->at_index_, evt.min_length, evt.max_length); // NOLINT
ESP_LOGV(TAG, "A i=%u min=%" PRIu32 " max=%" PRIu32, *this->at_index_, evt.min_length, evt.max_length); // NOLINT
this->schedule_is_valid_(evt.min_length);
this->schedule_is_not_valid_(evt.max_length);
} else if (*this->at_index_ + 1 != this->timing_.size()) {
ESP_LOGV(TAG, "B i=%u min=%u", *this->at_index_, evt.min_length); // NOLINT
ESP_LOGV(TAG, "B i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT
this->cancel_timeout("is_not_valid");
this->schedule_is_valid_(evt.min_length);
} else {
ESP_LOGV(TAG, "C i=%u min=%u", *this->at_index_, evt.min_length); // NOLINT
ESP_LOGV(TAG, "C i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT
this->is_valid_ = false;
this->cancel_timeout("is_not_valid");
this->set_timeout("trigger", evt.min_length, [this]() { this->trigger_(); });
@@ -68,7 +68,8 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) {
*this->at_index_ = *this->at_index_ + 1;
}
void binary_sensor::MultiClickTrigger::schedule_cooldown_() {
ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %u ms...", this->invalid_cooldown_);
ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %" PRIu32 " ms...",
this->invalid_cooldown_);
this->is_in_cooldown_ = true;
this->set_timeout("cooldown", this->invalid_cooldown_, [this]() {
ESP_LOGV(TAG, "Multi Click: Cooldown ended, matching is now enabled again.");

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cinttypes>
#include <utility>
#include <vector>

View File

@@ -1,5 +1,6 @@
#include "bl0939.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace bl0939 {
@@ -80,7 +81,7 @@ void BL0939::setup() {
void BL0939::received_package_(const DataPacket *data) const {
// Bad header
if (data->frame_header != BL0939_PACKET_HEADER) {
ESP_LOGI("bl0939", "Invalid data. Header mismatch: %d", data->frame_header);
ESP_LOGI(TAG, "Invalid data. Header mismatch: %d", data->frame_header);
return;
}
@@ -120,8 +121,9 @@ void BL0939::received_package_(const DataPacket *data) const {
energy_sensor_sum_->publish_state(total_energy_consumption);
}
ESP_LOGV("bl0939", "BL0939: U %fV, I1 %fA, I2 %fA, P1 %fW, P2 %fW, CntA %d, CntB %d, ∫P1 %fkWh, ∫P2 %fkWh", v_rms,
ia_rms, ib_rms, a_watt, b_watt, cfa_cnt, cfb_cnt, a_energy_consumption, b_energy_consumption);
ESP_LOGV(TAG,
"BL0939: U %fV, I1 %fA, I2 %fA, P1 %fW, P2 %fW, CntA %" PRId32 ", CntB %" PRId32 ", ∫P1 %fkWh, ∫P2 %fkWh",
v_rms, ia_rms, ib_rms, a_watt, b_watt, cfa_cnt, cfb_cnt, a_energy_consumption, b_energy_consumption);
}
void BL0939::dump_config() { // NOLINT(readability-function-cognitive-complexity)

View File

@@ -1,5 +1,6 @@
#include "bl0940.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace bl0940 {
@@ -77,7 +78,7 @@ float BL0940::update_temp_(sensor::Sensor *sensor, ube16_t temperature) const {
float converted_temp = ((float) 170 / 448) * (tb / 2 - 32) - 45;
if (sensor != nullptr) {
if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
ESP_LOGD("bl0940", "Invalid temperature change. Sensor: '%s', Old temperature: %f, New temperature: %f",
ESP_LOGD(TAG, "Invalid temperature change. Sensor: '%s', Old temperature: %f, New temperature: %f",
sensor->get_name().c_str(), sensor->get_state(), converted_temp);
return 0.0f;
}
@@ -89,7 +90,7 @@ float BL0940::update_temp_(sensor::Sensor *sensor, ube16_t temperature) const {
void BL0940::received_package_(const DataPacket *data) const {
// Bad header
if (data->frame_header != BL0940_PACKET_HEADER) {
ESP_LOGI("bl0940", "Invalid data. Header mismatch: %d", data->frame_header);
ESP_LOGI(TAG, "Invalid data. Header mismatch: %d", data->frame_header);
return;
}
@@ -115,7 +116,7 @@ void BL0940::received_package_(const DataPacket *data) const {
energy_sensor_->publish_state(total_energy_consumption);
}
ESP_LOGV("bl0940", "BL0940: U %fV, I %fA, P %fW, Cnt %d, ∫P %fkWh, T1 %f°C, T2 %f°C", v_rms, i_rms, watt, cf_cnt,
ESP_LOGV(TAG, "BL0940: U %fV, I %fA, P %fW, Cnt %" PRId32 ", ∫P %fkWh, T1 %f°C, T2 %f°C", v_rms, i_rms, watt, cf_cnt,
total_energy_consumption, tps1, tps2);
}

View File

@@ -18,6 +18,7 @@ from esphome.const import (
UNIT_KILOWATT_HOURS,
UNIT_VOLT,
UNIT_WATT,
STATE_CLASS_TOTAL_INCREASING,
)
DEPENDENCIES = ["uart"]
@@ -54,6 +55,7 @@ CONFIG_SCHEMA = (
unit_of_measurement=UNIT_KILOWATT_HOURS,
accuracy_decimals=0,
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
cv.Optional(CONF_INTERNAL_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,

View File

@@ -1,5 +1,6 @@
#include "bl0942.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace bl0942 {
@@ -104,8 +105,8 @@ void BL0942::received_package_(DataPacket *data) {
frequency_sensor_->publish_state(frequency);
}
ESP_LOGV(TAG, "BL0942: U %fV, I %fA, P %fW, Cnt %d, ∫P %fkWh, frequency %f°Hz, status 0x%08X", v_rms, i_rms, watt,
cf_cnt, total_energy_consumption, frequency, data->status);
ESP_LOGV(TAG, "BL0942: U %fV, I %fA, P %fW, Cnt %" PRId32 ", ∫P %fkWh, frequency %fHz, status 0x%08X", v_rms, i_rms,
watt, cf_cnt, total_energy_consumption, frequency, data->status);
}
void BL0942::dump_config() { // NOLINT(readability-function-cognitive-complexity)

View File

@@ -19,6 +19,7 @@ from esphome.const import (
UNIT_VOLT,
UNIT_WATT,
UNIT_HERTZ,
STATE_CLASS_TOTAL_INCREASING,
)
DEPENDENCIES = ["uart"]
@@ -52,6 +53,7 @@ CONFIG_SCHEMA = (
unit_of_measurement=UNIT_KILOWATT_HOURS,
accuracy_decimals=0,
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
unit_of_measurement=UNIT_HERTZ,

View File

@@ -1,8 +1,8 @@
#include "ble_rssi_sensor.h"
#include "esphome/core/log.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
@@ -37,6 +37,10 @@ void BLEClientRSSISensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
}
case ESP_GATTC_SEARCH_CMPL_EVT:
this->node_state = espbt::ClientState::ESTABLISHED;
if (this->should_update_) {
this->should_update_ = false;
this->get_rssi_();
}
break;
default:
break;
@@ -50,6 +54,7 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
if (param->read_rssi_cmpl.status == ESP_BT_STATUS_SUCCESS) {
int8_t rssi = param->read_rssi_cmpl.rssi;
ESP_LOGI(TAG, "ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT RSSI: %d", rssi);
this->status_clear_warning();
this->publish_state(rssi);
}
break;
@@ -61,9 +66,12 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
void BLEClientRSSISensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
this->should_update_ = true;
return;
}
this->get_rssi_();
}
void BLEClientRSSISensor::get_rssi_() {
ESP_LOGV(TAG, "requesting rssi from %s", this->parent()->address_str().c_str());
auto status = esp_ble_gap_read_rssi(this->parent()->get_remote_bda());
if (status != ESP_OK) {

View File

@@ -1,9 +1,9 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/ble_client/ble_client.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/core/component.h"
#ifdef USE_ESP32
#include <esp_gattc_api.h>
@@ -24,6 +24,10 @@ class BLEClientRSSISensor : public sensor::Sensor, public PollingComponent, publ
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) override;
protected:
void get_rssi_();
bool should_update_{false};
};
} // namespace ble_client

View File

@@ -8,6 +8,7 @@
#include "bmp3xx.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include <cinttypes>
namespace esphome {
namespace bmp3xx {
@@ -198,8 +199,9 @@ void BMP3XXComponent::update() {
return;
}
ESP_LOGVV(TAG, "measurement time %d", uint32_t(ceilf(meas_time)));
this->set_timeout("data", uint32_t(ceilf(meas_time)), [this]() {
const uint32_t meas_timeout = uint32_t(ceilf(meas_time));
ESP_LOGVV(TAG, "measurement time %" PRIu32, meas_timeout);
this->set_timeout("data", meas_timeout, [this]() {
float temperature = 0.0f;
float pressure = 0.0f;
if (this->pressure_sensor_ != nullptr) {

View File

@@ -90,40 +90,41 @@ void BP1658CJ::set_channel_value_(uint8_t channel, uint16_t value) {
void BP1658CJ::write_bit_(bool value) {
this->data_pin_->digital_write(value);
this->clock_pin_->digital_write(true);
delayMicroseconds(BP1658CJ_DELAY);
this->clock_pin_->digital_write(true);
delayMicroseconds(BP1658CJ_DELAY);
this->clock_pin_->digital_write(false);
delayMicroseconds(BP1658CJ_DELAY);
}
void BP1658CJ::write_byte_(uint8_t data) {
for (uint8_t mask = 0x80; mask; mask >>= 1) {
this->write_bit_(data & mask);
delayMicroseconds(BP1658CJ_DELAY);
}
// ack bit
this->data_pin_->pin_mode(gpio::FLAG_INPUT);
this->clock_pin_->digital_write(true);
delayMicroseconds(BP1658CJ_DELAY);
this->clock_pin_->digital_write(false);
delayMicroseconds(BP1658CJ_DELAY);
this->data_pin_->pin_mode(gpio::FLAG_OUTPUT);
}
void BP1658CJ::write_buffer_(uint8_t *buffer, uint8_t size) {
this->data_pin_->digital_write(false);
delayMicroseconds(BP1658CJ_DELAY);
this->clock_pin_->digital_write(false);
delayMicroseconds(BP1658CJ_DELAY);
for (uint32_t i = 0; i < size; i++) {
this->write_byte_(buffer[i]);
delayMicroseconds(BP1658CJ_DELAY);
}
this->clock_pin_->digital_write(true);
delayMicroseconds(BP1658CJ_DELAY);
this->data_pin_->digital_write(true);
delayMicroseconds(BP1658CJ_DELAY);
}
} // namespace bp1658cj

View File

@@ -17,11 +17,12 @@ CONF_ON_FRAME = "on_frame"
def validate_id(config):
can_id = config[CONF_CAN_ID]
id_ext = config[CONF_USE_EXTENDED_ID]
if not id_ext:
if can_id > 0x7FF:
raise cv.Invalid("Standard IDs must be 11 Bit (0x000-0x7ff / 0-2047)")
if CONF_CAN_ID in config:
can_id = config[CONF_CAN_ID]
id_ext = config[CONF_USE_EXTENDED_ID]
if not id_ext:
if can_id > 0x7FF:
raise cv.Invalid("Standard IDs must be 11 Bit (0x000-0x7ff / 0-2047)")
return config
@@ -151,22 +152,18 @@ async def canbus_action_to_code(config, action_id, template_arg, args):
if can_id := config.get(CONF_CAN_ID):
can_id = await cg.templatable(can_id, args, cg.uint32)
cg.add(var.set_can_id(can_id))
use_extended_id = await cg.templatable(
config[CONF_USE_EXTENDED_ID], args, cg.uint32
)
cg.add(var.set_use_extended_id(use_extended_id))
cg.add(var.set_use_extended_id(config[CONF_USE_EXTENDED_ID]))
remote_transmission_request = await cg.templatable(
config[CONF_REMOTE_TRANSMISSION_REQUEST], args, bool
cg.add(
var.set_remote_transmission_request(config[CONF_REMOTE_TRANSMISSION_REQUEST])
)
cg.add(var.set_remote_transmission_request(remote_transmission_request))
data = config[CONF_DATA]
if isinstance(data, bytes):
data = [int(x) for x in data]
if cg.is_template(data):
templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8))
cg.add(var.set_data_template(templ))
else:
if isinstance(data, bytes):
data = [int(x) for x in data]
cg.add(var.set_data_static(data))
return var

View File

@@ -16,9 +16,9 @@ void Canbus::setup() {
void Canbus::dump_config() {
if (this->use_extended_id_) {
ESP_LOGCONFIG(TAG, "config extended id=0x%08x", this->can_id_);
ESP_LOGCONFIG(TAG, "config extended id=0x%08" PRIx32, this->can_id_);
} else {
ESP_LOGCONFIG(TAG, "config standard id=0x%03x", this->can_id_);
ESP_LOGCONFIG(TAG, "config standard id=0x%03" PRIx32, this->can_id_);
}
}
@@ -28,9 +28,11 @@ void Canbus::send_data(uint32_t can_id, bool use_extended_id, bool remote_transm
uint8_t size = static_cast<uint8_t>(data.size());
if (use_extended_id) {
ESP_LOGD(TAG, "send extended id=0x%08x rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request), size);
ESP_LOGD(TAG, "send extended id=0x%08" PRIx32 " rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request),
size);
} else {
ESP_LOGD(TAG, "send standard id=0x%03x rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request), size);
ESP_LOGD(TAG, "send standard id=0x%03" PRIx32 " rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request),
size);
}
if (size > CAN_MAX_DATA_LENGTH)
size = CAN_MAX_DATA_LENGTH;
@@ -49,9 +51,9 @@ void Canbus::send_data(uint32_t can_id, bool use_extended_id, bool remote_transm
void Canbus::add_trigger(CanbusTrigger *trigger) {
if (trigger->use_extended_id_) {
ESP_LOGVV(TAG, "add trigger for extended canid=0x%08x", trigger->can_id_);
ESP_LOGVV(TAG, "add trigger for extended canid=0x%08" PRIx32, trigger->can_id_);
} else {
ESP_LOGVV(TAG, "add trigger for std canid=0x%03x", trigger->can_id_);
ESP_LOGVV(TAG, "add trigger for std canid=0x%03" PRIx32, trigger->can_id_);
}
this->triggers_.push_back(trigger);
};
@@ -63,10 +65,10 @@ void Canbus::loop() {
while (this->read_message(&can_message) == canbus::ERROR_OK) {
message_counter++;
if (can_message.use_extended_id) {
ESP_LOGD(TAG, "received can message (#%d) extended can_id=0x%x size=%d", message_counter, can_message.can_id,
can_message.can_data_length_code);
ESP_LOGD(TAG, "received can message (#%d) extended can_id=0x%" PRIx32 " size=%d", message_counter,
can_message.can_id, can_message.can_data_length_code);
} else {
ESP_LOGD(TAG, "received can message (#%d) std can_id=0x%x size=%d", message_counter, can_message.can_id,
ESP_LOGD(TAG, "received can message (#%d) std can_id=0x%" PRIx32 " size=%d", message_counter, can_message.can_id,
can_message.can_data_length_code);
}

View File

@@ -4,6 +4,7 @@
#include "esphome/core/component.h"
#include "esphome/core/optional.h"
#include <cinttypes>
#include <vector>
namespace esphome {

View File

@@ -48,7 +48,7 @@ void CaptivePortal::start() {
this->dns_server_ = make_unique<DNSServer>();
this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip();
this->dns_server_->start(53, "*", IPAddress(ip));
this->dns_server_->start(53, "*", ip);
#endif
this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {

View File

@@ -1,5 +1,6 @@
#include "cd74hc4067.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace cd74hc4067 {
@@ -27,7 +28,7 @@ void CD74HC4067Component::dump_config() {
LOG_PIN(" S1 Pin: ", this->pin_s1_);
LOG_PIN(" S2 Pin: ", this->pin_s2_);
LOG_PIN(" S3 Pin: ", this->pin_s3_);
ESP_LOGCONFIG(TAG, "switch delay: %d", this->switch_delay_);
ESP_LOGCONFIG(TAG, "switch delay: %" PRIu32, this->switch_delay_);
}
void CD74HC4067Component::activate_pin(uint8_t pin) {

View File

@@ -8,6 +8,7 @@ from esphome.const import (
CONF_AWAY,
CONF_AWAY_COMMAND_TOPIC,
CONF_AWAY_STATE_TOPIC,
CONF_CURRENT_HUMIDITY_STATE_TOPIC,
CONF_CURRENT_TEMPERATURE_STATE_TOPIC,
CONF_CUSTOM_FAN_MODE,
CONF_CUSTOM_PRESET,
@@ -28,6 +29,8 @@ from esphome.const import (
CONF_SWING_MODE,
CONF_SWING_MODE_COMMAND_TOPIC,
CONF_SWING_MODE_STATE_TOPIC,
CONF_TARGET_HUMIDITY_COMMAND_TOPIC,
CONF_TARGET_HUMIDITY_STATE_TOPIC,
CONF_TARGET_TEMPERATURE,
CONF_TARGET_TEMPERATURE_COMMAND_TOPIC,
CONF_TARGET_TEMPERATURE_STATE_TOPIC,
@@ -106,6 +109,9 @@ CLIMATE_SWING_MODES = {
validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True)
CONF_CURRENT_TEMPERATURE = "current_temperature"
CONF_MIN_HUMIDITY = "min_humidity"
CONF_MAX_HUMIDITY = "max_humidity"
CONF_TARGET_HUMIDITY = "target_humidity"
visual_temperature = cv.float_with_unit(
"visual_temperature", "(°C|° C|°|C|° K|° K|K|°F|° F|F)?"
@@ -153,6 +159,8 @@ CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).
cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature,
cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature,
cv.Optional(CONF_TEMPERATURE_STEP): VISUAL_TEMPERATURE_STEP_SCHEMA,
cv.Optional(CONF_MIN_HUMIDITY): cv.percentage_int,
cv.Optional(CONF_MAX_HUMIDITY): cv.percentage_int,
}
),
cv.Optional(CONF_ACTION_STATE_TOPIC): cv.All(
@@ -167,6 +175,9 @@ CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).
cv.Optional(CONF_CURRENT_TEMPERATURE_STATE_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.publish_topic
),
cv.Optional(CONF_CURRENT_HUMIDITY_STATE_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.publish_topic
),
cv.Optional(CONF_FAN_MODE_COMMAND_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.publish_topic
),
@@ -209,6 +220,12 @@ CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).
cv.Optional(CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.publish_topic
),
cv.Optional(CONF_TARGET_HUMIDITY_COMMAND_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.publish_topic
),
cv.Optional(CONF_TARGET_HUMIDITY_STATE_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.publish_topic
),
cv.Optional(CONF_ON_CONTROL): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ControlTrigger),
@@ -238,6 +255,10 @@ async def setup_climate_core_(var, config):
visual[CONF_TEMPERATURE_STEP][CONF_CURRENT_TEMPERATURE],
)
)
if CONF_MIN_HUMIDITY in visual:
cg.add(var.set_visual_min_humidity_override(visual[CONF_MIN_HUMIDITY]))
if CONF_MAX_HUMIDITY in visual:
cg.add(var.set_visual_max_humidity_override(visual[CONF_MAX_HUMIDITY]))
if CONF_MQTT_ID in config:
mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var)
@@ -255,6 +276,12 @@ async def setup_climate_core_(var, config):
config[CONF_CURRENT_TEMPERATURE_STATE_TOPIC]
)
)
if CONF_CURRENT_HUMIDITY_STATE_TOPIC in config:
cg.add(
mqtt_.set_custom_current_humidity_state_topic(
config[CONF_CURRENT_HUMIDITY_STATE_TOPIC]
)
)
if CONF_FAN_MODE_COMMAND_TOPIC in config:
cg.add(
mqtt_.set_custom_fan_mode_command_topic(
@@ -323,6 +350,18 @@ async def setup_climate_core_(var, config):
config[CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC]
)
)
if CONF_TARGET_HUMIDITY_COMMAND_TOPIC in config:
cg.add(
mqtt_.set_custom_target_humidity_command_topic(
config[CONF_TARGET_HUMIDITY_COMMAND_TOPIC]
)
)
if CONF_TARGET_HUMIDITY_STATE_TOPIC in config:
cg.add(
mqtt_.set_custom_target_humidity_state_topic(
config[CONF_TARGET_HUMIDITY_STATE_TOPIC]
)
)
for conf in config.get(CONF_ON_STATE, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
@@ -351,6 +390,7 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema(
cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature),
cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature),
cv.Optional(CONF_TARGET_TEMPERATURE_HIGH): cv.templatable(cv.temperature),
cv.Optional(CONF_TARGET_HUMIDITY): cv.templatable(cv.percentage_int),
cv.Optional(CONF_AWAY): cv.invalid("Use preset instead"),
cv.Exclusive(CONF_FAN_MODE, "fan_mode"): cv.templatable(
validate_climate_fan_mode
@@ -387,6 +427,9 @@ async def climate_control_to_code(config, action_id, template_arg, args):
config[CONF_TARGET_TEMPERATURE_HIGH], args, float
)
cg.add(var.set_target_temperature_high(template_))
if CONF_TARGET_HUMIDITY in config:
template_ = await cg.templatable(config[CONF_TARGET_HUMIDITY], args, float)
cg.add(var.set_target_humidity(template_))
if CONF_FAN_MODE in config:
template_ = await cg.templatable(config[CONF_FAN_MODE], args, ClimateFanMode)
cg.add(var.set_fan_mode(template_))

View File

@@ -14,6 +14,7 @@ template<typename... Ts> class ControlAction : public Action<Ts...> {
TEMPLATABLE_VALUE(float, target_temperature)
TEMPLATABLE_VALUE(float, target_temperature_low)
TEMPLATABLE_VALUE(float, target_temperature_high)
TEMPLATABLE_VALUE(float, target_humidity)
TEMPLATABLE_VALUE(bool, away)
TEMPLATABLE_VALUE(ClimateFanMode, fan_mode)
TEMPLATABLE_VALUE(std::string, custom_fan_mode)
@@ -27,6 +28,7 @@ template<typename... Ts> class ControlAction : public Action<Ts...> {
call.set_target_temperature(this->target_temperature_.optional_value(x...));
call.set_target_temperature_low(this->target_temperature_low_.optional_value(x...));
call.set_target_temperature_high(this->target_temperature_high_.optional_value(x...));
call.set_target_humidity(this->target_humidity_.optional_value(x...));
if (away_.has_value()) {
call.set_preset(away_.value(x...) ? CLIMATE_PRESET_AWAY : CLIMATE_PRESET_HOME);
}

View File

@@ -45,6 +45,9 @@ void ClimateCall::perform() {
if (this->target_temperature_high_.has_value()) {
ESP_LOGD(TAG, " Target Temperature High: %.2f", *this->target_temperature_high_);
}
if (this->target_humidity_.has_value()) {
ESP_LOGD(TAG, " Target Humidity: %.0f", *this->target_humidity_);
}
this->parent_->control(*this);
}
void ClimateCall::validate_() {
@@ -213,6 +216,8 @@ ClimateCall &ClimateCall::set_preset(const std::string &preset) {
this->set_preset(CLIMATE_PRESET_SLEEP);
} else if (str_equals_case_insensitive(preset, "ACTIVITY")) {
this->set_preset(CLIMATE_PRESET_ACTIVITY);
} else if (str_equals_case_insensitive(preset, "NONE")) {
this->set_preset(CLIMATE_PRESET_NONE);
} else {
if (this->parent_->get_traits().supports_custom_preset(preset)) {
this->custom_preset_ = preset;
@@ -260,10 +265,16 @@ ClimateCall &ClimateCall::set_target_temperature_high(float target_temperature_h
this->target_temperature_high_ = target_temperature_high;
return *this;
}
ClimateCall &ClimateCall::set_target_humidity(float target_humidity) {
this->target_humidity_ = target_humidity;
return *this;
}
const optional<ClimateMode> &ClimateCall::get_mode() const { return this->mode_; }
const optional<float> &ClimateCall::get_target_temperature() const { return this->target_temperature_; }
const optional<float> &ClimateCall::get_target_temperature_low() const { return this->target_temperature_low_; }
const optional<float> &ClimateCall::get_target_temperature_high() const { return this->target_temperature_high_; }
const optional<float> &ClimateCall::get_target_humidity() const { return this->target_humidity_; }
const optional<ClimateFanMode> &ClimateCall::get_fan_mode() const { return this->fan_mode_; }
const optional<std::string> &ClimateCall::get_custom_fan_mode() const { return this->custom_fan_mode_; }
const optional<ClimatePreset> &ClimateCall::get_preset() const { return this->preset_; }
@@ -281,6 +292,10 @@ ClimateCall &ClimateCall::set_target_temperature(optional<float> target_temperat
this->target_temperature_ = target_temperature;
return *this;
}
ClimateCall &ClimateCall::set_target_humidity(optional<float> target_humidity) {
this->target_humidity_ = target_humidity;
return *this;
}
ClimateCall &ClimateCall::set_mode(optional<ClimateMode> mode) {
this->mode_ = mode;
return *this;
@@ -341,6 +356,9 @@ void Climate::save_state_() {
} else {
state.target_temperature = this->target_temperature;
}
if (traits.get_supports_target_humidity()) {
state.target_humidity = this->target_humidity;
}
if (traits.get_supports_fan_modes() && fan_mode.has_value()) {
state.uses_custom_fan_mode = false;
state.fan_mode = this->fan_mode.value();
@@ -406,6 +424,12 @@ void Climate::publish_state() {
} else {
ESP_LOGD(TAG, " Target Temperature: %.2f°C", this->target_temperature);
}
if (traits.get_supports_current_humidity()) {
ESP_LOGD(TAG, " Current Humidity: %.0f%%", this->current_humidity);
}
if (traits.get_supports_target_humidity()) {
ESP_LOGD(TAG, " Target Humidity: %.0f%%", this->target_humidity);
}
// Send state to frontend
this->state_callback_.call(*this);
@@ -425,6 +449,12 @@ ClimateTraits Climate::get_traits() {
traits.set_visual_target_temperature_step(*this->visual_target_temperature_step_override_);
traits.set_visual_current_temperature_step(*this->visual_current_temperature_step_override_);
}
if (this->visual_min_humidity_override_.has_value()) {
traits.set_visual_min_humidity(*this->visual_min_humidity_override_);
}
if (this->visual_max_humidity_override_.has_value()) {
traits.set_visual_max_humidity(*this->visual_max_humidity_override_);
}
return traits;
}
@@ -439,6 +469,12 @@ void Climate::set_visual_temperature_step_override(float target, float current)
this->visual_target_temperature_step_override_ = target;
this->visual_current_temperature_step_override_ = current;
}
void Climate::set_visual_min_humidity_override(float visual_min_humidity_override) {
this->visual_min_humidity_override_ = visual_min_humidity_override;
}
void Climate::set_visual_max_humidity_override(float visual_max_humidity_override) {
this->visual_max_humidity_override_ = visual_max_humidity_override;
}
ClimateCall Climate::make_call() { return ClimateCall(this); }
@@ -452,6 +488,9 @@ ClimateCall ClimateDeviceRestoreState::to_call(Climate *climate) {
} else {
call.set_target_temperature(this->target_temperature);
}
if (traits.get_supports_target_humidity()) {
call.set_target_humidity(this->target_humidity);
}
if (traits.get_supports_fan_modes() || !traits.get_supported_custom_fan_modes().empty()) {
call.set_fan_mode(this->fan_mode);
}
@@ -472,6 +511,9 @@ void ClimateDeviceRestoreState::apply(Climate *climate) {
} else {
climate->target_temperature = this->target_temperature;
}
if (traits.get_supports_target_humidity()) {
climate->target_humidity = this->target_humidity;
}
if (traits.get_supports_fan_modes() && !this->uses_custom_fan_mode) {
climate->fan_mode = this->fan_mode;
}
@@ -528,17 +570,25 @@ void Climate::dump_traits_(const char *tag) {
auto traits = this->get_traits();
ESP_LOGCONFIG(tag, "ClimateTraits:");
ESP_LOGCONFIG(tag, " [x] Visual settings:");
ESP_LOGCONFIG(tag, " - Min: %.1f", traits.get_visual_min_temperature());
ESP_LOGCONFIG(tag, " - Max: %.1f", traits.get_visual_max_temperature());
ESP_LOGCONFIG(tag, " - Step:");
ESP_LOGCONFIG(tag, " - Min temperature: %.1f", traits.get_visual_min_temperature());
ESP_LOGCONFIG(tag, " - Max temperature: %.1f", traits.get_visual_max_temperature());
ESP_LOGCONFIG(tag, " - Temperature step:");
ESP_LOGCONFIG(tag, " Target: %.1f", traits.get_visual_target_temperature_step());
ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step());
ESP_LOGCONFIG(tag, " - Min humidity: %.0f", traits.get_visual_min_humidity());
ESP_LOGCONFIG(tag, " - Max humidity: %.0f", traits.get_visual_max_humidity());
if (traits.get_supports_current_temperature()) {
ESP_LOGCONFIG(tag, " [x] Supports current temperature");
}
if (traits.get_supports_current_humidity()) {
ESP_LOGCONFIG(tag, " [x] Supports current humidity");
}
if (traits.get_supports_two_point_target_temperature()) {
ESP_LOGCONFIG(tag, " [x] Supports two-point target temperature");
}
if (traits.get_supports_target_humidity()) {
ESP_LOGCONFIG(tag, " [x] Supports target humidity");
}
if (traits.get_supports_action()) {
ESP_LOGCONFIG(tag, " [x] Supports action");
}

View File

@@ -64,6 +64,10 @@ class ClimateCall {
* For climate devices with two point target temperature control
*/
ClimateCall &set_target_temperature_high(optional<float> target_temperature_high);
/// Set the target humidity of the climate device.
ClimateCall &set_target_humidity(float target_humidity);
/// Set the target humidity of the climate device.
ClimateCall &set_target_humidity(optional<float> target_humidity);
/// Set the fan mode of the climate device.
ClimateCall &set_fan_mode(ClimateFanMode fan_mode);
/// Set the fan mode of the climate device.
@@ -93,6 +97,7 @@ class ClimateCall {
const optional<float> &get_target_temperature() const;
const optional<float> &get_target_temperature_low() const;
const optional<float> &get_target_temperature_high() const;
const optional<float> &get_target_humidity() const;
const optional<ClimateFanMode> &get_fan_mode() const;
const optional<ClimateSwingMode> &get_swing_mode() const;
const optional<std::string> &get_custom_fan_mode() const;
@@ -107,6 +112,7 @@ class ClimateCall {
optional<float> target_temperature_;
optional<float> target_temperature_low_;
optional<float> target_temperature_high_;
optional<float> target_humidity_;
optional<ClimateFanMode> fan_mode_;
optional<ClimateSwingMode> swing_mode_;
optional<std::string> custom_fan_mode_;
@@ -136,6 +142,7 @@ struct ClimateDeviceRestoreState {
float target_temperature_high;
};
};
float target_humidity;
/// Convert this struct to a climate call that can be performed.
ClimateCall to_call(Climate *climate);
@@ -160,24 +167,34 @@ struct ClimateDeviceRestoreState {
*/
class Climate : public EntityBase {
public:
Climate() {}
/// The active mode of the climate device.
ClimateMode mode{CLIMATE_MODE_OFF};
/// The active state of the climate device.
ClimateAction action{CLIMATE_ACTION_OFF};
/// The current temperature of the climate device, as reported from the integration.
float current_temperature{NAN};
/// The current humidity of the climate device, as reported from the integration.
float current_humidity{NAN};
union {
/// The target temperature of the climate device.
float target_temperature;
struct {
/// The minimum target temperature of the climate device, for climate devices with split target temperature.
float target_temperature_low;
float target_temperature_low{NAN};
/// The maximum target temperature of the climate device, for climate devices with split target temperature.
float target_temperature_high;
float target_temperature_high{NAN};
};
};
/// The target humidity of the climate device.
float target_humidity;
/// The active fan mode of the climate device.
optional<ClimateFanMode> fan_mode;
@@ -231,6 +248,8 @@ class Climate : public EntityBase {
void set_visual_min_temperature_override(float visual_min_temperature_override);
void set_visual_max_temperature_override(float visual_max_temperature_override);
void set_visual_temperature_step_override(float target, float current);
void set_visual_min_humidity_override(float visual_min_humidity_override);
void set_visual_max_humidity_override(float visual_max_humidity_override);
protected:
friend ClimateCall;
@@ -280,6 +299,8 @@ class Climate : public EntityBase {
optional<float> visual_max_temperature_override_{};
optional<float> visual_target_temperature_step_override_{};
optional<float> visual_current_temperature_step_override_{};
optional<float> visual_min_humidity_override_{};
optional<float> visual_max_humidity_override_{};
};
} // namespace climate

View File

@@ -44,10 +44,18 @@ class ClimateTraits {
void set_supports_current_temperature(bool supports_current_temperature) {
supports_current_temperature_ = supports_current_temperature;
}
bool get_supports_current_humidity() const { return supports_current_humidity_; }
void set_supports_current_humidity(bool supports_current_humidity) {
supports_current_humidity_ = supports_current_humidity;
}
bool get_supports_two_point_target_temperature() const { return supports_two_point_target_temperature_; }
void set_supports_two_point_target_temperature(bool supports_two_point_target_temperature) {
supports_two_point_target_temperature_ = supports_two_point_target_temperature;
}
bool get_supports_target_humidity() const { return supports_target_humidity_; }
void set_supports_target_humidity(bool supports_target_humidity) {
supports_target_humidity_ = supports_target_humidity;
}
void set_supported_modes(std::set<ClimateMode> modes) { supported_modes_ = std::move(modes); }
void add_supported_mode(ClimateMode mode) { supported_modes_.insert(mode); }
ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
@@ -153,6 +161,11 @@ class ClimateTraits {
int8_t get_target_temperature_accuracy_decimals() const;
int8_t get_current_temperature_accuracy_decimals() const;
float get_visual_min_humidity() const { return visual_min_humidity_; }
void set_visual_min_humidity(float visual_min_humidity) { visual_min_humidity_ = visual_min_humidity; }
float get_visual_max_humidity() const { return visual_max_humidity_; }
void set_visual_max_humidity(float visual_max_humidity) { visual_max_humidity_ = visual_max_humidity; }
protected:
void set_mode_support_(climate::ClimateMode mode, bool supported) {
if (supported) {
@@ -177,7 +190,9 @@ class ClimateTraits {
}
bool supports_current_temperature_{false};
bool supports_current_humidity_{false};
bool supports_two_point_target_temperature_{false};
bool supports_target_humidity_{false};
std::set<climate::ClimateMode> supported_modes_ = {climate::CLIMATE_MODE_OFF};
bool supports_action_{false};
std::set<climate::ClimateFanMode> supported_fan_modes_;
@@ -190,6 +205,8 @@ class ClimateTraits {
float visual_max_temperature_{30};
float visual_target_temperature_step_{0.1};
float visual_current_temperature_step_{0.1};
float visual_min_humidity_{30};
float visual_max_humidity_{99};
};
} // namespace climate

View File

@@ -1,38 +1,37 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import (
climate,
remote_transmitter,
remote_receiver,
sensor,
remote_base,
)
from esphome.components.remote_base import CONF_RECEIVER_ID, CONF_TRANSMITTER_ID
from esphome.components import climate, sensor, remote_base
from esphome.const import CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT, CONF_SENSOR
DEPENDENCIES = ["remote_transmitter"]
AUTO_LOAD = ["sensor", "remote_base"]
CODEOWNERS = ["@glmnet"]
climate_ir_ns = cg.esphome_ns.namespace("climate_ir")
ClimateIR = climate_ir_ns.class_(
"ClimateIR", climate.Climate, cg.Component, remote_base.RemoteReceiverListener
"ClimateIR",
climate.Climate,
cg.Component,
remote_base.RemoteReceiverListener,
remote_base.RemoteTransmittable,
)
CLIMATE_IR_SCHEMA = climate.CLIMATE_SCHEMA.extend(
{
cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(
remote_transmitter.RemoteTransmitterComponent
),
cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean,
cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
}
).extend(cv.COMPONENT_SCHEMA)
CLIMATE_IR_SCHEMA = (
climate.CLIMATE_SCHEMA.extend(
{
cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean,
cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
}
)
.extend(cv.COMPONENT_SCHEMA)
.extend(remote_base.REMOTE_TRANSMITTABLE_SCHEMA)
)
CLIMATE_IR_WITH_RECEIVER_SCHEMA = CLIMATE_IR_SCHEMA.extend(
{
cv.Optional(CONF_RECEIVER_ID): cv.use_id(
remote_receiver.RemoteReceiverComponent
cv.Optional(remote_base.CONF_RECEIVER_ID): cv.use_id(
remote_base.RemoteReceiverBase
),
}
)
@@ -41,15 +40,11 @@ CLIMATE_IR_WITH_RECEIVER_SCHEMA = CLIMATE_IR_SCHEMA.extend(
async def register_climate_ir(var, config):
await cg.register_component(var, config)
await climate.register_climate(var, config)
await remote_base.register_transmittable(var, config)
cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL]))
cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT]))
if remote_base.CONF_RECEIVER_ID in config:
await remote_base.register_listener(var, config)
if sensor_id := config.get(CONF_SENSOR):
sens = await cg.get_variable(sensor_id)
cg.add(var.set_sensor(sens))
if receiver_id := config.get(CONF_RECEIVER_ID):
receiver = await cg.get_variable(receiver_id)
cg.add(receiver.register_listener(var))
transmitter = await cg.get_variable(config[CONF_TRANSMITTER_ID])
cg.add(var.set_transmitter(transmitter))

View File

@@ -18,7 +18,10 @@ namespace climate_ir {
Likewise to decode a IR into the AC state, implement
bool RemoteReceiverListener::on_receive(remote_base::RemoteReceiveData data) and return true
*/
class ClimateIR : public climate::Climate, public Component, public remote_base::RemoteReceiverListener {
class ClimateIR : public Component,
public climate::Climate,
public remote_base::RemoteReceiverListener,
public remote_base::RemoteTransmittable {
public:
ClimateIR(float minimum_temperature, float maximum_temperature, float temperature_step = 1.0f,
bool supports_dry = false, bool supports_fan_only = false, std::set<climate::ClimateFanMode> fan_modes = {},
@@ -35,9 +38,6 @@ class ClimateIR : public climate::Climate, public Component, public remote_base:
void setup() override;
void dump_config() override;
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
this->transmitter_ = transmitter;
}
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
@@ -64,7 +64,6 @@ class ClimateIR : public climate::Climate, public Component, public remote_base:
std::set<climate::ClimateSwingMode> swing_modes_ = {};
std::set<climate::ClimatePreset> presets_ = {};
remote_transmitter::RemoteTransmitterComponent *transmitter_;
sensor::Sensor *sensor_{nullptr};
};

View File

@@ -121,7 +121,7 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) {
}
}
ESP_LOGD(TAG, "Decoded 0x%02X", remote_state);
ESP_LOGD(TAG, "Decoded 0x%02" PRIX32, remote_state);
if ((remote_state & 0xFF00000) != 0x8800000)
return false;
@@ -173,7 +173,7 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) {
}
void LgIrClimate::transmit_(uint32_t value) {
calc_checksum_(value);
ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02X", value);
ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02" PRIX32, value);
auto transmit = this->transmitter_->transmit();
auto *data = transmit.get_data();

View File

@@ -2,6 +2,8 @@
#include "esphome/components/climate_ir/climate_ir.h"
#include <cinttypes>
namespace esphome {
namespace climate_ir_lg {

View File

@@ -101,12 +101,8 @@ void CoolixClimate::transmit_state() {
}
}
}
ESP_LOGV(TAG, "Sending coolix code: 0x%06X", remote_state);
auto transmit = this->transmitter_->transmit();
auto *data = transmit.get_data();
remote_base::CoolixProtocol().encode(data, remote_state);
transmit.perform();
ESP_LOGV(TAG, "Sending coolix code: 0x%06" PRIX32, remote_state);
this->transmit_<remote_base::CoolixProtocol>(remote_state);
}
bool CoolixClimate::on_coolix(climate::Climate *parent, remote_base::RemoteReceiveData data) {
@@ -115,7 +111,7 @@ bool CoolixClimate::on_coolix(climate::Climate *parent, remote_base::RemoteRecei
return false;
// Decoded remote state y 3 bytes long code.
uint32_t remote_state = (*decoded).second;
ESP_LOGV(TAG, "Decoded 0x%06X", remote_state);
ESP_LOGV(TAG, "Decoded 0x%06" PRIX32, remote_state);
if ((remote_state & 0xFF0000) != 0xB20000)
return false;

View File

@@ -2,6 +2,8 @@
#include "esphome/components/climate_ir/climate_ir.h"
#include <cinttypes>
namespace esphome {
namespace coolix {

View File

@@ -12,6 +12,7 @@ void CopyFan::setup() {
this->oscillating = source_->oscillating;
this->speed = source_->speed;
this->direction = source_->direction;
this->preset_mode = source_->preset_mode;
this->publish_state();
});
@@ -19,6 +20,7 @@ void CopyFan::setup() {
this->oscillating = source_->oscillating;
this->speed = source_->speed;
this->direction = source_->direction;
this->preset_mode = source_->preset_mode;
this->publish_state();
}
@@ -33,6 +35,7 @@ fan::FanTraits CopyFan::get_traits() {
traits.set_speed(base.supports_speed());
traits.set_supported_speed_count(base.supported_speed_count());
traits.set_direction(base.supports_direction());
traits.set_supported_preset_modes(base.supported_preset_modes());
return traits;
}
@@ -46,6 +49,8 @@ void CopyFan::control(const fan::FanCall &call) {
call2.set_speed(*call.get_speed());
if (call.get_direction().has_value())
call2.set_direction(*call.get_direction());
if (!call.get_preset_mode().empty())
call2.set_preset_mode(call.get_preset_mode());
call2.perform();
}

View File

@@ -0,0 +1,36 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import text
from esphome.const import (
CONF_ENTITY_CATEGORY,
CONF_ICON,
CONF_MODE,
CONF_SOURCE_ID,
)
from esphome.core.entity_helpers import inherit_property_from
from .. import copy_ns
CopyText = copy_ns.class_("CopyText", text.Text, cg.Component)
CONFIG_SCHEMA = text.TEXT_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(CopyText),
cv.Required(CONF_SOURCE_ID): cv.use_id(text.Text),
}
).extend(cv.COMPONENT_SCHEMA)
FINAL_VALIDATE_SCHEMA = cv.All(
inherit_property_from(CONF_ICON, CONF_SOURCE_ID),
inherit_property_from(CONF_ENTITY_CATEGORY, CONF_SOURCE_ID),
inherit_property_from(CONF_MODE, CONF_SOURCE_ID),
)
async def to_code(config):
var = await text.new_text(config)
await cg.register_component(var, config)
source = await cg.get_variable(config[CONF_SOURCE_ID])
cg.add(var.set_source(source))

View File

@@ -0,0 +1,25 @@
#include "copy_text.h"
#include "esphome/core/log.h"
namespace esphome {
namespace copy {
static const char *const TAG = "copy.text";
void CopyText::setup() {
source_->add_on_state_callback([this](const std::string &value) { this->publish_state(value); });
if (source_->has_state())
this->publish_state(source_->state);
}
void CopyText::dump_config() { LOG_TEXT("", "Copy Text", this); }
void CopyText::control(const std::string &value) {
auto call2 = source_->make_call();
call2.set_value(value);
call2.perform();
}
} // namespace copy
} // namespace esphome

View File

@@ -0,0 +1,23 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/text/text.h"
namespace esphome {
namespace copy {
class CopyText : public text::Text, public Component {
public:
void set_source(text::Text *source) { source_ = source; }
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::DATA; }
protected:
void control(const std::string &value) override;
text::Text *source_;
};
} // namespace copy
} // namespace esphome

View File

@@ -86,7 +86,7 @@ void CS5460AComponent::hw_init_() {
}
uint32_t status = this->read_register_(REG_STATUS);
ESP_LOGCONFIG(TAG, " Version: %x", (status >> 6) & 7);
ESP_LOGCONFIG(TAG, " Version: %" PRIx32, (status >> 6) & 7);
this->write_register_(REG_CYCLE_COUNT, samples_);
this->write_register_(REG_PULSE_RATE, lroundf(pulse_freq_ * 32.0f));
@@ -323,7 +323,7 @@ void CS5460AComponent::dump_config() {
ESP_LOGCONFIG(TAG, " Init status: %s",
state == COMPONENT_STATE_LOOP ? "OK" : (state == COMPONENT_STATE_FAILED ? "failed" : "other"));
LOG_PIN(" CS Pin: ", cs_);
ESP_LOGCONFIG(TAG, " Samples / cycle: %u", samples_);
ESP_LOGCONFIG(TAG, " Samples / cycle: %" PRIu32, samples_);
ESP_LOGCONFIG(TAG, " Phase offset: %i", phase_offset_);
ESP_LOGCONFIG(TAG, " PGA Gain: %s", pga_gain_ == CS5460A_PGA_GAIN_50X ? "50x" : "10x");
ESP_LOGCONFIG(TAG, " Current gain: %.5f", current_gain_);

View File

@@ -5,6 +5,8 @@
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/spi/spi.h"
#include <cinttypes>
namespace esphome {
namespace cs5460a {

View File

@@ -217,7 +217,7 @@ void CSE7761Component::get_data_() {
this->voltage_sensor_->publish_state(voltage);
}
for (uint32_t channel = 0; channel < 2; channel++) {
for (uint8_t channel = 0; channel < 2; channel++) {
// Active power = PowerPA * PowerPAC * 1000 / 0x80000000
float active_power = (float) this->data_.active_power[channel] / this->coefficient_by_unit_(POWER_PAC); // W
float amps = (float) this->data_.current_rms[channel] / this->coefficient_by_unit_(RMS_IAC); // A

View File

@@ -1,5 +1,6 @@
#include "cse7766.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace cse7766 {
@@ -162,7 +163,7 @@ void CSE7766Component::update() {
if (counts != 0) {
const auto avg = acc / counts;
ESP_LOGV(TAG, "Got %s_acc=%.2f %s_counts=%d %s=%.1f", name, acc, name, counts, name, avg);
ESP_LOGV(TAG, "Got %s_acc=%.2f %s_counts=%" PRIu32 " %s=%.1f", name, acc, name, counts, name, avg);
if (sensor != nullptr) {
sensor->publish_state(avg);
@@ -178,7 +179,8 @@ void CSE7766Component::update() {
publish_state("power", this->power_sensor_, this->power_acc_, this->power_counts_);
if (this->energy_total_counts_ != 0) {
ESP_LOGV(TAG, "Got energy_total=%.2f energy_total_counts=%d", this->energy_total_, this->energy_total_counts_);
ESP_LOGV(TAG, "Got energy_total=%.2f energy_total_counts=%" PRIu32, this->energy_total_,
this->energy_total_counts_);
if (this->energy_sensor_ != nullptr) {
this->energy_sensor_->publish_state(this->energy_total_);

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