Compare commits

..

473 Commits

Author SHA1 Message Date
Franck Nijhof
06ea3a3014 2024.9.3 (#126566) 2024-09-24 09:01:55 +02:00
Franck Nijhof
59ecd47374 Hotfix test for patch release in fritzbox 2024-09-23 20:09:09 +02:00
Markus Jacobsen
95053f7114 Bump mozart_api to 3.4.1.8.8 (#126334)
Update API
2024-09-23 20:07:05 +02:00
Franck Nijhof
4949727cd5 Bump version to 2024.9.3 2024-09-23 19:47:41 +02:00
Markus Jacobsen
08b0064ce7 Fix blocking call in Bang & Olufsen API client initialization (#126456)
* Update API

* Add fix for blocking call to load_default_certs
2024-09-23 19:47:30 +02:00
Steve Easley
c9571126a3 Add support for new JVC Projector auth method (#126453) 2024-09-23 19:47:27 +02:00
David Knowles
06d825d6c8 Bump pydrawise to 2024.9.0 (#126431) 2024-09-23 19:47:24 +02:00
Mr. Bubbles
36e6ab4af8 Fix due date calculation for future dailies in Habitica integration (#126403)
Calculate next due date for dailies with startdate in the future
2024-09-23 19:47:21 +02:00
Manuel Frei
ccec85f047 Fix surepetcare token update (#126385)
Co-authored-by: Joostlek <joostlek@outlook.com>
2024-09-23 19:47:18 +02:00
G Johansson
e8a5a75e96 Bump python-holidays to 0.57 (#126367) 2024-09-23 19:47:15 +02:00
Michael
4eb1fca68e Fix next change (scheduler) sensors in AVM FRITZ!SmartHome (#126363) 2024-09-23 19:47:12 +02:00
Joost Lekkerkerker
fba24b8ead Bump airgradient to 0.9.0 (#126319)
* Bump airgradient to 0.9.0

* Bump airgradient to 0.9.0
2024-09-23 19:44:22 +02:00
Matthias Alphart
edfb9f3f6b Fix loading KNX UI entities with entity category set (#126290)
* Fix loading KNX UI entities with entity category set

* add test

* docstring fixes

* telegram order

* Optionally ignore telegram sending order in tests

because we can't know which platform initialises first
2024-09-23 19:44:18 +02:00
Marcel van der Veldt
2322d071e4 Fix Matter climate platform attributes when dedicated OnOff attribute is off (#126286) 2024-09-23 19:44:15 +02:00
Fredrik Erlandsson
7658ed8eaa Bump pydaikin to 2.13.7 (#126219) 2024-09-23 19:44:12 +02:00
Sebastian Nohn
c81f280bc1 Fix tibber fails if power production is enabled but no power is produced (#126209)
* fix #125312 - tibber integration fails if power production is enabled but no power is produced

* fix requirements_all.txt
2024-09-23 19:44:09 +02:00
Andrew Jackson
6e36febd37 Broaden scope of ConfigEntryNotReady in Mealie (#126208)
Broaden scope of ConfigEntryNotReady
2024-09-23 19:44:06 +02:00
Jan-Philipp Benecke
b38c193fe4 Prevent blocking event loop in ps4 (#126151)
* Prevent blocking event loop in ps4

* Process code review comment
2024-09-23 19:44:02 +02:00
Arun Philip
b336cae118 Fix qbittorrent error when torrent count is 0 (#126146)
Fix handling of `NoneType` for torrents in `count_torrents_in_states` function

Added a check to handle cases where the 'torrents' data is None, avoiding a `TypeError` when attempting to get the length of a `NoneType` object. The function now returns 0 if 'torrents' is None, ensuring robust behavior when no torrent data is available.
2024-09-23 19:43:59 +02:00
Milan Meulemans
991114eb7f Update Aseko to support new API (#126133)
* Update Aseko to support new API

* Apply suggestions from code review

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Use self.unit instead of self._unit

* Refactor sensor setup entry

* Keep same unique id and identifier

* Revert rename free_chlorine translation key

* Remove new heating entity to keep PR small

* Fix keep same unique id

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-09-23 19:43:56 +02:00
Tobias Sauerwein
d924fc5967 Fix set brightness for Netatmo lights (#126075)
* fix set brightness for Netatmo lights

* round returns int by default

* Update homeassistant/components/netatmo/light.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-09-23 19:43:50 +02:00
Brett Adams
c64222de4f Fix wall connector state in Teslemetry (#124149)
* Fix wall connector state

* review feedback

* Rename None to Disconnected

* Translate disconnected
2024-09-23 10:17:38 +02:00
Franck Nijhof
b69b5aa82a 2024.9.2 (#126062) 2024-09-16 19:44:37 +02:00
Jason Hunter
861fcbe598 Pin pyasn1 until fixed (#125712)
* pin pyasn1 until fixed

* add to gen requirements
2024-09-16 17:38:17 +02:00
Franck Nijhof
d259055af0 Bump version to 2024.9.2 2024-09-16 16:55:02 +02:00
TimL
fae26ee5da Abort zeroconf flow on connect error during discovery (#125980)
Abort zereconf flow on connect error during discovery
2024-09-16 15:58:51 +02:00
Noah Husby
c4eca4469f Bump aiorussound to 3.0.5 (#125975) 2024-09-16 15:58:48 +02:00
Galorhallen
d91cc96cd2 Bump govee light local to 1.5.2 (#125968)
Update govee light local library
2024-09-16 15:58:44 +02:00
starkillerOG
0b226c1868 Bump motionblinds to 0.6.25 (#125957) 2024-09-16 15:53:59 +02:00
puddly
359f61e55a Bump ZHA to 0.0.33 (#125914) 2024-09-16 15:53:55 +02:00
Josef Zweck
16e049b7fa Bump lmcloud to 1.2.3 (#125801) 2024-09-16 15:53:51 +02:00
puddly
8a6eec925f Add missing Zigbee/Thread firmware config flow translations (#125782) 2024-09-16 15:45:45 +02:00
starkillerOG
f365995c8a Fix favorite position missing for Motion Blinds TDBU devices (#125750)
* Add favorite position for TDBU

* fix styling
2024-09-16 15:45:41 +02:00
Assaf Akrabi
20ded56c99 Bump russound to 0.2.0 (#125743)
* Update russound library to fix BrokenPipeError

* Remove library from license expection list
2024-09-16 15:45:38 +02:00
Matthias Alphart
4583e070df Update knx-frontend to 2024.9.10.221729 (#125734) 2024-09-16 15:45:33 +02:00
epenet
d4be1f3666 Bump sfrbox-api to 0.0.11 (#125732)
* Bump sfrbox-api to 0.0.11

* Re-enable tests
2024-09-16 15:45:30 +02:00
puddly
06d4b3281b Remove unused keys from the ZHA config schema (#125710) 2024-09-16 15:45:27 +02:00
jonnynch
1dcd5471a0 Bump to python-nest-sdm to 5.0.1 (#125706) 2024-09-16 15:45:23 +02:00
Jan Bouwhuis
d0b6ef877e Fix incomfort invalid setpoint if override is reported as 0.0 (#125694) 2024-09-16 15:45:20 +02:00
Steven B.
1e63b956f5 Bump tplink python-kasa lib to 0.7.3 (#125686) 2024-09-16 15:45:17 +02:00
Steven B.
7734bdfdab Update tplink config to include aes keys (#125685) 2024-09-16 15:45:13 +02:00
Paul Bottein
7eb9036cbb Update frontend to 20240909.1 (#125610) 2024-09-16 15:45:10 +02:00
Pete Sage
6b2526ddbd FIx Sonos announce regression issue (#125515)
* initial commit

* initial commit
2024-09-16 15:45:06 +02:00
G Johansson
0b1a898c7c Fix yale_smart_alarm on missing key (#125508) 2024-09-16 15:45:03 +02:00
Avi Miller
fe247a60ef Bump aiolifx and aiolifx-themes to support more than 82 zones (#125487)
Signed-off-by: Avi Miller <me@dje.li>
2024-09-16 15:45:00 +02:00
J. Nick Koston
17402848f2 Bump yalexs to 8.6.4 (#125442)
adds a debounce to the updates to ensure we do
not request the activities api too often if
the websocket sends rapid updates

fixes #125277
2024-09-16 15:44:56 +02:00
tmenguy
e6b4c2e700 Fix renault plug state (#125421)
* Added PlugState 3, that is coming with renault-api 0.2.7, it fixes #124682 HA ticket

* Added PlugState 3, that is coming with renault-api 0.2.7, it fixes #124682 HA ticket
2024-09-16 15:44:52 +02:00
Willem-Jan van Rootselaar
e7c48d5870 Update diagnostics for BSBLan (#124508)
* update diagnostics to include static

and make room for multiple coordinator data objects

* fix mac address is not stored in config_entry but on device
2024-09-16 15:42:11 +02:00
Michał Jaworski
781342be40 Fix mired range in blebox color temp mode lights (#124258)
* fix: use default mired range in belbox lights running in color temp mode

* fix: ruff
2024-09-16 15:42:08 +02:00
David Knowles
73b26407f6 Fix Schlage removed locks (#123627)
* Fix bugs when a lock is no longer returned by the API

* Changes requested during review

* Only mark unavailable if lock is not present

* Remove stale comment

* Remove over-judicious nullability checks

* Remove another unnecessary null check
2024-09-16 15:42:05 +02:00
Simon
b1d691178e Use default voice id as fallback in get_tts_audio (#123624) 2024-09-16 15:42:02 +02:00
Kristof Mattei
dc189e1d58 Fix Lyric climate Auto mode (#123490)
fix: Lyric has an actual "Auto" mode that is exposed if the device has an Auto mode.
2024-09-16 15:41:52 +02:00
Paulus Schoutsen
444560543c 2024.9.1 (#125420) 2024-09-06 13:39:52 -04:00
Paulus Schoutsen
ed2d321746 Bump version to 2024.9.1 2024-09-06 14:57:08 +00:00
Pierre Ståhl
b50d8fca16 Bump pyatv to 0.15.1 (#125412) 2024-09-06 14:57:02 +00:00
Paul Bottein
1c7c6d6592 Update frontend to 20240906.0 (#125409) 2024-09-06 14:57:01 +00:00
Marlon
5cf89bf2bb Set min_power similar to max_power to support all inverters from apsystems (#124247)
Set min_power similar to max_power to support all inverters from apsystems ez1 series
2024-09-06 14:57:00 +00:00
TimL
0b95cf1251 Improve handling of old firmware versions (#125406)
* Update Info fixture with new fields from pysmlight 0.0.14

* Create repair if device is running unsupported firmware

* Add test for legacy firmware info

* Add strings for repair issue
2024-09-06 14:56:06 +00:00
Alexandre TRUPIN
a3f42e36ac Bump sfrbox-api to 0.0.10 (#125405)
* bump sfr_box requirement to 0.0.10

* upate manifest file

* Handle None values

---------

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2024-09-06 14:53:07 +00:00
Dave Leaver
973e43ae6a Fix controlling AC temperature in airtouch5 (#125394)
Fix controlling AC temperature
2024-09-06 14:53:06 +00:00
dontinelli
e80e189e6b Increase coordinator update_interval for fyta (#125393)
* Increase update_interval

* Update homeassistant/components/fyta/coordinator.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-09-06 14:53:05 +00:00
Andre Lengwenus
27dc2e1b9d Bump pypck to 0.7.22 (#125389) 2024-09-06 14:53:04 +00:00
TimL
edb7c76caa Bump pysmlight to 0.0.14 (#125387)
Bump pysmlight 0.0.14 for smlight
2024-09-06 14:53:03 +00:00
Ryan Mattson
7859d31ca0 Lyric: fixed missed snake case conversions (#125382)
fixed missed snake case conversions
2024-09-06 14:53:02 +00:00
Marcel van der Veldt
6c640d2abe Fix for Hue sending effect None at turn_on command while no effect is active (#125377)
* Fix for Hue sending effect None at turn_on command while no effect is active

* typo

* update tests
2024-09-06 14:53:01 +00:00
Erik Montnemery
61ee3a9412 Don't allow templating min, max, step in config entry template number (#125342) 2024-09-06 14:53:00 +00:00
Simon Lamon
4ed18495f3 Add follower to the PlayingMode enum (#125294)
Update media_player.py
2024-09-06 14:52:59 +00:00
Noah Husby
5c8b2cde92 Bump aiorussound to 3.0.4 (#125285)
feat: bump aiorussound to 3.0.4
2024-09-06 14:52:58 +00:00
Jordi
5c2073481d Increase AquaCell timeout and handle timeout exception properly (#125263)
* Increase timeout and add handling of timeout exception

* Raise update failed instead of config entry error
2024-09-06 14:52:57 +00:00
G Johansson
84c204a7b3 Don't show input panel if default code provided in envisalink (#125256) 2024-09-06 14:52:56 +00:00
G Johansson
6c15f251c6 Fix blocking call in yale_smart_alarm (#125255) 2024-09-06 14:52:56 +00:00
Joost Lekkerkerker
48fcf58eb9 Revert #122676 Yamaha discovery (#125216)
Revert Yamaha discovery
2024-09-06 14:52:55 +00:00
Simon Lamon
3c13f4b4cc Improve play media support in LinkPlay (#125205)
Improve play media support in linkplay
2024-09-06 14:52:54 +00:00
Shay Levy
a14826d75e Fix BTHome validate triggers for device with multiple buttons (#125183)
* Fix BTHome validate triggers for device with multiple buttons

* Remove None default
2024-09-06 14:52:53 +00:00
Bram Kragten
36ec1b33fe 2024.9.0 (#124880) 2024-09-04 17:41:08 +02:00
Bram Kragten
84a0a28be2 Bump version to 2024.9.0 2024-09-04 17:08:18 +02:00
Michael Hansen
ac19ee3e2e Bump intents to 2024.9.4 (#125232) 2024-09-04 17:07:21 +02:00
Denis Shulyaka
438af042ed Update Anthropic default model to Haiku (#125225) 2024-09-04 17:07:20 +02:00
Robert Resch
122f11c790 Update modified_at datetime on storage collection changes (#125218) 2024-09-04 17:07:19 +02:00
Bram Kragten
de99dfef4e Bump version to 2024.9.0b5 2024-09-04 11:48:24 +02:00
Robert Resch
bcdc3563a5 Bump deebot-client to 8.4.0 (#125207) 2024-09-04 11:48:16 +02:00
Bram Kragten
9ef0a1f0a2 Update frontend to 20240904.0 (#125206) 2024-09-04 11:48:15 +02:00
Matthias Alphart
d0629d4e66 Update knx-frontend to 2024.9.4.64538 (#125196) 2024-09-04 11:48:15 +02:00
G Johansson
65e98eab9c Bump python-holidays to 0.56 (#125182) 2024-09-04 11:48:14 +02:00
J. Nick Koston
a0d9764443 Bump yalexs to 8.6.3 (#125176)
Fixes the battery state not refreshing due to a refactoring
error in the library.

changelog: https://github.com/bdraco/yalexs/compare/v8.6.2...v8.6.3
2024-09-04 11:48:13 +02:00
Joakim Plate
8293f270df Update gardena_bluetooth dependency to 1.4.3 (#125175) 2024-09-04 11:48:12 +02:00
Bram Kragten
116090bff1 Bump version to 2024.9.0b4 2024-09-03 21:12:20 +02:00
J. Nick Koston
6082220f7f Bump yalexs to 8.6.2 (#125162)
changelog: https://github.com/bdraco/yalexs/compare/v8.6.0...v8.6.2
2024-09-03 21:11:30 +02:00
Paul Bottein
74fd16b953 Update frontend to 20240903.1 (#125160) 2024-09-03 21:11:30 +02:00
Andrew Jackson
82cffcbc23 Bump aiomealie to 0.9.2 (#125153)
Bump mealie version
2024-09-03 21:11:29 +02:00
Erik Montnemery
4e1a77326e Restore unnecessary assignment of Template.hass in event helper (#125143) 2024-09-03 21:11:28 +02:00
Bram Kragten
54cf52069e Log deprecation warning when template.Template is created without hass (#125142)
* Log deprecation warning when template.Template is created without hass

* Improve docstring
2024-09-03 21:09:12 +02:00
Erik Montnemery
70b811096c Log deprecation warning when cv.template is called from wrong thread (#125141)
Log deprecation warning when cv.template is called from wrong thread
2024-09-03 19:55:38 +02:00
Marcel van der Veldt
1efd267ee6 Fix energy sensor for ThirdReality Matter powerplug (#125140) 2024-09-03 19:55:38 +02:00
Christopher Fenner
31267b4095 Correct device serial for ViCare integration (#125125)
* expose correct serial

* adapt inits

* adjust _build_entities

* adapt inits

* add serial data point

* update snapshot

* apply suggestions

* apply suggestions
2024-09-03 19:55:37 +02:00
Steven B.
4982e1cbcf Pass hass clientsession to ring config flow (#125119)
Pass hass clientsession to ring config flow
2024-09-03 19:55:36 +02:00
Artur Pragacz
be3b16b7fa Fix Onkyo action select_hdmi_output (#125115)
* Fix Onkyo service select_hdmi_output

* Move Hasskey directly under Onkyo domain
2024-09-03 19:55:35 +02:00
Aaron Bach
393a0ac0df Fix unhandled exception with missing IQVIA data (#125114) 2024-09-03 19:55:35 +02:00
Michal Jál
a0bbcb0401 Bump PySwitchbot to 0.48.2 (#125113) 2024-09-03 19:55:34 +02:00
J. Nick Koston
3f65bc78e8 Bump yalexs to 8.6.0 (#125102) 2024-09-03 19:55:33 +02:00
Avi Miller
d005440544 Bump aiolifx to 1.0.9 and remove unused HomeKit model prefixes (#125055)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-09-03 19:55:32 +02:00
Artur Pragacz
94d2da1685 Fix area registry indexing when there is a name collision (#125050) 2024-09-03 19:55:31 +02:00
ilan
4c5ba0617a Bump py-madvr2 to 1.6.32 (#125049)
feat: update lib
2024-09-03 19:55:31 +02:00
Richard Kroegel
a58bf149fc Fix blocking calls for OpenAI conversation (#125010) 2024-09-03 19:55:30 +02:00
MJJ
005be4e8ba Increase timeout for fetching buienradar weather data (#124597)
Increase timeout for fetching weather data
2024-09-03 19:55:29 +02:00
Allen Porter
b81d7a0ed8 Update nest to only include the image attachment payload for cameras that support fetching media (#124590)
Only include the image attachment payload for cameras that support fetching media
2024-09-03 19:55:28 +02:00
Martin Hjelmare
9a690ed421 Handle telegram polling errors (#124327) 2024-09-03 19:55:27 +02:00
Philip Vanloo
009989d7ae Add Linkplay mTLS/HTTPS and improve logging (#124307)
* Work

* Implement 0.0.8 changes, fixup tests

* Cleanup

* Implement new playmodes, close clientsession upon ha close

* Implement new playmodes, close clientsession upon ha close

* Add test for zeroconf bridge failure

* Bump 0.0.9
Address old comments in 113940

* Exact _async_register_default_clientsession_shutdown
2024-09-03 19:55:26 +02:00
UltimateGG
c7d1ad27f0 Fix updating insteon modem configuration while disconnected (#121918)
#121917 Fix updating insteon modem configuration while disconnected
2024-09-03 19:55:25 +02:00
Bram Kragten
3af11fb2b1 Bump version to 2024.9.0b3 2024-09-02 20:06:41 +02:00
Steven B.
c839cc1f15 Call async_write_ha_state after ring update (#125096)
Use async_write_ha_state after ring update
2024-09-02 20:06:21 +02:00
Paul Bottein
a0f2e2ebdd Update frontend to 20240902.0 (#125093) 2024-09-02 20:06:20 +02:00
dontinelli
d07e62b2f1 Bump fyta_cli to 0.6.6 (#125065) 2024-09-02 20:06:19 +02:00
tronikos
e7f957def2 Bump androidtvremote2 to 0.1.2 to fix blocking event loop when loading ssl certificate chain (#125061)
Bump androidtvremote2 to 0.1.2
2024-09-02 20:06:19 +02:00
Erik Montnemery
16ab57c9a6 Fix motionblinds_ble tests (#125060) 2024-09-02 20:06:18 +02:00
J. Nick Koston
1a67052cbd Bump habluetooth to 3.4.0 (#125058)
changelog: https://github.com/Bluetooth-Devices/habluetooth/compare/v3.3.2...v3.4.0
2024-09-02 20:06:17 +02:00
Erik Montnemery
f85a802ebd Don't raise when registering entity service with invalid schema (#125057)
* Don't raise when registering entity service with invalid schema

* Update homeassistant/helpers/service.py

Co-authored-by: Robert Resch <robert@resch.dev>

---------

Co-authored-by: Robert Resch <robert@resch.dev>
2024-09-02 20:06:16 +02:00
Shay Levy
3b5c08ecf8 Bump aioshelly to 11.4.2 (#125036) 2024-09-02 20:06:16 +02:00
J. Nick Koston
450c63ad28 Bump yarl to 1.9.7 (#125035) 2024-09-02 20:06:15 +02:00
Michael
a8f472f44e Add diagnostics platform to modern forms (#125032) 2024-09-02 20:06:14 +02:00
dontinelli
fa3a301e97 Add ConductivityConverter in websocket_api.py (#125029) 2024-09-02 20:06:13 +02:00
Martin Hjelmare
b1ef1be9a3 Bump python-telegram-bot to 21.5 (#125025) 2024-09-02 20:06:12 +02:00
Joost Lekkerkerker
62ef951ace Bump aiomealie to 0.9.1 (#125017) 2024-09-02 20:06:12 +02:00
Richard Kroegel
06660f9170 Fix BMW client blocking on load_default_certs (#125015)
* Fix BMW client blocking load_default_certs

* Use get_default_context
2024-09-02 20:06:11 +02:00
Richard Kroegel
7662ca8a96 Fix telegram_bot blocking on load_default_certs (#125014)
* Fix telegram_bot blocking on load_default_certs

* Use sync variant of create_issue
2024-09-02 20:06:10 +02:00
Richard Kroegel
e04fc74fcf Fix ollama blocking on load_default_certs (#125012)
* Fix ollama blocking on load_default_certs

* Use get_default_context instead of client_context
2024-09-02 20:06:09 +02:00
Alan Murray
f9bca7619c Bump aiopulse to 0.4.6 (#124964)
Non-breaking changes to fix isses:
 * eliminating hub exceptions raised due use of unicode strings.
 * eliminating hub exceptions raised due to Timers being configured on hub.
2024-09-02 20:06:08 +02:00
J. Nick Koston
1b9aa727f8 Bump yarl to 1.9.6 (#124955)
* Bump yarl to 1.9.5

changelog: https://github.com/aio-libs/yarl/compare/v1.9.4...v1.9.5

* remove default port since mocker does exact matching and yarl now normalizes this

* 1.9.6
2024-09-02 20:06:07 +02:00
Joost Lekkerkerker
d54c1935f8 Define household support in Mealie (#124950) 2024-09-02 20:06:07 +02:00
Steven B.
9cfad05793 Exclude tplink firmware entities (#124935)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-09-02 20:06:06 +02:00
Steven B.
03ab471d23 Bump python-kasa to 0.7.2 (#124930) 2024-09-02 20:06:05 +02:00
Joost Lekkerkerker
b2b69e40fd Make set_value required in number template (#124917)
* Make set_value required in number template

* Make set_value required in number template

* Fix tests
2024-09-02 20:06:04 +02:00
J. Nick Koston
c6ff445dd4 Bump aioshelly to 11.4.1 to accomodate shelly GetStatus calls that take a few seconds to respond (#124893)
Co-authored-by: Shay Levy <levyshay1@gmail.com>
2024-09-02 20:06:03 +02:00
vhkristof
0948a94409 Bump renault-api to v0.2.7 (#124858)
* Bump renault-api to v0.2.7

* Updated requirements_all and requirements_test_all
2024-09-02 20:06:02 +02:00
J. Nick Koston
9be20d6130 Restore sisyphus integration (#124749)
* Revert "Disable sisyphus integration (#124742)"

This reverts commit 1b304e60d9.

* Restore sisyphus integration

reverts #124742 and updates the lib instead

changelog: https://github.com/jkeljo/sisyphus-control/compare/v3.1.3...v3.1.4

release is pending: https://github.com/jkeljo/sisyphus-control/pull/8#issuecomment-2313893689
2024-09-02 20:06:01 +02:00
Etienne Soufflet
c4e484539d Fix Tado fan speed for AC (#122415)
* change capabilities

* fix tests 2

* improve usability with capabilities

* fix swings management

* Update homeassistant/components/tado/climate.py

Co-authored-by: Erwin Douna <e.douna@gmail.com>

* fix after Erwin's review

* fix after joostlek's review

* use constant

* use in instead of get

---------

Co-authored-by: Erwin Douna <e.douna@gmail.com>
2024-09-02 20:06:00 +02:00
Jeef
234f32265e Bump Intellifire to 4.1.9 (#121091)
* rebase

* Minor patch to fix duplicate DeviceInfo beign created - if data hasnt updated yet

* rebase

* Minor patch to fix duplicate DeviceInfo beign created - if data hasnt updated yet

* fixing formatting

* Update homeassistant/components/intellifire/__init__.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Update homeassistant/components/intellifire/__init__.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Removing cloud connectivity sensor - leaving local one in

* Renaming class to something more useful

* addressing pr

* Update homeassistant/components/intellifire/__init__.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* add ruff exception

* Fix test annotations

* remove access to private variable

* Bumping to 4.1.9 instead of 4.1.5

* A renaming

* rename

* Updated testing

* Update __init__.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* updateing styrings

* Update tests/components/intellifire/conftest.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Testing refactor - WIP

* everything is passing - cleanup still needed

* cleaning up comments

* update pr

* unrename

* Update homeassistant/components/intellifire/coordinator.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* fixing sentence

* fixed fixture and removed error codes

* reverted a bad change

* fixing strings.json

* revert renaming

* fix

* typing inother pr

* adding extra tests - one has a really dumb name

* using a real value

* added a migration in

* Update homeassistant/components/intellifire/config_flow.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update tests/components/intellifire/test_init.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* cleanup continues

* addressing pr

* switch back to debug

* Update tests/components/intellifire/conftest.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* some changes

* restore property mock cuase didnt work otherwise

* cleanup has begun

* removed extra text

* addressing pr stuff

* fixed reauth

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-09-02 20:05:59 +02:00
Bram Kragten
411b014da2 Bump version to 2024.9.0b2 2024-08-30 20:08:46 +02:00
Joost Lekkerkerker
3a8aa4200d Bump aiomealie to 0.9.0 (#124924)
* Bump aiomealie to 0.9.0

* Bump aiomealie to 0.9.0
2024-08-30 20:08:20 +02:00
Josef Zweck
dd8471e786 Bump lmcloud 1.2.2 (#124911)
bump lmcloud 1.2.2
2024-08-30 20:08:19 +02:00
Josef Zweck
f33b4b0dc0 Bump lmcloud to 1.2.1 (#124908) 2024-08-30 20:08:19 +02:00
J. Nick Koston
8ab8f7a740 Add a repair issue for Yale Home users using the August integration (#124895)
The Yale Home brand will stop working with the August integration very
soon. Users must migrate to the Yale integration to avoid an interruption in service.
2024-08-30 20:08:18 +02:00
J. Nick Koston
ee9e3fe27b Bump yalexs to 8.5.5 (#124891)
changelog: https://github.com/bdraco/yalexs/compare/v8.5.4...v8.5.5
2024-08-30 20:08:17 +02:00
J. Nick Koston
d4830caac0 Bump aioesphomeapi to 25.3.1 (#124890)
changelog: https://github.com/esphome/aioesphomeapi/compare/v25.2.1...v25.3.1
2024-08-30 20:08:16 +02:00
TheJulianJES
3b4e3b1370 Fix ZHA group removal entity registry cleanup (#124889)
* Fix ZHA cleanup entity registry parameter

* Fix missing `gateway` when accessing coordinator device

* Get `ZHADeviceProxy` for coordinator device
2024-08-30 20:08:15 +02:00
J. Nick Koston
533c8ca31c Address yale review comments part 2 (#124887)
* Remove some unneeded block till done

* Additional state check cleanups and snapshots

* Use more snapshots in yale tests
2024-08-30 20:08:15 +02:00
Michael Hansen
8668af17f6 Bump intents to 2024.8.29 (#124874) 2024-08-30 20:08:14 +02:00
Louis Christ
5b866e071c Handle CancelledError in bluesound integration (#124873)
Catch CancledError in async_will_remove_from_hass
2024-08-30 20:08:13 +02:00
IceBotYT
37af180edc Bump nice-go to 0.3.8 (#124872)
* Bump nice-go to 0.3.6

* Bump to 0.3.7

* Bump to 0.3.8
2024-08-30 20:08:13 +02:00
Robert Resch
0d5dc01048 Bump PyTurboJPEG to 1.7.5 (#124865) 2024-08-30 20:08:12 +02:00
Robert Resch
bd2be0a763 Optimize hassfest image (#124855)
* Optimize hassfest docker image

* Adjust CI

* Use dynamic uv version

* Remove workaround
2024-08-30 20:08:11 +02:00
J. Nick Koston
98cbd7d8da Address august review comments (#124819)
* Address august review comments

Followup to https://github.com/home-assistant/core/pull/124677

* cleanup loop

* drop mixin name

* event entity add cleanup

* remove duplicate prop

* pep0695 type

* remove some not needed block till done

* cleanup august tests

* switch to freezegun

* snapshots for dev reg

* SOURCE_USER nit

* snapshots

* pytest.raises

* not loaded check
2024-08-30 20:08:10 +02:00
puddly
26f3305743 Bump ZHA to 0.0.32 (#124804)
* Always prefer XY color mode in ZHA

Remove a few more HS remnants

* Use new ZHA OTA format

* Bump ZHA to 0.0.32

* Fix existing OTA unit tests

* Fix schema conversion test to account for new command parameters

* Update snapshot with new `zcl_type` kwarg

* Migrate existing entities to icon translations

* Remove "no longer compatible" test

* Test that the library release summary is correctly exposed to ZHA

* Revert "Always prefer XY color mode in ZHA"

This reverts commit 8fb7789ea8.

* Test `release_notes`, not `release_summary`
2024-08-30 20:08:10 +02:00
tronikos
3c0480596d Attempt to fix IndexError in Opower (#124478)
* Change the order of async_add_external_statistics in Opower

* Use consumption_statistic_id instead of cost_statistic_id
2024-08-30 20:08:09 +02:00
Jeef
81d2231e6f Bump weatherflow4py to 0.2.23 (#124072)
patch weatherflow for new data
2024-08-30 20:08:08 +02:00
Tony
2d041a1fa9 Bump aioruckus to v0.41 removing blocking call to load_default_certs from ruckus_unleashed integration (#123974)
* fix ruckusd_unleashed blocking call to load_default_certs

* remove extra loggers, bump aioruckus ver for debian packagers
2024-08-30 20:08:07 +02:00
Bram Kragten
03a02fa565 Bump version to 2024.9.0b1 2024-08-29 17:31:37 +02:00
Bram Kragten
b2f27a4519 Update frontend to 20240829.0 (#124864) 2024-08-29 17:28:06 +02:00
Joost Lekkerkerker
b906a1b521 Add missing translation key in Knocki (#124862) 2024-08-29 17:28:06 +02:00
Fredrik Erlandsson
754e4255b6 Bump pydaikin to 2.13.6 (#124852) 2024-08-29 17:28:05 +02:00
Andrew Jackson
ff39f09c4e Fix Mastodon migrate config entry log warning (#124848)
Fix migrate config entry
2024-08-29 17:28:04 +02:00
AutonomousOwl
3078b47d06 Update utility_account_id in Opower to be lowercase in statistic id (#124837)
Update utility_account_id to be lowercase in statistic id
2024-08-29 17:28:03 +02:00
J. Nick Koston
71de50dae8 Add missing dependencies to yale (#124821)
* Add missing dependencies to yale

* try another way

* Revert "try another way"

This reverts commit fbb731a334.

* patch out cloud setup
2024-08-29 17:28:03 +02:00
J. Nick Koston
e8b722f7b2 Redirect virtual integration yale_home to point to yale (#124817) 2024-08-29 17:28:02 +02:00
Pete Sage
a2053d073f Fix sonos get_queue service call to restrict to sonos media_player entities (#124815)
add sonos to filter
2024-08-29 17:28:01 +02:00
J. Nick Koston
aa72b08c16 Address yale review comments (#124810)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-29 17:28:00 +02:00
Fredrik Erlandsson
66480da218 Bump pydaikin to 2.13.5 (#124802)
bump pydaikin version
2024-08-29 17:27:59 +02:00
Tobias Sauerwein
3b214f6610 Bump pyatmo to 8.1.0 (#124340) 2024-08-29 17:27:59 +02:00
Bram Kragten
1e035064f4 2024.9.0b0: It's beta time (#124807) 2024-08-28 19:02:42 +02:00
Robert Resch
2856525c12 Bump version to 2024.9.0b0 2024-08-28 16:40:52 +00:00
Robert Resch
22cfb7059a Merge remote-tracking branch 'origin/rc' into edenhaus-2024.9.0b0 2024-08-28 16:36:20 +00:00
Matthias Alphart
1650cee16c Check KNX integration is loaded on websocket calls (#123178) 2024-08-28 18:10:38 +02:00
Kristian Haugene
25cdd737a9 Add current intraday price ranking to Tibber price sensor (#124595) 2024-08-28 18:05:27 +02:00
Sid
9153d16a6d Enable Ruff TCH rules (#124396)
* Enable Ruff TCH rules

* Ignore TCH001-003

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2024-08-28 18:01:41 +02:00
J. Nick Koston
03ead27f6c Split august and yale integrations (#124677)
* Split august and yale integrations [part 1] (#122253)

* merge with dev

* Remove unused constant

* Remove yale IPv6 workaround (#123409)

* Convert yale to use oauth (#123806)

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update yale for switch from pubnub to websockets (#124675)

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-28 17:46:03 +02:00
epenet
edad766fd3 Use start_reauth helper method in integration tests (u-z) (#124796) 2024-08-28 16:51:16 +02:00
epenet
9bcc31a9fe Use start_reauth helper method in integration tests (s) (#124793) 2024-08-28 16:49:05 +02:00
epenet
7652c35ee6 Use start_reauth helper method in integration tests (t) (#124794) 2024-08-28 16:47:10 +02:00
G Johansson
dd52f4c84a Remove deprecated mailbox platform (#123740)
* Remove deprecated mailbox platform

* Remove from const

* Remove from type hints

* Remove from pyproject
2024-08-28 16:41:23 +02:00
Robert Resch
45bb2cdd82 Build hassfest docker image and pushlish it on beta/stable releases (#124706) 2024-08-28 16:38:12 +02:00
Paul Bottein
a4bfb0e92c Update frontend to 20240828.0 (#124791) 2024-08-28 16:35:44 +02:00
epenet
26006f8036 Use start_reauth helper method in broadlink and bthome (#124783)
* Use start_reauth helper method in broadlink reauth tests

* Also include bthome
2024-08-28 16:34:09 +02:00
epenet
ef4caa951c Use start_reauth helper method in integration tests (p-r) (#124792) 2024-08-28 16:20:47 +02:00
Pete Sage
5824d06fd7 Add get_queue action for Sonos (#124707)
* initial commit

* use constants

* use constants

* update typing

* add queue fixture

* remove blank line

* update docstring

* update icons

* use list comprehension
2024-08-28 16:19:48 +02:00
epenet
57a73d1b1b Use start_reauth helper method in integration tests (m-o) (#124790) 2024-08-28 16:19:31 +02:00
Aidan Timson
731aaaafe2 Update aioazuredevops to 2.2.1 (#124788)
* Update aioazuredevops to 2.2.1

* Update test
2024-08-28 16:01:32 +02:00
epenet
bdd3aa8e39 Use start_reauth helper method in config flow tests (a-d) (#124780)
* Use start_reauth helper method in integration tests (a-d)

* Revert broadlink

* Revert bthome
2024-08-28 15:48:36 +02:00
epenet
99335a07e5 Use start_reauth helper method in integration tests (e-g) (#124785)
* Use start_reauth helper method in integration tests (e-g)

* Include fireservicerota
2024-08-28 15:47:57 +02:00
epenet
9d633f2087 Use start_reauth helper method in integration tests (h-l) (#124787) 2024-08-28 15:47:35 +02:00
Erik Montnemery
174f22aa2f Prevent nesting sections in data entry flows (#124645) 2024-08-28 15:42:15 +02:00
Brett Adams
e39b3796f3 Fix OAuth reauth in Tesla Fleet (#124744)
* Fix auth failure

* Test

* Fix test

* Only reauth on 401

* Cover 401 and others

* Update homeassistant/components/tesla_fleet/strings.json

Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>

---------

Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>
2024-08-28 14:58:16 +02:00
Michael
11370979e5 Fix translation for AVM Fritz!Box Tools (#124784)
add missing ssl option to strings
2024-08-28 14:54:30 +02:00
Erik Montnemery
0afae45bc5 Trigger full CI run on Blueprint integration changes (#124778) 2024-08-28 14:27:01 +02:00
Matrix
f8ac952cd7 Add YoLink lock V2 support (#124202)
* Add Lock V2 Support

* Change as suggestions
2024-08-28 14:18:55 +02:00
Erik Montnemery
c4e5d67551 Enforce new service icon schema for core integrations (#124772)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2024-08-28 14:14:45 +02:00
Erik Montnemery
cff4e46694 Deduplicate TTS mocks (#124773) 2024-08-28 13:48:49 +02:00
Erik Montnemery
38ef216894 Update icons.json to new service schema part 4 (#124771) 2024-08-28 13:48:13 +02:00
Erik Montnemery
1a2d013c97 Update icons.json to new service schema part 3 (#124770) 2024-08-28 13:48:01 +02:00
Erik Montnemery
cffa8b4feb Update icons.json to new service schema part 2 (#124769) 2024-08-28 13:47:41 +02:00
Erik Montnemery
fce2e21c9f Update icons.json to new service schema part 1 (#124768) 2024-08-28 13:47:02 +02:00
epenet
a0ffa69b49 Standardize reauth step variable name in aseko_pool_live (#124765) 2024-08-28 13:29:18 +02:00
epenet
a0089685dd Simplify aussie_broadband reauth flow (#124774)
* Simplify aussie_broadband config flow

* Apply suggestions from code review

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update config_flow.py

* Update config_flow.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-28 13:19:58 +02:00
Matthias Alphart
633ff0ea42 Handle KNX expose conversion exceptions and unavailable states (#124776) 2024-08-28 13:14:34 +02:00
epenet
163795e73a Use reauth_confirm in weatherflow_cloud (#124761) 2024-08-28 13:09:45 +02:00
epenet
45eebf3285 Use reauth_confirm in sharkiq (#124762) 2024-08-28 13:09:21 +02:00
epenet
14eec2e57a Add start_reauth helper method to MockConfigEntry (#124767)
* Add start_reauth helper method to MockConfigEntry

* Two more
2024-08-28 13:08:26 +02:00
epenet
274d98f4d7 Standardize reauth step variable name in permobil (#124764) 2024-08-28 13:02:21 +02:00
epenet
51a5a78eb5 Standardize reauth step variable name in config flows (#124760) 2024-08-28 13:01:00 +02:00
epenet
d4ae592a85 Improve config flow type hints in sms (#124352)
* Improve config flow type hints in sms

* Drop async_step_import
2024-08-28 13:00:30 +02:00
epenet
8ff8ed7f76 Cleanup unused import in upb config flow (#124694)
* Cleanup unused import in upb config flow

* More cleanup
2024-08-28 13:00:10 +02:00
epenet
18b49a6f62 Cleanup unused import in solarlog config flow (#124713) 2024-08-28 12:59:53 +02:00
epenet
35d318818a Improve config flow type hints in sense (#124350) 2024-08-28 12:59:12 +02:00
epenet
0a94242337 Improve config flow type hints in vesync (#124351) 2024-08-28 12:56:22 +02:00
starkillerOG
d1681fac72 Improve mediabrowser names for DUO lens Reolink cameras (#124766)
* Improve playback of DUO lens cameras like TrackMix

* fix styling

* Adjust tests accordingly
2024-08-28 12:54:30 +02:00
Matthias Alphart
8504a16e83 Use KNX group address format from project (#124084) 2024-08-28 12:34:28 +02:00
Matthias Alphart
41e66edd14 Set default name for KNX outgoing telegram source (#124439) 2024-08-28 12:31:30 +02:00
starkillerOG
10b3119b4a Use Position instead of Angle for TiltOnlyDevice in motion blinds (#123521)
Use Position instead of Angle for TiltOnlyBlinds
2024-08-28 11:27:34 +02:00
Erik Montnemery
c772c4a2d5 Allow specifying icons for service sections (#124656)
* Allow specifying icons for service sections

* Improve kitchen_sink example
2024-08-28 11:15:26 +02:00
starkillerOG
e9830f0835 Bump reolink_aio to 0.9.8 (#124763) 2024-08-28 11:13:37 +02:00
epenet
bcc66c9a86 Standardize import step variable name (part 5) (#124698)
* Standardize import step variable name (part 5)

* Revert point

* Adjust soma tests
2024-08-28 09:51:49 +02:00
epenet
1f3c99dff3 Standardize import step variable name in cert_expiry (#124696) 2024-08-28 09:51:25 +02:00
epenet
b085ac9296 Standardize import step variable name in geonetnz_volcano (#124699) 2024-08-28 09:48:17 +02:00
Erik Montnemery
1add00a68d Deduplicate STT mocks (#124754) 2024-08-28 09:25:56 +02:00
J. Nick Koston
f9bf7f7e05 Small cleanups to shelly (#124758) 2024-08-27 21:00:31 -10:00
J. Nick Koston
a63c5e6725 Cache shelly coordinator properties that never change (#124756) 2024-08-27 21:00:20 -10:00
Sergey Dudanov
4108b7ada6 Remove unused normalized units from unit converters (#122797)
remove unused normalized units in unit converters
2024-08-28 08:45:40 +02:00
J. Nick Koston
42388450e1 Restore control4 integration (#124750)
* Revert "Disable control4 integration (#124746)"

This reverts commit 16dd6b1712.

* Restore control4 integration

reverts #124746 and updates the lib instead

changelog: https://github.com/lawtancool/pyControl4/compare/v1.1.0...v1.1.3

Note that there is no release yet, see https://github.com/lawtancool/pyControl4/pull/32

* Apply suggestions from code review
2024-08-28 07:54:28 +02:00
Jan Bouwhuis
e720a14dc4 Cleanup removed schema option from mqtt vacuum platform (#124722) 2024-08-28 07:49:05 +02:00
J. Nick Koston
9d3895d69a Bump yalexs to 8.5.4 (#124672) 2024-08-27 15:36:00 -10:00
J. Nick Koston
16dd6b1712 Disable control4 integration (#124746) 2024-08-27 15:12:52 -10:00
functionpointer
e447d83024 Use ssl util in Tibber (#123369)
Tibber: Use homeassistant.util.ssl
2024-08-28 03:04:08 +02:00
Michael Hansen
8fee1975b4 Bump pyspeex-noise to 1.0.2 (#124721)
Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
2024-08-27 14:26:46 -10:00
puddly
3533ac163c Remove unnecessary assertion for the Yellow firmware type (#124747) 2024-08-28 01:57:08 +02:00
J. Nick Koston
1b304e60d9 Disable sisyphus integration (#124742) 2024-08-27 12:53:48 -10:00
J. Nick Koston
5bd17c9198 Bump aioshelly to 11.3.0 (#124741) 2024-08-27 12:34:30 -10:00
J. Nick Koston
136f0e423e Bump aioambient to 2024.08.0 (#124729) 2024-08-27 12:33:17 -10:00
Jesse Hills
e84d9e21f7 Handle single state requests from ESPHome (#124660)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-08-27 12:15:41 -10:00
J. Nick Koston
fa084143ef Bump dbus-fast to 2.24.0 (#124737)
changelog: https://github.com/Bluetooth-Devices/dbus-fast/compare/v2.23.0...v2.24.0
2024-08-27 23:58:11 +02:00
J. Nick Koston
ca17c70109 Remove socketio constraints (#124730)
We have been stuck on an old version of socketio for a few years
now due to https://github.com/jkeljo/sisyphus-control/issues/6 and
no solution has been reached.

The constraint is blocking any integration from using socketio 4.x servers as the old version
only supports socketio 3.x servers which have reached EOL (https://socket.io/docs/v3/)
2024-08-27 23:42:42 +02:00
puddly
5818e2c2d4 Yellow firmware selection options flow (#122868)
* Implement Yellow config flow for firmware selection

* Use the probed firmware type when setting up Yellow

* Add translation strings

* Ensure (most) existing `init` tests pass

* Remove multi-PAN setup config flow unit tests

* Get existing config flow unit tests passing

* Add unit tests for uninstalling multi-PAN and such

* Consolidate entity creation for Yellow and clean up steps

* Be explicit with multiple inheritance overrides

* Address review comments
2024-08-27 23:14:41 +02:00
Shay Levy
467749eb57 Fix Shelly sleepy RPC setup if device is already awake (#124734) 2024-08-27 10:48:13 -10:00
Jan Bouwhuis
dd0c353afb Fix nice_go integration tests (#124736) 2024-08-27 10:28:54 -10:00
IceBotYT
9e762fa222 Bump Nice G.O. to 0.3.5 (#124667)
* Bump Nice G.O. to 0.3.1

* Bump to 0.3.5
2024-08-27 19:53:00 +02:00
Michael
ea04269c49 Improve test coverage for nextcloud (#123148)
* add first data driven tests

* remove unused mock

* test unique_id migration

* test errors during setup

* test error during data update

* test update entity

* system_versionis always available

* make use of snapshot_platform helper

* use parametrize test for coordinator update errors

* apply suggestions

* don't touch internals on coordinator tests

* rework to use async_get_or_create instead of mock_registry
2024-08-27 19:48:39 +02:00
Erik Montnemery
e2d84f9a58 Add support for multiple otbr config entries (#124289)
* Add support for multiple otbr config entries

* Fix test

* Drop useless fixture

* Address review comments

* Change unique id from xa to id

* Improve error text

* Store data in ConfigEntry.runtime_data

* Remove useless function
2024-08-27 19:07:35 +02:00
Erik Montnemery
52b6f00363 Adjust name of Google Translate TTS provider (#124688) 2024-08-27 19:07:04 +02:00
Erik Montnemery
55c42fde88 Improve validation of entity service schemas (#124102)
* Improve validation of entity service schemas

* Update tests/helpers/test_entity_platform.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-27 19:05:49 +02:00
epenet
0dc1eb8757 Cleanup unused import in zwave_js config flow (#124716) 2024-08-27 18:41:27 +02:00
Paulus Schoutsen
1936aeccb9 Add a test for async_converse (#124697) 2024-08-27 11:01:00 -05:00
epenet
c1c158c0aa Adjust docstring in airvisual_pro config flow (#124712) 2024-08-27 16:48:04 +02:00
epenet
bcfc7ea481 Cleanup unused import in google config flow (#124711) 2024-08-27 07:36:07 -07:00
Antoine Reversat
de8bbaadd1 Fix review comments in fglair (#124710)
* Replace if len() == 0 with if not

* Replace list + filter with list comprehensions

* Move consts that are only used in one module to said module
2024-08-27 16:26:18 +02:00
epenet
318259689f Standardize import step variable name (part 4) (#124692)
* Standardize import step variable name (part 4)

* One more

* Revert geonetnz_volcano

* Revert SMS due to coverage

* Revert somfy_mylink due to coverage
2024-08-27 16:18:11 +02:00
epenet
f802611359 Cleanup unused import in somfy_mylink config flow (#124709) 2024-08-27 16:04:00 +02:00
Erik Montnemery
53479b5924 Adjust name of legacy Home Assistant Cloud TTS provider (#124685) 2024-08-27 15:13:58 +02:00
Erik Montnemery
9cae786f40 Add ConfigEntries.async_get_loaded (#124705) 2024-08-27 14:20:57 +02:00
functionpointer
48292beec8 Update pyTibber to 0.30.1 (#124407)
Update to pyTibber==0.30.1
2024-08-27 13:19:15 +02:00
Matrix
a45ba51f89 Update YoLink FlexFob Automation (#123631)
* Change FlexFob Trigger

* Update device trigger tests
2024-08-27 13:17:14 +02:00
Jon Seager
9119884e53 Add touchlinesl integration (#124557)
* touchlinesl: init integration

* integration(touchlinesl): address review feedback

* integration(touchlinesl): address review feedback

* integration(touchlinesl): add a coordinator to manage data updates

* integration(touchlinesl): address review feedback

* integration(touchline_sl): address feedback (and rename)

* integration(touchline_sl): address feedback

* integration(touchline_sl): address feedback

* integration(touchline_sl): update strings

* integration(touchline_sl): address feedback

* integration(touchline_sl): address feedback
2024-08-27 13:15:31 +02:00
Matrix
37e2839fa3 Add power entity for yolink plug (#124678)
* Add Plug power entity

* change state class to total

* Add translations and moving icon to icon.json

* sort translation key

* Fix suggestions
2024-08-27 12:03:50 +02:00
epenet
6b0428774d Standardize import step variable name (part 2) (#124679) 2024-08-27 11:22:35 +02:00
J. Nick Koston
0d2f22838a Reduce complexity of _sorted_statistics_to_dict (#123936)
* comp stats queries

* tweak

* reduce
2024-08-27 11:22:10 +02:00
J. Nick Koston
4bc19876ca Small speed up to creating stats database rows (#124587)
* Small speed up to creating stats database rows

Calling .timestamp() directly is faster on new cpython

* more cleanup
2024-08-27 11:18:12 +02:00
J. Nick Koston
902d76da36 Small cleanup to normalize states (#124614)
- Remove duplicate state_unit lookup
- Use undefined instead of object
2024-08-27 11:17:34 +02:00
J. Nick Koston
d8161c431f Add support for using an entityfilter to subscribe_entities (#124641)
* Add support for using an entityfilter to subscribe_entities

* filter init

* fix

* coverage
2024-08-27 11:17:05 +02:00
J. Nick Koston
68d6f1c1aa Bump zeroconf to 0.133.0 (#124673)
changelog: https://github.com/python-zeroconf/python-zeroconf/compare/0.132.2...0.133.0
2024-08-27 11:15:00 +02:00
Erik Montnemery
ef1d53c207 Include engine name in TTS WS responses (#124683) 2024-08-27 11:14:41 +02:00
Erik Montnemery
823b62d8ab Include engine name in STT WS responses (#124684) 2024-08-27 11:14:17 +02:00
epenet
dece7e0f9c Cleanup unused import in proximity config flow (#124681)
* Cleanup unused import in proximity config flow

* Cleanup tests
2024-08-27 11:08:33 +02:00
epenet
68cdf8877c Standardize import step variable name (part 3) (#124680) 2024-08-27 10:50:13 +02:00
epenet
831a1d7ad1 Standardize import step variable name (part 1) (#124674) 2024-08-27 10:34:47 +02:00
Erik Montnemery
715f4bd2c3 Set deprecated flag on TTS engines replaced by entities in WS list (#124676) 2024-08-27 10:09:49 +02:00
Yuxin Wang
74a12bb802 Replace LASTSTEST with LAST_S_TEST (#124668) 2024-08-27 06:50:15 +02:00
Ståle Storø Hauknes
51fd8e1288 Bump airthings-ble to 0.9.1 (#124658) 2024-08-26 13:59:28 -10:00
Richard Kroegel
2fe19c04b9 Bump bimmer_connected to 0.16.2 (#124651) 2024-08-26 13:57:25 -10:00
Jesse Hills
37019d33fd Bump aioesphomeapi to 25.2.1 (#124659) 2024-08-26 12:29:54 -10:00
Alexey ALERT Rubashёff
0fe939cd7c Update overkiz Atlantic Water Heater operation mode switching (#124619)
* conventional operation state usage

* MartinHjelmare indentation request

* Manual Mode binary sensor

* Removed usage of unconventional operation states

* Removed usage of unconventional operation state

* STATE_OFF operation mode support
2024-08-26 21:31:07 +02:00
Maciej Bieniek
b960ebeb8b Add WS outbound config to Shelly diagnostics (#124654)
Add WS Outbound config to diagnostics
2024-08-26 22:17:38 +03:00
starkillerOG
7334fb0125 Add Reolink chime play action (#123245)
* Add chime play service

* fix supported_feature

* finalize

* add tests

* Adjust to device service

* fix issue

* Add tests

* actions -> services

* fix styling

* Use conftest fixture for test_chime

* Update tests/components/reolink/test_services.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* use ATTR_RINGTONE and rename chime_play to play_chime

* Add translatable exceptions

* fix styling

* Remove option to use entity_id

* fixes

* Fix translations

* fix

* fix translation key

* remove translation key

* use callback for async_setup_services

* fix styling

* Add test_play_chime_service_unloaded

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-26 21:12:32 +02:00
Maciej Bieniek
d8fe3c5377 Add missing units for xpercent, xfreq and xcounts Shelly sensors (#124288) 2024-08-26 08:59:18 -10:00
J. Nick Koston
76182c246d Auto configure outbound websocket for sleepy shelly RPC devices (#124545) 2024-08-26 08:37:36 -10:00
Erik Montnemery
b9aaba0432 Prevent duplicating constraints during schema migration (#124616) 2024-08-26 08:35:54 -10:00
Paulus Schoutsen
156948c496 Fix defaults for cloud STT/TTS (#121229)
* Fix defaults for cloud STT/TTS

* Prefer entity over legacy provider

* Remove unrealistic tests

* Add tests which show cloud stt/tts entity is preferred

---------

Co-authored-by: Erik <erik@montnemery.com>
2024-08-26 19:39:09 +02:00
ilan
547dbf77aa Use runtime data instead of hass.data in jvc projector (#124608)
* feat: use runtime data instead of hass.data

* fix: extend ConfigEntry
2024-08-26 19:26:53 +02:00
Erik Montnemery
a68cd712c6 Move data entry section translations (#124648) 2024-08-26 18:45:28 +02:00
Maciej Bieniek
9e7aeed848 Bump nextdns to version 3.2.0 (#124646) 2024-08-26 18:25:10 +02:00
Álvaro Fernández Rojas
95fa123a0b Add Airzone main zone mode select (#124566)
* airzone: select: add zone master mode

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

* airzone: select: use MAIN instead of MASTER

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

* airzone: select: call async_add_entities once

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

* airzone: select: add options lambda function

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

* airzone: select: implement requested changes

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

* airzone: select: options_fn: return list

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

---------

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-08-26 17:57:31 +02:00
WebSpider
657ff58500 Fix device class for motion_light blueprint (#124495)
* Fix device class for motion_light blueprint.
Fixes #124353

* Update to accept both motion and occupancy
2024-08-26 17:39:27 +02:00
Jan Bouwhuis
ff029e5efc Cleanup not used data field for mqtt hassio config flow confirm step (#124486) 2024-08-26 17:33:47 +02:00
Erik Montnemery
f4528b288f Fix overriding name in MockTTSEntity (#124639)
* Fix overriding name in MockTTSEntity

* Fix
2024-08-26 15:28:55 +02:00
Paulus Schoutsen
1aa0dbdaf5 Revert "Revert "Use speex for noise suppression and auto gain"" (#124637)
Revert "Revert "Use speex for noise suppression and auto gain" (#124620)"

This reverts commit 302ffe5e56.
2024-08-26 15:10:43 +02:00
J. Nick Koston
743df84569 Reduce multiple calls to calculate sensor unit in tplink (#124606)
accessing unit on the feature is not cached and it had
to be looked up every time
2024-08-26 13:49:26 +02:00
J. Nick Koston
16231da5ef Bump cached-ipaddress to 0.5.0 (#124602)
changelog: https://github.com/bdraco/cached-ipaddress/compare/v0.3.0...v0.5.0
2024-08-26 13:48:52 +02:00
Erik Montnemery
7b71f024fb Prefer stt entity over legacy stt provider (#124625)
* Prefer stt entity over legacy stt provider

* Update assist_pipeline tests
2024-08-26 13:43:14 +02:00
darkfader
0a05cdc381 Add conductivity sensor to bthome (#124312)
* Add conductivity sensor to bthome

* Update icons.json

* Update sensor.py
2024-08-26 13:40:40 +02:00
dependabot[bot]
106559371c Bump github/codeql-action from 3.26.4 to 3.26.5 (#124615)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.4 to 3.26.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.4...v3.26.5)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 13:33:55 +02:00
Erik Montnemery
cafd953f87 Add test showing we prefer tts entity over legacy tts provider (#124624) 2024-08-26 11:10:58 +02:00
Andre Lengwenus
7ddd755acc Handle LCN entity instances only in corresponding platform (#124589)
* Handle switch entity instance only in switch platform

* Add other platforms
2024-08-26 10:17:51 +02:00
Paulus Schoutsen
302ffe5e56 Revert "Use speex for noise suppression and auto gain" (#124620)
Revert "Use speex for noise suppression and auto gain (#124591)"

This reverts commit 592f60643a.
2024-08-26 10:12:05 +02:00
Jan Bouwhuis
65216df3a5 Auto recover mqtt config entry secret if Mosquitto add-on was re-installed (#124514)
Auto recover mqtt config entry secret if Mosquitto add-on is re-installed
2024-08-26 09:40:25 +02:00
J. Nick Koston
76ebb0df08 Improve performance of generate diffs of state change events (#124601)
dict comps are inlined in cpython 3.12+
2024-08-26 08:49:31 +02:00
Christopher Fenner
0591b5e47b Improve code quality for ViCare integration (#124613)
* move type to module

* set translation key outside of init

* align import alias

* align constructor parameter order/naming

* move static attr init outside init function

* add missing types

* fix test

* revert move of _attributes
2024-08-26 08:30:28 +02:00
Yuxin Wang
bb6f9ec844 Set native value to be None instead of STATE_UNKNOWN for APCUPSD integration (#124609) 2024-08-25 19:09:37 -10:00
Michael Hansen
592f60643a Use speex for noise suppression and auto gain (#124591) 2024-08-25 23:50:32 -05:00
Brett Adams
3035588dfa Dont turn HVAC off with preset in Teslemetry (#124604)
Dont turn HVAC off with preset
2024-08-25 20:58:59 -07:00
J. Nick Koston
6e727a49bf Remove unused constant in dhcp (#124605) 2024-08-25 20:58:20 -07:00
Jeef
0dfe12840d Add SimpleFin binary sensor for errors (#122554)
* Binary Sensor Support

* updated requirements

* ng ambr

* update strings.json

* update snapshot
2024-08-25 20:57:57 -07:00
Jesse Hills
d915fee833 Bump aioesphomeapi to 25.2.0 (#124607) 2024-08-25 17:47:48 -10:00
J. Nick Koston
9ea41b4d26 Bump yalexs to 8.4.2 (#124593)
changelog: https://github.com/bdraco/yalexs/compare/v8.4.1...v8.4.2

If the pubnub connection failed, the integration would fallback
to polling. This would could get users banned so we no longer do that.
2024-08-25 23:45:06 +03:00
Pete Sage
8bc9fd23bb Add Sonos tests for announce and update error handling (#124539)
* initial commit

* update error message

* use match for error message
2024-08-25 21:25:20 +02:00
Allen Porter
18212052a4 Update nest events to include attachment image and video urls (#124554) 2024-08-25 21:24:06 +02:00
Allen Porter
3304e27fa3 Add ollama context window size configuration (#124555)
* Add ollama context window size configuration

* Set higher max context size
2024-08-25 21:22:57 +02:00
J. Nick Koston
be206156b0 Fix shelly sleepy entities never being created (#124547) 2024-08-25 09:21:23 -10:00
J. Nick Koston
0628f96713 Ensure all chars are polling when requesting manual update in homekit_controller (#124582)
related issue #123963
2024-08-25 21:21:15 +02:00
J. Nick Koston
41b129e990 Split esphome state property decorators (#124332) 2024-08-25 18:48:17 +02:00
epenet
ebc49d938a Improve config flow type hints (part 2) (#124344) 2024-08-25 18:36:44 +02:00
epenet
58b7711bdd Improve config flow type hints (part 3) (#124346) 2024-08-25 18:36:03 +02:00
epenet
909dfcc436 Improve config flow type hints (part 5) (#124349) 2024-08-25 18:34:39 +02:00
J. Nick Koston
70fc8fa2eb Improve performance of fetching stats metadata (#124428) 2024-08-25 18:33:21 +02:00
J. Nick Koston
242aae514e Small cleanups to list_statistic_ids (#124451) 2024-08-25 18:32:32 +02:00
dontinelli
d94b1e6e8a Add icons for conductivity (#124576) 2024-08-25 18:14:38 +02:00
Allen Porter
d18e81f932 Update a roborock blocking call to be fully async (#124266)
Remove a blocking call in roborock
2024-08-25 08:56:17 -07:00
Paulus Schoutsen
d3293336b1 Ensure write access to hassrelease data folder (#124573)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-08-25 17:24:06 +02:00
dontinelli
1eeb3bdcdf Bump fyta_cli to 0.6.3 (#124574) 2024-08-25 17:23:21 +02:00
Avi Miller
36bfd7b9ce Bump aiolifx to 1.0.8 to support LIFX B10 and T10 Candles (#124263)
Signed-off-by: Avi Miller <me@dje.li>
2024-08-25 07:15:51 -07:00
J. Nick Koston
f84a04e113 Bump ulid-transform to 1.0.2 (#124544)
changelog: https://github.com/bdraco/ulid-transform/compare/v0.13.1...v1.0.2

python 3.13 support added
python 3.10 support dropped
2024-08-25 07:13:40 -07:00
Paulus Schoutsen
516f3295bf 2024.8.3 (#124569) 2024-08-25 16:06:09 +02:00
J. Nick Koston
2d5289e7dd Revert "Exclude aiohappyeyeballs from license check" (#124116) 2024-08-25 13:41:47 +00:00
Paulus Schoutsen
18efd84a35 Bump version to 2024.8.3 2024-08-25 13:26:00 +00:00
Jan Bouwhuis
b34c90b189 Only support remote activity on Alexa if feature is set and at least one feature is in the activity_list (#124567)
Only support remote activity on Alexa if feaure is set and at least one feature is in the activity_list
2024-08-25 13:24:42 +00:00
Mr. Bubbles
a45c1a3914 Fix missing id in Habitica completed todos API response (#124565)
* Fix missing id in completed todos API response

* Copy id only if none

* Update homeassistant/components/habitica/coordinator.py

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

---------

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2024-08-25 13:24:42 +00:00
J. Nick Koston
1bdf9d657e Bump yalexs to 8.4.1 (#124553)
changelog: https://github.com/bdraco/yalexs/compare/v8.4.0...v8.4.1
2024-08-25 13:24:41 +00:00
J. Nick Koston
b294a92ad2 Bump yalexs to 8.4.0 (#124520) 2024-08-25 13:24:40 +00:00
J. Nick Koston
2db362ab3d Bump yalexs to 8.3.3 (#124492)
* Bump yalexs to 8.2.0

changelog: https://github.com/bdraco/yalexs/compare/v8.1.4...v8.2.0

* bump to 8.3.1

* bump

* one more bump to ensure we do not hit the ratelimit/shutdown cleanly

* empty commit to restart ci since close/open did not work in flight
2024-08-25 13:24:39 +00:00
Joost Lekkerkerker
5f275a6b9c Don't raise WLED user flow unique_id check (#124481) 2024-08-25 13:22:59 +00:00
Ino Dekker
fa914b2811 Bump aiohue to version 4.7.3 (#124436) 2024-08-25 13:22:58 +00:00
J. Nick Koston
a128e2e4fc Bump yalexs to 8.1.4 (#124425)
changelog: https://github.com/bdraco/yalexs/compare/v8.1.2...v8.1.4
2024-08-25 13:22:57 +00:00
Penny Wood
03c7f2cf5b Add supported features for iZone (#124416)
* Fix for #123462

* Set outside of constructor
2024-08-25 13:22:57 +00:00
Angel Nunez Mencias
102528e5d3 update ttn_client - fix crash with SenseCAP devices (#124370)
update ttn_client
2024-08-25 13:22:56 +00:00
Pete Sage
8f4af4f7c2 Fix Spotify Media Browsing fails for new config entries (#124368)
* initial commit

* tests

* tests

* update tests

* update tests

* update tests
2024-08-25 13:22:55 +00:00
karwosts
667af10017 Add missing strings for riemann options flow (#124317) 2024-08-25 13:22:54 +00:00
G Johansson
e5a64a1e0a Bump python-holidays to 0.55 (#124314) 2024-08-25 13:22:54 +00:00
G Johansson
236fa8e238 Bump python-holidays to 0.54 (#124170) 2024-08-25 13:22:53 +00:00
J. Nick Koston
70a58a0bb0 Bump yalexs to 8.1.2 (#124303) 2024-08-25 13:20:54 +00:00
Joost Lekkerkerker
769c7f1ea3 Don't abort airgradient user flow if flow in progress (#124300) 2024-08-25 13:20:53 +00:00
Marcel van der Veldt
5a8045d1fb Prevent KeyError when Matter device sends invalid value for StartUpOnOff (#124280) 2024-08-25 13:20:52 +00:00
Allen Porter
5a73b636e3 Bump python-roborock to 2.6.0 (#124268) 2024-08-25 13:20:51 +00:00
Matthias Alphart
524e09b45e Update xknx to 3.1.1 (#124257) 2024-08-25 13:20:51 +00:00
J. Nick Koston
1f46670266 Bump aiohttp to 3.10.5 (#124254) 2024-08-25 13:20:50 +00:00
Erik Montnemery
a857f603c8 Bump pyhomeworks to 1.1.2 (#124199) 2024-08-25 13:20:49 +00:00
J. Nick Koston
b7d8f3d005 Fix shelly available check when device is not initialized (#124182)
* Fix shelly available check when device is not initialized

available needs to check for device.initialized or if the device
is sleepy as calls to status will raise NotInitialized which results
in many unretrieved exceptions while writing state

fixes
```
2024-08-18 09:33:03.757 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved (None)
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 258, in _handle_refresh_interval
    await self._async_refresh(log_failures=True, scheduled=True)
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 453, in _async_refresh
    self.async_update_listeners()
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 168, in async_update_listeners
    update_callback()
  File "/config/custom_components/shelly/entity.py", line 374, in _update_callback
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1005, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1130, in _async_write_ha_state
    self.__async_calculate_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1067, in __async_calculate_state
    state = self._stringify_state(available)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1011, in _stringify_state
    if (state := self.state) is None:
                 ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/binary_sensor/__init__.py", line 293, in state
    if (is_on := self.is_on) is None:
                 ^^^^^^^^^^
  File "/config/custom_components/shelly/binary_sensor.py", line 331, in is_on
    return bool(self.attribute_value)
                ^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/shelly/entity.py", line 545, in attribute_value
    self._last_value = self.sub_status
                       ^^^^^^^^^^^^^^^
  File "/config/custom_components/shelly/entity.py", line 534, in sub_status
    return self.status[self.entity_description.sub_key]
           ^^^^^^^^^^^
  File "/config/custom_components/shelly/entity.py", line 364, in status
    return cast(dict, self.coordinator.device.status[self.key])
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aioshelly/rpc_device/device.py", line 390, in status
    raise NotInitialized
aioshelly.exceptions.NotInitialized
```

* tweak

* cover

* fix

* cover

* fixes
2024-08-25 13:19:57 +00:00
Shay Levy
129035967b Shelly RPC - do not stop BLE scanner if a sleeping device (#124147) 2024-08-25 13:17:46 +00:00
Christopher Maio
45b44f8a59 Update Matter light transition blocklist to include GE Cync Undercabinet Lights (#124138) 2024-08-25 13:17:45 +00:00
J. Nick Koston
e80dc52175 Bump aiohttp to 3.10.4 (#124137)
changelog: https://github.com/aio-libs/aiohttp/compare/v3.10.3...v3.10.4
2024-08-25 13:17:45 +00:00
MarkGodwin
22bb3e5477 Bump tplink-omada-api to 1.4.2 (#124136)
Fix for bad pre-registered clients
2024-08-25 13:17:44 +00:00
Allen Porter
f89e8e6ceb Bump nest to 4.0.7 to increase subscriber deadline (#124131)
Bump nest to 4.0.7
2024-08-25 13:17:43 +00:00
J. Nick Koston
157a61845b Bump aiohomekit to 3.2.3 (#124115) 2024-08-25 13:17:43 +00:00
Artem Draft
0fcdc3c200 Bump pybravia to 0.3.4 (#124113) 2024-08-25 13:17:42 +00:00
cdnninja
d1f09ecd0c Add Alt Core300s model to vesync integration (#124091) 2024-08-25 13:17:41 +00:00
J. Nick Koston
3484ab3c0c Bump aioshelly to 11.2.4 (#124080) 2024-08-25 13:17:40 +00:00
J. Nick Koston
80df582ebd Bump yalexs to 8.0.2 (#123817) 2024-08-25 13:17:39 +00:00
J. Nick Koston
dc967e2ef2 Bump yalexs to 6.5.0 (#123739) 2024-08-25 13:17:39 +00:00
Daniel Rozycki
e2c1a38d87 Skip NextBus update if integration is still loading (#123564)
* Skip NextBus update if integration is still loading

Fixes a race between the loading thread and
update thread leading to an unrecoverable error

* Use async_at_started

* Use local copy of _route_stops to avoid NextBus race condition

* Update homeassistant/components/nextbus/coordinator.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-25 13:17:38 +00:00
Mr. Bubbles
c9e7c76ee5 Fix missing id in Habitica completed todos API response (#124565)
* Fix missing id in completed todos API response

* Copy id only if none

* Update homeassistant/components/habitica/coordinator.py

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

---------

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2024-08-25 15:15:47 +02:00
Jan Bouwhuis
5550b1a74e Only support remote activity on Alexa if feature is set and at least one feature is in the activity_list (#124567)
Only support remote activity on Alexa if feaure is set and at least one feature is in the activity_list
2024-08-25 15:09:08 +02:00
Marcel van der Veldt
51b520db0c Prevent KeyError when Matter device sends invalid value for StartUpOnOff (#124280) 2024-08-25 15:06:16 +02:00
Christopher Maio
f06c21c8cc Update Matter light transition blocklist to include GE Cync Undercabinet Lights (#124138) 2024-08-25 15:05:13 +02:00
IceBotYT
fcf0bef2cd Remove platform from unique ID in Nice G.O. (#124548)
* Remove domain from unique ID in Nice G.O.

* Snapshots
2024-08-25 14:13:50 +02:00
J. Nick Koston
7c8e00e5e0 Bump yalexs to 8.4.1 (#124553)
changelog: https://github.com/bdraco/yalexs/compare/v8.4.0...v8.4.1
2024-08-25 13:16:20 +02:00
Jonas Bergler
ce72157bf7 Bump pyEmby to 1.10 (#124549) 2024-08-25 11:43:21 +02:00
Andrew Jackson
31f5539311 Change logger level on config migration for Mastodon (#124558) 2024-08-25 09:53:30 +02:00
J. Nick Koston
b63fb9f17f Bump bluetooth-data-tools to 1.20.0 (#124542)
changelog: https://github.com/Bluetooth-Devices/bluetooth-data-tools/compare/v1.19.4...v1.20.0
2024-08-24 18:18:54 -10:00
IceBotYT
9b3718edfb Remove sync API use in Nice G.O. (#124546) 2024-08-25 03:27:08 +02:00
Michael Hansen
156e39ebb2 Add minimum command seconds to VAD (#124447) 2024-08-24 22:21:03 +02:00
Allen Porter
c506188c13 Fix nest event entities to only register a single event per session (#124535) 2024-08-24 22:17:59 +02:00
Allen Porter
b64c21cce6 Bump to python-nest-sdm to 5.0.0 (#124536) 2024-08-24 22:16:55 +02:00
David F. Mulcahey
e85755fbda Fix ZHA device lookup when ZHA devices are shared with additional integrations (#124429)
* Fix ZHA device lookup when ZHA devices are shared with additional integrations

* clean up except error types

* remove impossible to create exceptions
2024-08-24 15:52:27 -04:00
Allen Porter
3e3d27f48d Add nest event platform (#123042)
* Add nest event platform

* Translate entities

* Put motion events into a single entity type

* Remove none types

* Set event entity descriptions as kw only

* Update translations for event entities

* Add single event entity per trait type

* Update translation keys
2024-08-24 08:44:44 -07:00
red-island
32f75597a9 Fix tilt calculation for HomeKit cover devices (#123532) 2024-08-24 16:12:32 +01:00
cnico
d7d35f74f2 Bump flipr-api to 1.6.0 (#124522)
bump flipr-api to 1.6.0
2024-08-24 17:09:52 +02:00
Markus Jacobsen
5dc03752ca Add type hinting to Bang & Olufsen test (#124423) 2024-08-24 12:59:08 +02:00
Michael Arthur
b26446bd88 Add returning activity to ecovacs lawn mower (#124519) 2024-08-24 12:53:49 +02:00
Robert Svensson
9e13184256 Add deCONZ Air Purifier Fan Mode select entity support (#124513)
* Add deCONZ Air Purifier Fan Mode select entity support

* Remove unused constants
2024-08-24 09:51:09 +02:00
J. Nick Koston
b7170c78a5 Bump yalexs to 8.4.0 (#124520) 2024-08-23 20:44:12 -10:00
Steven B.
e26d363b5e Convert ring integration to the async ring-doorbell api (#124365)
* Bump ring-doorbell to 0.9.0

* Convert ring integration to async ring-doorbell api

* Use mock auth fixture class to get token_updater

* Fix typo in fixture name
2024-08-24 08:23:31 +02:00
Joost Lekkerkerker
7ae8f4c9d0 Don't abort airgradient user flow if flow in progress (#124300) 2024-08-24 07:20:00 +02:00
Lenn
664e0258bf Bump motionblindsble to 0.1.1 (#124322) 2024-08-24 07:19:11 +02:00
Joost Lekkerkerker
8023cbcc38 Don't raise WLED user flow unique_id check (#124481) 2024-08-24 07:04:50 +02:00
jjlawren
22c322fc37 Bump plexapi to 4.15.16 (#124512) 2024-08-24 07:01:25 +02:00
J. Nick Koston
2bb4a8747c Bump fnv-hash-fast to 1.0.2 (#124489) 2024-08-24 06:58:52 +02:00
Andre Lengwenus
098a006f32 Bump lcn-frontend to 0.1.6 (#124490) 2024-08-24 06:56:48 +02:00
David F. Mulcahey
d47a296d7a Resolve versions of ZHA dependencies earlier to prevent blocking call in event loop (#124496) 2024-08-24 06:52:58 +02:00
Matthias Alphart
c2ce71a38c Update xknx to 3.1.1 (#124257) 2024-08-24 06:48:02 +02:00
Artur Pragacz
a7c6abc54e Always assign unique_id in Onkyo (#120543) 2024-08-23 21:04:44 -07:00
Christophe Gagnier
79ba315008 Add charging enabled switch to TechnoVE (#121484)
* Add session_active switch to TechnoVE

* Replace multi-line lambda with function def

* Make lambda one line
2024-08-23 22:45:26 +02:00
Jan Bouwhuis
26e87509be Cleanup hassio fixtures in home assistant hardware integration tests (#124500) 2024-08-23 19:40:35 +02:00
J. Nick Koston
af2fec89d8 Bump yalexs to 8.3.3 (#124492)
* Bump yalexs to 8.2.0

changelog: https://github.com/bdraco/yalexs/compare/v8.1.4...v8.2.0

* bump to 8.3.1

* bump

* one more bump to ensure we do not hit the ratelimit/shutdown cleanly

* empty commit to restart ci since close/open did not work in flight
2024-08-23 19:23:05 +02:00
Steven B.
61cee043e6 Do not report tplink discovery failures as legacy connection failures (#124432)
* Do not report discovery failures as legacy connection failures

* Fix catching BaseException
2024-08-23 10:17:48 -05:00
Jan Bouwhuis
fd57931cc9 Cleanup redundant fixtures on matter integration for addon tests (#124445) 2024-08-23 16:27:14 +02:00
Jan Bouwhuis
44b6bca89a Refactor and cleanup zwave_js fixtures to share them (#124485)
Refactor and cleanup zwave_js fixtures to use
2024-08-23 15:42:57 +02:00
starkillerOG
0bd9386df2 Reolink add 100% coverage of siren platform (#124474) 2024-08-23 15:15:04 +02:00
Franck Nijhof
94516de724 2024.8.2 (#124069) 2024-08-16 18:43:41 +02:00
Joost Lekkerkerker
a2027fc78c Exclude aiohappyeyeballs from license check (#124041) 2024-08-16 18:13:33 +02:00
Franck Nijhof
be5577c2f9 Bump version to 2024.8.2 2024-08-16 18:02:52 +02:00
Joost Lekkerkerker
93dc08a05f Bump aiomealie to 0.8.1 (#124047) 2024-08-16 18:02:41 +02:00
Matthias Alphart
def2ace4ec Fix loading KNX integration actions when not using YAML (#124027)
* Fix loading KNX integration services when not using YAML

* remove unnecessary comment

* Remove unreachable test
2024-08-16 18:02:38 +02:00
J. Nick Koston
4f0261d739 Bump bluetooth-adapters to 0.19.4 (#124018)
Fixes a call to enumerate USB devices that did blocking
I/O
2024-08-16 18:02:35 +02:00
Brett Adams
6103811de8 Fix rear trunk logic in Tessie (#124011)
Allow open to be anything not zero
2024-08-16 18:02:32 +02:00
Robert Svensson
fd904c65a7 Bump aiounifi to v80 (#124004) 2024-08-16 18:02:29 +02:00
Joost Lekkerkerker
04bf8482b2 Re-enable concord232 (#124000) 2024-08-16 18:02:26 +02:00
Sid
f5fd5e0457 Bump openwebifpy to 4.2.7 (#123995)
* Bump openwebifpy to 4.2.6

* Bump openwebifpy to 4.2.7

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2024-08-16 18:02:23 +02:00
J. Nick Koston
0de89b42aa Ensure event entities are allowed for linked homekit config via YAML (#123994) 2024-08-16 18:02:20 +02:00
Erik Montnemery
e8914552b1 Bump pyhomeworks to 1.1.1 (#123981) 2024-08-16 18:02:17 +02:00
Glenn Waters
bfd302109e Environment Canada weather format fix (#123960)
* Add missing isoformat.

* Move fixture loading to common conftest.py

* Add deepcopy.
2024-08-16 18:02:14 +02:00
Andre Lengwenus
796ad47dd0 Bump pypck to 0.7.20 (#123948) 2024-08-16 18:02:11 +02:00
IceBotYT
e9915463a9 Bump LaCrosse View to 1.0.2, fixes blocking call (#123935) 2024-08-16 18:02:07 +02:00
Michael
59aecda8cf Fix PI-Hole update entity when no update available (#123930)
show installed version when no update available
2024-08-16 17:58:24 +02:00
J. Nick Koston
7d00ccbbbc Bump pylutron_caseta to 0.21.1 (#123924) 2024-08-16 17:58:21 +02:00
Álvaro Fernández Rojas
55a911120c Handle timeouts on Airzone DHCP config flow (#123869)
airzone: config_flow: dhcp: catch timeout exception

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-08-16 17:58:18 +02:00
Michael
80abf90c87 Fix translation for integration not found repair issue (#123868)
* correct setp id in strings

* add issue_ignored string
2024-08-16 17:58:15 +02:00
Robert Resch
8539591307 Fix blocking I/O of SSLContext.load_default_certs in Ecovacs (#123856) 2024-08-16 17:58:12 +02:00
Michael
6234deeee1 Bump py-synologydsm-api to 2.4.5 (#123815)
bump py-synologydsm-api to 2.4.5
2024-08-16 17:57:59 +02:00
Louis Christ
81fabb1bfa Fix status update loop in bluesound integration (#123790)
* Fix retry loop for status update

* Use 'available' instead of _is_online

* Fix tests
2024-08-16 17:56:23 +02:00
Matthias Alphart
ff4e5859cf Fix KNX UI Light color temperature DPT (#123778) 2024-08-16 17:13:31 +02:00
Matthias Alphart
f2e42eafc7 Update xknx to 3.1.0 and fix climate read only mode (#123776) 2024-08-16 17:13:28 +02:00
Allen Porter
63f28ae2fe Bump python-nest-sdm to 4.0.6 (#123762) 2024-08-16 17:13:25 +02:00
Ian
5b6c6141c5 Bump py-nextbusnext to 2.0.4 (#123750) 2024-08-16 17:13:22 +02:00
Michael
396ef7a642 Fix error message in html5 (#123749) 2024-08-16 17:13:19 +02:00
Franck Nijhof
17f59a5665 Update wled to 0.20.2 (#123746) 2024-08-16 17:13:16 +02:00
David F. Mulcahey
10846dc97b Bump ZHA lib to 0.0.31 (#123743) 2024-08-16 17:13:13 +02:00
Álvaro Fernández Rojas
17bb00727d Update aioqsw to v0.4.1 (#123721) 2024-08-16 17:13:10 +02:00
Álvaro Fernández Rojas
bc021dbbc6 Update aioairzone-cloud to v0.6.2 (#123719) 2024-08-16 17:13:06 +02:00
Álvaro Fernández Rojas
e3cb9c0844 Update AEMET-OpenData to v0.5.4 (#123716) 2024-08-16 17:13:03 +02:00
David Knowles
050e2c9404 Bump pyschlage to 2024.8.0 (#123714) 2024-08-16 17:13:00 +02:00
Cyrill Raccaud
5ea447ba48 Fix startup block from Swiss public transport (#123704) 2024-08-16 17:12:57 +02:00
J. Nick Koston
a23b063922 Bump aiohomekit to 3.2.2 (#123669) 2024-08-16 17:12:53 +02:00
Aidan Timson
c269d57259 System Bridge package updates (#123657) 2024-08-16 17:12:50 +02:00
kingy444
d512f327c5 Bump pydaikin to 2.13.4 (#123623)
* bump pydaikin to 2.13.3

* bump pydaikin to 2.13.4
2024-08-16 17:12:46 +02:00
Maciej Bieniek
9bf8c5a54b Bump aioshelly to version 11.2.0 (#123602)
Bump aioshelly to version 11.2.0
2024-08-16 17:12:43 +02:00
J. Nick Koston
725e2f16f5 Ensure HomeKit connection is kept alive for devices that timeout too quickly (#123601) 2024-08-16 17:12:21 +02:00
G Johansson
d98d0cdad0 Change WoL to be secondary on device info (#123591) 2024-08-16 17:07:24 +02:00
Noah Husby
e2f4aa893f Fix secondary russound controller discovery failure (#123590) 2024-08-16 17:07:21 +02:00
Matthias Alphart
6b81fa89d3 Update knx-frontend to 2024.8.9.225351 (#123557) 2024-08-16 17:07:18 +02:00
J. Nick Koston
c886587915 Bump aiohttp to 3.10.3 (#123549) 2024-08-16 17:07:15 +02:00
Phill (pssc)
059d3eed98 Handle Yamaha ValueError (#123547)
* fix yamaha remove info logging

* ruff

* fix yamnaha supress rxv.find UnicodeDecodeError

* fix formatting

* make more realistic

* make more realistic and use parms

* add value error after more feedback

* ruff format

* Update homeassistant/components/yamaha/media_player.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* remove unused method

* add more debugging

* Increase discovery timeout add more debug allow config to overrite dicovery for name

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2024-08-16 17:07:12 +02:00
Erik Montnemery
f9ae2b4453 Drop violating rows before adding foreign constraints in DB schema 44 migration (#123454)
* Drop violating rows before adding foreign constraints

* Don't delete rows with null-references

* Only delete rows when integrityerror is caught

* Move restore of dropped foreign key constraints to a separate migration step

* Use aliases for tables

* Update homeassistant/components/recorder/migration.py

* Update test

* Don't use alias for table we're deleting from, improve test

* Fix MySQL

* Update instead of deleting in case of self references

* Improve log messages

* Batch updates

* Add workaround for unsupported LIMIT in PostgreSQL

* Simplify

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2024-08-16 17:07:09 +02:00
ilan
742c7ba23f Fix Madvr sensor values on startup (#122479)
* fix: add startup values

* fix: update snap

* fix: use native value to show None
2024-08-16 17:07:06 +02:00
wittypluck
e7ae5c5c24 Avoid Exception on Glances missing key (#114628)
* Handle case of sensors removed server side

* Update available state on value update

* Set uptime to None if key is missing

* Replace _attr_available by _data_valid
2024-08-16 17:07:02 +02:00
Franck Nijhof
ae4fc9504a 2024.8.1 (#123544) 2024-08-10 19:32:02 +02:00
Franck Nijhof
2ef337ec2e Bump version to 2024.8.1 2024-08-10 18:41:57 +02:00
cnico
723b7bd532 Upgrade chacon_dio_api to version 1.2.0 (#123528)
Upgrade api version 1.2.0 with the first user feedback improvement
2024-08-10 18:41:39 +02:00
Joost Lekkerkerker
4fdb11b0d8 Bump AirGradient to 0.8.0 (#123527) 2024-08-10 18:41:36 +02:00
Matt Way
fe2e6c37f4 Bump pydaikin to 2.13.2 (#123519) 2024-08-10 18:41:32 +02:00
Michael
4a75c55a8f Fix cleanup of old orphan device entries in AVM Fritz!Tools (#123516)
fix cleanup of old orphan device entries
2024-08-10 18:41:29 +02:00
Duco Sebel
dfb59469cf Bumb python-homewizard-energy to 6.2.0 (#123514) 2024-08-10 18:41:26 +02:00
David F. Mulcahey
bdb2e1e2e9 Bump zha lib to 0.0.30 (#123499) 2024-08-10 18:41:22 +02:00
Franck Nijhof
c4f6f1e3d8 Update frontend to 20240809.0 (#123485) 2024-08-10 18:41:19 +02:00
Louis Christ
fb3eae54ea Fix startup blocked by bluesound integration (#123483) 2024-08-10 18:41:16 +02:00
Jake Martin
d3f8fce788 Bump monzopy to 1.3.2 (#123480) 2024-08-10 18:41:13 +02:00
Steve Easley
44e58a8c87 Bump pyjvcprojector to 1.0.12 to fix blocking call (#123473) 2024-08-10 18:41:09 +02:00
puddly
3d3879b0db Bump ZHA library to 0.0.29 (#123464)
* Bump zha to 0.0.29

* Pass the Core timezone to ZHA

* Add a unit test
2024-08-10 18:41:06 +02:00
Franck Nijhof
a8b1eb34f3 Support action YAML syntax in old-style notify groups (#123457) 2024-08-10 18:41:03 +02:00
Matrix
fd77058def Bump YoLink API to 0.4.7 (#123441) 2024-08-10 18:41:00 +02:00
Brett Adams
b147ca6c5b Add missing logger to Tessie (#123413) 2024-08-10 18:40:57 +02:00
dupondje
670c4cacfa Also migrate dsmr entries for devices with correct serial (#123407)
dsmr: also migrate entries for devices with correct serial

When the dsmr code could not find the serial_nr for the gas meter,
it creates the gas meter device with the entry_id as identifier.

But when there is a correct serial_nr, it will use that as identifier
for the dsmr gas device.

Now the migration code did not take this into account, so migration to
the new name failed since it didn't look for the device with correct
serial_nr.

This commit fixes this and adds a test for this.
2024-08-10 18:40:53 +02:00
J. Nick Koston
1ed0a89303 Bump aiohttp to 3.10.2 (#123394) 2024-08-10 18:40:50 +02:00
J. Nick Koston
ab0597da7b Ensure legacy event foreign key is removed from the states table when a previous rebuild failed (#123388)
* Ensure legacy event foreign key is removed from the states table

If the system ran out of disk space removing the FK, it would
fail. #121938 fixed that to try again, however that PR was made
ineffective by #122069 since it will never reach the check.

To solve this, the migration version is incremented to 2, and
the migration is no longer marked as done unless the rebuild
/fk removal is successful.

* fix logic for mysql

* fix test

* asserts

* coverage

* coverage

* narrow test

* fixes

* split tests

* should have skipped

* fixture must be used
2024-08-10 18:40:47 +02:00
Erik Montnemery
a3db6bc8fa Revert "Fix blocking I/O while validating config schema" (#123377) 2024-08-10 18:40:44 +02:00
Noah Husby
9bfc8f6e27 Bump aiorussound to 2.2.2 (#123319) 2024-08-10 18:40:41 +02:00
J. Nick Koston
6fddef2dc5 Fix doorbird with externally added events (#123313) 2024-08-10 18:40:38 +02:00
fustom
ec08a85aa0 Fix limit and order property for transmission integration (#123305) 2024-08-10 18:40:35 +02:00
Evgeny
de7af575c5 Bump OpenWeatherMap to 0.1.1 (#120178)
* add owm modes

* fix tests

* fix modes

* remove sensors

* Update homeassistant/components/openweathermap/sensor.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-10 18:40:32 +02:00
Tom Brien
d3831bae4e Add support for v3 Coinbase API (#116345)
* Add support for v3 Coinbase API

* Add deps

* Move tests
2024-08-10 18:40:28 +02:00
1265 changed files with 33430 additions and 11536 deletions

View File

@@ -61,6 +61,7 @@ components: &components
- homeassistant/components/auth/** - homeassistant/components/auth/**
- homeassistant/components/automation/** - homeassistant/components/automation/**
- homeassistant/components/backup/** - homeassistant/components/backup/**
- homeassistant/components/blueprint/**
- homeassistant/components/bluetooth/** - homeassistant/components/bluetooth/**
- homeassistant/components/cloud/** - homeassistant/components/cloud/**
- homeassistant/components/config/** - homeassistant/components/config/**

View File

@@ -482,3 +482,56 @@ jobs:
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}" export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
twine upload dist/* --skip-existing twine upload dist/* --skip-existing
hassfest-image:
name: Build and test hassfest image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
needs: ["init"]
if: github.repository_owner == 'home-assistant'
env:
HASSFEST_IMAGE_NAME: ghcr.io/home-assistant/hassfest
HASSFEST_IMAGE_TAG: ghcr.io/home-assistant/hassfest:${{ needs.init.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker image
uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 # v6.7.0
with:
context: . # So action will not pull the repository again
file: ./script/hassfest/docker/Dockerfile
load: true
tags: ${{ env.HASSFEST_IMAGE_TAG }}
- name: Run hassfest against core
run: docker run --rm -v ${{ github.workspace }}/homeassistant:/github/workspace/homeassistant ${{ env.HASSFEST_IMAGE_TAG }} --core-integrations-path=/github/workspace/homeassistant/components
- name: Push Docker image
if: needs.init.outputs.channel != 'dev' && needs.init.outputs.publish == 'true'
id: push
uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 # v6.7.0
with:
context: . # So action will not pull the repository again
file: ./script/hassfest/docker/Dockerfile
push: true
tags: ${{ env.HASSFEST_IMAGE_TAG }},${{ env.HASSFEST_IMAGE_NAME }}:latest
- name: Generate artifact attestation
if: needs.init.outputs.channel != 'dev' && needs.init.outputs.publish == 'true'
uses: actions/attest-build-provenance@6149ea5740be74af77f260b9db67e633f6b0a9a1 # v1.4.2
with:
subject-name: ${{ env.HASSFEST_IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

View File

@@ -24,11 +24,11 @@ jobs:
uses: actions/checkout@v4.1.7 uses: actions/checkout@v4.1.7
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3.26.4 uses: github/codeql-action/init@v3.26.5
with: with:
languages: python languages: python
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3.26.4 uses: github/codeql-action/analyze@v3.26.5
with: with:
category: "/language:python" category: "/language:python"

View File

@@ -294,7 +294,6 @@ homeassistant.components.london_underground.*
homeassistant.components.lookin.* homeassistant.components.lookin.*
homeassistant.components.luftdaten.* homeassistant.components.luftdaten.*
homeassistant.components.madvr.* homeassistant.components.madvr.*
homeassistant.components.mailbox.*
homeassistant.components.manual.* homeassistant.components.manual.*
homeassistant.components.map.* homeassistant.components.map.*
homeassistant.components.mastodon.* homeassistant.components.mastodon.*

View File

@@ -1493,6 +1493,8 @@ build.json @home-assistant/supervisor
/tests/components/tomorrowio/ @raman325 @lymanepp /tests/components/tomorrowio/ @raman325 @lymanepp
/homeassistant/components/totalconnect/ @austinmroczek /homeassistant/components/totalconnect/ @austinmroczek
/tests/components/totalconnect/ @austinmroczek /tests/components/totalconnect/ @austinmroczek
/homeassistant/components/touchline_sl/ @jnsgruk
/tests/components/touchline_sl/ @jnsgruk
/homeassistant/components/tplink/ @rytilahti @bdraco @sdb9696 /homeassistant/components/tplink/ @rytilahti @bdraco @sdb9696
/tests/components/tplink/ @rytilahti @bdraco @sdb9696 /tests/components/tplink/ @rytilahti @bdraco @sdb9696
/homeassistant/components/tplink_omada/ @MarkGodwin /homeassistant/components/tplink_omada/ @MarkGodwin
@@ -1658,6 +1660,8 @@ build.json @home-assistant/supervisor
/tests/components/xiaomi_miio/ @rytilahti @syssi @starkillerOG /tests/components/xiaomi_miio/ @rytilahti @syssi @starkillerOG
/homeassistant/components/xiaomi_tv/ @simse /homeassistant/components/xiaomi_tv/ @simse
/homeassistant/components/xmpp/ @fabaff @flowolf /homeassistant/components/xmpp/ @fabaff @flowolf
/homeassistant/components/yale/ @bdraco
/tests/components/yale/ @bdraco
/homeassistant/components/yale_smart_alarm/ @gjohansson-ST /homeassistant/components/yale_smart_alarm/ @gjohansson-ST
/tests/components/yale_smart_alarm/ @gjohansson-ST /tests/components/yale_smart_alarm/ @gjohansson-ST
/homeassistant/components/yalexs_ble/ @bdraco /homeassistant/components/yalexs_ble/ @bdraco

View File

@@ -42,7 +42,8 @@ WORKDIR /usr/src
# Setup hass-release # Setup hass-release
RUN git clone --depth 1 https://github.com/home-assistant/hass-release \ RUN git clone --depth 1 https://github.com/home-assistant/hass-release \
&& uv pip install --system -e hass-release/ && uv pip install --system -e hass-release/ \
&& chown -R vscode /usr/src/hass-release/data
USER vscode USER vscode
ENV VIRTUAL_ENV="/home/vscode/.local/ha-venv" ENV VIRTUAL_ENV="/home/vscode/.local/ha-venv"

View File

@@ -0,0 +1,5 @@
{
"domain": "roth",
"name": "Roth",
"integrations": ["touchline", "touchline_sl"]
}

View File

@@ -1,5 +1,11 @@
{ {
"domain": "yale", "domain": "yale",
"name": "Yale", "name": "Yale",
"integrations": ["august", "yale_smart_alarm", "yalexs_ble", "yale_home"] "integrations": [
"august",
"yale_smart_alarm",
"yalexs_ble",
"yale_home",
"yale"
]
} }

View File

@@ -7,8 +7,14 @@
} }
}, },
"services": { "services": {
"capture_image": "mdi:camera", "capture_image": {
"change_setting": "mdi:cog", "service": "mdi:camera"
"trigger_automation": "mdi:play" },
"change_setting": {
"service": "mdi:cog"
},
"trigger_automation": {
"service": "mdi:play"
}
} }
} }

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/acmeda", "documentation": "https://www.home-assistant.io/integrations/acmeda",
"iot_class": "local_push", "iot_class": "local_push",
"loggers": ["aiopulse"], "loggers": ["aiopulse"],
"requirements": ["aiopulse==0.4.4"] "requirements": ["aiopulse==0.4.6"]
} }

View File

@@ -66,10 +66,20 @@
} }
}, },
"services": { "services": {
"add_url": "mdi:link-plus", "add_url": {
"remove_url": "mdi:link-off", "service": "mdi:link-plus"
"enable_url": "mdi:link-variant", },
"disable_url": "mdi:link-variant-off", "remove_url": {
"refresh": "mdi:refresh" "service": "mdi:link-off"
},
"enable_url": {
"service": "mdi:link-variant"
},
"disable_url": {
"service": "mdi:link-variant-off"
},
"refresh": {
"service": "mdi:refresh"
}
} }
} }

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"write_data_by_name": "mdi:pencil" "write_data_by_name": {
"service": "mdi:pencil"
}
} }
} }

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"set_time_to": "mdi:timer-cog" "set_time_to": {
"service": "mdi:timer-cog"
}
} }
} }

View File

@@ -7,7 +7,11 @@
} }
}, },
"services": { "services": {
"add_tracking": "mdi:package-variant-plus", "add_tracking": {
"remove_tracking": "mdi:package-variant-minus" "service": "mdi:package-variant-plus"
},
"remove_tracking": {
"service": "mdi:package-variant-minus"
}
} }
} }

View File

@@ -1,9 +1,19 @@
{ {
"services": { "services": {
"start_recording": "mdi:record-rec", "start_recording": {
"stop_recording": "mdi:stop", "service": "mdi:record-rec"
"enable_alerts": "mdi:bell-alert", },
"disable_alerts": "mdi:bell-off", "stop_recording": {
"snapshot": "mdi:camera" "service": "mdi:stop"
},
"enable_alerts": {
"service": "mdi:bell-alert"
},
"disable_alerts": {
"service": "mdi:bell-off"
},
"snapshot": {
"service": "mdi:camera"
}
} }
} }

View File

@@ -92,7 +92,9 @@ class AirGradientConfigFlow(ConfigFlow, domain=DOMAIN):
except AirGradientError: except AirGradientError:
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
else: else:
await self.async_set_unique_id(current_measures.serial_number) await self.async_set_unique_id(
current_measures.serial_number, raise_on_progress=False
)
self._abort_if_unique_id_configured() self._abort_if_unique_id_configured()
await self.set_configuration_source() await self.set_configuration_source()
return self.async_create_entry( return self.async_create_entry(

View File

@@ -6,6 +6,6 @@
"documentation": "https://www.home-assistant.io/integrations/airgradient", "documentation": "https://www.home-assistant.io/integrations/airgradient",
"integration_type": "device", "integration_type": "device",
"iot_class": "local_polling", "iot_class": "local_polling",
"requirements": ["airgradient==0.8.0"], "requirements": ["airgradient==0.9.0"],
"zeroconf": ["_airgradient._tcp.local."] "zeroconf": ["_airgradient._tcp.local."]
} }

View File

@@ -24,5 +24,5 @@
"dependencies": ["bluetooth_adapters"], "dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/airthings_ble", "documentation": "https://www.home-assistant.io/integrations/airthings_ble",
"iot_class": "local_polling", "iot_class": "local_polling",
"requirements": ["airthings-ble==0.9.0"] "requirements": ["airthings-ble==0.9.1"]
} }

View File

@@ -262,7 +262,7 @@ class Airtouch5AC(Airtouch5ClimateEntity):
_LOGGER.debug("Argument `temperature` is missing in set_temperature") _LOGGER.debug("Argument `temperature` is missing in set_temperature")
return return
await self._control(temp=temp) await self._control(setpoint=SetpointControl.CHANGE_SETPOINT, temp=temp)
class Airtouch5Zone(Airtouch5ClimateEntity): class Airtouch5Zone(Airtouch5ClimateEntity):

View File

@@ -80,11 +80,9 @@ class AirVisualProFlowHandler(ConfigFlow, domain=DOMAIN):
"""Initialize.""" """Initialize."""
self._reauth_entry: ConfigEntry | None = None self._reauth_entry: ConfigEntry | None = None
async def async_step_import( async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
self, import_config: dict[str, Any] """Import a config entry from `airvisual` integration (see #83882)."""
) -> ConfigFlowResult: return await self.async_step_user(import_data)
"""Import a config entry from configuration.yaml."""
return await self.async_step_user(import_config)
async def async_step_reauth( async def async_step_reauth(
self, entry_data: Mapping[str, Any] self, entry_data: Mapping[str, Any]

View File

@@ -2,16 +2,21 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Final from typing import Any, Final
from aioairzone.common import GrilleAngle, SleepTimeout from aioairzone.common import GrilleAngle, OperationMode, SleepTimeout
from aioairzone.const import ( from aioairzone.const import (
API_COLD_ANGLE, API_COLD_ANGLE,
API_HEAT_ANGLE, API_HEAT_ANGLE,
API_MODE,
API_SLEEP, API_SLEEP,
AZD_COLD_ANGLE, AZD_COLD_ANGLE,
AZD_HEAT_ANGLE, AZD_HEAT_ANGLE,
AZD_MASTER,
AZD_MODE,
AZD_MODES,
AZD_SLEEP, AZD_SLEEP,
AZD_ZONES, AZD_ZONES,
) )
@@ -33,6 +38,9 @@ class AirzoneSelectDescription(SelectEntityDescription):
api_param: str api_param: str
options_dict: dict[str, int] options_dict: dict[str, int]
options_fn: Callable[[dict[str, Any], dict[str, int]], list[str]] = (
lambda zone_data, value: list(value)
)
GRILLE_ANGLE_DICT: Final[dict[str, int]] = { GRILLE_ANGLE_DICT: Final[dict[str, int]] = {
@@ -42,6 +50,15 @@ GRILLE_ANGLE_DICT: Final[dict[str, int]] = {
"40deg": GrilleAngle.DEG_40, "40deg": GrilleAngle.DEG_40,
} }
MODE_DICT: Final[dict[str, int]] = {
"cool": OperationMode.COOLING,
"dry": OperationMode.DRY,
"fan": OperationMode.FAN,
"heat": OperationMode.HEATING,
"heat_cool": OperationMode.AUTO,
"stop": OperationMode.STOP,
}
SLEEP_DICT: Final[dict[str, int]] = { SLEEP_DICT: Final[dict[str, int]] = {
"off": SleepTimeout.SLEEP_OFF, "off": SleepTimeout.SLEEP_OFF,
"30m": SleepTimeout.SLEEP_30, "30m": SleepTimeout.SLEEP_30,
@@ -50,6 +67,26 @@ SLEEP_DICT: Final[dict[str, int]] = {
} }
def main_zone_options(
zone_data: dict[str, Any],
options: dict[str, int],
) -> list[str]:
"""Filter available modes."""
modes = zone_data.get(AZD_MODES, [])
return [k for k, v in options.items() if v in modes]
MAIN_ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
AirzoneSelectDescription(
api_param=API_MODE,
key=AZD_MODE,
options_dict=MODE_DICT,
options_fn=main_zone_options,
translation_key="modes",
),
)
ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = ( ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
AirzoneSelectDescription( AirzoneSelectDescription(
api_param=API_COLD_ANGLE, api_param=API_COLD_ANGLE,
@@ -95,7 +132,20 @@ async def async_setup_entry(
received_zones = set(zones_data) received_zones = set(zones_data)
new_zones = received_zones - added_zones new_zones = received_zones - added_zones
if new_zones: if new_zones:
async_add_entities( entities: list[AirzoneZoneSelect] = [
AirzoneZoneSelect(
coordinator,
description,
entry,
system_zone_id,
zones_data.get(system_zone_id),
)
for system_zone_id in new_zones
for description in MAIN_ZONE_SELECT_TYPES
if description.key in zones_data.get(system_zone_id)
and zones_data.get(system_zone_id).get(AZD_MASTER) is True
]
entities += [
AirzoneZoneSelect( AirzoneZoneSelect(
coordinator, coordinator,
description, description,
@@ -106,7 +156,8 @@ async def async_setup_entry(
for system_zone_id in new_zones for system_zone_id in new_zones
for description in ZONE_SELECT_TYPES for description in ZONE_SELECT_TYPES
if description.key in zones_data.get(system_zone_id) if description.key in zones_data.get(system_zone_id)
) ]
async_add_entities(entities)
added_zones.update(new_zones) added_zones.update(new_zones)
entry.async_on_unload(coordinator.async_add_listener(_async_entity_listener)) entry.async_on_unload(coordinator.async_add_listener(_async_entity_listener))
@@ -153,6 +204,11 @@ class AirzoneZoneSelect(AirzoneZoneEntity, AirzoneBaseSelect):
f"{self._attr_unique_id}_{system_zone_id}_{description.key}" f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
) )
self.entity_description = description self.entity_description = description
self._attr_options = self.entity_description.options_fn(
zone_data, description.options_dict
)
self.values_dict = {v: k for k, v in description.options_dict.items()} self.values_dict = {v: k for k, v in description.options_dict.items()}
self._async_update_attrs() self._async_update_attrs()

View File

@@ -52,6 +52,17 @@
"40deg": "[%key:component::airzone::entity::select::grille_angles::state::40deg%]" "40deg": "[%key:component::airzone::entity::select::grille_angles::state::40deg%]"
} }
}, },
"modes": {
"name": "Mode",
"state": {
"cool": "[%key:component::climate::entity_component::_::state::cool%]",
"dry": "[%key:component::climate::entity_component::_::state::dry%]",
"fan": "[%key:component::climate::entity_component::_::state::fan_only%]",
"heat": "[%key:component::climate::entity_component::_::state::heat%]",
"heat_cool": "[%key:component::climate::entity_component::_::state::heat_cool%]",
"stop": "Stop"
}
},
"sleep_times": { "sleep_times": {
"name": "Sleep", "name": "Sleep",
"state": { "state": {

View File

@@ -15,12 +15,26 @@
} }
}, },
"services": { "services": {
"alarm_arm_away": "mdi:shield-lock", "alarm_arm_away": {
"alarm_arm_home": "mdi:shield-home", "service": "mdi:shield-lock"
"alarm_arm_night": "mdi:shield-moon", },
"alarm_arm_custom_bypass": "mdi:security", "alarm_arm_home": {
"alarm_disarm": "mdi:shield-off", "service": "mdi:shield-home"
"alarm_trigger": "mdi:bell-ring", },
"alarm_arm_vacation": "mdi:shield-airplane" "alarm_arm_night": {
"service": "mdi:shield-moon"
},
"alarm_arm_custom_bypass": {
"service": "mdi:security"
},
"alarm_disarm": {
"service": "mdi:shield-off"
},
"alarm_trigger": {
"service": "mdi:bell-ring"
},
"alarm_arm_vacation": {
"service": "mdi:shield-airplane"
}
} }
} }

View File

@@ -7,7 +7,11 @@
} }
}, },
"services": { "services": {
"alarm_keypress": "mdi:dialpad", "alarm_keypress": {
"alarm_toggle_chime": "mdi:abc" "service": "mdi:dialpad"
},
"alarm_toggle_chime": {
"service": "mdi:abc"
}
} }
} }

View File

@@ -1,7 +1,13 @@
{ {
"services": { "services": {
"toggle": "mdi:bell-ring", "toggle": {
"turn_off": "mdi:bell-off", "service": "mdi:bell-ring"
"turn_on": "mdi:bell-alert" },
"turn_off": {
"service": "mdi:bell-off"
},
"turn_on": {
"service": "mdi:bell-alert"
}
} }
} }

View File

@@ -661,9 +661,12 @@ class RemoteCapabilities(AlexaEntity):
def interfaces(self) -> Generator[AlexaCapability]: def interfaces(self) -> Generator[AlexaCapability]:
"""Yield the supported interfaces.""" """Yield the supported interfaces."""
yield AlexaPowerController(self.entity) yield AlexaPowerController(self.entity)
yield AlexaModeController( supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
self.entity, instance=f"{remote.DOMAIN}.{remote.ATTR_ACTIVITY}" activities = self.entity.attributes.get(remote.ATTR_ACTIVITY_LIST) or []
) if activities and supported & remote.RemoteEntityFeature.ACTIVITY:
yield AlexaModeController(
self.entity, instance=f"{remote.DOMAIN}.{remote.ATTR_ACTIVITY}"
)
yield AlexaEndpointHealth(self.hass, self.entity) yield AlexaEndpointHealth(self.hass, self.entity)
yield Alexa(self.entity) yield Alexa(self.entity)

View File

@@ -7,5 +7,5 @@
"integration_type": "service", "integration_type": "service",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["aioambient"], "loggers": ["aioambient"],
"requirements": ["aioambient==2024.01.0"] "requirements": ["aioambient==2024.08.0"]
} }

View File

@@ -7,5 +7,5 @@
"integration_type": "hub", "integration_type": "hub",
"iot_class": "cloud_push", "iot_class": "cloud_push",
"loggers": ["aioambient"], "loggers": ["aioambient"],
"requirements": ["aioambient==2024.01.0"] "requirements": ["aioambient==2024.08.0"]
} }

View File

@@ -1,15 +1,37 @@
{ {
"services": { "services": {
"enable_recording": "mdi:record-rec", "enable_recording": {
"disable_recording": "mdi:stop", "service": "mdi:record-rec"
"enable_audio": "mdi:volume-high", },
"disable_audio": "mdi:volume-off", "disable_recording": {
"enable_motion_recording": "mdi:motion-sensor", "service": "mdi:stop"
"disable_motion_recording": "mdi:motion-sensor-off", },
"goto_preset": "mdi:pan", "enable_audio": {
"set_color_bw": "mdi:palette", "service": "mdi:volume-high"
"start_tour": "mdi:panorama", },
"stop_tour": "mdi:panorama-outline", "disable_audio": {
"ptz_control": "mdi:pan" "service": "mdi:volume-off"
},
"enable_motion_recording": {
"service": "mdi:motion-sensor"
},
"disable_motion_recording": {
"service": "mdi:motion-sensor-off"
},
"goto_preset": {
"service": "mdi:pan"
},
"set_color_bw": {
"service": "mdi:palette"
},
"start_tour": {
"service": "mdi:panorama"
},
"stop_tour": {
"service": "mdi:panorama-outline"
},
"ptz_control": {
"service": "mdi:pan"
}
} }
} }

View File

@@ -1,8 +1,16 @@
{ {
"services": { "services": {
"adb_command": "mdi:console", "adb_command": {
"download": "mdi:download", "service": "mdi:console"
"upload": "mdi:upload", },
"learn_sendevent": "mdi:remote" "download": {
"service": "mdi:download"
},
"upload": {
"service": "mdi:upload"
},
"learn_sendevent": {
"service": "mdi:remote"
}
} }
} }

View File

@@ -8,6 +8,6 @@
"iot_class": "local_push", "iot_class": "local_push",
"loggers": ["androidtvremote2"], "loggers": ["androidtvremote2"],
"quality_scale": "platinum", "quality_scale": "platinum",
"requirements": ["androidtvremote2==0.1.1"], "requirements": ["androidtvremote2==0.1.2"],
"zeroconf": ["_androidtvremote2._tcp.local."] "zeroconf": ["_androidtvremote2._tcp.local."]
} }

View File

@@ -8,7 +8,7 @@ LOGGER = logging.getLogger(__package__)
CONF_RECOMMENDED = "recommended" CONF_RECOMMENDED = "recommended"
CONF_PROMPT = "prompt" CONF_PROMPT = "prompt"
CONF_CHAT_MODEL = "chat_model" CONF_CHAT_MODEL = "chat_model"
RECOMMENDED_CHAT_MODEL = "claude-3-5-sonnet-20240620" RECOMMENDED_CHAT_MODEL = "claude-3-haiku-20240307"
CONF_MAX_TOKENS = "max_tokens" CONF_MAX_TOKENS = "max_tokens"
RECOMMENDED_MAX_TOKENS = 1024 RECOMMENDED_MAX_TOKENS = 1024
CONF_TEMPERATURE = "temperature" CONF_TEMPERATURE = "temperature"

View File

@@ -6,4 +6,4 @@ DOMAIN: Final = "apcupsd"
CONNECTION_TIMEOUT: int = 10 CONNECTION_TIMEOUT: int = 10
# Field name of last self test retrieved from apcupsd. # Field name of last self test retrieved from apcupsd.
LASTSTEST: Final = "laststest" LAST_S_TEST: Final = "laststest"

View File

@@ -13,7 +13,6 @@ from homeassistant.components.sensor import (
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
PERCENTAGE, PERCENTAGE,
STATE_UNKNOWN,
UnitOfApparentPower, UnitOfApparentPower,
UnitOfElectricCurrent, UnitOfElectricCurrent,
UnitOfElectricPotential, UnitOfElectricPotential,
@@ -26,7 +25,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN, LASTSTEST from .const import DOMAIN, LAST_S_TEST
from .coordinator import APCUPSdCoordinator from .coordinator import APCUPSdCoordinator
PARALLEL_UPDATES = 0 PARALLEL_UPDATES = 0
@@ -157,8 +156,8 @@ SENSORS: dict[str, SensorEntityDescription] = {
device_class=SensorDeviceClass.TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
LASTSTEST: SensorEntityDescription( LAST_S_TEST: SensorEntityDescription(
key=LASTSTEST, key=LAST_S_TEST,
translation_key="last_self_test", translation_key="last_self_test",
), ),
"lastxfer": SensorEntityDescription( "lastxfer": SensorEntityDescription(
@@ -423,7 +422,7 @@ async def async_setup_entry(
# periodical (or manual) self test since last daemon restart. It might not be available # periodical (or manual) self test since last daemon restart. It might not be available
# when we set up the integration, and we do not know if it would ever be available. Here we # when we set up the integration, and we do not know if it would ever be available. Here we
# add it anyway and mark it as unknown initially. # add it anyway and mark it as unknown initially.
for resource in available_resources | {LASTSTEST}: for resource in available_resources | {LAST_S_TEST}:
if resource not in SENSORS: if resource not in SENSORS:
_LOGGER.warning("Invalid resource from APCUPSd: %s", resource.upper()) _LOGGER.warning("Invalid resource from APCUPSd: %s", resource.upper())
continue continue
@@ -484,7 +483,7 @@ class APCUPSdSensor(CoordinatorEntity[APCUPSdCoordinator], SensorEntity):
# performed) and may disappear again after certain event. So we mark the state as "unknown" # performed) and may disappear again after certain event. So we mark the state as "unknown"
# when it becomes unknown after such events. # when it becomes unknown after such events.
if key not in self.coordinator.data: if key not in self.coordinator.data:
self._attr_native_value = STATE_UNKNOWN self._attr_native_value = None
return return
self._attr_native_value, inferred_unit = infer_unit(self.coordinator.data[key]) self._attr_native_value, inferred_unit = infer_unit(self.coordinator.data[key])

View File

@@ -7,7 +7,7 @@
"documentation": "https://www.home-assistant.io/integrations/apple_tv", "documentation": "https://www.home-assistant.io/integrations/apple_tv",
"iot_class": "local_push", "iot_class": "local_push",
"loggers": ["pyatv", "srptools"], "loggers": ["pyatv", "srptools"],
"requirements": ["pyatv==0.15.0"], "requirements": ["pyatv==0.15.1"],
"zeroconf": [ "zeroconf": [
"_mediaremotetv._tcp.local.", "_mediaremotetv._tcp.local.",
"_companion-link._tcp.local.", "_companion-link._tcp.local.",

View File

@@ -36,10 +36,11 @@ class ApSystemsDataCoordinator(DataUpdateCoordinator[ApSystemsSensorData]):
async def _async_setup(self) -> None: async def _async_setup(self) -> None:
try: try:
max_power = (await self.api.get_device_info()).maxPower device_info = await self.api.get_device_info()
except (ConnectionError, TimeoutError): except (ConnectionError, TimeoutError):
raise UpdateFailed from None raise UpdateFailed from None
self.api.max_power = max_power self.api.max_power = device_info.maxPower
self.api.min_power = device_info.minPower
async def _async_update_data(self) -> ApSystemsSensorData: async def _async_update_data(self) -> ApSystemsSensorData:
output_data = await self.api.get_output_data() output_data = await self.api.get_output_data()

View File

@@ -26,7 +26,6 @@ async def async_setup_entry(
class ApSystemsMaxOutputNumber(ApSystemsEntity, NumberEntity): class ApSystemsMaxOutputNumber(ApSystemsEntity, NumberEntity):
"""Base sensor to be used with description.""" """Base sensor to be used with description."""
_attr_native_min_value = 30
_attr_native_step = 1 _attr_native_step = 1
_attr_device_class = NumberDeviceClass.POWER _attr_device_class = NumberDeviceClass.POWER
_attr_mode = NumberMode.BOX _attr_mode = NumberMode.BOX
@@ -42,6 +41,7 @@ class ApSystemsMaxOutputNumber(ApSystemsEntity, NumberEntity):
self._api = data.coordinator.api self._api = data.coordinator.api
self._attr_unique_id = f"{data.device_id}_output_limit" self._attr_unique_id = f"{data.device_id}_output_limit"
self._attr_native_max_value = data.coordinator.api.max_power self._attr_native_max_value = data.coordinator.api.max_power
self._attr_native_min_value = data.coordinator.api.min_power
async def async_update(self) -> None: async def async_update(self) -> None:
"""Set the state with the value fetched from the inverter.""" """Set the state with the value fetched from the inverter."""

View File

@@ -56,7 +56,7 @@ class AquaCellConfigFlow(ConfigFlow, domain=DOMAIN):
refresh_token = await api.authenticate( refresh_token = await api.authenticate(
user_input[CONF_EMAIL], user_input[CONF_PASSWORD] user_input[CONF_EMAIL], user_input[CONF_PASSWORD]
) )
except ApiException: except (ApiException, TimeoutError):
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
except AuthenticationFailed: except AuthenticationFailed:
errors["base"] = "invalid_auth" errors["base"] = "invalid_auth"

View File

@@ -56,7 +56,7 @@ class AquacellCoordinator(DataUpdateCoordinator[dict[str, Softener]]):
so entities can quickly look up their data. so entities can quickly look up their data.
""" """
async with asyncio.timeout(10): async with asyncio.timeout(30):
# Check if the refresh token is expired # Check if the refresh token is expired
expiry_time = ( expiry_time = (
self.refresh_token_creation_time self.refresh_token_creation_time
@@ -72,7 +72,7 @@ class AquacellCoordinator(DataUpdateCoordinator[dict[str, Softener]]):
softeners = await self.aquacell_api.get_all_softeners() softeners = await self.aquacell_api.get_all_softeners()
except AuthenticationFailed as err: except AuthenticationFailed as err:
raise ConfigEntryError from err raise ConfigEntryError from err
except AquacellApiException as err: except (AquacellApiException, TimeoutError) as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err raise UpdateFailed(f"Error communicating with API: {err}") from err
return {softener.dsn: softener for softener in softeners} return {softener.dsn: softener for softener in softeners}

View File

@@ -4,13 +4,12 @@ from __future__ import annotations
import logging import logging
from aioaseko import APIUnavailable, InvalidAuthCredentials, MobileAccount from aioaseko import Aseko, AsekoNotLoggedIn
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN from .const import DOMAIN
from .coordinator import AsekoDataUpdateCoordinator from .coordinator import AsekoDataUpdateCoordinator
@@ -22,28 +21,17 @@ PLATFORMS: list[str] = [Platform.BINARY_SENSOR, Platform.SENSOR]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Aseko Pool Live from a config entry.""" """Set up Aseko Pool Live from a config entry."""
account = MobileAccount( aseko = Aseko(entry.data[CONF_EMAIL], entry.data[CONF_PASSWORD])
async_get_clientsession(hass),
username=entry.data[CONF_EMAIL],
password=entry.data[CONF_PASSWORD],
)
try: try:
units = await account.get_units() await aseko.login()
except InvalidAuthCredentials as err: except AsekoNotLoggedIn as err:
raise ConfigEntryAuthFailed from err raise ConfigEntryAuthFailed from err
except APIUnavailable as err:
raise ConfigEntryNotReady from err
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = []
for unit in units:
coordinator = AsekoDataUpdateCoordinator(hass, unit)
await coordinator.async_config_entry_first_refresh()
hass.data[DOMAIN][entry.entry_id].append((unit, coordinator))
coordinator = AsekoDataUpdateCoordinator(hass, aseko)
await coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True return True
@@ -51,7 +39,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id) hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok return unload_ok

View File

@@ -8,7 +8,6 @@ from dataclasses import dataclass
from aioaseko import Unit from aioaseko import Unit
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity, BinarySensorEntity,
BinarySensorEntityDescription, BinarySensorEntityDescription,
) )
@@ -25,26 +24,14 @@ from .entity import AsekoEntity
class AsekoBinarySensorEntityDescription(BinarySensorEntityDescription): class AsekoBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Describes an Aseko binary sensor entity.""" """Describes an Aseko binary sensor entity."""
value_fn: Callable[[Unit], bool] value_fn: Callable[[Unit], bool | None]
UNIT_BINARY_SENSORS: tuple[AsekoBinarySensorEntityDescription, ...] = ( BINARY_SENSORS: tuple[AsekoBinarySensorEntityDescription, ...] = (
AsekoBinarySensorEntityDescription( AsekoBinarySensorEntityDescription(
key="water_flow", key="water_flow",
translation_key="water_flow", translation_key="water_flow_to_probes",
value_fn=lambda unit: unit.water_flow, value_fn=lambda unit: unit.water_flow_to_probes,
),
AsekoBinarySensorEntityDescription(
key="has_alarm",
translation_key="alarm",
value_fn=lambda unit: unit.has_alarm,
device_class=BinarySensorDeviceClass.SAFETY,
),
AsekoBinarySensorEntityDescription(
key="has_error",
translation_key="error",
value_fn=lambda unit: unit.has_error,
device_class=BinarySensorDeviceClass.PROBLEM,
), ),
) )
@@ -55,33 +42,22 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the Aseko Pool Live binary sensors.""" """Set up the Aseko Pool Live binary sensors."""
data: list[tuple[Unit, AsekoDataUpdateCoordinator]] = hass.data[DOMAIN][ coordinator: AsekoDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
config_entry.entry_id units = coordinator.data.values()
]
async_add_entities( async_add_entities(
AsekoUnitBinarySensorEntity(unit, coordinator, description) AsekoBinarySensorEntity(unit, coordinator, description)
for unit, coordinator in data for description in BINARY_SENSORS
for description in UNIT_BINARY_SENSORS for unit in units
if description.value_fn(unit) is not None
) )
class AsekoUnitBinarySensorEntity(AsekoEntity, BinarySensorEntity): class AsekoBinarySensorEntity(AsekoEntity, BinarySensorEntity):
"""Representation of a unit water flow binary sensor entity.""" """Representation of an Aseko binary sensor entity."""
entity_description: AsekoBinarySensorEntityDescription entity_description: AsekoBinarySensorEntityDescription
def __init__(
self,
unit: Unit,
coordinator: AsekoDataUpdateCoordinator,
entity_description: AsekoBinarySensorEntityDescription,
) -> None:
"""Initialize the unit binary sensor."""
super().__init__(unit, coordinator)
self.entity_description = entity_description
self._attr_unique_id = f"{self._unit.serial_number}_{entity_description.key}"
@property @property
def is_on(self) -> bool: def is_on(self) -> bool | None:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self.entity_description.value_fn(self._unit) return self.entity_description.value_fn(self.unit)

View File

@@ -6,12 +6,11 @@ from collections.abc import Mapping
import logging import logging
from typing import Any from typing import Any
from aioaseko import APIUnavailable, InvalidAuthCredentials, WebAccount from aioaseko import Aseko, AsekoAPIError, AsekoInvalidCredentials
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, CONF_UNIQUE_ID from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, CONF_UNIQUE_ID
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN from .const import DOMAIN
@@ -34,15 +33,12 @@ class AsekoConfigFlow(ConfigFlow, domain=DOMAIN):
async def get_account_info(self, email: str, password: str) -> dict: async def get_account_info(self, email: str, password: str) -> dict:
"""Get account info from the mobile API and the web API.""" """Get account info from the mobile API and the web API."""
session = async_get_clientsession(self.hass) aseko = Aseko(email, password)
user = await aseko.login()
web_account = WebAccount(session, email, password)
web_account_info = await web_account.login()
return { return {
CONF_EMAIL: email, CONF_EMAIL: email,
CONF_PASSWORD: password, CONF_PASSWORD: password,
CONF_UNIQUE_ID: web_account_info.user_id, CONF_UNIQUE_ID: user.user_id,
} }
async def async_step_user( async def async_step_user(
@@ -58,9 +54,9 @@ class AsekoConfigFlow(ConfigFlow, domain=DOMAIN):
info = await self.get_account_info( info = await self.get_account_info(
user_input[CONF_EMAIL], user_input[CONF_PASSWORD] user_input[CONF_EMAIL], user_input[CONF_PASSWORD]
) )
except APIUnavailable: except AsekoAPIError:
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
except InvalidAuthCredentials: except AsekoInvalidCredentials:
errors["base"] = "invalid_auth" errors["base"] = "invalid_auth"
except Exception: except Exception:
_LOGGER.exception("Unexpected exception") _LOGGER.exception("Unexpected exception")
@@ -101,7 +97,7 @@ class AsekoConfigFlow(ConfigFlow, domain=DOMAIN):
) )
async def async_step_reauth( async def async_step_reauth(
self, user_input: Mapping[str, Any] self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult: ) -> ConfigFlowResult:
"""Perform reauth upon an API authentication error.""" """Perform reauth upon an API authentication error."""
@@ -109,10 +105,10 @@ class AsekoConfigFlow(ConfigFlow, domain=DOMAIN):
self.context["entry_id"] self.context["entry_id"]
) )
return await self.async_step_reauth_confirm(user_input) return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm( async def async_step_reauth_confirm(
self, user_input: Mapping | None = None self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult: ) -> ConfigFlowResult:
"""Dialog that informs the user that reauth is required.""" """Dialog that informs the user that reauth is required."""
@@ -122,9 +118,9 @@ class AsekoConfigFlow(ConfigFlow, domain=DOMAIN):
info = await self.get_account_info( info = await self.get_account_info(
user_input[CONF_EMAIL], user_input[CONF_PASSWORD] user_input[CONF_EMAIL], user_input[CONF_PASSWORD]
) )
except APIUnavailable: except AsekoAPIError:
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
except InvalidAuthCredentials: except AsekoInvalidCredentials:
errors["base"] = "invalid_auth" errors["base"] = "invalid_auth"
except Exception: except Exception:
_LOGGER.exception("Unexpected exception") _LOGGER.exception("Unexpected exception")

View File

@@ -5,34 +5,31 @@ from __future__ import annotations
from datetime import timedelta from datetime import timedelta
import logging import logging
from aioaseko import Unit, Variable from aioaseko import Aseko, Unit
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
class AsekoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Variable]]): class AsekoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Unit]]):
"""Class to manage fetching Aseko unit data from single endpoint.""" """Class to manage fetching Aseko unit data from single endpoint."""
def __init__(self, hass: HomeAssistant, unit: Unit) -> None: def __init__(self, hass: HomeAssistant, aseko: Aseko) -> None:
"""Initialize global Aseko unit data updater.""" """Initialize global Aseko unit data updater."""
self._unit = unit self._aseko = aseko
if self._unit.name:
name = self._unit.name
else:
name = f"{self._unit.type}-{self._unit.serial_number}"
super().__init__( super().__init__(
hass, hass,
_LOGGER, _LOGGER,
name=name, name=DOMAIN,
update_interval=timedelta(minutes=2), update_interval=timedelta(minutes=2),
) )
async def _async_update_data(self) -> dict[str, Variable]: async def _async_update_data(self) -> dict[str, Unit]:
"""Fetch unit data.""" """Fetch unit data."""
await self._unit.get_state() units = await self._aseko.get_units()
return {variable.type: variable for variable in self._unit.variables} return {unit.serial_number: unit for unit in units}

View File

@@ -3,6 +3,7 @@
from aioaseko import Unit from aioaseko import Unit
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN from .const import DOMAIN
@@ -14,20 +15,44 @@ class AsekoEntity(CoordinatorEntity[AsekoDataUpdateCoordinator]):
_attr_has_entity_name = True _attr_has_entity_name = True
def __init__(self, unit: Unit, coordinator: AsekoDataUpdateCoordinator) -> None: def __init__(
self,
unit: Unit,
coordinator: AsekoDataUpdateCoordinator,
description: EntityDescription,
) -> None:
"""Initialize the aseko entity.""" """Initialize the aseko entity."""
super().__init__(coordinator) super().__init__(coordinator)
self.entity_description = description
self._unit = unit self._unit = unit
self._attr_unique_id = f"{self.unit.serial_number}{self.entity_description.key}"
if self._unit.type == "Remote":
self._device_model = "ASIN Pool"
else:
self._device_model = f"ASIN AQUA {self._unit.type}"
self._device_name = self._unit.name if self._unit.name else self._device_model
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
name=self._device_name, identifiers={(DOMAIN, self.unit.serial_number)},
identifiers={(DOMAIN, str(self._unit.serial_number))}, serial_number=self.unit.serial_number,
manufacturer="Aseko", name=unit.name or unit.serial_number,
model=self._device_model, manufacturer=(
self.unit.brand_name.primary
if self.unit.brand_name is not None
else None
),
model=(
self.unit.brand_name.secondary
if self.unit.brand_name is not None
else None
),
configuration_url=f"https://aseko.cloud/unit/{self.unit.serial_number}",
)
@property
def unit(self) -> Unit:
"""Return the aseko unit."""
return self.coordinator.data[self._unit.serial_number]
@property
def available(self) -> bool:
"""Return True if entity is available."""
return (
super().available
and self.unit.serial_number in self.coordinator.data
and self.unit.online
) )

View File

@@ -1,16 +1,25 @@
{ {
"entity": { "entity": {
"binary_sensor": { "binary_sensor": {
"water_flow": { "water_flow_to_probes": {
"default": "mdi:waves-arrow-right" "default": "mdi:waves-arrow-right"
} }
}, },
"sensor": { "sensor": {
"air_temperature": {
"default": "mdi:thermometer-lines"
},
"free_chlorine": { "free_chlorine": {
"default": "mdi:flask" "default": "mdi:pool"
},
"redox": {
"default": "mdi:pool"
},
"salinity": {
"default": "mdi:pool"
}, },
"water_temperature": { "water_temperature": {
"default": "mdi:coolant-temperature" "default": "mdi:pool-thermometer"
} }
} }
} }

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/aseko_pool_live", "documentation": "https://www.home-assistant.io/integrations/aseko_pool_live",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["aioaseko"], "loggers": ["aioaseko"],
"requirements": ["aioaseko==0.2.0"] "requirements": ["aioaseko==1.0.0"]
} }

View File

@@ -2,77 +2,104 @@
from __future__ import annotations from __future__ import annotations
from aioaseko import Unit, Variable from collections.abc import Callable
from dataclasses import dataclass
from aioaseko import Unit
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,
SensorEntity, SensorEntity,
SensorEntityDescription,
SensorStateClass, SensorStateClass,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfElectricPotential, UnitOfTemperature
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import DOMAIN from .const import DOMAIN
from .coordinator import AsekoDataUpdateCoordinator from .coordinator import AsekoDataUpdateCoordinator
from .entity import AsekoEntity from .entity import AsekoEntity
@dataclass(frozen=True, kw_only=True)
class AsekoSensorEntityDescription(SensorEntityDescription):
"""Describes an Aseko sensor entity."""
value_fn: Callable[[Unit], StateType]
SENSORS: list[AsekoSensorEntityDescription] = [
AsekoSensorEntityDescription(
key="airTemp",
translation_key="air_temperature",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda unit: unit.air_temperature,
),
AsekoSensorEntityDescription(
key="free_chlorine",
translation_key="free_chlorine",
native_unit_of_measurement="mg/l",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda unit: unit.cl_free,
),
AsekoSensorEntityDescription(
key="ph",
device_class=SensorDeviceClass.PH,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda unit: unit.ph,
),
AsekoSensorEntityDescription(
key="rx",
translation_key="redox",
native_unit_of_measurement=UnitOfElectricPotential.MILLIVOLT,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda unit: unit.redox,
),
AsekoSensorEntityDescription(
key="salinity",
translation_key="salinity",
native_unit_of_measurement="kg/m³",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda unit: unit.salinity,
),
AsekoSensorEntityDescription(
key="waterTemp",
translation_key="water_temperature",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda unit: unit.water_temperature,
),
]
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the Aseko Pool Live sensors.""" """Set up the Aseko Pool Live sensors."""
data: list[tuple[Unit, AsekoDataUpdateCoordinator]] = hass.data[DOMAIN][ coordinator: AsekoDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
config_entry.entry_id units = coordinator.data.values()
]
async_add_entities( async_add_entities(
VariableSensorEntity(unit, variable, coordinator) AsekoSensorEntity(unit, coordinator, description)
for unit, coordinator in data for description in SENSORS
for variable in unit.variables for unit in units
if description.value_fn(unit) is not None
) )
class VariableSensorEntity(AsekoEntity, SensorEntity): class AsekoSensorEntity(AsekoEntity, SensorEntity):
"""Representation of a unit variable sensor entity.""" """Representation of an Aseko unit sensor entity."""
_attr_state_class = SensorStateClass.MEASUREMENT entity_description: AsekoSensorEntityDescription
def __init__(
self, unit: Unit, variable: Variable, coordinator: AsekoDataUpdateCoordinator
) -> None:
"""Initialize the variable sensor."""
super().__init__(unit, coordinator)
self._variable = variable
translation_key = {
"Air temp.": "air_temperature",
"Cl free": "free_chlorine",
"Water temp.": "water_temperature",
}.get(self._variable.name)
if translation_key is not None:
self._attr_translation_key = translation_key
else:
self._attr_name = self._variable.name
self._attr_unique_id = f"{self._unit.serial_number}{self._variable.type}"
self._attr_native_unit_of_measurement = self._variable.unit
self._attr_icon = {
"rx": "mdi:test-tube",
"waterLevel": "mdi:waves",
}.get(self._variable.type)
self._attr_device_class = {
"airTemp": SensorDeviceClass.TEMPERATURE,
"waterTemp": SensorDeviceClass.TEMPERATURE,
"ph": SensorDeviceClass.PH,
}.get(self._variable.type)
@property @property
def native_value(self) -> int | None: def native_value(self) -> StateType:
"""Return the state of the sensor.""" """Return the state of the sensor."""
variable = self.coordinator.data[self._variable.type] return self.entity_description.value_fn(self.unit)
return variable.current_value

View File

@@ -26,11 +26,8 @@
}, },
"entity": { "entity": {
"binary_sensor": { "binary_sensor": {
"water_flow": { "water_flow_to_probes": {
"name": "Water flow" "name": "Water flow to probes"
},
"alarm": {
"name": "Alarm"
} }
}, },
"sensor": { "sensor": {
@@ -40,6 +37,12 @@
"free_chlorine": { "free_chlorine": {
"name": "Free chlorine" "name": "Free chlorine"
}, },
"redox": {
"name": "Redox potential"
},
"salinity": {
"name": "Salinity"
},
"water_temperature": { "water_temperature": {
"name": "Water temperature" "name": "Water temperature"
} }

View File

@@ -5,6 +5,7 @@ from dataclasses import dataclass
import logging import logging
from pymicro_vad import MicroVad from pymicro_vad import MicroVad
from pyspeex_noise import AudioProcessor
from .const import BYTES_PER_CHUNK from .const import BYTES_PER_CHUNK
@@ -41,8 +42,8 @@ class AudioEnhancer(ABC):
"""Enhance chunk of PCM audio @ 16Khz with 16-bit mono samples.""" """Enhance chunk of PCM audio @ 16Khz with 16-bit mono samples."""
class MicroVadEnhancer(AudioEnhancer): class MicroVadSpeexEnhancer(AudioEnhancer):
"""Audio enhancer that just runs microVAD.""" """Audio enhancer that runs microVAD and speex."""
def __init__( def __init__(
self, auto_gain: int, noise_suppression: int, is_vad_enabled: bool self, auto_gain: int, noise_suppression: int, is_vad_enabled: bool
@@ -50,6 +51,24 @@ class MicroVadEnhancer(AudioEnhancer):
"""Initialize audio enhancer.""" """Initialize audio enhancer."""
super().__init__(auto_gain, noise_suppression, is_vad_enabled) super().__init__(auto_gain, noise_suppression, is_vad_enabled)
self.audio_processor: AudioProcessor | None = None
# Scale from 0-4
self.noise_suppression = noise_suppression * -15
# Scale from 0-31
self.auto_gain = auto_gain * 300
if (self.auto_gain != 0) or (self.noise_suppression != 0):
self.audio_processor = AudioProcessor(
self.auto_gain, self.noise_suppression
)
_LOGGER.debug(
"Initialized speex with auto_gain=%s, noise_suppression=%s",
self.auto_gain,
self.noise_suppression,
)
self.vad: MicroVad | None = None self.vad: MicroVad | None = None
self.threshold = 0.5 self.threshold = 0.5
@@ -61,12 +80,17 @@ class MicroVadEnhancer(AudioEnhancer):
"""Enhance 10ms chunk of PCM audio @ 16Khz with 16-bit mono samples.""" """Enhance 10ms chunk of PCM audio @ 16Khz with 16-bit mono samples."""
is_speech: bool | None = None is_speech: bool | None = None
assert len(audio) == BYTES_PER_CHUNK
if self.vad is not None: if self.vad is not None:
# Run VAD # Run VAD
assert len(audio) == BYTES_PER_CHUNK
speech_prob = self.vad.Process10ms(audio) speech_prob = self.vad.Process10ms(audio)
is_speech = speech_prob > self.threshold is_speech = speech_prob > self.threshold
if self.audio_processor is not None:
# Run noise suppression and auto gain
audio = self.audio_processor.Process10ms(audio).audio
return EnhancedAudioChunk( return EnhancedAudioChunk(
audio=audio, timestamp_ms=timestamp_ms, is_speech=is_speech audio=audio, timestamp_ms=timestamp_ms, is_speech=is_speech
) )

View File

@@ -7,5 +7,5 @@
"integration_type": "system", "integration_type": "system",
"iot_class": "local_push", "iot_class": "local_push",
"quality_scale": "internal", "quality_scale": "internal",
"requirements": ["pymicro-vad==1.0.1"] "requirements": ["pymicro-vad==1.0.1", "pyspeex-noise==1.0.2"]
} }

View File

@@ -49,7 +49,7 @@ from homeassistant.util import (
) )
from homeassistant.util.limited_size_dict import LimitedSizeDict from homeassistant.util.limited_size_dict import LimitedSizeDict
from .audio_enhancer import AudioEnhancer, EnhancedAudioChunk, MicroVadEnhancer from .audio_enhancer import AudioEnhancer, EnhancedAudioChunk, MicroVadSpeexEnhancer
from .const import ( from .const import (
BYTES_PER_CHUNK, BYTES_PER_CHUNK,
CONF_DEBUG_RECORDING_DIR, CONF_DEBUG_RECORDING_DIR,
@@ -589,7 +589,7 @@ class PipelineRun:
# Initialize with audio settings # Initialize with audio settings
if self.audio_settings.needs_processor and (self.audio_enhancer is None): if self.audio_settings.needs_processor and (self.audio_enhancer is None):
# Default audio enhancer # Default audio enhancer
self.audio_enhancer = MicroVadEnhancer( self.audio_enhancer = MicroVadSpeexEnhancer(
self.audio_settings.auto_gain_dbfs, self.audio_settings.auto_gain_dbfs,
self.audio_settings.noise_suppression_level, self.audio_settings.noise_suppression_level,
self.audio_settings.is_vad_enabled, self.audio_settings.is_vad_enabled,

View File

@@ -78,6 +78,9 @@ class VoiceCommandSegmenter:
speech_seconds: float = 0.3 speech_seconds: float = 0.3
"""Seconds of speech before voice command has started.""" """Seconds of speech before voice command has started."""
command_seconds: float = 1.0
"""Minimum number of seconds for a voice command."""
silence_seconds: float = 0.7 silence_seconds: float = 0.7
"""Seconds of silence after voice command has ended.""" """Seconds of silence after voice command has ended."""
@@ -96,6 +99,9 @@ class VoiceCommandSegmenter:
_speech_seconds_left: float = 0.0 _speech_seconds_left: float = 0.0
"""Seconds left before considering voice command as started.""" """Seconds left before considering voice command as started."""
_command_seconds_left: float = 0.0
"""Seconds left before voice command could stop."""
_silence_seconds_left: float = 0.0 _silence_seconds_left: float = 0.0
"""Seconds left before considering voice command as stopped.""" """Seconds left before considering voice command as stopped."""
@@ -112,6 +118,7 @@ class VoiceCommandSegmenter:
def reset(self) -> None: def reset(self) -> None:
"""Reset all counters and state.""" """Reset all counters and state."""
self._speech_seconds_left = self.speech_seconds self._speech_seconds_left = self.speech_seconds
self._command_seconds_left = self.command_seconds - self.speech_seconds
self._silence_seconds_left = self.silence_seconds self._silence_seconds_left = self.silence_seconds
self._timeout_seconds_left = self.timeout_seconds self._timeout_seconds_left = self.timeout_seconds
self._reset_seconds_left = self.reset_seconds self._reset_seconds_left = self.reset_seconds
@@ -142,6 +149,9 @@ class VoiceCommandSegmenter:
if self._speech_seconds_left <= 0: if self._speech_seconds_left <= 0:
# Inside voice command # Inside voice command
self.in_command = True self.in_command = True
self._command_seconds_left = (
self.command_seconds - self.speech_seconds
)
self._silence_seconds_left = self.silence_seconds self._silence_seconds_left = self.silence_seconds
_LOGGER.debug("Voice command started") _LOGGER.debug("Voice command started")
else: else:
@@ -154,7 +164,8 @@ class VoiceCommandSegmenter:
# Silence in command # Silence in command
self._reset_seconds_left = self.reset_seconds self._reset_seconds_left = self.reset_seconds
self._silence_seconds_left -= chunk_seconds self._silence_seconds_left -= chunk_seconds
if self._silence_seconds_left <= 0: self._command_seconds_left -= chunk_seconds
if (self._silence_seconds_left <= 0) and (self._command_seconds_left <= 0):
# Command finished successfully # Command finished successfully
self.reset() self.reset()
_LOGGER.debug("Voice command finished") _LOGGER.debug("Voice command finished")
@@ -163,6 +174,7 @@ class VoiceCommandSegmenter:
# Speech in command. # Speech in command.
# Reset silence counter if enough speech. # Reset silence counter if enough speech.
self._reset_seconds_left -= chunk_seconds self._reset_seconds_left -= chunk_seconds
self._command_seconds_left -= chunk_seconds
if self._reset_seconds_left <= 0: if self._reset_seconds_left <= 0:
self._silence_seconds_left = self.silence_seconds self._silence_seconds_left = self.silence_seconds
self._reset_seconds_left = self.reset_seconds self._reset_seconds_left = self.reset_seconds

View File

@@ -6,15 +6,16 @@ from pathlib import Path
from typing import cast from typing import cast
from aiohttp import ClientResponseError from aiohttp import ClientResponseError
from yalexs.const import Brand
from yalexs.exceptions import AugustApiAIOHTTPError from yalexs.exceptions import AugustApiAIOHTTPError
from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation
from yalexs.manager.gateway import Config as YaleXSConfig from yalexs.manager.gateway import Config as YaleXSConfig
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr, issue_registry as ir
from .const import DOMAIN, PLATFORMS from .const import DOMAIN, PLATFORMS
from .data import AugustData from .data import AugustData
@@ -24,7 +25,27 @@ from .util import async_create_august_clientsession
type AugustConfigEntry = ConfigEntry[AugustData] type AugustConfigEntry = ConfigEntry[AugustData]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @callback
def _async_create_yale_brand_migration_issue(
hass: HomeAssistant, entry: AugustConfigEntry
) -> None:
"""Create an issue for a brand migration."""
ir.async_create_issue(
hass,
DOMAIN,
"yale_brand_migration",
breaks_in_ha_version="2024.9",
learn_more_url="https://www.home-assistant.io/integrations/yale",
translation_key="yale_brand_migration",
is_fixable=False,
severity=ir.IssueSeverity.CRITICAL,
translation_placeholders={
"migrate_url": "https://my.home-assistant.io/redirect/config_flow_start?domain=yale"
},
)
async def async_setup_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool:
"""Set up August from a config entry.""" """Set up August from a config entry."""
session = async_create_august_clientsession(hass) session = async_create_august_clientsession(hass)
august_gateway = AugustGateway(Path(hass.config.config_dir), session) august_gateway = AugustGateway(Path(hass.config.config_dir), session)
@@ -40,6 +61,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True return True
async def async_remove_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> None:
"""Remove an August config entry."""
ir.async_delete_issue(hass, DOMAIN, "yale_brand_migration")
async def async_unload_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
@@ -51,6 +77,8 @@ async def async_setup_august(
"""Set up the August component.""" """Set up the August component."""
config = cast(YaleXSConfig, entry.data) config = cast(YaleXSConfig, entry.data)
await august_gateway.async_setup(config) await august_gateway.async_setup(config)
if august_gateway.api.brand == Brand.YALE_HOME:
_async_create_yale_brand_migration_issue(hass, entry)
await august_gateway.async_authenticate() await august_gateway.async_authenticate()
await august_gateway.async_refresh_access_token_if_needed() await august_gateway.async_refresh_access_token_if_needed()
data = entry.runtime_data = AugustData(hass, august_gateway) data = entry.runtime_data = AugustData(hass, august_gateway)

View File

@@ -109,12 +109,11 @@ async def async_setup_entry(
for description in SENSOR_TYPES_DOORBELL for description in SENSOR_TYPES_DOORBELL
) )
for doorbell in data.doorbells: entities.extend(
entities.extend( AugustDoorbellBinarySensor(data, doorbell, description)
AugustDoorbellBinarySensor(data, doorbell, description) for description in SENSOR_TYPES_DOORBELL + SENSOR_TYPES_VIDEO_DOORBELL
for description in SENSOR_TYPES_DOORBELL + SENSOR_TYPES_VIDEO_DOORBELL for doorbell in data.doorbells
) )
async_add_entities(entities) async_add_entities(entities)

View File

@@ -5,7 +5,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AugustConfigEntry from . import AugustConfigEntry
from .entity import AugustEntityMixin from .entity import AugustEntity
async def async_setup_entry( async def async_setup_entry(
@@ -18,7 +18,7 @@ async def async_setup_entry(
async_add_entities(AugustWakeLockButton(data, lock, "wake") for lock in data.locks) async_add_entities(AugustWakeLockButton(data, lock, "wake") for lock in data.locks)
class AugustWakeLockButton(AugustEntityMixin, ButtonEntity): class AugustWakeLockButton(AugustEntity, ButtonEntity):
"""Representation of an August lock wake button.""" """Representation of an August lock wake button."""
_attr_translation_key = "wake" _attr_translation_key = "wake"

View File

@@ -16,7 +16,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AugustConfigEntry, AugustData from . import AugustConfigEntry, AugustData
from .const import DEFAULT_NAME, DEFAULT_TIMEOUT from .const import DEFAULT_NAME, DEFAULT_TIMEOUT
from .entity import AugustEntityMixin from .entity import AugustEntity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -38,7 +38,7 @@ async def async_setup_entry(
) )
class AugustCamera(AugustEntityMixin, Camera): class AugustCamera(AugustEntity, Camera):
"""An implementation of an August security camera.""" """An implementation of an August security camera."""
_attr_translation_key = "camera" _attr_translation_key = "camera"

View File

@@ -9,7 +9,7 @@ from typing import Any
import aiohttp import aiohttp
import voluptuous as vol import voluptuous as vol
from yalexs.authenticator_common import ValidationResult from yalexs.authenticator_common import ValidationResult
from yalexs.const import BRANDS, DEFAULT_BRAND from yalexs.const import BRANDS_WITHOUT_OAUTH, DEFAULT_BRAND, Brand
from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
@@ -28,6 +28,12 @@ from .const import (
from .gateway import AugustGateway from .gateway import AugustGateway
from .util import async_create_august_clientsession from .util import async_create_august_clientsession
# The Yale Home Brand is not supported by the August integration
# anymore and should migrate to the Yale integration
AVAILABLE_BRANDS = BRANDS_WITHOUT_OAUTH.copy()
del AVAILABLE_BRANDS[Brand.YALE_HOME]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -118,7 +124,7 @@ class AugustConfigFlow(ConfigFlow, domain=DOMAIN):
vol.Required( vol.Required(
CONF_BRAND, CONF_BRAND,
default=self._user_auth_details.get(CONF_BRAND, DEFAULT_BRAND), default=self._user_auth_details.get(CONF_BRAND, DEFAULT_BRAND),
): vol.In(BRANDS), ): vol.In(AVAILABLE_BRANDS),
vol.Required( vol.Required(
CONF_LOGIN_METHOD, CONF_LOGIN_METHOD,
default=self._user_auth_details.get( default=self._user_auth_details.get(
@@ -208,7 +214,7 @@ class AugustConfigFlow(ConfigFlow, domain=DOMAIN):
vol.Required( vol.Required(
CONF_BRAND, CONF_BRAND,
default=self._user_auth_details.get(CONF_BRAND, DEFAULT_BRAND), default=self._user_auth_details.get(CONF_BRAND, DEFAULT_BRAND),
): vol.In(BRANDS), ): vol.In(BRANDS_WITHOUT_OAUTH),
vol.Required(CONF_PASSWORD): str, vol.Required(CONF_PASSWORD): str,
} }
), ),

View File

@@ -20,7 +20,7 @@ from .const import MANUFACTURER
DEVICE_TYPES = ["keypad", "lock", "camera", "doorbell", "door", "bell"] DEVICE_TYPES = ["keypad", "lock", "camera", "doorbell", "door", "bell"]
class AugustEntityMixin(Entity): class AugustEntity(Entity):
"""Base implementation for August device.""" """Base implementation for August device."""
_attr_should_poll = False _attr_should_poll = False
@@ -87,7 +87,7 @@ class AugustEntityMixin(Entity):
self._update_from_data() self._update_from_data()
class AugustDescriptionEntity(AugustEntityMixin): class AugustDescriptionEntity(AugustEntity):
"""An August entity with a description.""" """An August entity with a description."""
def __init__( def __init__(

View File

@@ -63,22 +63,17 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up the august event platform.""" """Set up the august event platform."""
data = config_entry.runtime_data data = config_entry.runtime_data
entities: list[AugustEventEntity] = [] entities: list[AugustEventEntity] = [
AugustEventEntity(data, lock, description)
for lock in data.locks: for description in TYPES_DOORBELL
detail = data.get_device_detail(lock.device_id) for lock in data.locks
if detail.doorbell: if (detail := data.get_device_detail(lock.device_id)) and detail.doorbell
entities.extend( ]
AugustEventEntity(data, lock, description) entities.extend(
for description in TYPES_DOORBELL AugustEventEntity(data, doorbell, description)
) for description in TYPES_DOORBELL + TYPES_VIDEO_DOORBELL
for doorbell in data.doorbells
for doorbell in data.doorbells: )
entities.extend(
AugustEventEntity(data, doorbell, description)
for description in TYPES_DOORBELL + TYPES_VIDEO_DOORBELL
)
async_add_entities(entities) async_add_entities(entities)
@@ -86,7 +81,6 @@ class AugustEventEntity(AugustDescriptionEntity, EventEntity):
"""An august event entity.""" """An august event entity."""
entity_description: AugustEventEntityDescription entity_description: AugustEventEntityDescription
_attr_has_entity_name = True
_last_activity: Activity | None = None _last_activity: Activity | None = None
@callback @callback

View File

@@ -19,7 +19,7 @@ from homeassistant.helpers.restore_state import RestoreEntity
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from . import AugustConfigEntry, AugustData from . import AugustConfigEntry, AugustData
from .entity import AugustEntityMixin from .entity import AugustEntity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -36,7 +36,7 @@ async def async_setup_entry(
async_add_entities(AugustLock(data, lock) for lock in data.locks) async_add_entities(AugustLock(data, lock) for lock in data.locks)
class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity): class AugustLock(AugustEntity, RestoreEntity, LockEntity):
"""Representation of an August lock.""" """Representation of an August lock."""
_attr_name = None _attr_name = None

View File

@@ -4,10 +4,6 @@
"codeowners": ["@bdraco"], "codeowners": ["@bdraco"],
"config_flow": true, "config_flow": true,
"dhcp": [ "dhcp": [
{
"hostname": "yale-connect-plus",
"macaddress": "00177A*"
},
{ {
"hostname": "connect", "hostname": "connect",
"macaddress": "D86162*" "macaddress": "D86162*"
@@ -28,5 +24,5 @@
"documentation": "https://www.home-assistant.io/integrations/august", "documentation": "https://www.home-assistant.io/integrations/august",
"iot_class": "cloud_push", "iot_class": "cloud_push",
"loggers": ["pubnub", "yalexs"], "loggers": ["pubnub", "yalexs"],
"requirements": ["yalexs==8.1.4", "yalexs-ble==2.4.3"] "requirements": ["yalexs==8.6.4", "yalexs-ble==2.4.3"]
} }

View File

@@ -4,7 +4,7 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Generic, TypeVar, cast from typing import Any, cast
from yalexs.activity import ActivityType, LockOperationActivity from yalexs.activity import ActivityType, LockOperationActivity
from yalexs.doorbell import Doorbell from yalexs.doorbell import Doorbell
@@ -42,7 +42,7 @@ from .const import (
OPERATION_METHOD_REMOTE, OPERATION_METHOD_REMOTE,
OPERATION_METHOD_TAG, OPERATION_METHOD_TAG,
) )
from .entity import AugustDescriptionEntity, AugustEntityMixin from .entity import AugustDescriptionEntity, AugustEntity
def _retrieve_device_battery_state(detail: LockDetail) -> int: def _retrieve_device_battery_state(detail: LockDetail) -> int:
@@ -55,14 +55,13 @@ def _retrieve_linked_keypad_battery_state(detail: KeypadDetail) -> int | None:
return detail.battery_percentage return detail.battery_percentage
_T = TypeVar("_T", LockDetail, KeypadDetail)
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class AugustSensorEntityDescription(SensorEntityDescription, Generic[_T]): class AugustSensorEntityDescription[T: LockDetail | KeypadDetail](
SensorEntityDescription
):
"""Mixin for required keys.""" """Mixin for required keys."""
value_fn: Callable[[_T], int | None] value_fn: Callable[[T], int | None]
SENSOR_TYPE_DEVICE_BATTERY = AugustSensorEntityDescription[LockDetail]( SENSOR_TYPE_DEVICE_BATTERY = AugustSensorEntityDescription[LockDetail](
@@ -114,7 +113,7 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
class AugustOperatorSensor(AugustEntityMixin, RestoreSensor): class AugustOperatorSensor(AugustEntity, RestoreSensor):
"""Representation of an August lock operation sensor.""" """Representation of an August lock operation sensor."""
_attr_translation_key = "operator" _attr_translation_key = "operator"
@@ -198,10 +197,12 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreSensor):
self._operated_autorelock = last_attrs[ATTR_OPERATION_AUTORELOCK] self._operated_autorelock = last_attrs[ATTR_OPERATION_AUTORELOCK]
class AugustBatterySensor(AugustDescriptionEntity, SensorEntity, Generic[_T]): class AugustBatterySensor[T: LockDetail | KeypadDetail](
AugustDescriptionEntity, SensorEntity
):
"""Representation of an August sensor.""" """Representation of an August sensor."""
entity_description: AugustSensorEntityDescription[_T] entity_description: AugustSensorEntityDescription[T]
_attr_device_class = SensorDeviceClass.BATTERY _attr_device_class = SensorDeviceClass.BATTERY
_attr_native_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE

View File

@@ -1,4 +1,10 @@
{ {
"issues": {
"yale_brand_migration": {
"title": "Yale Home has a new integration",
"description": "Add the [Yale integration]({migrate_url}), and remove the August integration as soon as possible to avoid an interruption in service. The Yale Home brand will stop working with the August integration soon and will be removed in a future release."
}
},
"config": { "config": {
"error": { "error": {
"unhandled": "Unhandled error: {error}", "unhandled": "Unhandled error: {error}",

View File

@@ -63,16 +63,11 @@ def _activity_time_based(latest: Activity) -> Activity | None:
"""Get the latest state of the sensor.""" """Get the latest state of the sensor."""
start = latest.activity_start_time start = latest.activity_start_time
end = latest.activity_end_time + TIME_TO_DECLARE_DETECTION end = latest.activity_end_time + TIME_TO_DECLARE_DETECTION
if start <= _native_datetime() <= end: if start <= datetime.now() <= end:
return latest return latest
return None return None
def _native_datetime() -> datetime:
"""Return time in the format august uses without timezone."""
return datetime.now()
def retrieve_online_state( def retrieve_online_state(
data: AugustData, detail: DoorbellDetail | LockDetail data: AugustData, detail: DoorbellDetail | LockDetail
) -> bool: ) -> bool:

View File

@@ -75,11 +75,10 @@ class AuroraABBConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
def __init__(self): def __init__(self) -> None:
"""Initialise the config flow.""" """Initialise the config flow."""
self.config = None
self._com_ports_list: list[str] | None = None self._com_ports_list: list[str] | None = None
self._default_com_port = None self._default_com_port: str | None = None
async def async_step_user( async def async_step_user(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None

View File

@@ -22,11 +22,11 @@ class AussieBroadbandConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
def __init__(self): def __init__(self) -> None:
"""Initialize the config flow.""" """Initialize the config flow."""
self.data: dict = {} self.data: dict = {}
self.options: dict = {CONF_SERVICES: []} self.options: dict = {CONF_SERVICES: []}
self.services: list[dict[str]] = [] self.services: list[dict[str, Any]] = []
self.client: AussieBB | None = None self.client: AussieBB | None = None
self._reauth_username: str | None = None self._reauth_username: str | None = None
@@ -99,15 +99,11 @@ class AussieBroadbandConfigFlow(ConfigFlow, domain=DOMAIN):
} }
if not (errors := await self.async_auth(data)): if not (errors := await self.async_auth(data)):
entry = await self.async_set_unique_id(self._reauth_username.lower()) entry = self.hass.config_entries.async_get_entry(
if entry: self.context["entry_id"]
self.hass.config_entries.async_update_entry( )
entry, assert entry
data=data, return self.async_update_reload_and_abort(entry, data=data)
)
await self.hass.config_entries.async_reload(entry.entry_id)
return self.async_abort(reason="reauth_successful")
return self.async_create_entry(title=self._reauth_username, data=data)
return self.async_show_form( return self.async_show_form(
step_id="reauth_confirm", step_id="reauth_confirm",

View File

@@ -10,8 +10,10 @@ blueprint:
selector: selector:
entity: entity:
filter: filter:
device_class: motion - device_class: occupancy
domain: binary_sensor domain: binary_sensor
- device_class: motion
domain: binary_sensor
light_target: light_target:
name: Light name: Light
selector: selector:

View File

@@ -9,10 +9,20 @@
} }
}, },
"services": { "services": {
"turn_on": "mdi:robot", "turn_on": {
"turn_off": "mdi:robot-off", "service": "mdi:robot"
"toggle": "mdi:robot", },
"trigger": "mdi:robot", "turn_off": {
"reload": "mdi:reload" "service": "mdi:robot-off"
},
"toggle": {
"service": "mdi:robot"
},
"trigger": {
"service": "mdi:robot"
},
"reload": {
"service": "mdi:reload"
}
} }
} }

View File

@@ -1,6 +1,5 @@
"""Config flow for AWS component.""" """Config flow for AWS component."""
from collections.abc import Mapping
from typing import Any from typing import Any
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
@@ -13,11 +12,9 @@ class AWSFlowHandler(ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
async def async_step_import( async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
self, user_input: Mapping[str, Any]
) -> ConfigFlowResult:
"""Import a config entry.""" """Import a config entry."""
if self._async_current_entries(): if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed") return self.async_abort(reason="single_instance_allowed")
return self.async_create_entry(title="configuration.yaml", data=user_input) return self.async_create_entry(title="configuration.yaml", data=import_data)

View File

@@ -6,7 +6,7 @@ import logging
from typing import Final from typing import Final
from aioazuredevops.client import DevOpsClient from aioazuredevops.client import DevOpsClient
from aioazuredevops.models.builds import Build from aioazuredevops.models.build import Build
from aioazuredevops.models.core import Project from aioazuredevops.models.core import Project
import aiohttp import aiohttp

View File

@@ -2,7 +2,7 @@
from dataclasses import dataclass from dataclasses import dataclass
from aioazuredevops.models.builds import Build from aioazuredevops.models.build import Build
from aioazuredevops.models.core import Project from aioazuredevops.models.core import Project

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/azure_devops", "documentation": "https://www.home-assistant.io/integrations/azure_devops",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["aioazuredevops"], "loggers": ["aioazuredevops"],
"requirements": ["aioazuredevops==2.1.1"] "requirements": ["aioazuredevops==2.2.1"]
} }

View File

@@ -8,7 +8,7 @@ from datetime import datetime
import logging import logging
from typing import Any from typing import Any
from aioazuredevops.models.builds import Build from aioazuredevops.models.build import Build
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,

View File

@@ -154,17 +154,15 @@ class AEHConfigFlow(ConfigFlow, domain=DOMAIN):
options=self._options, options=self._options,
) )
async def async_step_import( async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
self, import_config: dict[str, Any]
) -> ConfigFlowResult:
"""Import config from configuration.yaml.""" """Import config from configuration.yaml."""
if self._async_current_entries(): if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed") return self.async_abort(reason="single_instance_allowed")
if CONF_SEND_INTERVAL in import_config: if CONF_SEND_INTERVAL in import_data:
self._options[CONF_SEND_INTERVAL] = import_config.pop(CONF_SEND_INTERVAL) self._options[CONF_SEND_INTERVAL] = import_data.pop(CONF_SEND_INTERVAL)
if CONF_MAX_DELAY in import_config: if CONF_MAX_DELAY in import_data:
self._options[CONF_MAX_DELAY] = import_config.pop(CONF_MAX_DELAY) self._options[CONF_MAX_DELAY] = import_data.pop(CONF_MAX_DELAY)
self._data = import_config self._data = import_data
errors = await validate_data(self._data) errors = await validate_data(self._data)
if errors: if errors:
return self.async_abort(reason=errors["base"]) return self.async_abort(reason=errors["base"])

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"create": "mdi:cloud-upload" "create": {
"service": "mdi:cloud-upload"
}
} }
} }

View File

@@ -17,6 +17,7 @@ from homeassistant.const import CONF_HOST, CONF_MODEL, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
import homeassistant.helpers.device_registry as dr import homeassistant.helpers.device_registry as dr
from homeassistant.util.ssl import get_default_context
from .const import DOMAIN from .const import DOMAIN
from .websocket import BangOlufsenWebsocket from .websocket import BangOlufsenWebsocket
@@ -48,7 +49,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
model=entry.data[CONF_MODEL], model=entry.data[CONF_MODEL],
) )
client = MozartClient(host=entry.data[CONF_HOST]) client = MozartClient(host=entry.data[CONF_HOST], ssl_context=get_default_context())
# Check API and WebSocket connection # Check API and WebSocket connection
try: try:

View File

@@ -14,6 +14,7 @@ from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_HOST, CONF_MODEL from homeassistant.const import CONF_HOST, CONF_MODEL
from homeassistant.helpers.selector import SelectSelector, SelectSelectorConfig from homeassistant.helpers.selector import SelectSelector, SelectSelectorConfig
from homeassistant.util.ssl import get_default_context
from .const import ( from .const import (
ATTR_FRIENDLY_NAME, ATTR_FRIENDLY_NAME,
@@ -87,7 +88,9 @@ class BangOlufsenConfigFlowHandler(ConfigFlow, domain=DOMAIN):
errors={"base": _exception_map[type(error)]}, errors={"base": _exception_map[type(error)]},
) )
self._client = MozartClient(self._host) self._client = MozartClient(
host=self._host, ssl_context=get_default_context()
)
# Try to get information from Beolink self method. # Try to get information from Beolink self method.
async with self._client: async with self._client:
@@ -136,7 +139,7 @@ class BangOlufsenConfigFlowHandler(ConfigFlow, domain=DOMAIN):
return self.async_abort(reason="ipv6_address") return self.async_abort(reason="ipv6_address")
# Check connection to ensure valid address is received # Check connection to ensure valid address is received
self._client = MozartClient(self._host) self._client = MozartClient(self._host, ssl_context=get_default_context())
async with self._client: async with self._client:
try: try:

View File

@@ -6,6 +6,6 @@
"documentation": "https://www.home-assistant.io/integrations/bang_olufsen", "documentation": "https://www.home-assistant.io/integrations/bang_olufsen",
"integration_type": "device", "integration_type": "device",
"iot_class": "local_push", "iot_class": "local_push",
"requirements": ["mozart-api==3.4.1.8.6"], "requirements": ["mozart-api==3.4.1.8.8"],
"zeroconf": ["_bangolufsen._tcp.local."] "zeroconf": ["_bangolufsen._tcp.local."]
} }

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"reload": "mdi:reload" "reload": {
"service": "mdi:reload"
}
} }
} }

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"set_all_zones": "mdi:home-sound-in" "set_all_zones": {
"service": "mdi:home-sound-in"
}
} }
} }

View File

@@ -35,15 +35,11 @@ from .const import (
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
def host_port(data):
"""Return a list with host and port."""
return (data[CONF_HOST], data[CONF_PORT])
def create_schema(previous_input=None): def create_schema(previous_input=None):
"""Create a schema with given values as default.""" """Create a schema with given values as default."""
if previous_input is not None: if previous_input is not None:
host, port = host_port(previous_input) host = previous_input[CONF_HOST]
port = previous_input[CONF_PORT]
else: else:
host = DEFAULT_HOST host = DEFAULT_HOST
port = DEFAULT_PORT port = DEFAULT_PORT
@@ -70,9 +66,9 @@ class BleBoxConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
def __init__(self): def __init__(self) -> None:
"""Initialize the BleBox config flow.""" """Initialize the BleBox config flow."""
self.device_config = {} self.device_config: dict[str, Any] = {}
def handle_step_exception( def handle_step_exception(
self, step, exception, schema, host, port, message_id, log_fn self, step, exception, schema, host, port, message_id, log_fn
@@ -146,7 +142,9 @@ class BleBoxConfigFlow(ConfigFlow, domain=DOMAIN):
}, },
) )
async def async_step_user(self, user_input=None): async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle initial user-triggered config step.""" """Handle initial user-triggered config step."""
hass = self.hass hass = self.hass
schema = create_schema(user_input) schema = create_schema(user_input)
@@ -159,14 +157,14 @@ class BleBoxConfigFlow(ConfigFlow, domain=DOMAIN):
description_placeholders={}, description_placeholders={},
) )
addr = host_port(user_input) host = user_input[CONF_HOST]
port = user_input[CONF_PORT]
username = user_input.get(CONF_USERNAME) username = user_input.get(CONF_USERNAME)
password = user_input.get(CONF_PASSWORD) password = user_input.get(CONF_PASSWORD)
for entry in self._async_current_entries(): for entry in self._async_current_entries():
if addr == host_port(entry.data): if host == entry.data[CONF_HOST] and port == entry.data[CONF_PORT]:
host, port = addr
return self.async_abort( return self.async_abort(
reason=ADDRESS_ALREADY_CONFIGURED, reason=ADDRESS_ALREADY_CONFIGURED,
description_placeholders={"address": f"{host}:{port}"}, description_placeholders={"address": f"{host}:{port}"},
@@ -174,27 +172,35 @@ class BleBoxConfigFlow(ConfigFlow, domain=DOMAIN):
websession = get_maybe_authenticated_session(hass, password, username) websession = get_maybe_authenticated_session(hass, password, username)
api_host = ApiHost(*addr, DEFAULT_SETUP_TIMEOUT, websession, hass.loop, _LOGGER) api_host = ApiHost(
host, port, DEFAULT_SETUP_TIMEOUT, websession, hass.loop, _LOGGER
)
try: try:
product = await Box.async_from_host(api_host) product = await Box.async_from_host(api_host)
except UnsupportedBoxVersion as ex: except UnsupportedBoxVersion as ex:
return self.handle_step_exception( return self.handle_step_exception(
"user", ex, schema, *addr, UNSUPPORTED_VERSION, _LOGGER.debug "user",
ex,
schema,
host,
port,
UNSUPPORTED_VERSION,
_LOGGER.debug,
) )
except UnauthorizedRequest as ex: except UnauthorizedRequest as ex:
return self.handle_step_exception( return self.handle_step_exception(
"user", ex, schema, *addr, CANNOT_CONNECT, _LOGGER.error "user", ex, schema, host, port, CANNOT_CONNECT, _LOGGER.error
) )
except Error as ex: except Error as ex:
return self.handle_step_exception( return self.handle_step_exception(
"user", ex, schema, *addr, CANNOT_CONNECT, _LOGGER.warning "user", ex, schema, host, port, CANNOT_CONNECT, _LOGGER.warning
) )
except RuntimeError as ex: except RuntimeError as ex:
return self.handle_step_exception( return self.handle_step_exception(
"user", ex, schema, *addr, UNKNOWN, _LOGGER.error "user", ex, schema, host, port, UNKNOWN, _LOGGER.error
) )
# Check if configured but IP changed since # Check if configured but IP changed since

View File

@@ -60,6 +60,9 @@ COLOR_MODE_MAP = {
class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity): class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
"""Representation of BleBox lights.""" """Representation of BleBox lights."""
_attr_max_mireds = 370 # 1,000,000 divided by 2700 Kelvin = 370 Mireds
_attr_min_mireds = 154 # 1,000,000 divided by 6500 Kelvin = 154 Mireds
def __init__(self, feature: blebox_uniapi.light.Light) -> None: def __init__(self, feature: blebox_uniapi.light.Light) -> None:
"""Initialize a BleBox light.""" """Initialize a BleBox light."""
super().__init__(feature) super().__init__(feature)
@@ -87,12 +90,7 @@ class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
Set values to _attr_ibutes if needed. Set values to _attr_ibutes if needed.
""" """
color_mode_tmp = COLOR_MODE_MAP.get(self._feature.color_mode, ColorMode.ONOFF) return COLOR_MODE_MAP.get(self._feature.color_mode, ColorMode.ONOFF)
if color_mode_tmp == ColorMode.COLOR_TEMP:
self._attr_min_mireds = 1
self._attr_max_mireds = 255
return color_mode_tmp
@property @property
def supported_color_modes(self): def supported_color_modes(self):

View File

@@ -12,10 +12,20 @@
} }
}, },
"services": { "services": {
"record": "mdi:video-box", "record": {
"trigger_camera": "mdi:image-refresh", "service": "mdi:video-box"
"save_video": "mdi:file-video", },
"save_recent_clips": "mdi:file-video", "trigger_camera": {
"send_pin": "mdi:two-factor-authentication" "service": "mdi:image-refresh"
},
"save_video": {
"service": "mdi:file-video"
},
"save_recent_clips": {
"service": "mdi:file-video"
},
"send_pin": {
"service": "mdi:two-factor-authentication"
}
} }
} }

View File

@@ -1,8 +1,16 @@
{ {
"services": { "services": {
"join": "mdi:link-variant", "join": {
"unjoin": "mdi:link-variant-off", "service": "mdi:link-variant"
"set_sleep_timer": "mdi:sleep", },
"clear_sleep_timer": "mdi:sleep-off" "unjoin": {
"service": "mdi:link-variant-off"
},
"set_sleep_timer": {
"service": "mdi:sleep"
},
"clear_sleep_timer": {
"service": "mdi:sleep-off"
}
} }
} }

View File

@@ -309,7 +309,7 @@ class BluesoundPlayer(MediaPlayerEntity):
return True return True
async def _start_poll_command(self): async def _poll_loop(self):
"""Loop which polls the status of the player.""" """Loop which polls the status of the player."""
while True: while True:
try: try:
@@ -335,7 +335,7 @@ class BluesoundPlayer(MediaPlayerEntity):
await super().async_added_to_hass() await super().async_added_to_hass()
self._polling_task = self.hass.async_create_background_task( self._polling_task = self.hass.async_create_background_task(
self._start_poll_command(), self._poll_loop(),
name=f"bluesound.polling_{self.host}:{self.port}", name=f"bluesound.polling_{self.host}:{self.port}",
) )
@@ -345,7 +345,9 @@ class BluesoundPlayer(MediaPlayerEntity):
assert self._polling_task is not None assert self._polling_task is not None
if self._polling_task.cancel(): if self._polling_task.cancel():
await self._polling_task # the sleeps in _poll_loop will raise CancelledError
with suppress(CancelledError):
await self._polling_task
self.hass.data[DATA_BLUESOUND].remove(self) self.hass.data[DATA_BLUESOUND].remove(self)

View File

@@ -18,8 +18,8 @@
"bleak-retry-connector==3.5.0", "bleak-retry-connector==3.5.0",
"bluetooth-adapters==0.19.4", "bluetooth-adapters==0.19.4",
"bluetooth-auto-recovery==1.4.2", "bluetooth-auto-recovery==1.4.2",
"bluetooth-data-tools==1.19.4", "bluetooth-data-tools==1.20.0",
"dbus-fast==2.23.0", "dbus-fast==2.24.0",
"habluetooth==3.3.2" "habluetooth==3.4.0"
] ]
} }

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"update": "mdi:update" "update": {
"service": "mdi:update"
}
} }
} }

View File

@@ -15,6 +15,7 @@ from homeassistant.const import CONF_PASSWORD, CONF_REGION, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util.ssl import get_default_context
from .const import CONF_GCID, CONF_READ_ONLY, CONF_REFRESH_TOKEN, DOMAIN, SCAN_INTERVALS from .const import CONF_GCID, CONF_READ_ONLY, CONF_REFRESH_TOKEN, DOMAIN, SCAN_INTERVALS
@@ -33,6 +34,7 @@ class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]):
entry.data[CONF_PASSWORD], entry.data[CONF_PASSWORD],
get_region_from_name(entry.data[CONF_REGION]), get_region_from_name(entry.data[CONF_REGION]),
observer_position=GPSPosition(hass.config.latitude, hass.config.longitude), observer_position=GPSPosition(hass.config.latitude, hass.config.longitude),
verify=get_default_context(),
) )
self.read_only = entry.options[CONF_READ_ONLY] self.read_only = entry.options[CONF_READ_ONLY]
self._entry = entry self._entry = entry

View File

@@ -7,5 +7,5 @@
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["bimmer_connected"], "loggers": ["bimmer_connected"],
"quality_scale": "platinum", "quality_scale": "platinum",
"requirements": ["bimmer-connected[china]==0.16.1"] "requirements": ["bimmer-connected[china]==0.16.3"]
} }

View File

@@ -148,7 +148,8 @@
"cooling": "Cooling", "cooling": "Cooling",
"heating": "Heating", "heating": "Heating",
"inactive": "Inactive", "inactive": "Inactive",
"standby": "Standby" "standby": "Standby",
"ventilation": "Ventilation"
} }
}, },
"front_left_current_pressure": { "front_left_current_pressure": {

View File

@@ -96,12 +96,26 @@
} }
}, },
"services": { "services": {
"set_fan_speed_tracked_state": "mdi:fan", "set_fan_speed_tracked_state": {
"set_switch_power_tracked_state": "mdi:toggle-switch-variant", "service": "mdi:fan"
"set_light_power_tracked_state": "mdi:lightbulb", },
"set_light_brightness_tracked_state": "mdi:lightbulb-on", "set_switch_power_tracked_state": {
"start_increasing_brightness": "mdi:brightness-7", "service": "mdi:toggle-switch-variant"
"start_decreasing_brightness": "mdi:brightness-1", },
"stop": "mdi:stop" "set_light_power_tracked_state": {
"service": "mdi:lightbulb"
},
"set_light_brightness_tracked_state": {
"service": "mdi:lightbulb-on"
},
"start_increasing_brightness": {
"service": "mdi:brightness-7"
},
"start_decreasing_brightness": {
"service": "mdi:brightness-1"
},
"stop": {
"service": "mdi:stop"
}
} }
} }

View File

@@ -7,6 +7,8 @@
} }
}, },
"services": { "services": {
"send_message": "mdi:cellphone-message" "send_message": {
"service": "mdi:cellphone-message"
}
} }
} }

View File

@@ -5,7 +5,7 @@ import errno
from functools import partial from functools import partial
import logging import logging
import socket import socket
from typing import Any from typing import TYPE_CHECKING, Any
import broadlink as blk import broadlink as blk
from broadlink.exceptions import ( from broadlink.exceptions import (
@@ -39,9 +39,11 @@ class BroadlinkFlowHandler(ConfigFlow, domain=DOMAIN):
def __init__(self) -> None: def __init__(self) -> None:
"""Initialize the Broadlink flow.""" """Initialize the Broadlink flow."""
self.device = None self.device: blk.Device | None = None
async def async_set_device(self, device, raise_on_progress=True): async def async_set_device(
self, device: blk.Device, raise_on_progress: bool = True
) -> None:
"""Define a device for the config flow.""" """Define a device for the config flow."""
if device.type not in DEVICE_TYPES: if device.type not in DEVICE_TYPES:
_LOGGER.error( _LOGGER.error(
@@ -90,7 +92,9 @@ class BroadlinkFlowHandler(ConfigFlow, domain=DOMAIN):
await self.async_set_device(device) await self.async_set_device(device)
return await self.async_step_auth() return await self.async_step_auth()
async def async_step_user(self, user_input=None): async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a flow initiated by the user.""" """Handle a flow initiated by the user."""
errors = {} errors = {}
@@ -127,6 +131,8 @@ class BroadlinkFlowHandler(ConfigFlow, domain=DOMAIN):
) )
return await self.async_step_auth() return await self.async_step_auth()
if TYPE_CHECKING:
assert self.device
if device.mac == self.device.mac: if device.mac == self.device.mac:
await self.async_set_device(device, raise_on_progress=False) await self.async_set_device(device, raise_on_progress=False)
return await self.async_step_auth() return await self.async_step_auth()
@@ -308,10 +314,10 @@ class BroadlinkFlowHandler(ConfigFlow, domain=DOMAIN):
step_id="finish", data_schema=vol.Schema(data_schema), errors=errors step_id="finish", data_schema=vol.Schema(data_schema), errors=errors
) )
async def async_step_import(self, import_info): async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
"""Import a device.""" """Import a device."""
self._async_abort_entries_match({CONF_HOST: import_info[CONF_HOST]}) self._async_abort_entries_match({CONF_HOST: import_data[CONF_HOST]})
return await self.async_step_user(import_info) return await self.async_step_user(import_data)
async def async_step_reauth( async def async_step_reauth(
self, entry_data: Mapping[str, Any] self, entry_data: Mapping[str, Any]

View File

@@ -1,5 +1,7 @@
{ {
"services": { "services": {
"browse_url": "mdi:web" "browse_url": {
"service": "mdi:web"
}
} }
} }

View File

@@ -20,5 +20,8 @@ async def async_get_config_entry_diagnostics(
return { return {
"info": data.info.to_dict(), "info": data.info.to_dict(),
"device": data.device.to_dict(), "device": data.device.to_dict(),
"state": data.coordinator.data.state.to_dict(), "coordinator_data": {
"state": data.coordinator.data.state.to_dict(),
},
"static": data.static.to_dict(),
} }

View File

@@ -22,10 +22,10 @@ class BSBLanEntity(CoordinatorEntity[BSBLanUpdateCoordinator]):
def __init__(self, coordinator: BSBLanUpdateCoordinator, data: BSBLanData) -> None: def __init__(self, coordinator: BSBLanUpdateCoordinator, data: BSBLanData) -> None:
"""Initialize BSBLan entity.""" """Initialize BSBLan entity."""
super().__init__(coordinator, data) super().__init__(coordinator, data)
host = self.coordinator.config_entry.data["host"] host = coordinator.config_entry.data["host"]
mac = self.coordinator.config_entry.data["mac"] mac = data.device.MAC
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, data.device.MAC)}, identifiers={(DOMAIN, mac)},
connections={(CONNECTION_NETWORK_MAC, format_mac(mac))}, connections={(CONNECTION_NETWORK_MAC, format_mac(mac))},
name=data.device.name, name=data.device.name,
manufacturer="BSBLAN Inc.", manufacturer="BSBLAN Inc.",

View File

@@ -7,6 +7,9 @@ from typing import Any
import voluptuous as vol import voluptuous as vol
from homeassistant.components.device_automation import DEVICE_TRIGGER_BASE_SCHEMA from homeassistant.components.device_automation import DEVICE_TRIGGER_BASE_SCHEMA
from homeassistant.components.device_automation.exceptions import (
InvalidDeviceAutomationConfig,
)
from homeassistant.components.homeassistant.triggers import event as event_trigger from homeassistant.components.homeassistant.triggers import event as event_trigger
from homeassistant.const import ( from homeassistant.const import (
CONF_DEVICE_ID, CONF_DEVICE_ID,
@@ -43,33 +46,46 @@ TRIGGERS_BY_EVENT_CLASS = {
EVENT_CLASS_DIMMER: {"rotate_left", "rotate_right"}, EVENT_CLASS_DIMMER: {"rotate_left", "rotate_right"},
} }
SCHEMA_BY_EVENT_CLASS = { TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
EVENT_CLASS_BUTTON: DEVICE_TRIGGER_BASE_SCHEMA.extend( {vol.Required(CONF_TYPE): str, vol.Required(CONF_SUBTYPE): str}
{ )
vol.Required(CONF_TYPE): vol.In([EVENT_CLASS_BUTTON]),
vol.Required(CONF_SUBTYPE): vol.In(
TRIGGERS_BY_EVENT_CLASS[EVENT_CLASS_BUTTON]
),
}
),
EVENT_CLASS_DIMMER: DEVICE_TRIGGER_BASE_SCHEMA.extend(
{
vol.Required(CONF_TYPE): vol.In([EVENT_CLASS_DIMMER]),
vol.Required(CONF_SUBTYPE): vol.In(
TRIGGERS_BY_EVENT_CLASS[EVENT_CLASS_DIMMER]
),
}
),
}
async def async_validate_trigger_config( async def async_validate_trigger_config(
hass: HomeAssistant, config: ConfigType hass: HomeAssistant, config: ConfigType
) -> ConfigType: ) -> ConfigType:
"""Validate trigger config.""" """Validate trigger config."""
return SCHEMA_BY_EVENT_CLASS.get(config[CONF_TYPE], DEVICE_TRIGGER_BASE_SCHEMA)( # type: ignore[no-any-return] config = TRIGGER_SCHEMA(config)
config event_class = config[CONF_TYPE]
event_type = config[CONF_SUBTYPE]
device_registry = dr.async_get(hass)
device = device_registry.async_get(config[CONF_DEVICE_ID])
assert device is not None
config_entries = [
hass.config_entries.async_get_entry(entry_id)
for entry_id in device.config_entries
]
bthome_config_entry = next(
iter(entry for entry in config_entries if entry and entry.domain == DOMAIN)
) )
event_classes: list[str] = bthome_config_entry.data.get(
CONF_DISCOVERED_EVENT_CLASSES, []
)
if event_class not in event_classes:
raise InvalidDeviceAutomationConfig(
f"BTHome trigger {event_class} is not valid for device "
f"{device} ({config[CONF_DEVICE_ID]})"
)
if event_type not in TRIGGERS_BY_EVENT_CLASS.get(event_class.split("_")[0], ()):
raise InvalidDeviceAutomationConfig(
f"BTHome trigger {event_type} is not valid for device "
f"{device} ({config[CONF_DEVICE_ID]})"
)
return config
async def async_get_triggers( async def async_get_triggers(

View File

@@ -27,6 +27,7 @@ from homeassistant.const import (
PERCENTAGE, PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT, SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory, EntityCategory,
UnitOfConductivity,
UnitOfElectricCurrent, UnitOfElectricCurrent,
UnitOfElectricPotential, UnitOfElectricPotential,
UnitOfEnergy, UnitOfEnergy,
@@ -356,6 +357,16 @@ SENSOR_DESCRIPTIONS = {
native_unit_of_measurement=UnitOfVolume.LITERS, native_unit_of_measurement=UnitOfVolume.LITERS,
state_class=SensorStateClass.TOTAL, state_class=SensorStateClass.TOTAL,
), ),
# Conductivity (µS/cm)
(
BTHomeSensorDeviceClass.CONDUCTIVITY,
Units.CONDUCTIVITY,
): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.CONDUCTIVITY}_{Units.CONDUCTIVITY}",
device_class=SensorDeviceClass.CONDUCTIVITY,
native_unit_of_measurement=UnitOfConductivity.MICROSIEMENS,
state_class=SensorStateClass.MEASUREMENT,
),
} }

View File

@@ -2,6 +2,7 @@
DOMAIN = "buienradar" DOMAIN = "buienradar"
DEFAULT_TIMEOUT = 60
DEFAULT_TIMEFRAME = 60 DEFAULT_TIMEFRAME = 60
DEFAULT_DIMENSION = 700 DEFAULT_DIMENSION = 700

View File

@@ -1,9 +1,9 @@
"""Shared utilities for different supported platforms.""" """Shared utilities for different supported platforms."""
from asyncio import timeout
from datetime import datetime, timedelta from datetime import datetime, timedelta
from http import HTTPStatus from http import HTTPStatus
import logging import logging
from typing import Any
import aiohttp import aiohttp
from buienradar.buienradar import parse_data from buienradar.buienradar import parse_data
@@ -27,12 +27,12 @@ from buienradar.constants import (
from buienradar.urls import JSON_FEED_URL, json_precipitation_forecast_url from buienradar.urls import JSON_FEED_URL, json_precipitation_forecast_url
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE
from homeassistant.core import CALLBACK_TYPE, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from .const import SCHEDULE_NOK, SCHEDULE_OK from .const import DEFAULT_TIMEOUT, SCHEDULE_NOK, SCHEDULE_OK
__all__ = ["BrData"] __all__ = ["BrData"]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -59,10 +59,10 @@ class BrData:
load_error_count: int = WARN_THRESHOLD load_error_count: int = WARN_THRESHOLD
rain_error_count: int = WARN_THRESHOLD rain_error_count: int = WARN_THRESHOLD
def __init__(self, hass, coordinates, timeframe, devices): def __init__(self, hass: HomeAssistant, coordinates, timeframe, devices) -> None:
"""Initialize the data object.""" """Initialize the data object."""
self.devices = devices self.devices = devices
self.data = {} self.data: dict[str, Any] | None = {}
self.hass = hass self.hass = hass
self.coordinates = coordinates self.coordinates = coordinates
self.timeframe = timeframe self.timeframe = timeframe
@@ -93,9 +93,9 @@ class BrData:
resp = None resp = None
try: try:
websession = async_get_clientsession(self.hass) websession = async_get_clientsession(self.hass)
async with timeout(10): async with websession.get(
resp = await websession.get(url) url, timeout=aiohttp.ClientTimeout(total=DEFAULT_TIMEOUT)
) as resp:
result[STATUS_CODE] = resp.status result[STATUS_CODE] = resp.status
result[CONTENT] = await resp.text() result[CONTENT] = await resp.text()
if resp.status == HTTPStatus.OK: if resp.status == HTTPStatus.OK:

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