Compare commits

..

751 Commits

Author SHA1 Message Date
G Johansson bda95f4d7a Create preview for history_stats 2025-01-07 22:24:05 +00:00
dontinelli de9c05ad53 Add new sensors to fyta (#135032) 2025-01-07 22:01:21 +01:00
Brett Adams a01521b224 Bump pyaussiebb to 0.1.5 (#134943)
Bump
2025-01-07 21:54:39 +01:00
Norbert Rittel 2413bb4f52 Improve Huawei LTE suspend integration service description (#135021) 2025-01-07 19:30:56 -01:00
Steven B. 1496da8e94 Add data description translations to all tplink config flow steps (#135022) 2025-01-07 20:26:00 +01:00
Mick Vleeshouwer 802ad55493 Catch errors in automation (instead of raise unexpected error) in Overkiz (#135026)
Catch errors in automation (instead of raise unexpected error)
2025-01-07 20:24:39 +01:00
Allen Porter 48da88583f Bump voluptuous openapi to 0.0.6 (#134998) 2025-01-07 19:09:11 +01:00
Mick Vleeshouwer 0ab66a4ed1 Improve logic for event polling duration in Overkiz (#133617) 2025-01-07 19:06:57 +01:00
epenet 3b13c5bfdd Move OneWireConfigEntry type definition (#135004) 2025-01-07 19:04:31 +01:00
Kevin Worrel 42532e9695 Add Controller state sensor to screenlogic (#133827) 2025-01-07 19:02:34 +01:00
Luke Lashley 0dd9845501 Add total cleaning count sensor to Roborock (#135015) 2025-01-07 19:01:04 +01:00
Simone Chemelli 3a213b2d17 Use standard "entity_registry_enabled_by_default" fixture (#134962) 2025-01-07 18:21:26 +01:00
epenet d155d93462 Set PARALLEL_UPDATES to 1 in onewire (#135006) 2025-01-07 17:19:48 +01:00
Erik Montnemery 5888b83f22 Validate device id when adding or updating entity registry entry (#134982) 2025-01-07 16:10:51 +00:00
epenet 471f77fea4 Add reconfigure to onewire (#134996)
* Add reconfigure to onewire

* Adjust _async_abort_entries_match
2025-01-07 17:08:53 +01:00
Allen Porter c684b06734 Simplify roborock coordinator (#134700)
* Update roborock coordinator to require maps on startup

* Fix indent in merge
2025-01-07 07:09:32 -08:00
Erik Montnemery 393551d696 Fix DSMR migration (#134990) 2025-01-07 15:42:07 +01:00
Andrew Sayre 24b81df0e6 Update HEOS Quality Scale docs-related items (#134466)
Update docs items
2025-01-07 08:26:42 -06:00
Allen Porter a66cf62b09 Update roborock tests to only load the platform under test (#134694) 2025-01-07 14:08:12 +01:00
epenet 901099325b Set parallel-updates and scan-interval explicitly in onewire (#134953) 2025-01-07 14:06:19 +01:00
epenet 30695cfef5 Simplify onewire config-flow (#134952) 2025-01-07 13:22:16 +01:00
Joakim Sørensen 5d2a8e8208 Increase cloud backup download timeout (#134961)
Increese download timeout
2025-01-07 13:18:02 +01:00
Norbert Rittel 4019045e7b Use sentence case, capitalize "IP Secure" and "ID" (#134966) 2025-01-07 12:08:37 +01:00
Norbert Rittel ec2c8da1c5 Change "id" to uppercase for consistency (#134971) 2025-01-07 12:03:44 +01:00
J. Nick Koston d1e8a2a32d Bump zeroconf to 0.137.2 (#134942) 2025-01-07 10:44:22 +01:00
Kelyan Pegeot Selme feeee2d15e Bump renault-api to 0.2.9 (#134858)
* chore: Bump Renault api version

* Update requirements_all.txt

* Update requirements_test_all.txt
2025-01-07 10:13:40 +01:00
David Rapan 8a052177a4 Update Shelly integration: Remove double "Error fetching ..." from error messages (#134950)
refactor: Remove double "Error fetching" from error messages
2025-01-07 10:12:10 +02:00
Eli Schleifer 875727ed27 add proxy view for unifiprotect to grab snapshot at specific time (#133546)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-01-06 13:49:58 -10:00
Raphael Hehl f1c62000e1 UnifiProtect Refactor light control methods to use new API (#134625) 2025-01-06 13:48:22 -10:00
Norbert Rittel e38f21c4ef Fix spelling of "ID", slightly reword action descriptions (#134778) 2025-01-07 00:25:42 +01:00
Franck Nijhof 00c052bb22 Revert "Remove deprecated supported features warning in ..." (multiple) (#134933) 2025-01-07 00:08:02 +01:00
Simone Chemelli 111ef13a3f Add device tracker test for Vodafone Station (#134334) 2025-01-06 23:17:50 +01:00
J. Nick Koston 89c73f56b1 Migrate to using aiohttp-asyncmdnsresolver for aiohttp resolver (#134830) 2025-01-06 12:06:28 -10:00
Paulus Schoutsen d13c14eedb Add support for extra_system_prompt to OpenAI (#134931) 2025-01-06 23:01:13 +01:00
G Johansson 9532e98166 Remove deprecated config entry import from bluesound (#134926) 2025-01-06 22:58:29 +01:00
G Johansson 6884d790ca Remove deprecated hdr switch from reolink (#134924) 2025-01-06 22:46:59 +01:00
G Johansson 6ab45f8c9e Bump holidays to 0.64 (#134922) 2025-01-06 22:45:04 +01:00
Artur Pragacz 7009a96711 Revert "Remove deprecated supported features warning in LightEntity" (#134927) 2025-01-06 22:39:24 +01:00
Josef Zweck a47fa08a9b Add device trackers to enabled_by_default fixture (#134446) 2025-01-06 22:03:32 +01:00
Norbert Rittel 4eb23f3039 Remove excessive newline code, fix "ID", enhance descriptions (#134920) 2025-01-06 20:54:26 +01:00
Klaas Schoute 1c314b5c02 Bump powerfox to v1.2.0 (#134908) 2025-01-06 20:52:54 +01:00
Tomer Shemesh edee58f114 Bump pylutron-caseta to 0.23.0 (#134906) 2025-01-06 20:44:06 +01:00
Manu ef652e57d1 Add bring_api to loggers in Bring integration (#134897)
Add bring-api to loggers
2025-01-06 20:37:01 +01:00
Paulus Schoutsen b956aa68da Handle discovering user configured Wyoming flow (#134916) 2025-01-06 20:26:49 +01:00
Michael 75ce89dc41 Bump py-synologydsm-api to 2.6.0 (#134914)
bump py-synologydsm-api to 2.6.0
2025-01-06 20:08:58 +01:00
Manu a9540e893f Fix wrong power limit decimal place in IronOS (#134902) 2025-01-06 19:55:47 +01:00
Bram Kragten dd5625436b Update frontend to 20250106.0 (#134905) 2025-01-06 19:11:01 +01:00
Paulus Schoutsen 7a484ee0ae Add extra prompt to assist pipeline and conversation (#124743)
* Add extra prompt to assist pipeline and conversation

* extra_prompt -> extra_system_prompt

* Fix rebase

* Fix tests
2025-01-06 12:58:42 -05:00
starkillerOG e5c5d1bcfd Fix Reolink playback of recodings (#134652) 2025-01-06 18:54:32 +01:00
Glenn Reilly 56a9cd010e fix typo "looses" to "loses" in MQTT configuration message (#134894) 2025-01-06 17:59:31 +01:00
Steven B. b7b5577f0c Bump python-kasa to 0.9.1 (#134893)
Bump tplink python-kasa dependency to 0.9.1
2025-01-06 16:58:33 +01:00
Norbert Rittel 0787257cc0 Use uppercase for "ID" and sentence-case for "name" / "icon" (#134890) 2025-01-06 16:30:40 +01:00
Thijs W. 54263f1325 Bump pymodbus version to 3.8.3 (#134809) 2025-01-06 14:56:17 +00:00
Luke Lashley 14d2f2c589 Add extra failure exceptions during roborock setup (#134889)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-01-06 15:46:21 +01:00
starkillerOG c533f63a87 Add Decorquip virtual motion blinds integration (#134402) 2025-01-06 15:36:38 +01:00
Ludovic BOUÉ cd30f75be9 Matter Battery replacement icon (#134460) 2025-01-06 15:35:42 +01:00
jb101010-2 527775a5f1 Bump pysuezV2 to 2.0.1 (#134769) 2025-01-06 15:27:23 +01:00
Klaas Schoute 99d7f462a0 Add heat meter to Powerfox integration (#134799) 2025-01-06 15:23:47 +01:00
J. Diego Rodríguez Royo 67e2379d2b Iterate over a copy of the list of programs at Home Connect select setup entry (#134684) 2025-01-06 15:21:02 +01:00
Norbert Rittel fb0047ead0 Use correct uppercase for "ID" and sentence-case otherwise (#134815) 2025-01-06 15:15:31 +01:00
Norbert Rittel 9764d704bd Fix a few typos or grammar issues in asus_wrt (#134813) 2025-01-06 15:15:08 +01:00
Norbert Rittel 3690d7c2b4 Fix spelling of "set up", change "id" to uppercase (#134888) 2025-01-06 14:12:52 +00:00
Norbert Rittel 204b5989e0 Replace "id" with "ID" for consistency across HA (#134798) 2025-01-06 15:10:29 +01:00
G Johansson 3892f6d8f3 Remove deprecated binary sensor battery charging from technove (#134844) 2025-01-06 15:03:52 +01:00
J. Diego Rodríguez Royo 140ff50eaf Fix how function arguments are passed on actions at Home Connect (#134845) 2025-01-06 15:03:25 +01:00
Avi Miller 5ef06b1f33 Bump aiolifx-themes to update colors (#134846) 2025-01-06 15:02:57 +01:00
Manu 9638bee8de Bump pynecil to v4.0.1 (#134852) 2025-01-06 14:55:50 +01:00
Norbert Rittel cd88a8cebd Fix missing sentence-casing etc. in several strings (#134775) 2025-01-06 14:53:28 +01:00
G Johansson d896b4e66a Raise ImportError in python_script (#134792) 2025-01-06 14:52:40 +01:00
Robin Wohlers-Reichel e4eb414be8 Bump solax to 3.2.3 (#134876) 2025-01-06 14:47:52 +01:00
Joakim Sørensen fce5be928e Log upload BackupAgentError (#134865)
* Log out BackupAgentError

* Update homeassistant/components/backup/manager.py

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

* Update homeassistant/components/backup/manager.py

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

* Format

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-01-06 14:19:34 +01:00
Joakim Sørensen c4455c709b Log cloud backup upload response status (#134871)
Log the status of the upload response
2025-01-06 13:10:38 +01:00
Allen Porter 2c7a1446b8 Update Roborock config flow message when an account is already configured (#134854) 2025-01-06 11:24:06 +01:00
G Johansson 20cf21d88e Add horizontal swing to Sensibo (#132117)
* Add horizontal swing to Sensibo

* Fixes

* Only load select if already there

* Remove feature check

* Fixes

* Mods

* Last bits

* Mod

* Fixes

* Mods

* Fix test

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2025-01-06 11:20:11 +01:00
G Johansson eafbf1d1fd Add get device capabilities action call for Sensibo (#134596)
* Add get device capabilities action call for Sensibo

* Tests

* Mod

* Fix services

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2025-01-06 11:09:08 +01:00
Michael acd95975e4 Make ChunkAsyncStreamIterator an aiohttp helper (#134843)
make ChunkAsyncStreamIterator a generic aiohttp helper
2025-01-06 04:37:07 +01:00
G Johansson bc22e34fc3 Add python_script to strict typing (#134822) 2025-01-05 22:22:54 -05:00
G Johansson bf0cf1c30f Set single_config_entry in System monitor manifest (#134838) 2025-01-05 22:17:08 -05:00
G Johansson e95bfe438b Pass config entry directly to coordinator in System monitor (#134837) 2025-01-05 22:16:58 -05:00
Norbert Rittel 0a457979ec Fix spelling of "ID", slightly reword action description (#134817)
This commit fixes the spelling of "ID" (uppercase for abbreviations) and slightly changes the action description to use third-person singular.

The latter ensures proper (machine) translations, keeping a descriptive style.
2025-01-05 18:36:17 -08:00
Allen Porter 2f295efb3f Update roborock to ensure every room has a name, falling back to a placeholder (#134733)
* Update roborock to ensure every room has a name, falling back to a placeholder

* Change Map to Room
2025-01-05 18:28:17 -08:00
J. Nick Koston 74613ae0c4 Bump habluetooth to 3.7.0 (#134833) 2025-01-05 12:44:37 -10:00
Raphael Hehl 4d4cfabfba Bump uiprotect to version 7.4.1 (#134829) 2025-01-05 11:25:44 -10:00
Norbert Rittel 7ae81bae4c Fix spelling of "ID" in Roku integration (#134779)
* Fix spelling of "ID" and "Ethernet" in Roku integration

Small commit replacing "id" with "ID" and "ethernet" with "Ethernet".

* Revert entity change

Web editor does not support the necessary tests.
2025-01-05 20:21:06 +01:00
Norbert Rittel 7ec10bfd6f Use uppercase "ID" in Home Connect strings (#134783) 2025-01-05 20:19:45 +01:00
cdnninja d662a4465c Remove unneeded vesync device base class (#134499)
* Remove unneeded entity to make code cleaner

* Update light.py

* Update fan.py

* Typing.

* Update homeassistant/components/vesync/common.py

Co-authored-by: Allen Porter <allen.porter@gmail.com>

* Wrap

---------

Co-authored-by: Allen Porter <allen.porter@gmail.com>
2025-01-05 09:18:52 -08:00
Markus Lanthaler 66b4b24612 Add latest Nighthawk WiFi 7 routers to V2 models (#134765)
Click `WiFi Routers` | `Nighthawk WiFi 7 Router` on https://www.netgear.com/support/ to see the list of devices
2025-01-05 16:59:34 +01:00
TheJulianJES a2077405e2 Bump ZHA to 0.0.45 (#134726) 2025-01-05 16:49:58 +01:00
Lucas Gasenzer f0a1a6c2ad Add ATTR_MODEL to DeviceInfo for Aranet (#134307)
* add ATTR_MODEL to DeviceInfo

* add tests for device context

* Upstream change type.name --> type.model

* fix test to represent model names
2025-01-05 16:16:12 +02:00
Norbert Rittel 32b7b5aa66 Small fixes in the strings file of the Vera integration (#134780)
Just for consistency …
2025-01-05 15:10:32 +01:00
Norbert Rittel 871a7d0dc1 Use uppercase "Chime" for product name, fix "MAC address" (#134748) 2025-01-05 14:31:02 +01:00
Michael da807001ab Register base device entry during coordinator setup in AVM Fritz!Tools integration (#134764)
* register base device entry during coordinator setup

* make mypy happy
2025-01-05 08:16:33 -05:00
Norbert Rittel a104799893 Fix spelling of "MAC (address)" and "Slide" name in slide_local (#134747) 2025-01-05 13:06:48 +01:00
Duco Sebel 45d1624d70 Bumb python-homewizard-energy to 7.0.1 (#134753) 2025-01-05 12:37:06 +01:00
Lucas Gasenzer 1059cf3f07 Bump aranet4 to 2.5.0 (#134752)
update aranet4 to 2.5.0 before pull request
2025-01-05 13:10:08 +02:00
Norbert Rittel dd34a10934 Fix swapped letter order in "°F" and "°C" temperature units (#134750)
Fixes the wrong order "F°" and "C°" for the temperature units.
2025-01-05 10:43:32 +01:00
Klaas Schoute d4f3dd2335 Bump powerfox to v1.1.0 (#134730) 2025-01-05 10:10:55 +01:00
Sid 0ecb1ea8cf Bump openwebifpy to 4.3.1 (#134746) 2025-01-05 10:04:59 +01:00
Sid 3d5a42749d Bump ruff to 0.8.6 (#134745) 2025-01-05 09:47:42 +01:00
Rylie Pavlik a2c2d37eb1 Add support for "Lumin Smart Light" LD-0003 (#133328) 2025-01-04 13:53:16 -10:00
Andrew Sayre f68c16586d Deprecate HEOS sign_in and sign_out actions (#134616) 2025-01-05 00:13:46 +01:00
Norbert Rittel 11d80065ef Fix spelling of "MAC (address)" and "Gateway" name (#134724) 2025-01-05 00:05:15 +01:00
Norbert Rittel 7012648bf8 Fix typos / grammar in nasweb integration (#134721) 2025-01-04 23:23:26 +01:00
Norbert Rittel d96b2499e2 Fix typos / grammar in description of create_task action (#134705) 2025-01-04 23:21:23 +01:00
Norbert Rittel a41bdfe0cc Fix wrong description of group.set action (#134697) 2025-01-04 23:20:30 +01:00
dontinelli 0d3872a4c7 Change from host to ip in zeroconf discovery for slide_local (#134709) 2025-01-04 21:28:47 +01:00
Norbert Rittel 65d8d071dd Remove excessive newline codes from squeezebox strings (#134682) 2025-01-04 18:42:28 +01:00
Allen Porter bb97a16756 Add prompts to MCP server (#134619)
* Add prompts to MCP server

* Improve test coverage for get prompt error cases
2025-01-04 12:35:05 -05:00
Andrew Sayre c9a607aa45 Clean-up HEOS entity event setup (#134683)
* Use async_on_remove

* Remove redundant signal clearing
2025-01-04 12:32:19 -05:00
Allen Porter c7993eff99 Bump gcal_sync to 7.0.0 (#134687) 2025-01-04 12:30:57 -05:00
Cyrill Raccaud 8a880d6134 Cookidoo exotic domains (#134676) 2025-01-04 16:33:42 +01:00
Brynley McDonald cc0fb80481 Fix Flick Electric authentication (#134611) 2025-01-04 16:21:21 +01:00
epenet 276806d3e1 Fix hive color tunable light (#134628) 2025-01-04 16:19:38 +01:00
Franck Nijhof 0589df7d95 Update demetriek to 1.1.1 (#134663) 2025-01-04 16:19:16 +01:00
Joost Lekkerkerker aab676a313 Add Overseerr service to get requests (#134229)
* Add service to get requests

* Add service to get requests

* Add service to get requests

* fix

* Add tests
2025-01-04 15:53:15 +01:00
Joost Lekkerkerker 7f473b8260 Prefer a local webhook for Overseerr (#134667) 2025-01-04 15:39:47 +01:00
Shay Levy fea4a00424 Remove LG WebOS TV legacy uuid migration (#134671) 2025-01-04 15:31:36 +01:00
Cyrill Raccaud 7d146ddae0 Bump cookidoo-api library to 0.11.1 of for Cookidoo (#134661) 2025-01-04 15:02:00 +01:00
Franck Nijhof 8f06e0903f Update peblar to 0.3.3 (#134658) 2025-01-04 14:34:45 +01:00
Maikel Punie 677ba3a6a6 Add velbus cover platform testcases (#134654) 2025-01-04 14:07:25 +01:00
Franck Nijhof a322deaab8 Update twentemilieu to 2.2.1 (#134651) 2025-01-04 14:05:24 +01:00
Franck Nijhof 584439cade Update guppy to 3.1.5 (#134646) 2025-01-04 13:24:33 +01:00
Joost Lekkerkerker baa13debcc Remove call to remove slide (#134647) 2025-01-04 12:56:58 +01:00
Cyrill Raccaud 1d42890748 Set logging in manifest for Cookidoo (#134645) 2025-01-04 12:23:22 +01:00
Norbert Rittel 622d23cadd Fix description of device_id field of reconnect_client actions (#134275) 2025-01-04 12:21:25 +01:00
G Johansson ebeb2ecb09 Replace aioclient_mock in Sensibo tests (#134543) 2025-01-04 12:14:58 +01:00
Norbert Rittel b3cb2928fc Fix typo 'devide_id', use uppercase for abbreviations ID and LED (#134634) 2025-01-04 12:01:39 +01:00
J. Nick Koston b639466453 Bump bleak-esphome to 2.0.0 (#134580) 2025-01-04 11:30:41 +01:00
Teemu R. 69241e4ca6 Mention case-sensitivity in tplink credentials prompt (#134606) 2025-01-04 11:12:46 +01:00
Allen Porter 80371a865e Bump ical to 8.3.0 (#134617)
* Bump ical to 8.3.0

* Update snapshots
2025-01-04 09:49:56 +01:00
Maikel Punie c9dbb205dd Add velbus diagnostics tests (#134621) 2025-01-04 09:10:34 +01:00
Raphael Hehl 197ff932af Bump uiprotect to version 7.2.0 (#134587) 2025-01-04 00:27:06 +01:00
G Johansson 287b7eec13 Clean up docstrings in Sensibo (#134591) 2025-01-04 00:24:51 +01:00
Maikel Punie e6da6d9612 Add velbus light and sensor platform testcases (#134485)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-01-03 20:42:01 +01:00
peteS-UK d4f38099ae Small fix to allow playing of expandable favorites on Squeezebox (#134572) 2025-01-03 20:28:05 +01:00
Manu 9f2cb7bf56 Add image platform to Habitica integration (#129009) 2025-01-03 20:23:43 +01:00
Maikel Punie 8a84abd50f Velbus diagnostics code cleanup (#134553) 2025-01-03 20:15:58 +01:00
Nerdix b15e08ca9c Add sleep switch for all Foscam cameras if more than 1 camera are configured (#126064) 2025-01-03 20:15:09 +01:00
Norbert Rittel 3fb980901e Improve habitica action descriptions (#134563) 2025-01-03 20:07:30 +01:00
Joost Lekkerkerker bd3a3fd26c Require at least bronze for new integrations (#134537)
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2025-01-03 18:14:27 +00:00
Andrew Sayre dfcb977a1d Add HEOS Reauth Flow (#134465) 2025-01-03 18:11:10 +00:00
Abílio Costa 94ad6ae814 Bump whirlpool-sixth-sense to 0.18.11 (#134562) 2025-01-03 17:45:27 +01:00
G Johansson 97aa93f92b Add supported features property in Sensibo (#134479) 2025-01-03 17:30:18 +01:00
G Johansson ee025198e8 Update quality scale for Sensibo (#134551) 2025-01-03 17:28:02 +01:00
puddly 90265e2afd Move SiLabs firmware probing helper from ZHA into homeassistant_hardware (#131586)
* Move firmware probing helper out of ZHA and into hardware

* Add a unit test
2025-01-03 10:57:39 -05:00
Bram Kragten a53554dad3 Update frontend to 20250103.0 (#134561) 2025-01-03 16:36:40 +01:00
Joost Lekkerkerker 2b6ad84cf5 Set Ituran to silver (#134538) 2025-01-03 16:31:31 +01:00
Erik Montnemery 92655fd640 Log cloud backup agent file list (#134556) 2025-01-03 16:30:14 +01:00
Maciej Bieniek e43f72c452 Add support for xvoltage sensor for Shelly Plus UNI (#134261)
* Add support for xvoltage sensor

* Cleaning
2025-01-03 15:27:47 +01:00
Manu 9320ccfa4f Remove deprecated sensors in Habitica integration (#134320)
* Remove deprecated sensors

* remove todos/dailies also from enum
2025-01-03 14:48:26 +01:00
Erik Montnemery 336af8b551 Avoid early COMPLETED event when restoring backup (#134546) 2025-01-03 14:44:24 +01:00
starkillerOG 8a2f8dc736 Add Reolink proxy for playback (#133916) 2025-01-03 14:24:39 +01:00
Erik Montnemery dc048bfcf5 Simplify error handling when creating backup (#134528) 2025-01-03 14:16:05 +01:00
Norbert Rittel fb474827b5 Fix description of google_assistant.request_sync action (#134535) 2025-01-03 14:08:54 +01:00
Markus Adrario eec5fb2133 Add Homee integration to Core (#133738)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-01-03 13:44:06 +01:00
Erik Montnemery 8ad7c522f4 Add backup as after_dependency of frontend (#134534) 2025-01-03 13:35:56 +01:00
Maikel Punie c7f6630718 Velbus add init testcases (#134533) 2025-01-03 13:29:01 +01:00
Marc Mueller afa95293dc Enable strict typing for pandora (#134536) 2025-01-03 13:23:39 +01:00
G Johansson 36582f9ac2 Refactor all Sensibo tests (#134478)
* Add me json

* Mods

* Mods

* More

* Mods

* Mods

* clean

* last bits

* Fix

* unique id

* return_value

* remove blocking

* Fix rebase
2025-01-03 12:44:47 +01:00
Ståle Storø Hauknes 19852ecc24 Add state_class to Airthings integration (#134503)
Add state class
2025-01-03 11:55:24 +01:00
Manu 5726d090b0 Add get_tasks action to Habitica integration (#127687)
Add get_tasks action
2025-01-03 11:53:30 +01:00
Indu Prakash add401ffcf Add coordinator to vesync (#134087) 2025-01-03 11:33:16 +01:00
Robert Svensson fd12ae2ccd Handle deCONZ color temp 0 is never used when calculating kelvin CT (#134521) 2025-01-03 10:51:20 +01:00
Franck Nijhof e15eda3aa2 Only load Peblar customization update entity when present (#134526) 2025-01-03 10:51:05 +01:00
Dan Raper cc0adcf47f Add switch platform to Ohme (#134347)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-01-03 10:39:41 +01:00
Franck Nijhof 06580ce10f Update peblar to v0.3.2 (#134524) 2025-01-03 10:37:39 +01:00
Erik Montnemery b78e39da2d Fix activating backup retention config on startup (#134523) 2025-01-03 10:29:29 +01:00
G Johansson 46824a2a53 Add quality scale to Sensibo (#134296) 2025-01-03 10:23:25 +01:00
Joost Lekkerkerker ee01289ee8 Bump python-overseerr to 0.5.0 (#134522) 2025-01-03 10:22:59 +01:00
Erik Montnemery 0bd22eabc7 Improve recorder schema migration error test (#134518) 2025-01-03 10:05:07 +01:00
Erik Montnemery c901352bef Add error prints for recorder fatal errors (#134517) 2025-01-03 10:01:35 +01:00
Joost Lekkerkerker 23ed62c1bc Push Overseerr updates via webhook (#134187) 2025-01-03 08:26:01 +01:00
Paulus Schoutsen 0ef254bc9a Fix backup dir not existing (#134506) 2025-01-03 00:21:19 -05:00
rrooggiieerr 629d108078 Use the latest version of the pyserial-asyncio-fast library (#134501) 2025-01-03 03:15:46 +01:00
Marc Mueller 6f3544fa47 Add types package for pexpect (#134461) 2025-01-03 02:53:08 +01:00
Franck Nijhof cb389d29ea Fix input_datetime.set_datetime not accepting 0 timestamp value (#134489) 2025-01-02 23:45:00 +01:00
Josef Zweck ac26ca2da5 Bump aioacaia to 0.1.13 (#134496) 2025-01-03 00:28:29 +02:00
G Johansson d5bcb73d33 Bump psutil to 6.1.1 (#134494) 2025-01-02 22:45:24 +01:00
Marc Mueller e6a18357db Update pillow to 11.1.0 (#134469) 2025-01-02 22:36:14 +01:00
G Johansson 13ec0659ff Remove deprecated uptime sensor from qnap_qsw (#134493) 2025-01-02 22:29:50 +01:00
G Johansson a7fb20ab58 Remove deprecated attributes from ecovacs (#134492) 2025-01-02 22:19:51 +01:00
G Johansson 657da47458 Remove worldclock config entry import (#134491) 2025-01-02 21:45:20 +01:00
Franck Nijhof a4708876a9 Update peblar to 0.3.1 (#134486) 2025-01-02 21:41:54 +01:00
G Johansson 4239c5b557 Improve error strings in Sensibo (#134487) 2025-01-02 21:19:20 +01:00
G Johansson 836354bb99 Use username as config entry title in Sensibo (#134488) 2025-01-02 21:18:19 +01:00
Norbert Rittel a7af042e57 Fix a few small typos in peblar (#134481) 2025-01-02 21:17:29 +01:00
Franck Nijhof 09476ade82 Remove sneaked in IronOS submodule (#134477) 2025-01-02 20:22:17 +01:00
Andrea Arcangeli 25937d7868 open_meteo: correct UTC timezone handling in hourly forecast (#129664)
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2025-01-02 19:37:36 +01:00
Duco Sebel 4e74d14beb Include host in Peblar EV-Charger discovery setup description (#133954)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-01-02 19:34:51 +01:00
SparkyDan555 309b7eb436 Change Reolink person binary sensor icon (#134472) 2025-01-02 19:18:40 +01:00
Erik Montnemery cf238cd8f7 Don't start recorder if a database from the future is used (#134467) 2025-01-02 18:56:23 +01:00
Robert Resch ee46edffa3 Bump deebot-client to 10.1.0 (#134470) 2025-01-02 18:54:27 +01:00
Erik Montnemery 876b3423ba Improve hassio backup create and restore parameter checks (#134434) 2025-01-02 17:52:50 +01:00
Norbert Rittel 2752a35e23 Remove excessive newline codes from strings.json (#134468) 2025-01-02 17:43:49 +01:00
Craig Andrews 9e8df72c0d Improve is docker env checks (#132404)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
Co-authored-by: Sander Hoentjen <sander@hoentjen.eu>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
Co-authored-by: Robert Resch <robert@resch.dev>
2025-01-02 17:21:49 +01:00
Bram Kragten 5439613bff Update frontend to 20250102.0 (#134462) 2025-01-02 17:17:57 +01:00
Ілля Піскурьов 3b5455bc49 Add support for specifying hvac_onoff_register value on modbus (#128366)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-01-02 15:18:05 +00:00
Noah Husby 104151d322 Remove deprecated YAML import from MPD (#134459) 2025-01-02 16:08:33 +01:00
Martin Hjelmare a329828bdf Handle backup errors more consistently (#133522)
* Add backup manager and read writer errors

* Clean up not needed default argument

* Clean up todo comment

* Trap agent bugs during upload

* Always release stream

* Clean up leftover

* Update test for backup with automatic settings

* Fix use of vol.Any

* Refactor test helper

* Only update successful timestamp if completed event is sent

* Always delete surplus copies

* Fix after rebase

* Fix after rebase

* Revert "Fix use of vol.Any"

This reverts commit 28fd7a544899bb6ed05f771e9e608bc5b41d2b5e.

* Inherit BackupReaderWriterError in IncorrectPasswordError

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-01-02 15:45:46 +01:00
Marc Mueller aa9e721e8b Update pexpect to 4.9.0 (#134450) 2025-01-02 15:36:44 +01:00
Josef Zweck 1b49f88be9 Bump aioacaia to 0.1.12 (#134454) 2025-01-02 15:33:22 +01:00
Marc Mueller c345f2d548 Improve pandora media_player typing (#134447) 2025-01-02 13:55:59 +01:00
Manu 1d731875ae Remove deprecated yaml import from pyLoad integration (#134200) 2025-01-02 13:29:55 +01:00
Erik Montnemery 0c3489c1b3 Adjust language in backup integration (#134440)
* Adjust language in backup integration

* Update tests
2025-01-02 13:29:46 +01:00
Marc Mueller c5865c6d18 Add types package for pyserial (#134444) 2025-01-02 13:21:20 +01:00
Norbert Rittel e1a0fb2f1a Improve action descriptions with some more detail from the docs (#134120)
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2025-01-02 12:52:51 +01:00
Erik Montnemery d725cdae13 Initialize AppleTVConfigFlow.identifiers (#134443) 2025-01-02 12:49:03 +01:00
Erik Montnemery e1bd82ea32 Export IncorrectPasswordError from backup integration (#134436) 2025-01-02 12:40:10 +01:00
Thomas55555 4bcc551b61 Add sw_version to apsystems (#134441) 2025-01-02 12:28:48 +01:00
Marc Mueller 08019e76d8 Update types packages (#134433) 2025-01-02 12:00:29 +01:00
Sven Naumann 0b32342bf0 Add mode selector to Twinkly (#134041) 2025-01-02 10:54:29 +00:00
Krzysztof Dąbrowski add4e1a708 Add state attributes translations to GIOS (#134390) 2025-01-02 11:38:12 +01:00
Stefan Agner fb3105bdc0 Improve Supervisor backup error handling (#134346)
* Raise Home Assistant error in case backup restore fails

This change raises a Home Assistant error in case the backup restore
fails. The Supervisor is checking some common issues before starting
the actual restore in background. This early checks raise an exception
(represented by a HTTP 400 error). This change catches such errors and
raises a Home Assistant error with the message from the Supervisor
exception.

* Add test coverage
2025-01-02 11:37:25 +01:00
Norbert Rittel 3845acd0ce Improve names and descriptions in neato.custom_cleaning action (#134399) 2025-01-02 11:04:23 +01:00
Manu b45c68554c Remove habitipy references in Habitica integration (#134419) 2025-01-02 10:47:40 +01:00
G Johansson 8a45aa4c42 Add translations to all Sensibo errors (#134422)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-01-02 10:46:55 +01:00
G Johansson 51ccba12af Add action translations to Sensibo (#134420) 2025-01-02 10:45:20 +01:00
John Barreiros c8699dc066 Add current_humidity state attribute to Google Nest climate entity (#134426) 2025-01-02 10:44:15 +01:00
ashionky 87454babfa Add debug log and Optimize code (#134328)
* debug log

* add sw_version hw_version

* log
2025-01-02 09:10:01 +01:00
Andrew Sayre c9ff575628 Add HEOS options flow for optional authentication (#134105)
* Add heos options flow

* Add options flow tests

* Test error condition during options sign out

* Use credentials when setting up

* Update warning instructions

* Simplify exception logic

* Cover unknown command error condition

* Add test for options

* Correct const import location

* Review feedback

* Update per feedback

* Parameterize tests and remaining feedback

* Correct log level in init

* nitpick feedback
2025-01-02 09:07:34 +01:00
G Johansson 877d16273b Fix SQL sensor name (#134414) 2025-01-02 08:51:49 +01:00
Marc Mueller dc5bfba902 Update mypy-dev to 1.15.0a1 (#134416) 2025-01-02 08:45:05 +01:00
TheJulianJES 5e7a405f34 Bump ZHA to 0.0.44 (#134427) 2025-01-02 08:43:38 +01:00
Matthew FitzGerald-Chamberlain 5228f3d85c Improve support for Aprilaire S86WMUPR (#133974) 2025-01-02 08:39:57 +01:00
G Johansson 2efc75fdf5 Add base entity to Mill (#134415) 2025-01-02 07:31:54 +01:00
Michael Hansen a435fd12f0 Bump intents to 2025.1.1 (#134424) 2025-01-01 21:03:17 -05:00
Allen Porter a5d0c3528c Add the Model Context Protocol Server integration (#134122)
* Add the Model Context Protocol Server integration

* Remove unusued code in init

* Fix comment wording

* Use util.uild for unique ids

* Set config entry title to the LLM API name

* Extract an SSE parser and update comments

* Update comments and defend against already closed sessions

* Shorten description

* Update homeassistant/components/mcp_server/__init__.py

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

* Change integration type to service

---------

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2025-01-01 19:38:33 -05:00
Daniel Hjelseth Høyer 5e981d00a4 Add mill number platform (#134044)
* Mill number, max heating power

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>

* Mill number, max heating power

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>

* Mill number, max heating power

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>

* Mill number, max heating power

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>

* Mill number, max heating power

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>

* type

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>

---------

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2025-01-01 23:25:42 +01:00
G Johansson 97dc72a6e2 Move available property to base entity in Sensibo (#134410)
* Move available property to base entity in Sensibo

* Fix test
2025-01-01 23:02:06 +01:00
Maikel Punie 088b097a03 Velbus select platform testcases (#134394) 2025-01-01 17:39:39 +01:00
Jan Bouwhuis 85c94e6403 Calculate number of discovery topics correctly (#134393) 2025-01-01 16:55:41 +01:00
Maikel Punie a2ef1604af Add Velbus climate platform tests (#134387) 2025-01-01 16:01:02 +01:00
Sven Naumann 55dc4b0d2c Implement base entity class for Twinkly (#134382)
* implement base entity class for twinkly

* Update homeassistant/components/twinkly/entity.py

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

* super init

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-01-01 13:49:13 +01:00
Adam Štrauch 18e8a3b185 Add new ID LAP-V201S-AEUR for Vital200S AirPurifier in Vesync integration (#133999) 2025-01-01 13:10:40 +01:00
cdnninja 3a68a0a67f Vesync unload error when not all platforms used (#134166) 2025-01-01 13:03:39 +01:00
Josef Zweck 7ab2d2e07a Cleanup lamarzocco tests (#134383) 2025-01-01 13:00:14 +01:00
Keith 809629c0e2 Add integration for igloohome devices (#130657)
Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>
Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-01-01 12:55:04 +01:00
G Johansson 2be578a33f Add diagnostics to Trafikverket Weatherstation (#134314) 2025-01-01 12:32:35 +01:00
Maikel Punie 5cff79ce50 Add velbus switch platform testcases (#134207) 2025-01-01 12:11:27 +01:00
Brett Adams 513c8487c5 Check vehicle metadata (#134381) 2025-01-01 12:09:15 +01:00
Kenny Root 031de8da51 Bump zabbix-utils to 2.0.2 (#134373) 2025-01-01 11:42:16 +01:00
G Johansson 2e1463b9e9 Add placeholder url to Sensibo api description (#134342) 2024-12-31 20:09:49 -06:00
Norbert Rittel 9a58440296 Use "restore from" in field descriptions of restore_partial action (#134285) 2024-12-31 23:29:15 +01:00
Joost Lekkerkerker 26e0fcdb08 Improve Mealie set mealplan service (#130606)
* Improve Mealie set mealplan service

* Fix

* Fix
2024-12-31 17:06:42 -05:00
Bram Kragten e835e41d59 Update frontend to 20241231.0 (#134363) 2024-12-31 17:04:28 -05:00
Niels Mündler c53c0a13be Bump pysynthru version to 0.8.0 (#134294) 2024-12-31 23:03:35 +01:00
Jan Bouwhuis 8098122dfe Ensure an entity platform is added in mqtt tests (#134331) 2024-12-31 23:01:55 +01:00
starkillerOG 1d6ecbd1d5 Change Reolink test switch entity ID (#134339) 2024-12-31 22:57:43 +01:00
Dan Raper c8276ec325 Bump ohmepy to 1.2.3 (#134348) 2024-12-31 22:54:20 +01:00
Josef Zweck ddfad614ab Bump pylamarzocco to 1.4.6 (#134367) 2024-12-31 22:49:29 +01:00
Norbert Rittel 8eb21749b5 Remove leftover newline codes and periods from strings.json (#134354) 2024-12-31 22:39:07 +01:00
Josef Zweck a6ba25d3d4 Use text selectors for lamarzocco config flow (#134368) 2024-12-31 22:38:31 +01:00
starkillerOG 1e70a0060b Add Reolink baby crying binary sensor (#134290)
* Add baby crying detection

* Bump reolink-aio to 0.11.6
2024-12-31 22:27:01 +01:00
Noah Husby 6c47f03d17 Bump aiorussound to 4.4.0 (#134366) 2024-12-31 22:21:14 +01:00
Markus Jacobsen 2054988790 Add Bang & Olufsen button Event entities (#127550)
* Add button events

* Remove unused common keys
Rename Preset to Favourite

* Add event testing

* Add check for Beoconnect Core

* Rename device controls

* Add test for Beoconnect core event entity creation

* Fix config entry type

* Add a type checking check before assertion

* Add icon translations

* Remove useless defined icons

* Remove base event class

* Update homeassistant/components/bang_olufsen/event.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2024-12-31 21:55:24 +01:00
tronikos f1ad3040b8 Allow automations to pass any conversation_id for Google Generative AI (#134251) 2024-12-31 15:52:29 -05:00
Michael Hansen 53ca31c112 Bump hassil to 2.1.0 (#134359) 2024-12-31 15:52:15 -05:00
Michael Hansen 23459a0355 Revert speech seconds to 0.3 (#134360) 2024-12-31 20:04:41 +01:00
Simone Chemelli a8bfe285bf Bump aioshelly to 12.2.0 (#134352) 2024-12-31 17:16:12 +01:00
Noah Husby 0888d1a169 Bump aiorussound to 4.3.0 (#134242)
* Bump aiorussound to 4.3.0

* Force CI
2024-12-31 16:14:24 +01:00
Dave T 8b20272272 Refactor and simplify config flow in generic camera (#134330)
Refactor and simplify config flow
2024-12-31 07:05:50 -08:00
Bram Kragten 06b33e5589 Set backup manager state to completed when restore is finished (#134283) 2024-12-31 15:01:06 +01:00
Brynley McDonald 9348569f90 Update Flick Electric API (#133475) 2024-12-31 14:28:24 +01:00
starkillerOG 4a9d545ffe Bump reolink-aio to 0.11.6 (#134286) 2024-12-31 10:31:40 +01:00
Simone Chemelli 277ee03145 Full test coverage for Vodafone Station sensor platform (#133285)
Co-authored-by: Joostlek <joostlek@outlook.com>
2024-12-31 09:55:54 +01:00
Norbert Rittel 6c9c17f129 Update description of the script toggle action (#134093) 2024-12-31 07:07:52 +00:00
Dave T bf59241dab Add stream preview to options flow in generic camera (#133927)
* Add stream preview to options flow

* Increase test coverage

* Code review: use correct flow handler type in cast

* Restore test coverage to 100%

* Remove error and test that can't be triggered yet
2024-12-30 15:46:42 -08:00
Indu Prakash 57b7635b70 Bump pyvesync to 2.1.15 (#134156)
Bumped pyvesync to 2.1.15
2024-12-30 23:33:41 +01:00
G Johansson 4b96266647 Set parallel updates in Trafikverket Train (#134302) 2024-12-30 23:18:35 +01:00
G Johansson 6266a4153d Explicitly set config entry in Trafikverket Train coordinator (#134304) 2024-12-30 23:18:22 +01:00
G Johansson a9949a0aab Use typed config entry everywhere in Trafikverket Train (#134303) 2024-12-30 23:17:21 +01:00
G Johansson 428a74fa48 Explicitly set config entry in Trafikverket Ferry coordinator (#134305) 2024-12-30 23:17:04 +01:00
G Johansson 9f1023b195 Explicitly set config entry in Trafikverket Weatherstation coordinator (#134310) 2024-12-30 23:16:41 +01:00
G Johansson 256fc54aa1 Set parallel updates in Trafiverket Weatherstation (#134309) 2024-12-30 23:16:16 +01:00
G Johansson 94c1b9a434 Use typed config entry everywhere in Trafikverket Weatherstation (#134308) 2024-12-30 23:15:54 +01:00
G Johansson 275c15e2ae Set parallel updates in Trafikverket Ferry (#134301) 2024-12-30 22:50:47 +01:00
G Johansson 9cdbcd93cd Use typed config entry everywhere in Trafikverket Ferry (#134300) 2024-12-30 22:48:33 +01:00
G Johansson f2e856b8a2 Use typed config entry in Trafikverket Camera (#134299) 2024-12-30 22:48:22 +01:00
G Johansson 820f04e1e1 Add parallel updates to camera platform in Trafikverket Camera (#134298) 2024-12-30 22:48:12 +01:00
Noah Husby b7541f098c Add discovery to Russound RIO (#134245) 2024-12-30 22:46:08 +01:00
Norbert Rittel a345e80368 Replace unnecessary abbreviations in set_room_temperature action (#134278) 2024-12-30 21:28:38 +01:00
Norbert Rittel 7a3d9a9345 Replace "service" with "action" (#134279) 2024-12-30 21:26:53 +01:00
Dan Raper a0fb6df5ba Add battery sensor to ohme (#134222)
* Add battery sensor to ohme

* Forgot the snapshots!

* Add translation key to battery

* Change car to vehicle and fix snapshot tests

* Fix snapshot again - not sure what was going on with my local dev env
2024-12-30 20:15:11 +01:00
Bram Kragten 04020d5a56 Update frontend to 20241230.0 (#134284) 2024-12-30 20:04:50 +01:00
Norbert Rittel f785b17314 Fix two descriptions of yeelight actions (#134282) 2024-12-30 19:22:12 +01:00
Andrew Jackson 6631c57cfb Bump aiomealie to 0.9.5 (#134274) 2024-12-30 17:47:58 +01:00
Norbert Rittel bc76dc3c34 Remove excessive period at end of action name (#134272) 2024-12-30 16:22:30 +01:00
Ludovic BOUÉ ea4931ca3a Bump Python Matter server to 7.0.0 (Matter 1.4) (#132502)
* Matter 1.4 rename BridgedDevice device type

BREAKING change in the client: BridgedDevice is renamed to BridgedNode in the device types with Matter 1.4

* `ColorMode` enum type is renamed to `ColorModeEnum`

* Item `ColorTemperature` renamed to `ColorTemperatureMireds`

* Update ColorControl bitmaps and attributes

* Bump Python Matter server to 7.0.0 (Matter 1.4)

* Bump requirements to Python Matter server to 7.0.0
2024-12-30 15:41:14 +01:00
Arne Keller dd20204bf0 ollama: update to 0.4.5 (#134265) 2024-12-30 14:42:46 +01:00
Norbert Rittel ef46c62bc6 Make triggers and condition for monetary sensor consistent (#131184) 2024-12-30 13:47:16 +01:00
Alberto Geniola 2bb6e03a36 Bump elmax-api (#133845) 2024-12-30 13:46:53 +01:00
G Johansson 2288f89415 Fix duplicate sensor disk entities in Systemmonitor (#134139) 2024-12-30 13:38:48 +01:00
Josef Zweck e7ab5afc14 Bump pylamarzocco to 1.4.5 (#134259)
* Bump pylamarzocco to 1.4.4

* Bump pylamarzocco to 1.4.5

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-30 12:27:32 +01:00
Adam Goode 4db88dfaff Quickly process unavailable metrics in Prometheus (#133219) 2024-12-30 12:05:33 +01:00
Joost Lekkerkerker 906c95048c Record LG WebOS TV Quality scale (#133732)
Co-authored-by: Shay Levy <levyshay1@gmail.com>
2024-12-30 11:45:44 +01:00
Manu df38c1b1d7 Remove deprecated yaml import from OTP integration (#134196) 2024-12-30 11:12:16 +01:00
tronikos af97bf1c5f Fix 400 This voice does not support speaking rate or pitch parameters at this time for Google Cloud Journey voices (#134255) 2024-12-30 09:20:35 +01:00
tronikos a7c2d96ecf Avoid KeyError for ignored entries in async_step_zeroconf of Android TV Remote (#134250) 2024-12-30 10:13:51 +02:00
Noah Husby 1b06b4e45b Remove unused translations from Russound RIO (#134246) 2024-12-30 10:11:37 +02:00
Manu b74b9bc360 Bump habiticalib to v0.3.2 (#134244) 2024-12-30 10:10:18 +02:00
Brett Adams 810689ce66 Handle missing application credentials in Tesla Fleet (#134237)
* Handle missing application credentials

* Add tests

* Test reauth starts

* Only catch ValueError
2024-12-29 22:21:18 -08:00
G Johansson 249d93574a Set Scrape sensor unavailable when errors (#134143) 2024-12-29 22:59:57 +01:00
Michael e2c59f276a Bump aiopegelonline to 0.1.1 (#134230)
bump aiopegelonline to 0.1.1
2024-12-29 21:36:49 +01:00
Manu 9804e8aa98 Add reauth flow to Habitica integration (#131676)
* Add reauth flow to Habitica integration

* tests, invalid_credentials string

* test only api_key

* section consts

* test config entry

* test reauth is triggered

* set reauthentication-flow to done

* use consts in tests

* reauth_entry

* changes

* fix import

* changes
2024-12-29 21:12:36 +01:00
Paul Daumlechner 53e69af088 Bump pyvlx to 0.2.26 (#115483) 2024-12-29 10:00:26 -10:00
tronikos 1530edbe20 Bump opower to 0.8.7 (#134228)
* Bump opower to 0.8.7

* update deps
2024-12-29 11:44:33 -08:00
Paulus Schoutsen 7dbf32d693 Bump frontend to 20241229.0 (#134225) 2024-12-29 13:35:46 -05:00
Michael Hansen 49646ad994 Bump VoIP utils to 0.2.2 (#134219) 2024-12-29 11:56:27 -06:00
G Johansson 1e652db37f Use config entry runtime data in Open-Meteo (#134198) 2024-12-29 18:16:41 +01:00
Dan Raper 88d366b0c5 Add slot list service to ohme (#134170)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-29 18:07:12 +01:00
Lucas Gasenzer 65147f8d4c Fix Wake on LAN Port input as Box instead of Slider (#134216) 2024-12-29 18:03:41 +01:00
Simone Chemelli 52b919101a Bump aiocomelit to 0.10.1 (#134214) 2024-12-29 17:30:52 +01:00
Aaron Bach 24fd74d839 Change SimpliSafe websocket reconnection log to DEBUG-level (#134063)
* Change SimpliSafe websocket reconnection log to `DEBUG`-level

* revert
2024-12-29 11:23:44 -05:00
Marc Mueller 2599faa622 Fix method subtyping [helpers] (#134213) 2024-12-29 17:16:38 +01:00
Marc Mueller 3df91cfba5 Fix method subtyping [recorder] (#134212) 2024-12-29 17:16:11 +01:00
Marc Mueller d3fab42c85 Fix method subtyping [knx] (#134211) 2024-12-29 16:41:23 +01:00
Marc Mueller beb881492a Fix method subtyping [elkm1] (#134210) 2024-12-29 16:40:51 +01:00
Matthias Alphart 9d7c7f9fcf Update knx-frontend to 2024.12.26.233449 (#134184) 2024-12-29 16:39:37 +01:00
Shay Levy 419307a7c4 Bump aioswitcher to 6.0.0 (#134185) 2024-12-29 15:42:33 +01:00
G Johansson 409dc4ad48 Move coordinator to own file in Open-Meteo (#134197) 2024-12-29 15:25:40 +01:00
Michael 7704ef95a4 Make feedreader recoverable (#134202)
raise ConfigEntryNotReady on connection errors during setup
2024-12-29 15:08:15 +01:00
Manu 0db07a033b Migrate Habitica integration to habiticalib (#131032)
* Migrate data to habiticalib

* Add habiticalib to init and coordinator

* Migrate Habitica config flow to habiticalib

* migrate init to habiticalib

* migrate buttons to habiticalib

* migrate switch to habiticalib

* update habiticalib

* cast_skill action

* migrate update_score

* migrate transformation items action

* migrate quest actions

* fix fixture errors

* Migrate coordinator data and content

* bump habiticalib

* Remove habitipy and use wrapper in habiticalub

* changes

* some fixes

* minor refactoring

* class_needed annotation

* Update diagnostics

* do integration setup in coordinator setup

* small changes

* raise HomeAssistantError for TooManyRequestsError

* fix docstring

* update tests

* changes to tests/snapshots

* fix update_todo_item
2024-12-29 15:00:31 +01:00
Joost Lekkerkerker 4717eb3142 Bump python-overseerr to 0.4.0 (#134192) 2024-12-29 15:46:30 +02:00
Joost Lekkerkerker c23f5c9f2c Make elevenlabs recoverable (#134094)
* Make elevenlabs recoverable

* Add tests for entry setup

* Use the same fixtures for setup and config flow

* Update tests/components/elevenlabs/test_setup.py

Co-authored-by: Simon <80467011+sorgfresser@users.noreply.github.com>

---------

Co-authored-by: Simon Sorg <simon.sorg@student.hpi.de>
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
Co-authored-by: Simon <80467011+sorgfresser@users.noreply.github.com>
2024-12-29 14:26:59 +01:00
Michael 873b078bb3 Make PEGELONLINE recoverable (#134199) 2024-12-29 14:07:45 +01:00
Manu 0dd93a18c5 Add button platform to IronOS integration (#133678)
* Add button platform to IronOS integration

* Add tests

* load platform

* refactor

* update tests
2024-12-29 12:39:13 +01:00
Maikel Punie da96e2077b Add Velbus Button tests (#134186)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-29 11:55:52 +01:00
Manu 1d69cf11a5 Bump pynecil to v3.0.1 (#134174) 2024-12-29 10:06:29 +02:00
Manu adb1fbbbc4 Add switch platform to IronOS integration (#133691)
* Add switch platform

* Add tests

* prevent switch bouncing

* some changes

* icons

* update tests

* changes
2024-12-28 21:59:06 +01:00
G Johansson 645f2e44b9 Fix Nord Pool empty response (#134033)
* Fix Nord Pool empty response

* Mods

* reset validate prices
2024-12-28 21:38:04 +01:00
Artur Pragacz b3aede611a Fix Onkyo volume rounding (#134157) 2024-12-28 21:34:01 +01:00
jb101010-2 72a96249b1 Suez_water: clear quality scale (#134027)
* Suez_water: clear quality scale

Revert invalid done rules and mark inapplicable ones as exempted.

* Mark entity disabled as todo

* Mark devices as todo

* missing push

* Update homeassistant/components/suez_water/quality_scale.yaml

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update quality_scale.yaml

* Update quality_scale.yaml again

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2024-12-28 20:59:11 +01:00
Joost Lekkerkerker 80dbce14ec Add binary sensor to Tile (#134153) 2024-12-28 16:49:14 +01:00
Manu 0376f75ee3 Bump pynecil to v3.0.0 (#134151) 2024-12-28 16:48:28 +01:00
jb101010-2 e58bd62c68 Suez_water: use meter id as unique_id (#133959)
* Suez_water: use meter id as unique_id

* Review fixes

* No more afraid check :)

* review again

* Apply suggestions from code review

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-12-28 16:25:10 +01:00
Matthias Alphart 6dbcd130b0 Add quality_scale.yaml for KNX (#133937)
* Add quality_scale.yaml

* Update quality_scale.yaml
2024-12-28 16:24:49 +01:00
Andrew Jackson 4639f57014 Remove deprecated Mastodon yaml config import (#134040)
* Remove Mastodon yaml import

* Revert removal of async_migrate_entry
2024-12-28 16:22:32 +01:00
G Johansson 4080455c12 Use x,y in roborock action call (#134133)
* Use x,y in roborock action call

* Fix description
2024-12-28 16:12:09 +01:00
Joost Lekkerkerker df7d518f38 Add versions to Tile device (#134150)
* Add versions to Tile device

* Add versions to Tile device
2024-12-28 16:04:36 +01:00
Joost Lekkerkerker 47adfb574f Bump python-overseerr to 0.3.0 (#134147)
Bump Overseerr to 0.3.0
2024-12-28 15:44:15 +01:00
Joost Lekkerkerker 4c5d0c2ec4 Add Tile device tracker tests (#134137) 2024-12-28 15:36:56 +01:00
G Johansson 4febe43021 Add missing device classes in scrape (#134141) 2024-12-28 15:36:23 +01:00
Maikel Punie af13979855 Add Velbus binary sensor tests (#134132)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-28 14:57:48 +01:00
Marc Mueller d9f2140df3 Add ClassVar annotation for singleton patterns (#134135) 2024-12-28 13:17:15 +01:00
Joost Lekkerkerker cc80108629 Bump yt-dlp to 2024.12.23 (#134131) 2024-12-28 13:13:07 +01:00
Joost Lekkerkerker 16af76b968 Add Tile device tests (#134138) 2024-12-28 13:10:13 +01:00
Joost Lekkerkerker 590f0ce61f Refactor Tile tests (#134130) 2024-12-28 12:37:21 +01:00
Allen Porter 14059c6df8 Remove unused parameters from function calls in rainbird (#134124)
Remove unused parameters from rainbird function calls
2024-12-28 11:34:27 +00:00
Joost Lekkerkerker 268c21addd Add Overseerr integration (#133981)
* Add Overseerr integration

* Add Overseerr integration

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix
2024-12-28 11:50:36 +01:00
Andre Lengwenus 565fa4ea1f Remove incorrect device check in LCN events (#134116) 2024-12-28 09:26:49 +01:00
Raj Laud 28cd7f2473 Bump pysqueezebox to v0.11.1 (#134097) 2024-12-28 09:24:22 +01:00
Noah Husby aceb1b39ba Add mute support to Russound RIO (#134118) 2024-12-28 09:22:13 +01:00
Allen Porter 6edf06f8a4 Converge stream av open methods, options, and error handling (#134020)
* Converge stream av open methods, options, and error handling

* Remove exception that is never thrown

* Update exceptions thrown in generic tests

* Increase stream test coverage
2024-12-27 18:47:33 -08:00
Noah Husby 07ae9b15d0 Bump aiorussound to 4.2.0 (#134117) 2024-12-27 18:23:57 -08:00
G Johansson d676169b04 Cleanup devices in Nord Pool from reconfiguration (#134043)
* Cleanup devices in Nord Pool from reconfiguration

* Mods

* Mod
2024-12-27 21:33:37 +01:00
Noah Husby 24ce3d7daa Remove deprecated yaml import for Russound RIO (#134072) 2024-12-27 21:27:33 +01:00
Joost Lekkerkerker 417e736746 Migrate Tile to use entry.runtime_data (#134107) 2024-12-27 21:25:36 +01:00
Cyrill Raccaud bb8d4ca255 Add unit test for sensors in swiss public transport (#134115)
* add unit test for sensors

* clean up
2024-12-27 21:21:45 +01:00
Joost Lekkerkerker 375af6cb1c Introduce base entity for Tile (#134109) 2024-12-27 21:18:01 +01:00
Jan Bouwhuis 263e0acd3a Set PARALLEL_UPDATES for incomfort entity platforms (#134110) 2024-12-27 20:43:30 +01:00
Erwin Douna da531d0e4e Bump Tado to 0.18.5 (#133988) 2024-12-27 20:26:19 +01:00
Joost Lekkerkerker 844e36c8fe Bump python-homeassistant-analytics to 0.8.1 (#134101) 2024-12-27 20:21:12 +01:00
Joost Lekkerkerker 9976c07f89 Remove YAML import from Tile (#134108) 2024-12-27 20:15:48 +01:00
Aaron Bach 7df9d2e938 Bump pytile to 2024.12.0 (#134103) 2024-12-27 20:04:35 +01:00
Joost Lekkerkerker 52318f5f37 Extract Tile coordinator in separate file (#134104) 2024-12-27 19:30:13 +01:00
Joost Lekkerkerker b9c2b3f7e3 Remove Tile unique id migration (#134106) 2024-12-27 19:25:10 +01:00
Andrew Sayre a9ff5b8007 Bump pyheos to v0.8.0 (#134069)
Bump pyheos and update usage
2024-12-27 11:01:35 -06:00
Joost Lekkerkerker 7076ba7c9d Make google tasks recoverable (#134092) 2024-12-27 08:52:33 -08:00
Josef Zweck 5e0088feaa Add azure_data_explorer to microsoft brand (#134088) 2024-12-27 15:36:07 +01:00
Franck Nijhof f8399b2c0f Revert "Add state_class to EcoWittSensorTypes.DEGREE" (#134079) 2024-12-27 13:17:47 +01:00
Matthias Alphart 415fdf4956 Fix KNX config flow translations and add data descriptions (#134078)
* Fix KNX config flow translations and add data descriptions

* Update strings.json

* typo
2024-12-27 12:59:52 +01:00
Noah Husby ad89004189 Remove timeout from Russound RIO initialization (#134070) 2024-12-27 11:01:10 +01:00
Noah Husby b6afbe4b29 Bump aiorussound to 4.1.1 (#134058)
* Bump aiorussound to 4.1.1

* Trigger Build

* Trigger Build
2024-12-26 22:03:50 -06:00
Cyrill Raccaud 402340955e Fix swiss public transport line field none (#133964)
* fix #133116

The line can theoretically be none, when no line info is available (lets say walking sections first?)

* fix line field

* add unit test with missing line field
2024-12-27 00:24:47 +01:00
Raphael Hehl b2a160d926 Roborock Add vacuum_goto service (#133994)
* Roborock Add vacuum_goto service to control vacuum movement to specified coordinates

* roborock Add type specification for x_coord and y_coord in vacuum_goto service

* roborock Add get_current_position service to retrieve vacuum's current coordinates

* Rename vacuum services for clarity and consistency

* Apply suggestions from code review

Co-authored-by: G Johansson <goran.johansson@shiftit.se>

* Add integration field to vacuum service targets for Roborock

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-12-27 00:20:09 +01:00
Thomas Kunzfeld 9840785363 Add state_class to EcoWittSensorTypes.DEGREE (#134004)
Add state_class to EcoWittSensorTypes.DEGREE (#129260)
2024-12-27 00:12:54 +01:00
jb101010-2 a53c92d4b5 Suez_water: remove redundant log on refresh failure (#134025)
Suez_water: remove redundent log on refresh failure
2024-12-27 00:05:28 +01:00
Marc Mueller adc97b6c15 Fix unifiprotect DeprecationWarnings in tests (#134060) 2024-12-26 23:50:03 +01:00
Jan Bouwhuis 7b2a5d0684 Remove mqtt publish templates after 6 months of deprecation (#134056) 2024-12-26 23:25:44 +01:00
Diogo Gomes acb511d395 Bump pyipma to 3.0.8 (#134055)
bump pyipma
2024-12-26 21:01:53 +00:00
Norbert Rittel c025390c6c Replace "service" with "action" plus fixed descriptions (#134053) 2024-12-26 15:39:18 -05:00
J. Nick Koston 942fbdedcf Ensure all states have been migrated to use timestamps (#134007) 2024-12-26 07:48:55 -10:00
Allen Porter 3bfb6707e9 Fix Nest ConfigEntry typing (#134021) 2024-12-26 09:27:20 -08:00
Norbert Rittel 5172139579 Use correct uppercase for abbreviations (#134028)
Fix the spelling of "SSDP" and "MAC" (address) to ensure proper translations.
2024-12-26 11:09:30 +01:00
Norbert Rittel cfb43c7b58 Fix typo in get_command action description (#134026) 2024-12-26 09:56:08 +01:00
Allen Porter 45657ece7c Improve Google Tasks error messages (#134023) 2024-12-26 09:53:20 +01:00
Erwin Douna f7fe2f2122 Tado update code owners (#133987)
Update code owners
2024-12-26 09:13:24 +01:00
Allen Porter c75222e63c Bump python-google-nest-sdm to 7.0.0 (#134016)
Update python-google-nest-sdm to 7.0.0
2024-12-26 00:03:44 -05:00
Brett Adams 299250ebec Bump Tesla Fleet API library (#134019)
Bump Tesla Fleet
2024-12-25 23:26:55 -05:00
Josef Zweck ed8e242049 Bump pylamarzocco to 1.4.3 (#134008) 2024-12-25 16:25:13 -08:00
Cyrill Raccaud 95e4a40ad5 Update silver docs for swiss public transport (#134001)
update docs
2024-12-25 21:36:30 +01:00
Christopher Fenner e61717ce7a Fulfill IQS rule docs-removal-instructions in ViCare integration (#133982)
update iqs state
2024-12-25 15:30:33 +01:00
Cyrill Raccaud 73b6bd8bd3 Add config flow data description to swiss public transport (#133997)
* add config flow data description

* improve strings
2024-12-25 15:20:09 +01:00
Cyrill Raccaud 60774c69cd Add clear shopping list button for Cookidoo (#133583)
* add clear button

* set clear button to disabled per default

* add actions exception
2024-12-25 14:58:19 +01:00
Cyrill Raccaud c383b41a12 Add parallel updates to swiss public transport (#133996)
add parallel updates
2024-12-25 14:55:34 +01:00
J. Nick Koston 05a8b773b9 Bump numpy to 2.2.1 (#133844)
* Bump numpy to 2.2.1

changelog: https://github.com/numpy/numpy/compare/v2.2.0...v2.2.1

* make sure ninja is up to date

* Revert "make sure ninja is up to date"

This reverts commit a26dd8b768308c04b70ecaeb7700b40ff233c1c8.

* test

* Revert "test"

This reverts commit 972f40e3ee263a2c7ce8185fd13752be4e8bcdde.

* try a single build

* try a single build

* Revert "Revert "test""

This reverts commit ec282ce021c73d7fcf76df570e40857c1e70304e.

* Revert "Revert "Revert "test"""

This reverts commit 315599cbaee44f069b842c9da083de8d2999c7ab.

* Revert "try a single build"

This reverts commit 63529dd2c5e743b9ea84e80a6afd921f9e2ef52f.

* Revert "try a single build"

This reverts commit 7058ae928882050f85a08133840f811d33913e92.
2024-12-25 11:27:00 +02:00
G-Two 1bee423c22 Bump subarulink to 0.7.13 (#133970) 2024-12-25 10:13:04 +02:00
Marc Mueller 687afd23bc Add pip wheel build constraints to fix numpy builds (#133962) 2024-12-24 15:06:21 -10:00
cdnninja 0020c48a15 Update pyvesync version (#131433) 2024-12-24 17:51:40 +01:00
Bram Kragten 760cbcc596 Update frontend to 20241224.0 (#133963) 2024-12-24 16:41:36 +01:00
Philipp Danner da8f4e5b57 fix "Slow" response leads to "Could not find a charging station" #124129 (#133889)
fix #124129
2024-12-24 14:00:34 +01:00
Claudio Ruggeri - CR-Tech 5c0659c8df Fix reload modbus component issue (#133820)
fix issue 116675
2024-12-24 13:57:18 +01:00
Marc Mueller 15806c2af6 Update Jinja2 to 3.1.5 (#133951) 2024-12-24 13:44:09 +01:00
Maikel Punie 97d8d16cc5 Bump velbusaio to 2024.12.3 (#133939) 2024-12-24 12:35:22 +02:00
Khole 33435fa36f Hive: Fix error when device goes offline (#133848) 2024-12-24 10:42:35 +01:00
Joost Lekkerkerker 6fc1cfded9 Use SignedSession in Xbox (#133938) 2024-12-24 10:17:02 +01:00
Franck Nijhof a9d6a42781 Update apprise to v1.9.1 (#133936) 2024-12-24 10:15:21 +01:00
Kevin Worrel f2a706ecf7 Make screenlogic state enums lowercase (#133866) 2024-12-24 09:12:18 +01:00
G-Two 4a2ae7f6fd Stop using shared aiohttp client session for Subaru integration (#133931) 2024-12-24 08:59:51 +01:00
Franck Nijhof 771ead9d7b Prevent imports from tests in core codebase (#133928)
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2024-12-24 08:40:05 +01:00
Jordi 2d5e2aa4b4 Add Harvey virtual integration (#133874)
Add harvey virtual integration
2024-12-24 08:01:50 +01:00
Franck Nijhof 6f11524b84 Remove myself as codeowner from Tuya integration (#133921) 2024-12-24 07:55:44 +01:00
Dave T 561f319e3b Fix missing % in string for generic camera (#133925)
Fix missing % in generic camera string
2024-12-24 07:45:13 +01:00
Franck Nijhof 0c9ec4b699 Fix Peblar import in data coordinator (#133926) 2024-12-24 07:42:48 +01:00
Brett Adams cbb2930805 Slow down polling in Teslemetry (#133924) 2024-12-24 01:59:36 +01:00
Franck Nijhof aa29a93fbe Remove myself as codeowner from Plugwise (#133920) 2024-12-24 01:34:23 +01:00
J. Nick Koston ff4ba553c4 Sort integration platforms preload list (#133905)
* Sort integration platforms preload list

https://github.com/home-assistant/core/pull/133856#discussion_r1895385026

* sort

* Sort them all

---------

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2024-12-23 23:38:59 +01:00
Thomas55555 2f101c5054 Catch ClientConnectorError and TimeOutError in APSystems (#132027) 2024-12-23 22:49:59 +01:00
karwosts 72e2b835d9 Fix a history stats bug when window and tracked state change simultaneously (#133770) 2024-12-23 22:47:26 +01:00
Martin Mrazik 8f6e4cd294 Map RGB+CCT to RGB for WLED (#133900) 2024-12-23 22:26:38 +01:00
Mick Vleeshouwer bd0edd4996 Revise codeowners for Overkiz (#133784) 2024-12-23 22:24:22 +01:00
J. Nick Koston 3f441e7090 Ensure cloud and recorder backup platforms do not have to wait for the import executor (#133907)
* Ensure cloud and recorder backup platforms do not have to wait for the import executor

partially fixes #133904

* backup.backup as well
2024-12-23 22:19:28 +01:00
Abílio Costa 253098d79c Mark missing IQS requirements for Idasen Desk as done (#133910) 2024-12-23 21:38:27 +01:00
Abílio Costa 53ebf84339 Add cronsim to default dependencies (#133913) 2024-12-23 21:34:36 +01:00
J. Nick Koston 7cfbc3eeae Fix duplicate call to async_register_preload_platform (#133909) 2024-12-23 09:20:44 -10:00
Franck Nijhof 8d32531bc1 Bump version to 2025.2.0dev0 (#133893) 2024-12-23 17:54:32 +01:00
Simon 30d95f37d8 Add removal instructions to ElevenLabs (#133895) 2024-12-23 18:37:19 +02:00
Michael bbb5f9e717 Preload supported color properties in fritzbox lights (#133798) 2024-12-23 16:40:38 +01:00
Duco Sebel 6cbc803b28 Streamline Peblar translations (#133883) 2024-12-23 16:38:34 +01:00
Steven B. abe00884ea Use SD stream for tplink mpeg stream (#133879) 2024-12-23 16:37:42 +01:00
Steven B. 0cbc77ad3f Make tplink entities unavailable if camera is off (#133877) 2024-12-23 16:36:57 +01:00
Bram Kragten 5487e8673c Update frontend to 20241223.1 (#133886) 2024-12-23 16:03:56 +01:00
Matthias Alphart 45ae2f4736 Set Fronius integration quality scale to gold (#133884) 2024-12-23 15:54:57 +01:00
Robert Resch 8e86c3c775 Add Ecovacs station entities (#133876)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-23 15:54:40 +01:00
Álvaro Fernández Rojas 5ef12c3993 Add AEMET Weather Radar images (#131386)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-23 15:51:21 +01:00
Glenn Vandeuren (aka Iondependent) 43a420cf01 Add cover to the niko_home_control integration (#133801)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-23 15:47:09 +01:00
starkillerOG 70648da8fd Improve firmware update required issue (#133878) 2024-12-23 15:05:45 +01:00
Steven B. 7f6a77ad2f Fix tplink camera entity unique id (#133880) 2024-12-23 15:53:17 +02:00
Simon 386a722393 ElevenLabs invalid api key config flow testing (#133822) 2024-12-23 12:05:31 +01:00
Robert Resch c5fe25a001 Bump deebot-client to 10.0.1 (#133634) 2024-12-23 12:05:29 +01:00
Omni Flux cf3d4eb26a Respect ESPHome ClimateTrait supports_current_temperature (#132149) 2024-12-23 11:35:59 +01:00
Joost Lekkerkerker 939365887f Add coordinator to Twinkly (#133793) 2024-12-23 11:35:37 +01:00
epenet e3cf5c47b2 Add compatibility code for deprecated WaterHeaterEntityEntityDescription (#133351) 2024-12-23 11:28:20 +01:00
Franck Nijhof b2170ad732 Mark Peblar Rocksolid EV Chargers Platinum (#133823) 2024-12-23 11:23:26 +01:00
Franck Nijhof ed7da35de4 Add coordinator error handling for Peblar Rocksolid EV Chargers (#133809) 2024-12-23 11:11:25 +01:00
Marcel van der Veldt 83f5ca5a30 Add actions with response values to Music Assistant (#133521)
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: OzGav <gavnosp@hotmail.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-23 11:10:10 +01:00
Franck Nijhof 1f8f85d6eb Merge branch 'master' into dev 2024-12-23 09:40:42 +00:00
Duco Sebel 59d8c79371 Use user defined charge limit for charge limit range in Peblar (#133868) 2024-12-23 10:27:53 +01:00
Matrix a6f6317299 Add Leak detect entity for YoLink water meter controller (#131682) 2024-12-23 09:24:02 +01:00
dontinelli b1fe247eed Upgrade QS from silver to gold for slide_local (#133863)
Upgrade QS to gold
2024-12-23 09:23:13 +01:00
mrtlhfr 8991cd4f46 Adding initial support for Tuya Electric Fireplaces (#133503) 2024-12-23 09:23:04 +01:00
Matthias Alphart 9e1ba004d4 Add translated enum entity for Fronius error code (#133394) 2024-12-23 09:17:52 +01:00
J. Nick Koston ddb3edca5d Bump PySwitchbot to 0.55.4 (#133861) 2024-12-23 08:44:01 +01:00
jon6fingrs 4321d27ed3 Ensure icalendar==6.1.0 is installed for caldav integration (#133541) 2024-12-23 08:39:43 +01:00
dependabot[bot] ad0ee8f2d6 Bump github/codeql-action from 3.27.9 to 3.28.0 (#133862) 2024-12-23 08:18:23 +01:00
Teemu R. 6cdbdadc24 Ignore devices (bravias) with 'video' service_type for songpal discovery (#133724) 2024-12-22 19:38:10 -10:00
Martin Weinelt cf45c67055 Fix TypeError in maxcube climate action inference logic (#133853)
The maxcube-api library initializes the valve_position as a None value,
so that during initialization if the cube does not respond quickly enough
the comparison fails to compare a None-Type to an integer.
2024-12-22 23:26:11 -05:00
J. Nick Koston 3658cdba4c Ensure late import in backup of hassio.backup does not block the event loop (#133857)
* Ensure late import in backup of components.hassio.backup does not block the event loop

Preload backup when loading hassio to ensure it happens in the executor

https://github.com/home-assistant/core/blob/67f0de441b489890efa802a325f187b761098ad6/homeassistant/components/backup/__init__.py#L57

* improve comment
2024-12-22 23:19:44 -05:00
TheJulianJES dcc9be02ca Bump ZHA to 0.0.43 (#133854)
* Bump ZHA to 0.0.43

* Add strings for v2 quirk entities
2024-12-22 23:19:05 -05:00
J. Nick Koston de1b6a0dfc Add backup to the list of storage preloads (#133855) 2024-12-22 23:17:13 -05:00
J. Nick Koston 29fa40a5cf Add backup the list of integrations platforms to preload (#133856)
`backup` is now at the top of the startup time list. This will help reduce it.
2024-12-22 23:07:05 -05:00
Christopher Fenner 67f0de441b Fulfill IQS rule runtime-data in ViCare integration (#133633) 2024-12-23 00:06:01 +01:00
J. Nick Koston 353f085474 Bump anyio to 4.7.0 (#133842) 2024-12-22 13:05:51 -10:00
J. Nick Koston 00a1ae0eeb Bump protobuf to 5.29.2 (#133839) 2024-12-22 23:58:39 +01:00
Raphael Hehl df26166047 Unifiprotect: add error message if the get_user_keyring_info permissions are not sufficient (#133841) 2024-12-22 23:58:13 +01:00
Steven B. 8ab936b87c Add detection switches to tplink integration (#133828) 2024-12-22 23:54:44 +01:00
Mick Vleeshouwer 4ed0c21a4a Add data descriptions to Config Flow in Overkiz (#133758) 2024-12-22 23:35:50 +01:00
jb101010-2 a3657a0fef Suez_water: fix yesterday sensor extra_state invalid typing (#133425) 2024-12-22 23:21:52 +01:00
Andre Lengwenus 74b425a06e Reload on connection lost for LCN integration (#133638) 2024-12-22 23:20:01 +01:00
Norbert Rittel 0560b634e3 Make To-do action names and descriptions consistent with HA standard (#133734) 2024-12-22 23:14:01 +01:00
Mick Vleeshouwer 8eebbd45bd Bump pyOverkiz to 1.15.5 (#133835) 2024-12-22 22:52:35 +01:00
Joost Lekkerkerker c9ad87d464 Add light tests for Niko Home Control (#133750) 2024-12-22 22:44:15 +01:00
Lucas Gasenzer c2358d5158 Add Switchbot Water Leak Detector (BLE) (#133799)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-12-22 11:37:57 -10:00
Josef Zweck 2d2b979c7d Bump pylamarzocco to 1.4.2 (#133826) 2024-12-22 21:55:04 +01:00
Steven B. ebcb478f52 Add pan/tilt features to tplink integration (#133829) 2024-12-22 10:53:14 -10:00
Raphael Hehl 0f18f128fd Unifiprotect Add user information retrieval for NFC and fingerprint events (#132604)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-12-22 10:50:30 -10:00
G Johansson 368e958457 Load data for multiple days in Nord Pool (#133371)
* Load data for multiple days in Nord Pool

* Fix current day

* Fix tests

* Fix services

* Fix fixtures

* Mod get_data_current_day

* Mods

* simplify further
2024-12-22 21:10:12 +01:00
Noah Husby 26180486e7 Add media browsing to Cambridge Audio (#129106)
* Add media browsing to Cambridge Audio

* Remove one folder logic

* Remove class mapping for presets
2024-12-22 21:05:07 +01:00
Robert Resch 0ad9af0feb Add already exists config flow tests for Ecovacs (#133572)
Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-12-22 20:23:55 +01:00
dontinelli 07322c6992 Add reconfigure flow to slide_local (#133669) 2024-12-22 19:57:34 +01:00
Steven B. b1f6563fb2 Add camera platform to tplink integration (#129180)
Co-authored-by: Teemu R. <tpr@iki.fi>
2024-12-22 19:56:33 +01:00
J. Nick Koston 475f19c140 Bump flux_led to 1.1.0 (#133818) 2024-12-22 19:56:09 +01:00
Andre Lengwenus 344a03d9ce Remove unused fixture from LCN tests (#133821) 2024-12-22 19:55:45 +01:00
Raphael Hehl 6c70586f7e Add get_user_keyring_info service to UniFi Protect integration (#133138)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-12-22 08:54:14 -10:00
Franck Nijhof 0f1835139f Add number error handling for Peblar Rocksolid EV Chargers (#133803) 2024-12-22 19:53:00 +01:00
Franck Nijhof de5a49363e Add switch error handling for Peblar Rocksolid EV Chargers (#133805) 2024-12-22 19:47:31 +01:00
Arie Catsman c6789d70a4 Remove unneeded type for enphase_envoy coordinator in async_unload_entry (#133817) 2024-12-22 19:26:35 +01:00
Simon a2aba77973 Fix typo in ElevenLabs (#133819) 2024-12-22 19:26:15 +01:00
Franck Nijhof 84a3a9d495 Add select error handling for Peblar Rocksolid EV Chargers (#133804) 2024-12-22 19:25:55 +01:00
Barry vd. Heuvel d994884726 Add binary states for Weheat indoor unit (#133811)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-22 19:07:01 +01:00
Joost Lekkerkerker 0e9965150e Show device name in Twinkly discovery (#133814) 2024-12-22 19:00:49 +01:00
Barry vd. Heuvel feca7c28cf Add Compressor, Inside Unit and Energy Output fields to Weheat (#129632) 2024-12-22 18:45:33 +01:00
Steven Looman 0ba32e1d3a Bump async-upnp-client to 0.42.0 (#133806) 2024-12-22 07:18:05 -10:00
J. Nick Koston 6179da4321 Bump PySwitchbot to 0.55.3 (#133812)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-22 18:16:47 +01:00
jesperraemaekers 93c0eb73d2 Bump Weheat to 2024.12.22 (#133796) 2024-12-22 17:44:15 +01:00
Dave T 484f149e61 Add config flow stream preview to generic camera (#122563)
Co-authored-by: Allen Porter <allen.porter@gmail.com>
2024-12-22 17:31:03 +01:00
Steven B. 3cc75c3cf6 Use feature checks in tplink integration (#133795)
Clean up to use new upstream API:

* Use Feature attributes to check for supported

* Use color_temp range and update tests
2024-12-22 16:17:23 +01:00
Franck Nijhof 26d5c55d11 Add button error handling for Peblar Rocksolid EV Chargers (#133802) 2024-12-22 15:35:45 +01:00
Franck Nijhof 959f20c523 Add reconfigure flow to Peblar Rocksolid EV Chargers integration (#133785) 2024-12-22 14:23:12 +01:00
Franck Nijhof 075f95b9c4 Add base entity to Peblar Rocksolid EV Chargers integration (#133794) 2024-12-22 14:01:31 +01:00
PierreAronnax 1e68ae1bb8 Remove myself from govee_ble codeowners (#133790) 2024-12-22 13:35:36 +01:00
Joost Lekkerkerker 5ef3901b44 Add base entity for Niko Home Control (#133744) 2024-12-22 13:32:15 +01:00
Mick Vleeshouwer 56b58cec3e Fix errors in HitachiDHW in Overkiz (#133765)
* Small changes to fix errors in DHW

* Update

* Bugfix in float/int mistake

* Fix typing

* Fix code style

* Fix mypy
2024-12-22 12:17:09 +01:00
Franck Nijhof cdd73a5c5a Set parallel updates for Peblar Rocksolid EV Chargers integration (#133786) 2024-12-22 12:16:08 +01:00
Arie Catsman 88eb550ec1 Update quality-scale status for enphase_envoy config_flow missing data descriptions (#133726) 2024-12-22 12:01:13 +01:00
Joost Lekkerkerker 7be3cad1db Refactor Twinkly tests (#133725) 2024-12-22 12:00:24 +01:00
Franck Nijhof 31c6443a9b Add button platform to Peblar Rocksolid EV Chargers integration (#133780) 2024-12-22 11:51:01 +01:00
Mick Vleeshouwer 84d359c0d9 Fix binary_sensor typing in Overkiz (#133782) 2024-12-22 11:33:32 +01:00
Mick Vleeshouwer 619aed39b7 Use new UnitOfEnergy constants in Overkiz (#133778) 2024-12-22 10:36:07 +01:00
Mick Vleeshouwer 3f1acff652 Add support for HitachiAirToWaterHeatingZone in Overkiz (#133768)
* Add support for HitachiAirToWaterHeatingZone in Overkiz

* Clean up

* Fix typing

* Fix typing

* Fix typing

* Adapt to new PyOverkiz
2024-12-22 10:31:09 +01:00
Mick Vleeshouwer c3d0a01776 Migrate to runtime data in Overkiz (#133760)
* Migrate to runtime data

* Revert

* Improve typing
2024-12-22 10:25:59 +01:00
Arie Catsman cd6da9d9e8 Merge similar tests to parameterized tests for enphase_envoy (#133740) 2024-12-22 10:07:35 +01:00
Franck Nijhof 0c24afec6c Update integration quality scale for Peblar Rocksolid EV Chargers (#133764) 2024-12-22 10:03:16 +01:00
Mick Vleeshouwer 284ccbc778 Add additional Hitachi sensors to Overkiz (#133772)
Add additional Hitachi sensors
2024-12-22 09:40:06 +01:00
Mick Vleeshouwer cef182c596 Bump pyOverkiz to 1.15.4 (#133769)
Bump pyoverkiz to 1.15.4
2024-12-22 10:02:58 +02:00
Austin Mroczek d322398d06 TotalConnect use entry.runtime_data (#133756)
* use entry.runtime_data

* type the entry

* update quality scale

* recommended fixes

* Update homeassistant/components/totalconnect/alarm_control_panel.py

* Update homeassistant/components/totalconnect/binary_sensor.py

* Update homeassistant/components/totalconnect/button.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-22 08:59:54 +01:00
J. Nick Koston c2a9b0ff52 Reduce complexity to find unused data_ids and attributes_ids for db engines with slow range select (#133752) 2024-12-21 19:38:11 -10:00
J. Nick Koston 662dea28ed Replace queries using distinct with correlated scalar subqueries to significantly improve purge performance (#133748)
Replace queries using distinct with correlated scalar subqueries

like #133553 and #133699 PostgreSQL does not support skip/loose index scan https://wiki.postgresql.org/wiki/Loose_indexscan

This makes the `distinct` query (see section `Selecting Distinct Values` in the wiki above) to find the unused ids
very expense. We can replace them with correlated scalar subqueries
as done in #133553 to avoid the `distinct`
2024-12-21 22:25:48 -05:00
Franck Nijhof 9fcf8f22d2 Add reauthentication support to Peblar Rocksolid EV Chargers integration (#133757) 2024-12-21 23:00:29 +01:00
Franck Nijhof 9dc20b5709 Add more sensors to Peblar Rocksolid EV Chargers integration (#133754)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-21 22:40:15 +01:00
Franck Nijhof 5e4e1ce5a7 Add binary sensor platform to Peblar Rocksolid EV Chargers integration (#133755) 2024-12-21 22:29:11 +01:00
Franck Nijhof 85519a312c Fix Peblar current limit user setting value (#133753) 2024-12-21 22:23:36 +01:00
Franck Nijhof 81ce5f4505 Update peblar to v0.3.0 (#133751) 2024-12-21 21:26:40 +01:00
Franck Nijhof c67e2047e3 Add switch platform to Peblar Rocksolid EV Chargers integration (#133749) 2024-12-21 20:28:55 +01:00
Franck Nijhof 04276d3523 Add number platform to Peblar Rocksolid EV Chargers integration (#133739) 2024-12-21 20:16:18 +01:00
Joost Lekkerkerker f2df57e230 Add DHCP discovery to Withings (#133737) 2024-12-21 19:36:13 +01:00
Glenn Vandeuren (aka Iondependent) 0037799bfe Change niko_home_control library to nhc to get push updates (#132750)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: VandeurenGlenn <8685280+VandeurenGlenn@users.noreply.github.com>
Co-authored-by: Joostlek <joostlek@outlook.com>
2024-12-21 19:28:11 +01:00
Steven B. 944ad9022d Bump tplink python-kasa dependency to 0.9.0 (#133735)
Release notes: https://github.com/python-kasa/python-kasa/releases/tag/0.9.0
2024-12-21 19:04:09 +01:00
Tom 4b6febc757 Add reconfiguration flow to Plugwise (#132878)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-21 16:44:14 +01:00
Norbert Rittel ac2090d2f5 Replace "service" with "action" in Z-Wave action descriptions (#133727)
Replace all occurrence of "service" with "action"

Clean up the remaining occurrences of "service" with "action" to be consistent with the new terminology in Home Assistant.
2024-12-21 16:16:12 +01:00
Norbert Rittel 3dad5f6896 Replace two outdated occurrences of "service" with "action" (#133728) 2024-12-21 15:54:02 +01:00
Arie Catsman cc134c820b Reuse title of deleted enphase_envoy config entry if present (#133611) 2024-12-21 15:49:24 +01:00
Arie Catsman ef31413a59 Add missing asserts to enphase_envoy config flow test (#133730) 2024-12-21 15:20:10 +01:00
Álvaro Fernández Rojas 9292bfc6ed Update AEMET-OpenData to v0.6.4 (#133723) 2024-12-21 15:19:55 +01:00
Franck Nijhof 9e6c1d5b62 Add power and energy related sensors to Peblar Rocksolid EV Chargers (#133729) 2024-12-21 15:18:08 +01:00
Franck Nijhof 7e2d382ff4 Update aiohasupervisor to 0.2.2b5 (#133722) 2024-12-21 15:10:35 +01:00
Matthias Alphart b5a7a41ebe KNX: Option to select specific tunnel endpoint on TCP connections (#131996) 2024-12-21 15:10:14 +01:00
Franck Nijhof a3febc4449 Add select platform to Peblar Rocksolid EV Chargers integration (#133720) 2024-12-21 14:23:16 +01:00
Norbert Rittel 5abc03c21e Fix spelling of "Gateway PIN" and remove two excessive spaces (#133716) 2024-12-21 13:26:48 +01:00
Joost Lekkerkerker dc9133f919 Use mac address in Twinkly for unique id (#133717) 2024-12-21 13:26:09 +01:00
Arie Catsman a3fad89d0d Use super constructor self.config_entry in enphase_envoy coordinator (#133718) 2024-12-21 13:19:04 +01:00
Franck Nijhof a3fab094c3 Add device test for Peblar Rocksolid EV Chargers (#133713) 2024-12-21 13:03:44 +01:00
G Johansson 11efec49db Fix test coverage in workday (#133616) 2024-12-21 12:45:00 +01:00
Jan Bouwhuis 6b666b3a0f Test color_temp updates are processed when an mqtt json light is turned off (#133715) 2024-12-21 12:44:00 +01:00
Franck Nijhof 7e24b353ac Add updates tests for Peblar Rocksolid EV Chargers (#133712) 2024-12-21 12:31:58 +01:00
Maciej Bieniek 5665abf991 Store Twinkly runtime data in config entry (#133714) 2024-12-21 12:31:40 +01:00
Artur Pragacz 6314d7a44c Fix section translations check (#133683) 2024-12-21 12:31:17 +01:00
Manu b106b88f5c Adjust freezer tick in settings tests of IronOS integration (#133707) 2024-12-21 12:21:11 +01:00
Franck Nijhof dbe04f17ad Add sensors tests for Peblar Rocksolid EV Chargers (#133710) 2024-12-21 12:20:03 +01:00
Maciej Bieniek aad1d6a25d Use MAC address in Twinkly DeviceInfo.connections (#133708) 2024-12-21 12:19:11 +01:00
Franck Nijhof 7326555f03 Add diagnostic to Peblar Rocksolid EV Chargers integration (#133706) 2024-12-21 11:38:33 +01:00
Álvaro Fernández Rojas 5c2d769b54 Enable AEMET data cache (#131226) 2024-12-21 11:30:46 +01:00
Josef Zweck 66e863a2e3 Allow lamarzocco to reconnect websocket (#133635) 2024-12-21 11:29:24 +01:00
Richard Kroegel 78c9e47428 Improve BMW config flow (#133705) 2024-12-21 11:20:46 +01:00
J. Nick Koston 4e316429d3 Handle WebsocketConnectionError during mqtt auto reconnect (#133697)
followup to #133610 to handle the exception in the auto reconnect
path as well

fixes #132985
2024-12-21 11:18:47 +01:00
Norbert Rittel 989a3d1e24 Change "pin" to correct "PIN" for consistent translations (#133681) 2024-12-21 11:15:11 +01:00
Norbert Rittel 4efcf18c70 Change "pin" to "PIN" for consistency with common string (#133682) 2024-12-21 11:14:47 +01:00
Norbert Rittel 7998a05742 Replace lowercase "pin" in error message with the correct "PIN" (#133684) 2024-12-21 11:14:14 +01:00
Norbert Rittel 4ee9f813aa Fix inconsistent use of "pin" vs. "PIN" (#133685) 2024-12-21 11:13:44 +01:00
Franck Nijhof 859993e443 Add update platform to Peblar Rocksolid EV Chargers integration (#133570)
* Add update platform to Peblar Rocksolid EV Chargers integration

* Use device class translations
2024-12-21 10:55:00 +01:00
Allen Porter 4a063c3f9e Update the Google Tasks quality scale with documentation improvements (#133701) 2024-12-21 10:54:13 +01:00
J. Nick Koston 43fab48d4e Improve purge performance for PostgreSQL with large databases (#133699) 2024-12-21 10:53:15 +01:00
J. Nick Koston 02785a4ded Simplify query to find oldest state (#133700) 2024-12-21 10:37:16 +01:00
Andrew Sayre e43f4466e0 Improve HEOS group handling (#132213)
* Move register method to GroupManager

* Remove GroupManager mapping when entity removed

* Add test for when unloaded

* Error when group member not found

* Use entity registery to remove entity

* Update tests per feedback
2024-12-21 09:40:33 +01:00
Erik Montnemery 82f54eb9d2 Adjust the default backup name (#133668) 2024-12-21 09:38:59 +01:00
Abílio Costa 954b6133cb Use common mock fixture in Idasen Desk config flow tests (#133679) 2024-12-21 09:35:47 +01:00
Florent Thoumie 9c70ec4150 iaqualink: fix load_verify_locations() blocking call (#133459)
* Try to fix blocking call

* Fix lint
2024-12-21 09:26:38 +01:00
Dan Raper 3788e942a7 Bump Ohme library version to 1.2.0 (#133666)
Bump library version
2024-12-21 09:25:34 +01:00
Kevin Worrel e38a85da64 Add entity translation strings for ScreenLogic (#130708)
* Add translation strings for entities

* Translation key updates

* Mach original name

* Remove state translations

* Sentence case entity names

* Fix tests

* Add missing translation_key for Air temperature

* Revert inadvertant entity_id change on last_dose_time sensors

* Update homeassistant/components/screenlogic/strings.json

Lowercase 'entry'

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

* Define translations for each circuit delay sensor

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-21 09:25:21 +01:00
greyeee 861d9b3341 Add initial support for SwitchBot relay switch (#130863)
* Support relay switch

* 更新下版本

* add test case

* change to async_abort

* Upgrade PySwitchbot to 0.53.2

* change unit to volt

* upgrade pySwitchbot dependency

* bump lib, will be split into a seperate PR after testing is finished

* dry

* dry

* dry

* dry

* dry

* dry

* dry

* update tests

* fixes

* fixes

* cleanups

* fixes

* fixes

* fixes

* bump again

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-21 00:49:30 +01:00
J. Nick Koston b6819cbff3 Bump PySwitchbot to 0.55.2 (#133690)
changelog: https://github.com/sblibs/pySwitchbot/compare/0.54.0...0.55.2
2024-12-21 00:13:21 +01:00
Joost Lekkerkerker 9a0035e090 Fix Mealie test coverage (#133659) 2024-12-20 23:45:54 +01:00
Luke Lashley 1e420f16f7 Update Roborock to 2.8.4 (#133680) 2024-12-20 22:01:56 +01:00
G Johansson b29be34f55 Allow Filter title to be translated (#128929) 2024-12-20 21:21:41 +01:00
Michael Hansen 8607ba884c Bump intents to 2024.12.20 (#133676) 2024-12-20 14:23:12 -05:00
Joost Lekkerkerker 2639bdbefd Add parallel updates to Mealie (#133660) 2024-12-20 19:21:37 +00:00
Norbert Rittel c780933fa0 Reword invoke_pin action to avoid misunderstanding with "PIN" (#133665)
* Reword invoke_pin action to avoid misunderstanding with "PIN"

The previous mismatch between "PIN" and "pin" in the invoke_pin caused wrong translations as "PIN" was interpreted as the abbreviation for "Personal Identification Number".

This commit fixes this by explaining "pin" as related to "pinning" content on the device.

In addition the very "invoke" is replaced by "play" which every user and translator will understand immediately.

Along with those changes this commit reverts my previous change to "PIN" in all strings that made things worse.

* Use "Pin ID" for the field variable
2024-12-20 19:12:48 +01:00
Erik Montnemery a23b37114e Improve recorder data migrator tests (#133628) 2024-12-20 07:41:14 -10:00
Abílio Costa 17f0c24895 Replace tests for Idasen Desk with parameterized test (#133672) 2024-12-20 18:24:57 +01:00
Steven B. 6ed345f773 Add check for client errors to stream component (#132866) 2024-12-20 07:20:24 -10:00
elmurato 233395c181 Add missing await in Minecraft Server (#133670) 2024-12-20 17:58:31 +01:00
Andre Lengwenus 92195ff77d Bump pypck to 0.8.1 (#133646)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-12-20 17:10:37 +01:00
Joost Lekkerkerker ad7a334147 Add translations to Mealie exceptions (#133648) 2024-12-20 16:08:31 +01:00
Mick Vleeshouwer 87f5a7057e Fix target temperature for AtlanticElectricalTowelDryer in Overkiz (#133657) 2024-12-20 16:00:44 +01:00
Erik Montnemery 5afb9a5053 Validate password before restoring backup (#133647)
* Validate password before restoring backup

* Raise specific error when password is incorrect
2024-12-20 15:43:46 +01:00
shapournemati-iotty 1c0135880d Add outlet device class to iotty switch entity (#132912)
* upgrade iottycloud lib to 0.3.0

* Add outlet

* test outlet turn on and turn off

* test add outlet

* Refactor code to use only one SwitchEntity  with an EntityDescription to distinguish Outlet and Lightswitch

* Refactor switch entities to reduce duplicated code

* Refactor tests to reduce duplicated code

* Refactor code to improve abstraction layer using specific types instead of generics

* Remove print and redundant field
2024-12-20 15:33:05 +01:00
Erik Montnemery f49111a4d9 Bump aiohasupervisor to version 0.2.2b4 (#133652)
* Bump aiohasupervisor to version 0.2.2b4

* Update test
2024-12-20 09:23:21 -05:00
Erik Montnemery 10478f4ca5 Fix logic in backup retention filter (#133654) 2024-12-20 09:19:57 -05:00
Norbert Rittel 9f43a7a17b Fix inconsistent spelling of "PIN" and "ID" (#133653)
* Fix inconsistent spelling of "PIN" and "ID"

Several actions contain an inconsistent spelling of "PIN" and "ID" with lowercase characters.

Especially to avoid (automated) mistranslations as (connection) pin etc. this needs to be corrected.

* Fix lowercase "blink" as well

Additional commit to fix the wrong spelling of "blink" along the way.
2024-12-20 15:17:47 +01:00
Joost Lekkerkerker cbb4c06195 Add Mealie to strict typing (#133644) 2024-12-20 15:17:08 +01:00
Norbert Rittel 83fdc07df0 Fix inconsistent spelling of "PIN" vs. "pin" (#133655)
As "PIN" is an abbreviation it should be all-caps throughout the UI.

This commit fixes two inconsistent occurrences in the invoke_pin action.
2024-12-20 15:15:16 +01:00
Norbert Rittel 0d309aa632 Fix inconsistent spelling of "PIN" vs. "pin" (#133656)
Part of the strings in the strings.json use an inconsistent spelling of "PIN" as "pin"

This commit fixes this to ensure correct and consistent translations, too.
2024-12-20 15:14:04 +01:00
Erik Montnemery 7d04eef5c5 Reject duplicates in WS command backup/config/update (#133650)
* Reject duplicates in WS command backup/config/update

* Add tests
2024-12-20 15:06:55 +01:00
Joost Lekkerkerker 870dc4dbea Record Analytics Insights quality scale (#133571)
* Record Analytics Insights quality scale

* Record Analytics Insights quality scale

* Record Analytics Insights quality scale

* Update homeassistant/components/analytics_insights/quality_scale.yaml

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/analytics_insights/quality_scale.yaml

Co-authored-by: Josef Zweck <josef@zweck.dev>

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2024-12-20 13:14:41 +01:00
Erik Montnemery 4c96b83297 Fix reading extra metadata for local backups (#133643) 2024-12-20 13:13:25 +01:00
Erik Montnemery 5834ecb13e Fix homeassistant_included flag for local backups (#133640) 2024-12-20 12:36:54 +01:00
Cyrill Raccaud e62a563ec1 Add Swiss Public Transport quality scale record (#131629) 2024-12-20 12:30:55 +01:00
Joost Lekkerkerker 6a599dc27a Record NYT Games quality scale (#133592)
* Record NYT Games quality scale

* Record NYT Games quality scale

* Fix
2024-12-20 12:30:35 +01:00
Joost Lekkerkerker df383a3a31 Record Mealie quality scale (#133587)
* Record Mealie quality scale

* Record NYT Games quality scale

* Fix

* Fix

* Fix
2024-12-20 12:29:54 +01:00
Joost Lekkerkerker 86e43b7196 Record Knocki quality scale (#133582)
* Record Knocki quality scale

* Record Knocki quality scale

* Fix
2024-12-20 12:29:04 +01:00
dontinelli b5c4608373 Upgrade QS from bronze to silver for slide_local (#133560) 2024-12-20 12:25:45 +01:00
Josef Zweck bddd8624bb Add scale support to lamarzocco (#133335) 2024-12-20 12:24:15 +01:00
Franck Nijhof 6974f61703 2024.12.5 (#133636) 2024-12-20 11:45:57 +01:00
Erik Montnemery 3df992790d Bump aiohasupervisor to version 0.2.2b3 (#133631) 2024-12-20 10:59:52 +01:00
Kenny Root b391dfe647 Switch to official Zabbix Python API (#131674) 2024-12-20 10:59:30 +01:00
Franck Nijhof e7bdf1467b Bump version to 2024.12.5 2024-12-20 09:51:57 +00:00
J. Nick Koston ff9df15cb0 Handle mqtt.WebsocketConnectionError when connecting to the MQTT broker (#133610)
fixes #132985
2024-12-20 09:43:13 +00:00
Joost Lekkerkerker fdde9d3a52 Fix Twinkly raise on progress (#133601) 2024-12-20 09:43:09 +00:00
Marcel van der Veldt 8c1a18b383 Handle null value for elapsed time in Music Assistant (#133597) 2024-12-20 09:43:05 +00:00
J. Nick Koston 367749d93c Bump aiohttp to 3.11.11 (#133530) 2024-12-20 09:42:34 +00:00
Joakim Plate 13f32c6720 Bump gardena_bluetooth to 1.5.0 (#133502) 2024-12-20 09:41:07 +00:00
Joakim Plate f8e1a786be Update fjäråskupan to 2.3.2 (#133499) 2024-12-20 09:41:03 +00:00
Joakim Plate cd5a46f11d Update fjäråskupan to 2.3.1 (#133493) 2024-12-20 09:41:00 +00:00
Luke Lashley 0140aa7240 Update Roborock to 2.8.1 (#133492) 2024-12-20 09:40:56 +00:00
Mick Vleeshouwer 92f50c63b1 Don't raise Overkiz user flow unique_id check (#133471) 2024-12-20 09:40:52 +00:00
Mick Vleeshouwer 1afeabfd64 Bump pyOverkiz to 1.15.3 (#133458) 2024-12-20 09:40:49 +00:00
Quentame 709d15a79b Bump Freebox to 1.2.1 (#133455) 2024-12-20 09:40:45 +00:00
J. Nick Koston cf4dbcfebf Ensure screenlogic retries if the protocol adapter is still booting (#133444)
* Ensure screenlogic retries if the protocol adapter is still booting

If the protocol adapter is still booting, it will disconnect and never
retry

```
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 640, in __async_setup_with_context
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/screenlogic/__init__.py", line 65, in async_setup_entry
    await gateway.async_connect(**connect_info)
  File "/usr/local/lib/python3.13/site-packages/screenlogicpy/gateway.py", line 142, in async_connect
    connectPkg = await async_connect_to_gateway(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
    )
    ^
  File "/usr/local/lib/python3.13/site-packages/screenlogicpy/requests/login.py", line 107, in async_connect_to_gateway
    mac_address = await async_gateway_connect(transport, protocol, max_retries)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/screenlogicpy/requests/login.py", line 77, in async_gateway_connect
    raise ScreenLogicConnectionError("Host unexpectedly disconnected.")
screenlogicpy.const.common.ScreenLogicConnectionError: Host unexpectedly disconnected.
```

* coverage
2024-12-20 09:40:42 +00:00
Ron Weikamp 59e6fa5138 Bugfix: also schedule time based integration when source is 0 (#133438)
* Bugfix also schedule time based integration when source is 0

* Update tests/components/integration/test_sensor.py

Co-authored-by: Diogo Gomes <diogogomes@gmail.com>

* Improve comment in test. Remove redundant assertion.

---------

Co-authored-by: Diogo Gomes <diogogomes@gmail.com>
2024-12-20 09:40:38 +00:00
IceBotYT 8400ef8441 Add support for Nice G.O. HAE00080 wall station (#133186) 2024-12-20 09:40:35 +00:00
IceBotYT 6188db18c2 Bump nice-go to 1.0.0 (#133185)
* Bump Nice G.O. to 1.0.0

* Mypy

* Pytest
2024-12-20 09:40:31 +00:00
Jonas Fors Lellky 7e6392f062 Define setpoints as constants in flexit_bacnet (#133580)
* Define setpoints as consts

* Use a regular comment instead of docstring

* Un-indent comment
2024-12-20 10:11:50 +01:00
Joakim Sørensen 10191e7a23 Add async_register_backup_agents_listener to cloud/backup (#133584)
* Add async_register_backup_agents_listener to cloud/backup

* Coverage

* more coverage
2024-12-20 08:55:00 +01:00
G Johansson ad34bc8910 Add min/max price sensor to Nord Pool (#133534)
* Add min/max price sensor to Nord Pool

* Last fixes

* Make link in strings

* Replace func
2024-12-20 08:26:36 +01:00
Manu 26212798a3 Fixes and code cleanup for IronOS integration (#133579)
* Fix typing and cleanup in IronOS integration

* fix test not using freezer

* changes

* fix timedelta
2024-12-20 08:25:08 +01:00
J. Nick Koston 3d20c5c5d6 Remove lower bound for history start time state query (#133607)
Remove lower bound for start time state query

With the new query in #133553 we do not need a lower bound
on the search since it will always use index now and we
always want the newest value in the index before the
provided timestamp. The lower bound is redudant at this
point as it will always be older than the oldest
time point for the state. It only made sense when
the query would have had to examine a time window
of states instead of doing an index only search.
2024-12-20 08:24:47 +01:00
Christopher Fenner afae257a12 Bump PyViCare to 2.39.1 (#133619) 2024-12-20 01:14:48 +01:00
Quentame 64aba0c1a3 Bump Freebox to 1.2.1 (#133455) 2024-12-20 00:48:03 +01:00
J. Nick Koston 551a584ca6 Handle mqtt.WebsocketConnectionError when connecting to the MQTT broker (#133610)
fixes #132985
2024-12-19 21:39:39 +01:00
Jan-Philipp Benecke b261c7f18a Mark docs-installation-parameters for SABnzbd as done (#133609) 2024-12-19 20:29:12 +01:00
Joost Lekkerkerker 61e5f10d12 Fix Twinkly raise on progress (#133601) 2024-12-19 20:27:08 +01:00
adam-the-hero 2413fc4c0d Fix Watergate Water meter volume sensor (#133606) 2024-12-19 20:25:24 +01:00
Abílio Costa e6ef3fe507 Update Idasen Desk user flow step strings (#133605) 2024-12-19 20:24:10 +01:00
J. Nick Koston 04bcc8d3d3 Bump yalexs-ble to 2.5.6 (#133593) 2024-12-19 09:13:51 -10:00
Joost Lekkerkerker 52683c5f75 Improve Airgradient config flow tests (#133594) 2024-12-19 19:58:33 +01:00
Raphael Hehl 2f77cda822 Add basic UniFi Protect AiPort support (#133523)
* UnifiProtect add basic support for AiPort devices

* Sort ignore-words

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2024-12-19 08:18:21 -10:00
Marcel van der Veldt a97434976e Handle null value for elapsed time in Music Assistant (#133597) 2024-12-19 19:00:18 +01:00
epenet e357e0a406 Set default min/max color temperature in template lights (#133549) 2024-12-19 18:40:04 +01:00
Andrew Jackson 1a068d99d6 Add data descriptions to Mealie integration (#133590) 2024-12-19 18:28:50 +01:00
Joost Lekkerkerker 95b3d27b60 Update Airgradient quality scale (#133569) 2024-12-19 18:23:40 +01:00
Allen Porter a3ef3cce3e Improve Google Tasks coordinator updates behavior (#133316) 2024-12-19 16:41:47 +01:00
Erik Montnemery 255f85eb2f Fix boot loop after restoring backup (#133581) 2024-12-19 16:04:59 +01:00
Josef Zweck 94c7d18346 Bump pylamarzocco to 1.4.1 (#133557) 2024-12-19 13:36:32 +01:00
Noah Husby eb8ee1339c Set Russound RIO quality scale to silver (#133494) 2024-12-19 12:40:23 +01:00
Stefan Agner 962f1bad32 Add mW as unit of measurement for Matter electrical power sensors (#133504) 2024-12-19 11:40:05 +00:00
Erik Montnemery dd215b3d5d Revert "Revert "Simplify recorder RecorderRunsManager (#131785)"" (#133564)
Revert "Revert "Simplify recorder RecorderRunsManager" (#133201)"

This reverts commit 980b8a91e6.
2024-12-19 12:32:15 +01:00
Erik Montnemery bb7abd037c Revert "Revert "Improve recorder history queries (#131702)"" (#133561)
Revert "Revert "Improve recorder history queries (#131702)" (#133203)"

This reverts commit 74e4654c26.
2024-12-19 11:50:12 +01:00
J. Nick Koston d35b34f142 Replace start time state query with single correlated scalar subquery (#133553) 2024-12-19 00:14:32 -10:00
dependabot[bot] 1c119518db Bump codecov/codecov-action from 5.1.1 to 5.1.2 (#133547)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.1.1...v5.1.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-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-12-19 10:52:10 +01:00
Norbert Rittel 9a6c749714 Change 'GSuite' to 'Workspace', fix 'Start' field label (#133554)
* Change 'GSuite' to 'Workspace', fix 'Start' field label

Several years ago Google renamed "G Suite" to "Google Workspace", this commit applies the same change to one of the  field descriptions of the set_vacation action.

In addition the "Start" field of the action currently uses the common action (!) for Start which is wrong in this context, it stands for the beginning here.

This commit changes this back to a local definition of this label just like "End".

In German for example "Start" needs to be "Beginn" in this context while the common action is translated as "Starten".

* Use "Google Workspace" for more clarity

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

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-19 10:51:30 +01:00
Norbert Rittel 79484ea7f5 Grammar fixes for action names and descriptions (#133559)
Several KNX actions contain a wrong "s" at the end of their verbs while those are missing in several of the descriptions.

This commit changes all those to make them consistent with the remaining actions in KNX and the standard terminology in Home Assistant.
2024-12-19 10:50:12 +01:00
Franck Nijhof 3568bdca65 Update Home Assistant base image to 2024.12.0 (#133558) 2024-12-19 10:48:43 +01:00
Erik Montnemery a76f82080b Create repair issues when automatic backup fails (#133513)
* Create repair issues when automatic backup fails

* Improve test coverage

* Adjust issues
2024-12-19 10:40:07 +01:00
Christopher Fenner cd384cadbe Fulfill IQS rule config-flow in ViCare integration (#133524)
* add data_description

* Apply suggestions from code review

Co-authored-by: Josef Zweck <josef@zweck.dev>

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2024-12-19 10:04:26 +01:00
J. Nick Koston 69a8d3f3c1 Revert "Optimize start time state queries for PostgreSQL" (#133555) 2024-12-18 23:01:58 -10:00
J. Nick Koston a3fb6e8f92 Bump pydantic to 2.10.4 (#133539)
changelog: https://github.com/pydantic/pydantic/compare/v2.10.3...v2.10.4
2024-12-19 10:01:40 +01:00
Erik Montnemery c8480627ca Add comment motivating magic number for MySQL error codes (#133516)
* Add comment motivating magic number for MySQL error codes

* Pick nits
2024-12-19 09:56:32 +01:00
Franck Nijhof 893f605d61 Revert "Update docker base image to 2024.12.1" (#133552)
Revert "Update docker base image to 2024.12.1 (#133323)"

This reverts commit 66dcd38701.
2024-12-19 09:42:22 +01:00
epenet ddd2ba6c4a Set default min/max color temperature in hue lights (#133548) 2024-12-19 08:36:29 +01:00
Stefan Agner 681863f80e Use mV and mA as units for electrical power measurement in Matter (#133505) 2024-12-19 08:32:46 +01:00
J. Nick Koston 99698ef95d Optimize start time state queries for PostgreSQL (#133228) 2024-12-18 19:41:53 -10:00
Franck Nijhof 3fe08a7223 Add zeroconf discovery to Peblar Rocksolid EV chargers (#133529) 2024-12-19 00:39:14 +01:00
J. Nick Koston 35601480d2 Bump aiohttp to 3.11.11 (#133530) 2024-12-18 23:48:39 +01:00
Abílio Costa 0076bd8389 Simplify Idasen Desk entity properties (#133536) 2024-12-18 23:47:24 +01:00
Franck Nijhof 9f3c549f8d Add integration setup tests to Peblar Rocksolid EV Chargers (#133532) 2024-12-18 23:46:18 +01:00
Norbert Rittel 03707e6308 Improve field descriptions for Download file action (#133413)
* Improve field descriptions for Download file action

Currently two of the field descriptions for the Download file action don't explain exactly what should be entered but rather explain these like additional actions.

The third, the Overwrite file option is misleading as it does not refer to an existing file.

This commit fixes both issues by explaining the purpose of all three fields in a slightly more detailed fashion.

* Update homeassistant/components/downloader/strings.json

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/downloader/strings.json

Co-authored-by: Josef Zweck <josef@zweck.dev>

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2024-12-18 22:40:30 +01:00
Abílio Costa 9e6a8638dd Bump idasen-ha to 2.6.3 (#133508)
This is a minor bump that adds py.typed
2024-12-18 22:38:57 +01:00
Norbert Rittel 2a9082559a Fix names and description of two actions (#133528)
The two actions enable_motion_recording and disable_motion_recording use "Enables" and "Disables" in their names.

This is inconsistent with the name of the actions, all other actions of this component, and the standard way of naming them, too.

In addition the description of the latter misses the "s" which causes additional inconsistency – especially in translations.
2024-12-18 22:35:58 +01:00
starkillerOG ba3fca53b0 Reolink platinum quality scale (#133514) 2024-12-18 21:49:32 +01:00
Raphael Hehl e4bb351d2d Bump uiprotect to 7.1.0 (#133520)
* Bump uiprotect to version 7.1.0

* Add aiports to bootstrap fixture in unifiprotect tests
2024-12-18 21:41:22 +01:00
Christopher Fenner 1bdda0249e Bump PyViCare to 2.39.0 (#133519) 2024-12-18 21:38:52 +01:00
Erik Montnemery ff8bc763c3 Ensure indices needed by data migrators exist (#133367)
* Ensure indices needed by data migrators exist

* Update test

* Improve test

* Ignore index error on char(0) columns

* Adjust tests

* Address review comments

* Add comment motivating magic number
2024-12-18 21:29:52 +01:00
dontinelli 8a8be71f96 Add tests for cover and increase test coverage for slide_local (#133515) 2024-12-18 20:53:05 +01:00
starkillerOG 19e6867f1a Reolink translate errors (#132301) 2024-12-18 20:22:33 +01:00
Norbert Rittel c8f050ecbc Fix the local_file.update_file_path action's name and description (#133509) 2024-12-18 20:08:57 +01:00
IceBotYT b7ff27122a Add support for Nice G.O. HAE00080 wall station (#133186) 2024-12-18 19:47:41 +01:00
Shay Levy 3a8b0b3ea6 Use Switcher _async_call_api in climate (#133230) 2024-12-18 19:46:52 +01:00
mvn23 0ff2a0d66d Add "cancel room setpoint override" button to opentherm_gw (#132162) 2024-12-18 19:46:30 +01:00
Joakim Plate 4daf6dd41d Bump gardena_bluetooth to 1.5.0 (#133502) 2024-12-18 19:39:35 +01:00
Thomas55555 51bead3229 Update number platform values before add in APSystems and add tests (#131938)
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2024-12-18 19:34:49 +01:00
Manu 352e948d56 Add tests for already_configured erros in IronOS integration (#132265) 2024-12-18 19:33:33 +01:00
Manu 70ad4ee454 Add select platform to IronOS (#132218) 2024-12-18 19:32:51 +01:00
TJ Horner 53ef96c63e weatherkit: use stale data for up to an hour if updates fail (#130398) 2024-12-18 19:21:03 +01:00
Franck Nijhof bb2d027532 Add Peblar Rocksolid EV Chargers integration (#133501)
* Add Peblar Rocksolid EV Chargers integration

* Process review comments
2024-12-18 19:11:13 +01:00
Erik Montnemery 51d63ba508 Store automatic backup flag in backup metadata (#133500) 2024-12-18 18:30:46 +01:00
Arie Catsman fc622e398f add exception translation to enphase_envoy (#132483) 2024-12-18 18:24:12 +01:00
peteS-UK 920de90603 Increase Squeezebox config_flow test coverage to 100% (#133484)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-18 18:22:22 +01:00
Joakim Plate a6089b497a Update fjäråskupan to 2.3.2 (#133499) 2024-12-18 18:03:27 +01:00
Erik Montnemery 5516f3609d Rename strategy backup to automatic backup (#133489)
* Rename strategy backup to automatic backup

* Update homeassistant/components/backup/config.py

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

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2024-12-18 17:35:11 +01:00
Joakim Plate a1558213c4 Update fjäråskupan to 2.3.1 (#133493) 2024-12-18 16:53:15 +01:00
Luke Lashley 2564533dae Update Roborock to 2.8.1 (#133492) 2024-12-18 16:22:39 +01:00
Noah Husby f46e764982 Update quality scale for Russound RIO (#133093) 2024-12-18 16:06:48 +01:00
dontinelli d6c201de4a Add exceptions and translations for slide_local (#133490) 2024-12-18 15:33:11 +01:00
mkmer c9f1829c0b Add (de)humidifier platform to Honeywell (#132287)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-18 15:27:40 +01:00
dontinelli 1e075cdac7 Add diagnostics to slide_local (#133488) 2024-12-18 15:21:17 +01:00
Philip Baylas fce6d6246f Change log level of connection failure to info (#132625)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-12-18 15:07:03 +01:00
Maciej Bieniek 3132700492 Add ability to translate ENUM sensor states in Unifi integration (#131921) 2024-12-18 15:02:44 +01:00
adam-the-hero 943b1d9f08 Add sensors platform to Watergate integration (#133015) 2024-12-18 14:52:25 +01:00
Markus Jacobsen 2d6d313e5c Complete adding custom integration action sections support to hassfest (#132443) 2024-12-18 14:50:12 +01:00
Guido Schmitz 9716183997 Add entity translations to devolo Home Control (#132927) 2024-12-18 14:38:29 +01:00
Andre Lengwenus a46a0ad2b4 Add device_id parameter to LCN actions (service calls) (#129590) 2024-12-18 14:35:02 +01:00
J. Diego Rodríguez Royo c06bc53724 Deprecate Home Connect program switches (#131641) 2024-12-18 14:26:37 +01:00
Bas Brussee 4399d09820 Allow data description in sections (#128965)
* Allow data description in sections

* update format with ruff

* Add data_description to kitchen_sink input section

---------

Co-authored-by: Erik <erik@montnemery.com>
2024-12-18 14:02:08 +01:00
Abílio Costa ca2c7280eb Remove uneeded logger param from Idasen Desk Coordinator (#133485) 2024-12-18 13:59:56 +01:00
Erik Montnemery ecb3bf79f3 Revert "Add support for subentries to config entries" (#133470)
Revert "Add support for subentries to config entries (#117355)"

This reverts commit ad15786115.
2024-12-18 13:51:05 +01:00
Joost Lekkerkerker 2aba1d399b Rename test file to singular form (#133482) 2024-12-18 12:47:30 +00:00
greyeee be25cb7aa7 Add support for SwitchBot Relay Switch 1 and Relay Switch 1PM (#132327) 2024-12-18 13:19:45 +01:00
Mick Vleeshouwer 3bb6256572 Add test button for SmokeSensor in Overkiz (#133476) 2024-12-18 11:48:10 +01:00
Mick Vleeshouwer fc4100833e Change device class from Volume to Volume Storage in Overkiz (#133473)
Change device class from Volume to Volume Storage
2024-12-18 11:43:04 +01:00
Erik Montnemery 992afc4cd3 Set the with_strategy_settings to None for unknown backups (#133466) 2024-12-18 11:27:07 +01:00
Mick Vleeshouwer 7730f423b3 Add identify device class in Overkiz (#133474) 2024-12-18 11:22:32 +01:00
Mick Vleeshouwer 05b0c56191 Use enum instead of string for button entities key in Overkiz (#133472) 2024-12-18 11:22:22 +01:00
Mick Vleeshouwer fa0e54e658 Don't raise Overkiz user flow unique_id check (#133471) 2024-12-18 11:05:52 +01:00
Joakim Sørensen 869a0d7abc Add name to cloud connection info response (#133468) 2024-12-18 11:01:38 +01:00
dotvav 90208d2eb1 Bump pypalazzetti to 0.1.15 (#133433) 2024-12-18 10:58:25 +01:00
J. Diego Rodríguez Royo a6520d2627 Handle Home Connect error at diagnostics (#131644) 2024-12-18 10:52:45 +01:00
epenet 8b8c409916 Fix test-before-setup IQS check (#133467) 2024-12-18 10:44:19 +01:00
Ron Weikamp a2be5a383c Bugfix: also schedule time based integration when source is 0 (#133438)
* Bugfix also schedule time based integration when source is 0

* Update tests/components/integration/test_sensor.py

Co-authored-by: Diogo Gomes <diogogomes@gmail.com>

* Improve comment in test. Remove redundant assertion.

---------

Co-authored-by: Diogo Gomes <diogogomes@gmail.com>
2024-12-18 10:41:46 +01:00
Tomer Shemesh 39d781905d Add ssdp discovery to Onkyo (#131066) 2024-12-18 10:21:37 +01:00
Abílio Costa 5fb5e933e2 Use a common base entity for Idasen Desk (#132496)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-12-18 10:20:14 +01:00
Mick Vleeshouwer 413a578fdb Bump pyOverkiz to 1.15.3 (#133458) 2024-12-18 10:19:57 +01:00
Jan-Philipp Benecke c1cf0e23b2 Lift SABnzbd to bronze quality scale (#133453) 2024-12-18 10:10:42 +01:00
Noah Husby a449ca65be Improve test coverage for Russound RIO (#133096)
* Improve test coverage for Russound RIO

* Update

* Update
2024-12-18 09:33:17 +01:00
Arie Catsman 4c91d1b402 Add support for ACB batteries to Enphase Envoy (#131298)
* Add support for ACB batteries to Enphase Envoy

* Add tests for ACB battery support in ENphase Envoy

* make acb state sensordeviceclass ENUM

* Capitalize strings and use common idle
2024-12-18 08:48:37 +01:00
Noah Husby fab92d1cf8 Add reconfigure flow to Russound RIO (#133091)
* Add reconfigure flow to Russound RIO

* Mark reconfiguration flow as done

* Update

* Update
2024-12-18 08:40:27 +01:00
Assaf Inbal c10473844f Add sensors to Ituran integration (#133359)
Add sensors to Ituran
2024-12-18 08:36:42 +01:00
dependabot[bot] dfdd83789a Bump actions/upload-artifact from 4.4.3 to 4.5.0 (#133461) 2024-12-18 08:05:39 +01:00
J. Nick Koston 9bff9c5e7b Ensure screenlogic retries if the protocol adapter is still booting (#133444)
* Ensure screenlogic retries if the protocol adapter is still booting

If the protocol adapter is still booting, it will disconnect and never
retry

```
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 640, in __async_setup_with_context
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/screenlogic/__init__.py", line 65, in async_setup_entry
    await gateway.async_connect(**connect_info)
  File "/usr/local/lib/python3.13/site-packages/screenlogicpy/gateway.py", line 142, in async_connect
    connectPkg = await async_connect_to_gateway(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
    )
    ^
  File "/usr/local/lib/python3.13/site-packages/screenlogicpy/requests/login.py", line 107, in async_connect_to_gateway
    mac_address = await async_gateway_connect(transport, protocol, max_retries)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/screenlogicpy/requests/login.py", line 77, in async_gateway_connect
    raise ScreenLogicConnectionError("Host unexpectedly disconnected.")
screenlogicpy.const.common.ScreenLogicConnectionError: Host unexpectedly disconnected.
```

* coverage
2024-12-17 20:57:43 -05:00
Abílio Costa e73512e11c Add integration_type to Idasen Desk (#132486)
* Add Idasen Desk quality scale record

* Update wrong checks

* Add integration_type to Idasen Desk
2024-12-17 23:49:04 +01:00
G Johansson 4c60e36f4f Add Get price service to Nord Pool (#130185)
* Add get_price service to Nord Pool

* Tests and fixes

* Fixes

* Not used fixtures

* update qs

* Fixes

* docstring

* Remove selector from strings

* Mod service
2024-12-17 21:59:20 +01:00
G Johansson f8cd6204ca Fix reconfigure in Nord Pool (#133431) 2024-12-17 21:30:49 +01:00
Jan-Philipp Benecke eae25023e7 Do not remove services when last config entry is unloaded in SABnzbd (#133449) 2024-12-17 21:27:41 +01:00
Klaas Schoute 21c3bf48f9 Allow only single instance of easyenergy integration (#133447) 2024-12-17 21:02:39 +01:00
Franck Nijhof a5eb816dcf 2024.12.4 (#133422) 2024-12-17 15:28:28 +01:00
Franck Nijhof 517f3faa0a Bump version to 2024.12.4 2024-12-17 12:14:26 +00:00
G Johansson b4015805f7 Bump holidays to 0.63 (#133391) 2024-12-17 12:14:04 +00:00
Jonas Fors Lellky a56ad0273b Fix fan setpoints for flexit_bacnet (#133388) 2024-12-17 12:14:00 +00:00
Maciej Bieniek 2bc917c842 Bump imgw-pib to version 1.0.7 (#133364) 2024-12-17 12:13:57 +00:00
Michael 97f22b3a3d Allow load_verify_locations with only cadata passed (#133299) 2024-12-17 12:13:53 +00:00
J. Nick Koston a48a5adc81 Set code_arm_required to False for homekit_controller (#133284) 2024-12-17 12:13:50 +00:00
J. Nick Koston eb86b00dd4 Bump yalexs-ble to 2.5.5 (#133229)
changelog: https://github.com/bdraco/yalexs-ble/compare/v2.5.4...v2.5.5
2024-12-17 12:13:47 +00:00
Jan Bouwhuis e93256951e Bump incomfort-client to v0.6.4 (#133205) 2024-12-17 12:13:43 +00:00
Erik Montnemery 3b0ab421b0 Revert "Improve recorder history queries (#131702)" (#133203) 2024-12-17 12:11:13 +00:00
Erik Montnemery ca47253d81 Revert "Simplify recorder RecorderRunsManager" (#133201)
Revert "Simplify recorder RecorderRunsManager (#131785)"

This reverts commit cf0ee63507.
2024-12-17 12:08:41 +00:00
Avi Miller 9b0a489753 Bump aiolifx to 1.1.2 and add new HomeKit product prefixes (#133191)
Signed-off-by: Avi Miller <me@dje.li>
2024-12-17 11:44:54 +00:00
Conor Eager 9b02db008e Bump starlink-grpc-core to 1.2.1 to fix missing ping (#133183) 2024-12-17 11:44:50 +00:00
J. Nick Koston 223817a7fb Bump yalexs-ble to 2.5.4 (#133172) 2024-12-17 11:44:47 +00:00
G Johansson cdea9b5d3a Fix strptime in python_script (#133159)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2024-12-17 11:44:41 +00:00
Joost Lekkerkerker 8286ec9e60 Bump yt-dlp to 2024.12.13 (#133129) 2024-12-17 11:44:38 +00:00
rappenze cce7b9ac34 Fix fibaro climate hvac mode (#132508) 2024-12-17 11:44:34 +00:00
Erik Montnemery a42c0230c9 Simplify recorder RecorderRunsManager (#131785) 2024-12-17 11:44:30 +00:00
1561 changed files with 79557 additions and 17437 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
run: find ./homeassistant/components/*/translations -name "*.json" | tar zcvf translations.tar.gz -T -
- name: Upload translations
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: translations
path: translations.tar.gz
+14 -14
View File
@@ -40,7 +40,7 @@ env:
CACHE_VERSION: 11
UV_CACHE_VERSION: 1
MYPY_CACHE_VERSION: 9
HA_SHORT_VERSION: "2025.1"
HA_SHORT_VERSION: "2025.2"
DEFAULT_PYTHON: "3.12"
ALL_PYTHON_VERSIONS: "['3.12', '3.13']"
# 10.3 is the oldest supported version
@@ -537,7 +537,7 @@ jobs:
python --version
uv pip freeze >> pip_freeze.txt
- name: Upload pip_freeze artifact
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: pip-freeze-${{ matrix.python-version }}
path: pip_freeze.txt
@@ -661,7 +661,7 @@ jobs:
. venv/bin/activate
python -m script.licenses extract --output-file=licenses-${{ matrix.python-version }}.json
- name: Upload licenses
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: licenses-${{ github.run_number }}-${{ matrix.python-version }}
path: licenses-${{ matrix.python-version }}.json
@@ -877,7 +877,7 @@ jobs:
. venv/bin/activate
python -m script.split_tests ${{ needs.info.outputs.test_group_count }} tests
- name: Upload pytest_buckets
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: pytest_buckets
path: pytest_buckets.txt
@@ -979,14 +979,14 @@ jobs:
2>&1 | tee pytest-${{ matrix.python-version }}-${{ matrix.group }}.txt
- name: Upload pytest output
if: success() || failure() && steps.pytest-full.conclusion == 'failure'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{ matrix.group }}
path: pytest-*.txt
overwrite: true
- name: Upload coverage artifact
if: needs.info.outputs.skip_coverage != 'true'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: coverage-${{ matrix.python-version }}-${{ matrix.group }}
path: coverage.xml
@@ -1106,7 +1106,7 @@ jobs:
2>&1 | tee pytest-${{ matrix.python-version }}-${mariadb}.txt
- name: Upload pytest output
if: success() || failure() && steps.pytest-partial.conclusion == 'failure'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{
steps.pytest-partial.outputs.mariadb }}
@@ -1114,7 +1114,7 @@ jobs:
overwrite: true
- name: Upload coverage artifact
if: needs.info.outputs.skip_coverage != 'true'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: coverage-${{ matrix.python-version }}-${{
steps.pytest-partial.outputs.mariadb }}
@@ -1236,7 +1236,7 @@ jobs:
2>&1 | tee pytest-${{ matrix.python-version }}-${postgresql}.txt
- name: Upload pytest output
if: success() || failure() && steps.pytest-partial.conclusion == 'failure'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{
steps.pytest-partial.outputs.postgresql }}
@@ -1244,7 +1244,7 @@ jobs:
overwrite: true
- name: Upload coverage artifact
if: needs.info.outputs.skip_coverage != 'true'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: coverage-${{ matrix.python-version }}-${{
steps.pytest-partial.outputs.postgresql }}
@@ -1273,7 +1273,7 @@ jobs:
pattern: coverage-*
- name: Upload coverage to Codecov
if: needs.info.outputs.test_full_suite == 'true'
uses: codecov/codecov-action@v5.1.1
uses: codecov/codecov-action@v5.1.2
with:
fail_ci_if_error: true
flags: full-suite
@@ -1378,14 +1378,14 @@ jobs:
2>&1 | tee pytest-${{ matrix.python-version }}-${{ matrix.group }}.txt
- name: Upload pytest output
if: success() || failure() && steps.pytest-partial.conclusion == 'failure'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{ matrix.group }}
path: pytest-*.txt
overwrite: true
- name: Upload coverage artifact
if: needs.info.outputs.skip_coverage != 'true'
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: coverage-${{ matrix.python-version }}-${{ matrix.group }}
path: coverage.xml
@@ -1411,7 +1411,7 @@ jobs:
pattern: coverage-*
- name: Upload coverage to Codecov
if: needs.info.outputs.test_full_suite == 'false'
uses: codecov/codecov-action@v5.1.1
uses: codecov/codecov-action@v5.1.2
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
+2 -2
View File
@@ -24,11 +24,11 @@ jobs:
uses: actions/checkout@v4.2.2
- name: Initialize CodeQL
uses: github/codeql-action/init@v3.27.9
uses: github/codeql-action/init@v3.28.0
with:
languages: python
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3.27.9
uses: github/codeql-action/analyze@v3.28.0
with:
category: "/language:python"
+36 -7
View File
@@ -76,18 +76,37 @@ jobs:
# Use C-Extension for SQLAlchemy
echo "REQUIRE_SQLALCHEMY_CEXT=1"
# Add additional pip wheel build constraints
echo "PIP_CONSTRAINT=build_constraints.txt"
) > .env_file
- name: Write pip wheel build constraints
run: |
(
# ninja 1.11.1.2 + 1.11.1.3 seem to be broken on at least armhf
# this caused the numpy builds to fail
# https://github.com/scikit-build/ninja-python-distributions/issues/274
echo "ninja==1.11.1.1"
) > build_constraints.txt
- name: Upload env_file
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: env_file
path: ./.env_file
include-hidden-files: true
overwrite: true
- name: Upload build_constraints
uses: actions/upload-artifact@v4.5.0
with:
name: build_constraints
path: ./build_constraints.txt
overwrite: true
- name: Upload requirements_diff
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: requirements_diff
path: ./requirements_diff.txt
@@ -99,7 +118,7 @@ jobs:
python -m script.gen_requirements_all ci
- name: Upload requirements_all_wheels
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.5.0
with:
name: requirements_all_wheels
path: ./requirements_all_wheels_*.txt
@@ -123,6 +142,11 @@ jobs:
with:
name: env_file
- name: Download build_constraints
uses: actions/download-artifact@v4.1.8
with:
name: build_constraints
- name: Download requirements_diff
uses: actions/download-artifact@v4.1.8
with:
@@ -142,7 +166,7 @@ jobs:
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "libffi-dev;openssl-dev;yaml-dev;nasm;zlib-dev"
apk: "libffi-dev;openssl-dev;yaml-dev;nasm;zlib-ng-dev"
skip-binary: aiohttp;multidict;propcache;yarl;SQLAlchemy
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
@@ -167,6 +191,11 @@ jobs:
with:
name: env_file
- name: Download build_constraints
uses: actions/download-artifact@v4.1.8
with:
name: build_constraints
- name: Download requirements_diff
uses: actions/download-artifact@v4.1.8
with:
@@ -205,7 +234,7 @@ jobs:
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev;nasm;zlib-dev"
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev;nasm;zlib-ng-dev"
skip-binary: aiohttp;charset-normalizer;grpcio;multidict;SQLAlchemy;propcache;protobuf;pymicro-vad;yarl
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
@@ -219,7 +248,7 @@ jobs:
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev;nasm;zlib-dev"
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev;nasm;zlib-ng-dev"
skip-binary: aiohttp;charset-normalizer;grpcio;multidict;SQLAlchemy;propcache;protobuf;pymicro-vad;yarl
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
@@ -233,7 +262,7 @@ jobs:
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev;nasm;zlib-dev"
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev;nasm;zlib-ng-dev"
skip-binary: aiohttp;charset-normalizer;grpcio;multidict;SQLAlchemy;propcache;protobuf;pymicro-vad;yarl
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
+2 -2
View File
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.3
rev: v0.8.6
hooks:
- id: ruff
args:
@@ -12,7 +12,7 @@ repos:
hooks:
- id: codespell
args:
- --ignore-words-list=astroid,checkin,currenty,hass,iif,incomfort,lookin,nam,NotIn
- --ignore-words-list=aiport,astroid,checkin,currenty,hass,iif,incomfort,lookin,nam,NotIn
- --skip="./.*,*.csv,*.json,*.ambr"
- --quiet-level=2
exclude_types: [csv, json, html]
+6
View File
@@ -311,6 +311,8 @@ homeassistant.components.manual.*
homeassistant.components.mastodon.*
homeassistant.components.matrix.*
homeassistant.components.matter.*
homeassistant.components.mcp_server.*
homeassistant.components.mealie.*
homeassistant.components.media_extractor.*
homeassistant.components.media_player.*
homeassistant.components.media_source.*
@@ -361,8 +363,11 @@ homeassistant.components.openuv.*
homeassistant.components.oralb.*
homeassistant.components.otbr.*
homeassistant.components.overkiz.*
homeassistant.components.overseerr.*
homeassistant.components.p1_monitor.*
homeassistant.components.pandora.*
homeassistant.components.panel_custom.*
homeassistant.components.peblar.*
homeassistant.components.peco.*
homeassistant.components.persistent_notification.*
homeassistant.components.pi_hole.*
@@ -378,6 +383,7 @@ homeassistant.components.pure_energie.*
homeassistant.components.purpleair.*
homeassistant.components.pushbullet.*
homeassistant.components.pvoutput.*
homeassistant.components.python_script.*
homeassistant.components.qnap_qsw.*
homeassistant.components.rabbitair.*
homeassistant.components.radarr.*
+23 -12
View File
@@ -578,8 +578,8 @@ build.json @home-assistant/supervisor
/tests/components/google_tasks/ @allenporter
/homeassistant/components/google_travel_time/ @eifinger
/tests/components/google_travel_time/ @eifinger
/homeassistant/components/govee_ble/ @bdraco @PierreAronnax
/tests/components/govee_ble/ @bdraco @PierreAronnax
/homeassistant/components/govee_ble/ @bdraco
/tests/components/govee_ble/ @bdraco
/homeassistant/components/govee_light_local/ @Galorhallen
/tests/components/govee_light_local/ @Galorhallen
/homeassistant/components/gpsd/ @fabaff @jrieger
@@ -637,6 +637,8 @@ build.json @home-assistant/supervisor
/tests/components/homeassistant_sky_connect/ @home-assistant/core
/homeassistant/components/homeassistant_yellow/ @home-assistant/core
/tests/components/homeassistant_yellow/ @home-assistant/core
/homeassistant/components/homee/ @Taraman17
/tests/components/homee/ @Taraman17
/homeassistant/components/homekit/ @bdraco
/tests/components/homekit/ @bdraco
/homeassistant/components/homekit_controller/ @Jc2k @bdraco
@@ -686,6 +688,8 @@ build.json @home-assistant/supervisor
/tests/components/icloud/ @Quentame @nzapponi
/homeassistant/components/idasen_desk/ @abmantis
/tests/components/idasen_desk/ @abmantis
/homeassistant/components/igloohome/ @keithle888
/tests/components/igloohome/ @keithle888
/homeassistant/components/ign_sismologia/ @exxamalte
/tests/components/ign_sismologia/ @exxamalte
/homeassistant/components/image/ @home-assistant/core
@@ -887,6 +891,8 @@ build.json @home-assistant/supervisor
/tests/components/matrix/ @PaarthShah
/homeassistant/components/matter/ @home-assistant/matter
/tests/components/matter/ @home-assistant/matter
/homeassistant/components/mcp_server/ @allenporter
/tests/components/mcp_server/ @allenporter
/homeassistant/components/mealie/ @joostlek @andrew-codechimp
/tests/components/mealie/ @joostlek @andrew-codechimp
/homeassistant/components/meater/ @Sotolotl @emontnemery
@@ -1066,8 +1072,8 @@ build.json @home-assistant/supervisor
/tests/components/ondilo_ico/ @JeromeHXP
/homeassistant/components/onewire/ @garbled1 @epenet
/tests/components/onewire/ @garbled1 @epenet
/homeassistant/components/onkyo/ @arturpragacz
/tests/components/onkyo/ @arturpragacz
/homeassistant/components/onkyo/ @arturpragacz @eclair4151
/tests/components/onkyo/ @arturpragacz @eclair4151
/homeassistant/components/onvif/ @hunterjm
/tests/components/onvif/ @hunterjm
/homeassistant/components/open_meteo/ @frenck
@@ -1103,8 +1109,10 @@ build.json @home-assistant/supervisor
/tests/components/otbr/ @home-assistant/core
/homeassistant/components/ourgroceries/ @OnFreund
/tests/components/ourgroceries/ @OnFreund
/homeassistant/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev @tronix117 @alexfp14
/tests/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev @tronix117 @alexfp14
/homeassistant/components/overkiz/ @imicknl
/tests/components/overkiz/ @imicknl
/homeassistant/components/overseerr/ @joostlek
/tests/components/overseerr/ @joostlek
/homeassistant/components/ovo_energy/ @timmo001
/tests/components/ovo_energy/ @timmo001
/homeassistant/components/p1_monitor/ @klaasnicolaas
@@ -1113,6 +1121,8 @@ build.json @home-assistant/supervisor
/tests/components/palazzetti/ @dotvav
/homeassistant/components/panel_custom/ @home-assistant/frontend
/tests/components/panel_custom/ @home-assistant/frontend
/homeassistant/components/peblar/ @frenck
/tests/components/peblar/ @frenck
/homeassistant/components/peco/ @IceBotYT
/tests/components/peco/ @IceBotYT
/homeassistant/components/pegel_online/ @mib1185
@@ -1133,8 +1143,8 @@ build.json @home-assistant/supervisor
/tests/components/plaato/ @JohNan
/homeassistant/components/plex/ @jjlawren
/tests/components/plex/ @jjlawren
/homeassistant/components/plugwise/ @CoMPaTech @bouwew @frenck
/tests/components/plugwise/ @CoMPaTech @bouwew @frenck
/homeassistant/components/plugwise/ @CoMPaTech @bouwew
/tests/components/plugwise/ @CoMPaTech @bouwew
/homeassistant/components/plum_lightpad/ @ColinHarrington @prystupa
/tests/components/plum_lightpad/ @ColinHarrington @prystupa
/homeassistant/components/point/ @fredrike
@@ -1476,8 +1486,8 @@ build.json @home-assistant/supervisor
/tests/components/system_bridge/ @timmo001
/homeassistant/components/systemmonitor/ @gjohansson-ST
/tests/components/systemmonitor/ @gjohansson-ST
/homeassistant/components/tado/ @chiefdragon @erwindouna
/tests/components/tado/ @chiefdragon @erwindouna
/homeassistant/components/tado/ @erwindouna
/tests/components/tado/ @erwindouna
/homeassistant/components/tag/ @balloob @dmulcahey
/tests/components/tag/ @balloob @dmulcahey
/homeassistant/components/tailscale/ @frenck
@@ -1571,8 +1581,8 @@ build.json @home-assistant/supervisor
/tests/components/triggercmd/ @rvmey
/homeassistant/components/tts/ @home-assistant/core
/tests/components/tts/ @home-assistant/core
/homeassistant/components/tuya/ @Tuya @zlinoliver @frenck
/tests/components/tuya/ @Tuya @zlinoliver @frenck
/homeassistant/components/tuya/ @Tuya @zlinoliver
/tests/components/tuya/ @Tuya @zlinoliver
/homeassistant/components/twentemilieu/ @frenck
/tests/components/twentemilieu/ @frenck
/homeassistant/components/twinkly/ @dr1rrb @Robbie1221 @Olen
@@ -1740,6 +1750,7 @@ build.json @home-assistant/supervisor
/tests/components/youless/ @gjong
/homeassistant/components/youtube/ @joostlek
/tests/components/youtube/ @joostlek
/homeassistant/components/zabbix/ @kruton
/homeassistant/components/zamg/ @killer0071234
/tests/components/zamg/ @killer0071234
/homeassistant/components/zengge/ @emontnemery
+5 -5
View File
@@ -1,10 +1,10 @@
image: ghcr.io/home-assistant/{arch}-homeassistant
build_from:
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2024.12.1
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2024.12.1
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2024.12.1
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2024.12.1
i386: ghcr.io/home-assistant/i386-homeassistant-base:2024.12.1
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2024.12.0
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2024.12.0
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2024.12.0
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2024.12.0
i386: ghcr.io/home-assistant/i386-homeassistant-base:2024.12.0
codenotary:
signer: notary@home-assistant.io
base_image: notary@home-assistant.io
+3
View File
@@ -64,6 +64,9 @@ def restore_backup_file_content(config_dir: Path) -> RestoreBackupFileContent |
)
except (FileNotFoundError, KeyError, json.JSONDecodeError):
return None
finally:
# Always remove the backup instruction file to prevent a boot loop
instruction_path.unlink(missing_ok=True)
def _clear_configuration_directory(config_dir: Path, keep: Iterable[str]) -> None:
+3 -1
View File
@@ -89,7 +89,7 @@ from .helpers import (
)
from .helpers.dispatcher import async_dispatcher_send_internal
from .helpers.storage import get_internal_store_manager
from .helpers.system_info import async_get_system_info, is_official_image
from .helpers.system_info import async_get_system_info
from .helpers.typing import ConfigType
from .setup import (
# _setup_started is marked as protected to make it clear
@@ -106,6 +106,7 @@ from .util.async_ import create_eager_task
from .util.hass_dict import HassKey
from .util.logging import async_activate_log_queue_handler
from .util.package import async_get_user_site, is_docker_env, is_virtual_env
from .util.system_info import is_official_image
with contextlib.suppress(ImportError):
# Ensure anyio backend is imported to avoid it being imported in the event loop
@@ -252,6 +253,7 @@ PRELOAD_STORAGE = [
"assist_pipeline.pipelines",
"core.analytics",
"auth_module.totp",
"backup",
]
+1
View File
@@ -2,6 +2,7 @@
"domain": "microsoft",
"name": "Microsoft",
"integrations": [
"azure_data_explorer",
"azure_devops",
"azure_event_hub",
"azure_service_bus",
+5 -5
View File
@@ -34,17 +34,17 @@
"services": {
"capture_image": {
"name": "Capture image",
"description": "Request a new image capture from a camera device.",
"description": "Requests a new image capture from a camera device.",
"fields": {
"entity_id": {
"name": "Entity",
"description": "Entity id of the camera to request an image."
"description": "Entity ID of the camera to request an image from."
}
}
},
"change_setting": {
"name": "Change setting",
"description": "Change an Abode system setting.",
"description": "Changes an Abode system setting.",
"fields": {
"setting": {
"name": "Setting",
@@ -58,11 +58,11 @@
},
"trigger_automation": {
"name": "Trigger automation",
"description": "Trigger an Abode automation.",
"description": "Triggers an Abode automation.",
"fields": {
"entity_id": {
"name": "Entity",
"description": "Entity id of the automation to trigger."
"description": "Entity ID of the automation to trigger."
}
}
}
+1 -1
View File
@@ -26,5 +26,5 @@
"iot_class": "local_push",
"loggers": ["aioacaia"],
"quality_scale": "platinum",
"requirements": ["aioacaia==0.1.11"]
"requirements": ["aioacaia==0.1.13"]
}
+15 -1
View File
@@ -1,6 +1,7 @@
"""The AEMET OpenData component."""
import logging
import shutil
from aemet_opendata.exceptions import AemetError, TownNotFound
from aemet_opendata.interface import AEMET, ConnectionOptions, UpdateFeature
@@ -10,8 +11,9 @@ from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CON
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.storage import STORAGE_DIR
from .const import CONF_STATION_UPDATES, PLATFORMS
from .const import CONF_RADAR_UPDATES, CONF_STATION_UPDATES, DOMAIN, PLATFORMS
from .coordinator import AemetConfigEntry, AemetData, WeatherUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
@@ -24,11 +26,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: AemetConfigEntry) -> boo
latitude = entry.data[CONF_LATITUDE]
longitude = entry.data[CONF_LONGITUDE]
update_features: int = UpdateFeature.FORECAST
if entry.options.get(CONF_RADAR_UPDATES, False):
update_features |= UpdateFeature.RADAR
if entry.options.get(CONF_STATION_UPDATES, True):
update_features |= UpdateFeature.STATION
options = ConnectionOptions(api_key, update_features)
aemet = AEMET(aiohttp_client.async_get_clientsession(hass), options)
aemet.set_api_data_dir(hass.config.path(STORAGE_DIR, f"{DOMAIN}-{entry.unique_id}"))
try:
await aemet.select_coordinates(latitude, longitude)
except TownNotFound as err:
@@ -57,3 +63,11 @@ async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Remove a config entry."""
await hass.async_add_executor_job(
shutil.rmtree,
hass.config.path(STORAGE_DIR, f"{DOMAIN}-{entry.unique_id}"),
)
@@ -17,10 +17,11 @@ from homeassistant.helpers.schema_config_entry_flow import (
SchemaOptionsFlowHandler,
)
from .const import CONF_STATION_UPDATES, DEFAULT_NAME, DOMAIN
from .const import CONF_RADAR_UPDATES, CONF_STATION_UPDATES, DEFAULT_NAME, DOMAIN
OPTIONS_SCHEMA = vol.Schema(
{
vol.Required(CONF_RADAR_UPDATES, default=False): bool,
vol.Required(CONF_STATION_UPDATES, default=True): bool,
}
)
+2 -1
View File
@@ -51,8 +51,9 @@ from homeassistant.components.weather import (
from homeassistant.const import Platform
ATTRIBUTION = "Powered by AEMET OpenData"
CONF_RADAR_UPDATES = "radar_updates"
CONF_STATION_UPDATES = "station_updates"
PLATFORMS = [Platform.SENSOR, Platform.WEATHER]
PLATFORMS = [Platform.IMAGE, Platform.SENSOR, Platform.WEATHER]
DEFAULT_NAME = "AEMET"
DOMAIN = "aemet"
@@ -4,7 +4,7 @@ from __future__ import annotations
from typing import Any
from aemet_opendata.const import AOD_COORDS
from aemet_opendata.const import AOD_COORDS, AOD_IMG_BYTES
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import (
@@ -26,6 +26,7 @@ TO_REDACT_CONFIG = [
TO_REDACT_COORD = [
AOD_COORDS,
AOD_IMG_BYTES,
]
+86
View File
@@ -0,0 +1,86 @@
"""Support for the AEMET OpenData images."""
from __future__ import annotations
from typing import Final
from aemet_opendata.const import AOD_DATETIME, AOD_IMG_BYTES, AOD_IMG_TYPE, AOD_RADAR
from aemet_opendata.helpers import dict_nested_value
from homeassistant.components.image import Image, ImageEntity, ImageEntityDescription
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .coordinator import AemetConfigEntry, WeatherUpdateCoordinator
from .entity import AemetEntity
AEMET_IMAGES: Final[tuple[ImageEntityDescription, ...]] = (
ImageEntityDescription(
key=AOD_RADAR,
translation_key="weather_radar",
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: AemetConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up AEMET OpenData image entities based on a config entry."""
domain_data = config_entry.runtime_data
name = domain_data.name
coordinator = domain_data.coordinator
unique_id = config_entry.unique_id
assert unique_id is not None
async_add_entities(
AemetImage(
hass,
name,
coordinator,
description,
unique_id,
)
for description in AEMET_IMAGES
if dict_nested_value(coordinator.data["lib"], [description.key]) is not None
)
class AemetImage(AemetEntity, ImageEntity):
"""Implementation of an AEMET OpenData image."""
entity_description: ImageEntityDescription
def __init__(
self,
hass: HomeAssistant,
name: str,
coordinator: WeatherUpdateCoordinator,
description: ImageEntityDescription,
unique_id: str,
) -> None:
"""Initialize the image."""
super().__init__(coordinator, name, unique_id)
ImageEntity.__init__(self, hass)
self.entity_description = description
self._attr_unique_id = f"{unique_id}-{description.key}"
self._async_update_attrs()
@callback
def _handle_coordinator_update(self) -> None:
"""Update attributes when the coordinator updates."""
self._async_update_attrs()
super()._handle_coordinator_update()
@callback
def _async_update_attrs(self) -> None:
"""Update image attributes."""
image_data = self.get_aemet_value([self.entity_description.key])
self._cached_image = Image(
content_type=image_data.get(AOD_IMG_TYPE),
content=image_data.get(AOD_IMG_BYTES),
)
self._attr_image_last_updated = image_data.get(AOD_DATETIME)
+1 -1
View File
@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/aemet",
"iot_class": "cloud_polling",
"loggers": ["aemet_opendata"],
"requirements": ["AEMET-OpenData==0.6.3"]
"requirements": ["AEMET-OpenData==0.6.4"]
}
@@ -18,10 +18,18 @@
}
}
},
"entity": {
"image": {
"weather_radar": {
"name": "Weather radar"
}
}
},
"options": {
"step": {
"init": {
"data": {
"radar_updates": "Gather data from AEMET weather radar",
"station_updates": "Gather data from AEMET weather stations"
}
}
@@ -31,7 +31,9 @@ rules:
# Silver
action-exceptions: todo
config-entry-unloading: done
docs-configuration-parameters: todo
docs-configuration-parameters:
status: exempt
comment: No options to configure
docs-installation-parameters: todo
entity-unavailable: done
integration-owner: done
@@ -41,12 +43,16 @@ rules:
status: exempt
comment: |
This integration does not require authentication.
test-coverage: done
test-coverage: todo
# Gold
devices: done
diagnostics: done
discovery-update-info: done
discovery: done
discovery-update-info:
status: todo
comment: DHCP is still possible
discovery:
status: todo
comment: DHCP is still possible
docs-data-update: todo
docs-examples: todo
docs-known-limitations: todo
@@ -39,45 +39,54 @@ SENSORS: dict[str, SensorEntityDescription] = {
key="temp",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
),
"humidity": SensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
"pressure": SensorEntityDescription(
key="pressure",
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
native_unit_of_measurement=UnitOfPressure.MBAR,
state_class=SensorStateClass.MEASUREMENT,
),
"battery": SensorEntityDescription(
key="battery",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
),
"co2": SensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
"voc": SensorEntityDescription(
key="voc",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
state_class=SensorStateClass.MEASUREMENT,
),
"light": SensorEntityDescription(
key="light",
native_unit_of_measurement=PERCENTAGE,
translation_key="light",
state_class=SensorStateClass.MEASUREMENT,
),
"virusRisk": SensorEntityDescription(
key="virusRisk",
translation_key="virus_risk",
state_class=SensorStateClass.MEASUREMENT,
),
"mold": SensorEntityDescription(
key="mold",
translation_key="mold",
state_class=SensorStateClass.MEASUREMENT,
),
"rssi": SensorEntityDescription(
key="rssi",
@@ -85,16 +94,19 @@ SENSORS: dict[str, SensorEntityDescription] = {
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
),
"pm1": SensorEntityDescription(
key="pm1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
),
"pm25": SensorEntityDescription(
key="pm25",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
}
@@ -41,7 +41,7 @@
}
},
"enable_motion_recording": {
"name": "Enables motion recording",
"name": "Enable motion recording",
"description": "Enables recording a clip to camera storage when motion is detected.",
"fields": {
"entity_id": {
@@ -51,8 +51,8 @@
}
},
"disable_motion_recording": {
"name": "Disables motion recording",
"description": "Disable recording a clip to camera storage when motion is detected.",
"name": "Disable motion recording",
"description": "Disables recording a clip to camera storage when motion is detected.",
"fields": {
"entity_id": {
"name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]",
@@ -11,12 +11,7 @@ from python_homeassistant_analytics import (
from python_homeassistant_analytics.models import IntegrationType
import voluptuous as vol
from homeassistant.config_entries import (
ConfigEntry,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow
from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.selector import (
@@ -25,6 +20,7 @@ from homeassistant.helpers.selector import (
SelectSelectorConfig,
)
from . import AnalyticsInsightsConfigEntry
from .const import (
CONF_TRACKED_ADDONS,
CONF_TRACKED_CUSTOM_INTEGRATIONS,
@@ -46,7 +42,7 @@ class HomeassistantAnalyticsConfigFlow(ConfigFlow, domain=DOMAIN):
@staticmethod
@callback
def async_get_options_flow(
config_entry: ConfigEntry,
config_entry: AnalyticsInsightsConfigEntry,
) -> HomeassistantAnalyticsOptionsFlowHandler:
"""Get the options flow for this handler."""
return HomeassistantAnalyticsOptionsFlowHandler()
@@ -7,6 +7,6 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["python_homeassistant_analytics"],
"requirements": ["python-homeassistant-analytics==0.8.0"],
"requirements": ["python-homeassistant-analytics==0.8.1"],
"single_config_entry": true
}
@@ -0,0 +1,100 @@
rules:
# Bronze
action-setup:
status: exempt
comment: |
This integration does not provide additional actions.
appropriate-polling: done
brands: done
common-modules: done
config-flow-test-coverage: done
config-flow: done
dependency-transparency: done
docs-actions:
status: exempt
comment: |
This integration does not provide additional actions.
docs-high-level-description: todo
docs-installation-instructions: todo
docs-removal-instructions: todo
entity-event-setup:
status: exempt
comment: |
Entities of this integration does not explicitly subscribe to events.
entity-unique-id: done
has-entity-name: done
runtime-data: done
test-before-configure: done
test-before-setup: done
unique-config-entry: done
# Silver
action-exceptions:
status: exempt
comment: |
This integration does not provide actions.
config-entry-unloading: done
docs-configuration-parameters: todo
docs-installation-parameters: todo
entity-unavailable:
status: done
comment: |
The coordinator handles this.
integration-owner: done
log-when-unavailable:
status: done
comment: |
The coordinator handles this.
parallel-updates: todo
reauthentication-flow:
status: exempt
comment: |
This integration does not require authentication.
test-coverage: todo
# Gold
devices: done
diagnostics: todo
discovery-update-info:
status: exempt
comment: |
This integration is a cloud service and thus does not support discovery.
discovery:
status: exempt
comment: |
This integration is a cloud service and thus does not support discovery.
docs-data-update: todo
docs-examples: todo
docs-known-limitations: todo
docs-supported-devices: todo
docs-supported-functions: todo
docs-troubleshooting: todo
docs-use-cases: todo
dynamic-devices:
status: exempt
comment: |
This integration has a fixed single service.
entity-category: done
entity-device-class:
status: exempt
comment: |
This integration does not have entities with device classes.
entity-disabled-by-default: done
entity-translations: done
exception-translations: todo
icon-translations: done
reconfiguration-flow:
status: exempt
comment: All the options of this integration are managed via the options flow
repair-issues:
status: exempt
comment: |
This integration doesn't have any cases where raising an issue is needed.
stale-devices:
status: exempt
comment: |
This integration has a fixed single service.
# Platinum
async-dependency: done
inject-websession: done
strict-typing: done
@@ -21,7 +21,7 @@
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"invalid_unique_id": "Impossible to determine a valid unique id for the device"
"invalid_unique_id": "Impossible to determine a valid unique ID for the device"
}
},
"options": {
@@ -38,17 +38,17 @@
}
},
"apps": {
"title": "Configure Android Apps",
"description": "Configure application id {app_id}",
"title": "Configure Android apps",
"description": "Configure application ID {app_id}",
"data": {
"app_name": "Application Name",
"app_name": "Application name",
"app_id": "Application ID",
"app_delete": "Check to delete this application"
}
},
"rules": {
"title": "Configure Android state detection rules",
"description": "Configure detection rule for application id {rule_id}",
"description": "Configure detection rule for application ID {rule_id}",
"data": {
"rule_id": "[%key:component::androidtv::options::step::apps::data::app_id%]",
"rule_values": "List of state detection rules (see documentation)",
@@ -156,7 +156,12 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
# and one of them, which could end up being in discovery_info.host, is from a
# different device. If any of the discovery_info.ip_addresses matches the
# existing host, don't update the host.
if existing_config_entry and len(discovery_info.ip_addresses) > 1:
if (
existing_config_entry
# Ignored entries don't have host
and CONF_HOST in existing_config_entry.data
and len(discovery_info.ip_addresses) > 1
):
existing_host = existing_config_entry.data[CONF_HOST]
if existing_host != self.host:
if existing_host in [
@@ -44,12 +44,12 @@
}
},
"apps": {
"title": "Configure Android Apps",
"description": "Configure application id {app_id}",
"title": "Configure Android apps",
"description": "Configure application ID {app_id}",
"data": {
"app_name": "Application Name",
"app_name": "Application name",
"app_id": "Application ID",
"app_icon": "Application Icon",
"app_icon": "Application icon",
"app_delete": "Check to delete this application"
}
}
@@ -98,7 +98,6 @@ class AppleTVConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1
scan_filter: str | None = None
all_identifiers: set[str]
atv: BaseConfig | None = None
atv_identifiers: list[str] | None = None
_host: str # host in zeroconf discovery info, should not be accessed by other flows
@@ -118,6 +117,7 @@ class AppleTVConfigFlow(ConfigFlow, domain=DOMAIN):
def __init__(self) -> None:
"""Initialize a new AppleTVConfigFlow."""
self.credentials: dict[int, str | None] = {} # Protocol -> credentials
self.all_identifiers: set[str] = set()
@property
def device_identifier(self) -> str | None:
@@ -6,5 +6,5 @@
"iot_class": "cloud_push",
"loggers": ["apprise"],
"quality_scale": "legacy",
"requirements": ["apprise==1.9.0"]
"requirements": ["apprise==1.9.1"]
}
@@ -120,6 +120,8 @@ class AprilaireCoordinator(BaseDataUpdateCoordinatorProtocol):
"""Wait for the client to be ready."""
if not self.data or Attribute.MAC_ADDRESS not in self.data:
await self.client.read_mac_address()
data = await self.client.wait_for_response(
FunctionalDomain.IDENTIFICATION, 2, WAIT_TIMEOUT
)
@@ -130,12 +132,9 @@ class AprilaireCoordinator(BaseDataUpdateCoordinatorProtocol):
return False
if not self.data or Attribute.NAME not in self.data:
await self.client.wait_for_response(
FunctionalDomain.IDENTIFICATION, 4, WAIT_TIMEOUT
)
if not self.data or Attribute.THERMOSTAT_MODES not in self.data:
await self.client.read_thermostat_iaq_available()
await self.client.wait_for_response(
FunctionalDomain.CONTROL, 7, WAIT_TIMEOUT
)
@@ -144,10 +143,16 @@ class AprilaireCoordinator(BaseDataUpdateCoordinatorProtocol):
not self.data
or Attribute.INDOOR_TEMPERATURE_CONTROLLING_SENSOR_STATUS not in self.data
):
await self.client.read_sensors()
await self.client.wait_for_response(
FunctionalDomain.SENSORS, 2, WAIT_TIMEOUT
)
await self.client.read_thermostat_status()
await self.client.read_iaq_status()
await ready_callback(True)
return True
@@ -7,5 +7,5 @@
"integration_type": "device",
"iot_class": "local_push",
"loggers": ["pyaprilaire"],
"requirements": ["pyaprilaire==0.7.4"]
"requirements": ["pyaprilaire==0.7.7"]
}
@@ -29,6 +29,8 @@ class ApSystemsSensorData:
class ApSystemsDataCoordinator(DataUpdateCoordinator[ApSystemsSensorData]):
"""Coordinator used for all sensors."""
device_version: str
def __init__(self, hass: HomeAssistant, api: APsystemsEZ1M) -> None:
"""Initialize my coordinator."""
super().__init__(
@@ -46,6 +48,7 @@ class ApSystemsDataCoordinator(DataUpdateCoordinator[ApSystemsSensorData]):
raise UpdateFailed from None
self.api.max_power = device_info.maxPower
self.api.min_power = device_info.minPower
self.device_version = device_info.devVer
async def _async_update_data(self) -> ApSystemsSensorData:
try:
+2 -1
View File
@@ -21,7 +21,8 @@ class ApSystemsEntity(Entity):
"""Initialize the APsystems entity."""
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, data.device_id)},
serial_number=data.device_id,
manufacturer="APsystems",
model="EZ1-M",
serial_number=data.device_id,
sw_version=data.coordinator.device_version.split(" ")[1],
)
+10 -2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
from aiohttp import ClientConnectorError
from homeassistant.components.number import NumberDeviceClass, NumberEntity, NumberMode
from homeassistant.const import UnitOfPower
from homeassistant.core import HomeAssistant
@@ -20,7 +22,7 @@ async def async_setup_entry(
) -> None:
"""Set up the sensor platform."""
add_entities([ApSystemsMaxOutputNumber(config_entry.runtime_data)])
add_entities([ApSystemsMaxOutputNumber(config_entry.runtime_data)], True)
class ApSystemsMaxOutputNumber(ApSystemsEntity, NumberEntity):
@@ -45,7 +47,13 @@ class ApSystemsMaxOutputNumber(ApSystemsEntity, NumberEntity):
async def async_update(self) -> None:
"""Set the state with the value fetched from the inverter."""
self._attr_native_value = await self._api.get_max_power()
try:
status = await self._api.get_max_power()
except (TimeoutError, ClientConnectorError):
self._attr_available = False
else:
self._attr_available = True
self._attr_native_value = status
async def async_set_native_value(self, value: float) -> None:
"""Set the desired output power."""
@@ -19,5 +19,5 @@
"documentation": "https://www.home-assistant.io/integrations/aranet",
"integration_type": "device",
"iot_class": "local_push",
"requirements": ["aranet4==2.4.0"]
"requirements": ["aranet4==2.5.0"]
}
@@ -22,6 +22,7 @@ from homeassistant.components.sensor import (
)
from homeassistant.const import (
ATTR_MANUFACTURER,
ATTR_MODEL,
ATTR_NAME,
ATTR_SW_VERSION,
CONCENTRATION_PARTS_PER_MILLION,
@@ -142,6 +143,7 @@ def _sensor_device_info_to_hass(
if adv.readings and adv.readings.name:
hass_device_info[ATTR_NAME] = adv.readings.name
hass_device_info[ATTR_MANUFACTURER] = ARANET_MANUFACTURER_NAME
hass_device_info[ATTR_MODEL] = adv.readings.type.model
if adv.manufacturer_data:
hass_device_info[ATTR_SW_VERSION] = str(adv.manufacturer_data.version)
return hass_device_info
@@ -90,7 +90,7 @@ class ArubaDeviceScanner(DeviceScanner):
"""Retrieve data from Aruba Access Point and return parsed result."""
connect = f"ssh {self.username}@{self.host} -o HostKeyAlgorithms=ssh-rsa"
ssh = pexpect.spawn(connect)
ssh: pexpect.spawn[str] = pexpect.spawn(connect, encoding="utf-8")
query = ssh.expect(
[
"password:",
@@ -125,12 +125,12 @@ class ArubaDeviceScanner(DeviceScanner):
ssh.expect("#")
ssh.sendline("show clients")
ssh.expect("#")
devices_result = ssh.before.split(b"\r\n")
devices_result = (ssh.before or "").splitlines()
ssh.sendline("exit")
devices: dict[str, dict[str, str]] = {}
for device in devices_result:
if match := _DEVICES_REGEX.search(device.decode("utf-8")):
if match := _DEVICES_REGEX.search(device):
devices[match.group("ip")] = {
"ip": match.group("ip"),
"mac": match.group("mac").upper(),
+1 -1
View File
@@ -6,5 +6,5 @@
"iot_class": "local_polling",
"loggers": ["pexpect", "ptyprocess"],
"quality_scale": "legacy",
"requirements": ["pexpect==4.6.0"]
"requirements": ["pexpect==4.9.0"]
}
@@ -108,6 +108,7 @@ async def async_pipeline_from_audio_stream(
device_id: str | None = None,
start_stage: PipelineStage = PipelineStage.STT,
end_stage: PipelineStage = PipelineStage.TTS,
conversation_extra_system_prompt: str | None = None,
) -> None:
"""Create an audio pipeline from an audio stream.
@@ -119,6 +120,7 @@ async def async_pipeline_from_audio_stream(
stt_metadata=stt_metadata,
stt_stream=stt_stream,
wake_word_phrase=wake_word_phrase,
conversation_extra_system_prompt=conversation_extra_system_prompt,
run=PipelineRun(
hass,
context=context,
@@ -1010,7 +1010,11 @@ class PipelineRun:
self.intent_agent = agent_info.id
async def recognize_intent(
self, intent_input: str, conversation_id: str | None, device_id: str | None
self,
intent_input: str,
conversation_id: str | None,
device_id: str | None,
conversation_extra_system_prompt: str | None,
) -> str:
"""Run intent recognition portion of pipeline. Returns text to speak."""
if self.intent_agent is None:
@@ -1045,6 +1049,7 @@ class PipelineRun:
device_id=device_id,
language=input_language,
agent_id=self.intent_agent,
extra_system_prompt=conversation_extra_system_prompt,
)
processed_locally = self.intent_agent == conversation.HOME_ASSISTANT_AGENT
@@ -1392,8 +1397,13 @@ class PipelineInput:
"""Input for text-to-speech. Required when start_stage = tts."""
conversation_id: str | None = None
"""Identifier for the conversation."""
conversation_extra_system_prompt: str | None = None
"""Extra prompt information for the conversation agent."""
device_id: str | None = None
"""Identifier of the device that is processing the input/output of the pipeline."""
async def execute(self) -> None:
"""Run pipeline."""
@@ -1483,6 +1493,7 @@ class PipelineInput:
intent_input,
self.conversation_id,
self.device_id,
self.conversation_extra_system_prompt,
)
if tts_input.strip():
current_stage = PipelineStage.TTS
@@ -75,7 +75,7 @@ class AudioBuffer:
class VoiceCommandSegmenter:
"""Segments an audio stream into voice commands."""
speech_seconds: float = 0.1
speech_seconds: float = 0.3
"""Seconds of speech before voice command has started."""
command_seconds: float = 1.0
@@ -31,8 +31,8 @@
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"abort": {
"invalid_unique_id": "Impossible to determine a valid unique id for the device",
"no_unique_id": "A device without a valid unique id is already configured. Configuration of multiple instance is not possible"
"invalid_unique_id": "Impossible to determine a valid unique ID for the device",
"no_unique_id": "A device without a valid unique ID is already configured. Configuration of multiple instances is not possible"
}
},
"options": {
@@ -42,7 +42,7 @@
"consider_home": "Seconds to wait before considering a device away",
"track_unknown": "Track unknown / unnamed devices",
"interface": "The interface that you want statistics from (e.g. eth0, eth1 etc)",
"dnsmasq": "The location in the router of the dnsmasq.leases files",
"dnsmasq": "The location of the dnsmasq.leases file in the router",
"require_ip": "Devices must have IP (for access point mode)"
}
}
@@ -28,5 +28,5 @@
"documentation": "https://www.home-assistant.io/integrations/august",
"iot_class": "cloud_push",
"loggers": ["pubnub", "yalexs"],
"requirements": ["yalexs==8.10.0", "yalexs-ble==2.5.5"]
"requirements": ["yalexs==8.10.0", "yalexs-ble==2.5.6"]
}
@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/aussie_broadband",
"iot_class": "cloud_polling",
"loggers": ["aussiebb"],
"requirements": ["pyaussiebb==0.1.4"]
"requirements": ["pyaussiebb==0.1.5"]
}
@@ -5,6 +5,10 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.typing import ConfigType
# Pre-import backup to avoid it being imported
# later when the import executor is busy and delaying
# startup
from . import backup # noqa: F401
from .agent import (
BackupAgent,
BackupAgentError,
@@ -17,8 +21,10 @@ from .manager import (
BackupManager,
BackupPlatformProtocol,
BackupReaderWriter,
BackupReaderWriterError,
CoreBackupReaderWriter,
CreateBackupEvent,
IncorrectPasswordError,
ManagerBackup,
NewBackup,
WrittenBackup,
@@ -35,8 +41,10 @@ __all__ = [
"BackupAgentPlatformProtocol",
"BackupPlatformProtocol",
"BackupReaderWriter",
"BackupReaderWriterError",
"CreateBackupEvent",
"Folder",
"IncorrectPasswordError",
"LocalBackupAgent",
"NewBackup",
"WrittenBackup",
+29 -23
View File
@@ -17,7 +17,7 @@ from homeassistant.helpers.typing import UNDEFINED, UndefinedType
from homeassistant.util import dt as dt_util
from .const import LOGGER
from .models import Folder
from .models import BackupManagerError, Folder
if TYPE_CHECKING:
from .manager import BackupManager, ManagerBackup
@@ -33,8 +33,8 @@ class StoredBackupConfig(TypedDict):
"""Represent the stored backup config."""
create_backup: StoredCreateBackupConfig
last_attempted_strategy_backup: str | None
last_completed_strategy_backup: str | None
last_attempted_automatic_backup: str | None
last_completed_automatic_backup: str | None
retention: StoredRetentionConfig
schedule: StoredBackupSchedule
@@ -44,8 +44,8 @@ class BackupConfigData:
"""Represent loaded backup config data."""
create_backup: CreateBackupConfig
last_attempted_strategy_backup: datetime | None = None
last_completed_strategy_backup: datetime | None = None
last_attempted_automatic_backup: datetime | None = None
last_completed_automatic_backup: datetime | None = None
retention: RetentionConfig
schedule: BackupSchedule
@@ -59,12 +59,12 @@ class BackupConfigData:
include_folders = None
retention = data["retention"]
if last_attempted_str := data["last_attempted_strategy_backup"]:
if last_attempted_str := data["last_attempted_automatic_backup"]:
last_attempted = dt_util.parse_datetime(last_attempted_str)
else:
last_attempted = None
if last_attempted_str := data["last_completed_strategy_backup"]:
if last_attempted_str := data["last_completed_automatic_backup"]:
last_completed = dt_util.parse_datetime(last_attempted_str)
else:
last_completed = None
@@ -79,8 +79,8 @@ class BackupConfigData:
name=data["create_backup"]["name"],
password=data["create_backup"]["password"],
),
last_attempted_strategy_backup=last_attempted,
last_completed_strategy_backup=last_completed,
last_attempted_automatic_backup=last_attempted,
last_completed_automatic_backup=last_completed,
retention=RetentionConfig(
copies=retention["copies"],
days=retention["days"],
@@ -90,20 +90,20 @@ class BackupConfigData:
def to_dict(self) -> StoredBackupConfig:
"""Convert backup config data to a dict."""
if self.last_attempted_strategy_backup:
last_attempted = self.last_attempted_strategy_backup.isoformat()
if self.last_attempted_automatic_backup:
last_attempted = self.last_attempted_automatic_backup.isoformat()
else:
last_attempted = None
if self.last_completed_strategy_backup:
last_completed = self.last_completed_strategy_backup.isoformat()
if self.last_completed_automatic_backup:
last_completed = self.last_completed_automatic_backup.isoformat()
else:
last_completed = None
return StoredBackupConfig(
create_backup=self.create_backup.to_dict(),
last_attempted_strategy_backup=last_attempted,
last_completed_strategy_backup=last_completed,
last_attempted_automatic_backup=last_attempted,
last_completed_automatic_backup=last_completed,
retention=self.retention.to_dict(),
schedule=self.schedule.to_dict(),
)
@@ -124,6 +124,7 @@ class BackupConfig:
def load(self, stored_config: StoredBackupConfig) -> None:
"""Load config."""
self.data = BackupConfigData.from_dict(stored_config)
self.data.retention.apply(self._manager)
self.data.schedule.apply(self._manager)
async def update(
@@ -160,8 +161,13 @@ class RetentionConfig:
def apply(self, manager: BackupManager) -> None:
"""Apply backup retention configuration."""
if self.days is not None:
LOGGER.debug(
"Scheduling next automatic delete of backups older than %s in 1 day",
self.days,
)
self._schedule_next(manager)
else:
LOGGER.debug("Unscheduling next automatic delete")
self._unschedule_next(manager)
def to_dict(self) -> StoredRetentionConfig:
@@ -286,7 +292,7 @@ class BackupSchedule:
self._unschedule_next(manager)
now = dt_util.now()
if (cron_event := self.cron_event) is None:
seed_time = manager.config.data.last_completed_strategy_backup or now
seed_time = manager.config.data.last_completed_automatic_backup or now
cron_event = self.cron_event = CronSim(cron_pattern, seed_time)
next_time = next(cron_event)
@@ -316,11 +322,11 @@ class BackupSchedule:
include_homeassistant=True, # always include HA
name=config_data.create_backup.name,
password=config_data.create_backup.password,
with_strategy_settings=True,
with_automatic_settings=True,
)
except BackupManagerError as err:
LOGGER.error("Error creating backup: %s", err)
except Exception: # noqa: BLE001
# another more specific exception will be added
# and handled in the future
LOGGER.exception("Unexpected error creating automatic backup")
manager.remove_next_backup_event = async_track_point_in_time(
@@ -404,14 +410,14 @@ async def _delete_filtered_backups(
get_agent_errors,
)
# only delete backups that are created by the backup strategy
# only delete backups that are created with the saved automatic settings
backups = {
backup_id: backup
for backup_id, backup in backups.items()
if backup.with_strategy_settings
if backup.with_automatic_settings
}
LOGGER.debug("Total strategy backups: %s", backups)
LOGGER.debug("Total automatic backups: %s", backups)
filtered_backups = backup_filter(backups)
@@ -467,7 +473,7 @@ async def delete_backups_exceeding_configured_count(manager: BackupManager) -> N
sorted(
backups.items(),
key=lambda backup_item: backup_item[1].date,
)[: len(backups) - manager.config.data.retention.copies]
)[: max(len(backups) - manager.config.data.retention.copies, 0)]
)
await _delete_filtered_backups(manager, _backups_filter)
+242 -88
View File
@@ -23,7 +23,11 @@ from homeassistant.backup_restore import RESTORE_BACKUP_FILE, password_to_key
from homeassistant.const import __version__ as HAVERSION
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import integration_platform
from homeassistant.helpers import (
instance_id,
integration_platform,
issue_registry as ir,
)
from homeassistant.helpers.json import json_bytes
from homeassistant.util import dt as dt_util
@@ -42,9 +46,9 @@ from .const import (
EXCLUDE_FROM_BACKUP,
LOGGER,
)
from .models import AgentBackup, Folder
from .models import AgentBackup, BackupManagerError, Folder
from .store import BackupStore
from .util import make_backup_dir, read_backup
from .util import make_backup_dir, read_backup, validate_password
@dataclass(frozen=True, kw_only=True, slots=True)
@@ -60,7 +64,7 @@ class ManagerBackup(AgentBackup):
agent_ids: list[str]
failed_agent_ids: list[str]
with_strategy_settings: bool
with_automatic_settings: bool | None
@dataclass(frozen=True, kw_only=True, slots=True)
@@ -200,6 +204,7 @@ class BackupReaderWriter(abc.ABC):
*,
agent_ids: list[str],
backup_name: str,
extra_metadata: dict[str, bool | str],
include_addons: list[str] | None,
include_all_addons: bool,
include_database: bool,
@@ -236,6 +241,14 @@ class BackupReaderWriter(abc.ABC):
"""Restore a backup."""
class BackupReaderWriterError(HomeAssistantError):
"""Backup reader/writer error."""
class IncorrectPasswordError(BackupReaderWriterError):
"""Raised when the password is incorrect."""
class BackupManager:
"""Define the format that backup managers can have."""
@@ -364,7 +377,9 @@ class BackupManager:
)
for result in pre_backup_results:
if isinstance(result, Exception):
raise result
raise BackupManagerError(
f"Error during pre-backup: {result}"
) from result
async def async_post_backup_actions(self) -> None:
"""Perform post backup actions."""
@@ -377,7 +392,9 @@ class BackupManager:
)
for result in post_backup_results:
if isinstance(result, Exception):
raise result
raise BackupManagerError(
f"Error during post-backup: {result}"
) from result
async def load_platforms(self) -> None:
"""Load backup platforms."""
@@ -413,11 +430,22 @@ class BackupManager:
return_exceptions=True,
)
for idx, result in enumerate(sync_backup_results):
if isinstance(result, Exception):
if isinstance(result, BackupReaderWriterError):
# writer errors will affect all agents
# no point in continuing
raise BackupManagerError(str(result)) from result
if isinstance(result, BackupAgentError):
LOGGER.error("Error uploading to %s: %s", agent_ids[idx], result)
agent_errors[agent_ids[idx]] = result
LOGGER.exception(
"Error during backup upload - %s", result, exc_info=result
)
continue
if isinstance(result, Exception):
# trap bugs from agents
agent_errors[agent_ids[idx]] = result
LOGGER.error("Unexpected error: %s", result, exc_info=result)
continue
if isinstance(result, BaseException):
raise result
return agent_errors
async def async_get_backups(
@@ -440,21 +468,23 @@ class BackupManager:
agent_errors[agent_ids[idx]] = result
continue
if isinstance(result, BaseException):
raise result
raise result # unexpected error
for agent_backup in result:
if (backup_id := agent_backup.backup_id) not in backups:
if known_backup := self.known_backups.get(backup_id):
failed_agent_ids = known_backup.failed_agent_ids
with_strategy_settings = known_backup.with_strategy_settings
else:
failed_agent_ids = []
with_strategy_settings = False
with_automatic_settings = self.is_our_automatic_backup(
agent_backup, await instance_id.async_get(self.hass)
)
backups[backup_id] = ManagerBackup(
agent_ids=[],
addons=agent_backup.addons,
backup_id=backup_id,
date=agent_backup.date,
database_included=agent_backup.database_included,
extra_metadata=agent_backup.extra_metadata,
failed_agent_ids=failed_agent_ids,
folders=agent_backup.folders,
homeassistant_included=agent_backup.homeassistant_included,
@@ -462,7 +492,7 @@ class BackupManager:
name=agent_backup.name,
protected=agent_backup.protected,
size=agent_backup.size,
with_strategy_settings=with_strategy_settings,
with_automatic_settings=with_automatic_settings,
)
backups[backup_id].agent_ids.append(agent_ids[idx])
@@ -488,22 +518,24 @@ class BackupManager:
agent_errors[agent_ids[idx]] = result
continue
if isinstance(result, BaseException):
raise result
raise result # unexpected error
if not result:
continue
if backup is None:
if known_backup := self.known_backups.get(backup_id):
failed_agent_ids = known_backup.failed_agent_ids
with_strategy_settings = known_backup.with_strategy_settings
else:
failed_agent_ids = []
with_strategy_settings = False
with_automatic_settings = self.is_our_automatic_backup(
result, await instance_id.async_get(self.hass)
)
backup = ManagerBackup(
agent_ids=[],
addons=result.addons,
backup_id=result.backup_id,
date=result.date,
database_included=result.database_included,
extra_metadata=result.extra_metadata,
failed_agent_ids=failed_agent_ids,
folders=result.folders,
homeassistant_included=result.homeassistant_included,
@@ -511,12 +543,28 @@ class BackupManager:
name=result.name,
protected=result.protected,
size=result.size,
with_strategy_settings=with_strategy_settings,
with_automatic_settings=with_automatic_settings,
)
backup.agent_ids.append(agent_ids[idx])
return (backup, agent_errors)
@staticmethod
def is_our_automatic_backup(
backup: AgentBackup, our_instance_id: str
) -> bool | None:
"""Check if a backup was created by us and return automatic_settings flag.
Returns `None` if the backup was not created by us, or if the
automatic_settings flag is not a boolean.
"""
if backup.extra_metadata.get("instance_id") != our_instance_id:
return None
with_automatic_settings = backup.extra_metadata.get("with_automatic_settings")
if not isinstance(with_automatic_settings, bool):
return None
return with_automatic_settings
async def async_delete_backup(self, backup_id: str) -> dict[str, Exception]:
"""Delete a backup."""
agent_errors: dict[str, Exception] = {}
@@ -534,7 +582,7 @@ class BackupManager:
agent_errors[agent_ids[idx]] = result
continue
if isinstance(result, BaseException):
raise result
raise result # unexpected error
if not agent_errors:
self.known_backups.remove(backup_id)
@@ -549,7 +597,7 @@ class BackupManager:
) -> None:
"""Receive and store a backup file from upload."""
if self.state is not BackupManagerState.IDLE:
raise HomeAssistantError(f"Backup manager busy: {self.state}")
raise BackupManagerError(f"Backup manager busy: {self.state}")
self.async_on_backup_event(
ReceiveBackupEvent(stage=None, state=ReceiveBackupState.IN_PROGRESS)
)
@@ -598,7 +646,7 @@ class BackupManager:
open_stream=written_backup.open_stream,
)
await written_backup.release_stream()
self.known_backups.add(written_backup.backup, agent_errors, False)
self.known_backups.add(written_backup.backup, agent_errors)
async def async_create_backup(
self,
@@ -611,7 +659,7 @@ class BackupManager:
include_homeassistant: bool,
name: str | None,
password: str | None,
with_strategy_settings: bool = False,
with_automatic_settings: bool = False,
) -> NewBackup:
"""Create a backup."""
new_backup = await self.async_initiate_backup(
@@ -623,7 +671,8 @@ class BackupManager:
include_homeassistant=include_homeassistant,
name=name,
password=password,
with_strategy_settings=with_strategy_settings,
raise_task_error=True,
with_automatic_settings=with_automatic_settings,
)
assert self._backup_finish_task
await self._backup_finish_task
@@ -640,14 +689,15 @@ class BackupManager:
include_homeassistant: bool,
name: str | None,
password: str | None,
with_strategy_settings: bool = False,
raise_task_error: bool = False,
with_automatic_settings: bool = False,
) -> NewBackup:
"""Initiate generating a backup."""
if self.state is not BackupManagerState.IDLE:
raise HomeAssistantError(f"Backup manager busy: {self.state}")
raise BackupManagerError(f"Backup manager busy: {self.state}")
if with_strategy_settings:
self.config.data.last_attempted_strategy_backup = dt_util.now()
if with_automatic_settings:
self.config.data.last_attempted_automatic_backup = dt_util.now()
self.store.save()
self.async_on_backup_event(
@@ -663,13 +713,16 @@ class BackupManager:
include_homeassistant=include_homeassistant,
name=name,
password=password,
with_strategy_settings=with_strategy_settings,
raise_task_error=raise_task_error,
with_automatic_settings=with_automatic_settings,
)
except Exception:
self.async_on_backup_event(
CreateBackupEvent(stage=None, state=CreateBackupState.FAILED)
)
self.async_on_backup_event(IdleEvent())
if with_automatic_settings:
self._update_issue_backup_failed()
raise
async def _async_create_backup(
@@ -683,48 +736,81 @@ class BackupManager:
include_homeassistant: bool,
name: str | None,
password: str | None,
with_strategy_settings: bool,
raise_task_error: bool,
with_automatic_settings: bool,
) -> NewBackup:
"""Initiate generating a backup."""
if not agent_ids:
raise HomeAssistantError("At least one agent must be selected")
if any(agent_id not in self.backup_agents for agent_id in agent_ids):
raise HomeAssistantError("Invalid agent selected")
raise BackupManagerError("At least one agent must be selected")
if invalid_agents := [
agent_id for agent_id in agent_ids if agent_id not in self.backup_agents
]:
raise BackupManagerError(f"Invalid agents selected: {invalid_agents}")
if include_all_addons and include_addons:
raise HomeAssistantError(
raise BackupManagerError(
"Cannot include all addons and specify specific addons"
)
backup_name = name or f"Core {HAVERSION}"
new_backup, self._backup_task = await self._reader_writer.async_create_backup(
agent_ids=agent_ids,
backup_name=backup_name,
include_addons=include_addons,
include_all_addons=include_all_addons,
include_database=include_database,
include_folders=include_folders,
include_homeassistant=include_homeassistant,
on_progress=self.async_on_backup_event,
password=password,
backup_name = (
name
or f"{"Automatic" if with_automatic_settings else "Custom"} backup {HAVERSION}"
)
self._backup_finish_task = self.hass.async_create_task(
self._async_finish_backup(agent_ids, with_strategy_settings),
try:
(
new_backup,
self._backup_task,
) = await self._reader_writer.async_create_backup(
agent_ids=agent_ids,
backup_name=backup_name,
extra_metadata={
"instance_id": await instance_id.async_get(self.hass),
"with_automatic_settings": with_automatic_settings,
},
include_addons=include_addons,
include_all_addons=include_all_addons,
include_database=include_database,
include_folders=include_folders,
include_homeassistant=include_homeassistant,
on_progress=self.async_on_backup_event,
password=password,
)
except BackupReaderWriterError as err:
raise BackupManagerError(str(err)) from err
backup_finish_task = self._backup_finish_task = self.hass.async_create_task(
self._async_finish_backup(agent_ids, with_automatic_settings),
name="backup_manager_finish_backup",
)
if not raise_task_error:
def log_finish_task_error(task: asyncio.Task[None]) -> None:
if task.done() and not task.cancelled() and (err := task.exception()):
if isinstance(err, BackupManagerError):
LOGGER.error("Error creating backup: %s", err)
else:
LOGGER.error("Unexpected error: %s", err, exc_info=err)
backup_finish_task.add_done_callback(log_finish_task_error)
return new_backup
async def _async_finish_backup(
self, agent_ids: list[str], with_strategy_settings: bool
self, agent_ids: list[str], with_automatic_settings: bool
) -> None:
"""Finish a backup."""
if TYPE_CHECKING:
assert self._backup_task is not None
backup_success = False
try:
written_backup = await self._backup_task
except Exception as err: # noqa: BLE001
LOGGER.debug("Generating backup failed", exc_info=err)
self.async_on_backup_event(
CreateBackupEvent(stage=None, state=CreateBackupState.FAILED)
)
except Exception as err:
if with_automatic_settings:
self._update_issue_backup_failed()
if isinstance(err, BackupReaderWriterError):
raise BackupManagerError(str(err)) from err
raise # unexpected error
else:
LOGGER.debug(
"Generated new backup with backup_id %s, uploading to agents %s",
@@ -737,29 +823,40 @@ class BackupManager:
state=CreateBackupState.IN_PROGRESS,
)
)
agent_errors = await self._async_upload_backup(
backup=written_backup.backup,
agent_ids=agent_ids,
open_stream=written_backup.open_stream,
)
await written_backup.release_stream()
if with_strategy_settings:
# create backup was successful, update last_completed_strategy_backup
self.config.data.last_completed_strategy_backup = dt_util.now()
self.store.save()
self.known_backups.add(
written_backup.backup, agent_errors, with_strategy_settings
)
try:
agent_errors = await self._async_upload_backup(
backup=written_backup.backup,
agent_ids=agent_ids,
open_stream=written_backup.open_stream,
)
finally:
await written_backup.release_stream()
self.known_backups.add(written_backup.backup, agent_errors)
if not agent_errors:
if with_automatic_settings:
# create backup was successful, update last_completed_automatic_backup
self.config.data.last_completed_automatic_backup = dt_util.now()
self.store.save()
backup_success = True
if with_automatic_settings:
self._update_issue_after_agent_upload(agent_errors)
# delete old backups more numerous than copies
# try this regardless of agent errors above
await delete_backups_exceeding_configured_count(self)
self.async_on_backup_event(
CreateBackupEvent(stage=None, state=CreateBackupState.COMPLETED)
)
finally:
self._backup_task = None
self._backup_finish_task = None
self.async_on_backup_event(
CreateBackupEvent(
stage=None,
state=CreateBackupState.COMPLETED
if backup_success
else CreateBackupState.FAILED,
)
)
self.async_on_backup_event(IdleEvent())
async def async_restore_backup(
@@ -775,7 +872,7 @@ class BackupManager:
) -> None:
"""Initiate restoring a backup."""
if self.state is not BackupManagerState.IDLE:
raise HomeAssistantError(f"Backup manager busy: {self.state}")
raise BackupManagerError(f"Backup manager busy: {self.state}")
self.async_on_backup_event(
RestoreBackupEvent(stage=None, state=RestoreBackupState.IN_PROGRESS)
@@ -790,6 +887,9 @@ class BackupManager:
restore_folders=restore_folders,
restore_homeassistant=restore_homeassistant,
)
self.async_on_backup_event(
RestoreBackupEvent(stage=None, state=RestoreBackupState.COMPLETED)
)
except Exception:
self.async_on_backup_event(
RestoreBackupEvent(stage=None, state=RestoreBackupState.FAILED)
@@ -812,7 +912,7 @@ class BackupManager:
"""Initiate restoring a backup."""
agent = self.backup_agents[agent_id]
if not await agent.async_get_backup(backup_id):
raise HomeAssistantError(
raise BackupManagerError(
f"Backup {backup_id} not found in agent {agent_id}"
)
@@ -855,6 +955,38 @@ class BackupManager:
self._backup_event_subscriptions.append(on_event)
return remove_subscription
def _update_issue_backup_failed(self) -> None:
"""Update issue registry when a backup fails."""
ir.async_create_issue(
self.hass,
DOMAIN,
"automatic_backup_failed",
is_fixable=False,
is_persistent=True,
learn_more_url="homeassistant://config/backup",
severity=ir.IssueSeverity.WARNING,
translation_key="automatic_backup_failed_create",
)
def _update_issue_after_agent_upload(
self, agent_errors: dict[str, Exception]
) -> None:
"""Update issue registry after a backup is uploaded to agents."""
if not agent_errors:
ir.async_delete_issue(self.hass, DOMAIN, "automatic_backup_failed")
return
ir.async_create_issue(
self.hass,
DOMAIN,
"automatic_backup_failed",
is_fixable=False,
is_persistent=True,
learn_more_url="homeassistant://config/backup",
severity=ir.IssueSeverity.WARNING,
translation_key="automatic_backup_failed_upload_agents",
translation_placeholders={"failed_agents": ", ".join(agent_errors)},
)
class KnownBackups:
"""Track known backups."""
@@ -870,7 +1002,6 @@ class KnownBackups:
backup["backup_id"]: KnownBackup(
backup_id=backup["backup_id"],
failed_agent_ids=backup["failed_agent_ids"],
with_strategy_settings=backup["with_strategy_settings"],
)
for backup in stored_backups
}
@@ -883,13 +1014,11 @@ class KnownBackups:
self,
backup: AgentBackup,
agent_errors: dict[str, Exception],
with_strategy_settings: bool,
) -> None:
"""Add a backup."""
self._backups[backup.backup_id] = KnownBackup(
backup_id=backup.backup_id,
failed_agent_ids=list(agent_errors),
with_strategy_settings=with_strategy_settings,
)
self._manager.store.save()
@@ -911,14 +1040,12 @@ class KnownBackup:
backup_id: str
failed_agent_ids: list[str]
with_strategy_settings: bool
def to_dict(self) -> StoredKnownBackup:
"""Convert known backup to a dict."""
return {
"backup_id": self.backup_id,
"failed_agent_ids": self.failed_agent_ids,
"with_strategy_settings": self.with_strategy_settings,
}
@@ -927,7 +1054,6 @@ class StoredKnownBackup(TypedDict):
backup_id: str
failed_agent_ids: list[str]
with_strategy_settings: bool
class CoreBackupReaderWriter(BackupReaderWriter):
@@ -945,6 +1071,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
*,
agent_ids: list[str],
backup_name: str,
extra_metadata: dict[str, bool | str],
include_addons: list[str] | None,
include_all_addons: bool,
include_database: bool,
@@ -958,17 +1085,18 @@ class CoreBackupReaderWriter(BackupReaderWriter):
backup_id = _generate_backup_id(date_str, backup_name)
if include_addons or include_all_addons or include_folders:
raise HomeAssistantError(
raise BackupReaderWriterError(
"Addons and folders are not supported by core backup"
)
if not include_homeassistant:
raise HomeAssistantError("Home Assistant must be included in backup")
raise BackupReaderWriterError("Home Assistant must be included in backup")
backup_task = self._hass.async_create_task(
self._async_create_backup(
agent_ids=agent_ids,
backup_id=backup_id,
backup_name=backup_name,
extra_metadata=extra_metadata,
include_database=include_database,
date_str=date_str,
on_progress=on_progress,
@@ -987,6 +1115,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
backup_id: str,
backup_name: str,
date_str: str,
extra_metadata: dict[str, bool | str],
include_database: bool,
on_progress: Callable[[ManagerStateEvent], None],
password: str | None,
@@ -1012,6 +1141,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
backup_data = {
"compressed": True,
"date": date_str,
"extra": extra_metadata,
"homeassistant": {
"exclude_database": not include_database,
"version": HAVERSION,
@@ -1030,11 +1160,19 @@ class CoreBackupReaderWriter(BackupReaderWriter):
password,
local_agent_tar_file_path,
)
except (BackupManagerError, OSError, tarfile.TarError, ValueError) as err:
# BackupManagerError from async_pre_backup_actions
# OSError from file operations
# TarError from tarfile
# ValueError from json_bytes
raise BackupReaderWriterError(str(err)) from err
else:
backup = AgentBackup(
addons=[],
backup_id=backup_id,
database_included=include_database,
date=date_str,
extra_metadata=extra_metadata,
folders=[],
homeassistant_included=True,
homeassistant_version=HAVERSION,
@@ -1046,12 +1184,15 @@ class CoreBackupReaderWriter(BackupReaderWriter):
async_add_executor_job = self._hass.async_add_executor_job
async def send_backup() -> AsyncIterator[bytes]:
f = await async_add_executor_job(tar_file_path.open, "rb")
try:
while chunk := await async_add_executor_job(f.read, 2**20):
yield chunk
finally:
await async_add_executor_job(f.close)
f = await async_add_executor_job(tar_file_path.open, "rb")
try:
while chunk := await async_add_executor_job(f.read, 2**20):
yield chunk
finally:
await async_add_executor_job(f.close)
except OSError as err:
raise BackupReaderWriterError(str(err)) from err
async def open_backup() -> AsyncIterator[bytes]:
return send_backup()
@@ -1059,14 +1200,20 @@ class CoreBackupReaderWriter(BackupReaderWriter):
async def remove_backup() -> None:
if local_agent_tar_file_path:
return
await async_add_executor_job(tar_file_path.unlink, True)
try:
await async_add_executor_job(tar_file_path.unlink, True)
except OSError as err:
raise BackupReaderWriterError(str(err)) from err
return WrittenBackup(
backup=backup, open_stream=open_backup, release_stream=remove_backup
)
finally:
# Inform integrations the backup is done
await manager.async_post_backup_actions()
try:
await manager.async_post_backup_actions()
except BackupManagerError as err:
raise BackupReaderWriterError(str(err)) from err
def _mkdir_and_generate_backup_contents(
self,
@@ -1136,6 +1283,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
if self._local_agent_id in agent_ids:
local_agent = manager.local_backup_agents[self._local_agent_id]
tar_file_path = local_agent.get_backup_path(backup.backup_id)
await async_add_executor_job(make_backup_dir, tar_file_path.parent)
await async_add_executor_job(shutil.move, temp_file, tar_file_path)
else:
tar_file_path = temp_file
@@ -1179,11 +1327,11 @@ class CoreBackupReaderWriter(BackupReaderWriter):
"""
if restore_addons or restore_folders:
raise HomeAssistantError(
raise BackupReaderWriterError(
"Addons and folders are not supported in core restore"
)
if not restore_homeassistant and not restore_database:
raise HomeAssistantError(
raise BackupReaderWriterError(
"Home Assistant or database must be included in restore"
)
@@ -1206,6 +1354,12 @@ class CoreBackupReaderWriter(BackupReaderWriter):
remove_after_restore = True
password_valid = await self._hass.async_add_executor_job(
validate_password, path, password
)
if not password_valid:
raise IncorrectPasswordError("The password provided is incorrect.")
def _write_restore_file() -> None:
"""Write the restore file."""
Path(self._hass.config.path(RESTORE_BACKUP_FILE)).write_text(
@@ -1222,7 +1376,7 @@ class CoreBackupReaderWriter(BackupReaderWriter):
)
await self._hass.async_add_executor_job(_write_restore_file)
await self._hass.services.async_call("homeassistant", "restart", {})
await self._hass.services.async_call("homeassistant", "restart", blocking=True)
def _generate_backup_id(date: str, name: str) -> str:
+14
View File
@@ -6,6 +6,8 @@ from dataclasses import asdict, dataclass
from enum import StrEnum
from typing import Any, Self
from homeassistant.exceptions import HomeAssistantError
@dataclass(frozen=True, kw_only=True)
class AddonInfo:
@@ -33,6 +35,7 @@ class AgentBackup:
backup_id: str
date: str
database_included: bool
extra_metadata: dict[str, bool | str]
folders: list[Folder]
homeassistant_included: bool
homeassistant_version: str | None # None if homeassistant_included is False
@@ -44,6 +47,12 @@ class AgentBackup:
"""Return a dict representation of this backup."""
return asdict(self)
def as_frontend_json(self) -> dict:
"""Return a dict representation of this backup for sending to frontend."""
return {
key: val for key, val in asdict(self).items() if key != "extra_metadata"
}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Self:
"""Create an instance from a JSON serialization."""
@@ -52,6 +61,7 @@ class AgentBackup:
backup_id=data["backup_id"],
date=data["date"],
database_included=data["database_included"],
extra_metadata=data["extra_metadata"],
folders=[Folder(folder) for folder in data["folders"]],
homeassistant_included=data["homeassistant_included"],
homeassistant_version=data["homeassistant_version"],
@@ -59,3 +69,7 @@ class AgentBackup:
protected=data["protected"],
size=data["size"],
)
class BackupManagerError(HomeAssistantError):
"""Backup manager error."""
@@ -1,4 +1,14 @@
{
"issues": {
"automatic_backup_failed_create": {
"title": "Automatic backup could not be created",
"description": "The automatic backup could not be created. Please check the logs for more information. Another attempt will be made at the next scheduled time if a backup schedule is configured."
},
"automatic_backup_failed_upload_agents": {
"title": "Automatic backup could not be uploaded to the configured locations",
"description": "The automatic backup could not be uploaded to the configured locations {failed_agents}. Please check the logs for more information. Another attempt will be made at the next scheduled time if a backup schedule is configured."
}
},
"services": {
"create": {
"name": "Create backup",
+38 -1
View File
@@ -9,11 +9,13 @@ import tarfile
from typing import cast
import aiohttp
from securetar import SecureTarFile
from homeassistant.backup_restore import password_to_key
from homeassistant.core import HomeAssistant
from homeassistant.util.json import JsonObjectType, json_loads_object
from .const import BUF_SIZE
from .const import BUF_SIZE, LOGGER
from .models import AddonInfo, AgentBackup, Folder
@@ -50,6 +52,7 @@ def read_backup(backup_path: Path) -> AgentBackup:
if (
homeassistant := cast(JsonObjectType, data.get("homeassistant"))
) and "version" in homeassistant:
homeassistant_included = True
homeassistant_version = cast(str, homeassistant["version"])
database_included = not cast(
bool, homeassistant.get("exclude_database", False)
@@ -60,6 +63,7 @@ def read_backup(backup_path: Path) -> AgentBackup:
backup_id=cast(str, data["slug"]),
database_included=database_included,
date=cast(str, data["date"]),
extra_metadata=cast(dict[str, bool | str], data.get("extra", {})),
folders=folders,
homeassistant_included=homeassistant_included,
homeassistant_version=homeassistant_version,
@@ -69,6 +73,39 @@ def read_backup(backup_path: Path) -> AgentBackup:
)
def validate_password(path: Path, password: str | None) -> bool:
"""Validate the password."""
with tarfile.open(path, "r:", bufsize=BUF_SIZE) as backup_file:
compressed = False
ha_tar_name = "homeassistant.tar"
try:
ha_tar = backup_file.extractfile(ha_tar_name)
except KeyError:
compressed = True
ha_tar_name = "homeassistant.tar.gz"
try:
ha_tar = backup_file.extractfile(ha_tar_name)
except KeyError:
LOGGER.error("No homeassistant.tar or homeassistant.tar.gz found")
return False
try:
with SecureTarFile(
path, # Not used
gzip=compressed,
key=password_to_key(password) if password is not None else None,
mode="r",
fileobj=ha_tar,
):
# If we can read the tar file, the password is correct
return True
except tarfile.ReadError:
LOGGER.debug("Invalid password")
return False
except Exception: # noqa: BLE001
LOGGER.exception("Unexpected error validating password")
return False
async def receive_file(
hass: HomeAssistant, contents: aiohttp.BodyPartReader, path: Path
) -> None:
+30 -22
View File
@@ -9,7 +9,7 @@ from homeassistant.core import HomeAssistant, callback
from .config import ScheduleState
from .const import DATA_MANAGER, LOGGER
from .manager import ManagerStateEvent
from .manager import IncorrectPasswordError, ManagerStateEvent
from .models import Folder
@@ -25,7 +25,7 @@ def async_register_websocket_handlers(hass: HomeAssistant, with_hassio: bool) ->
websocket_api.async_register_command(hass, handle_details)
websocket_api.async_register_command(hass, handle_info)
websocket_api.async_register_command(hass, handle_create)
websocket_api.async_register_command(hass, handle_create_with_strategy_settings)
websocket_api.async_register_command(hass, handle_create_with_automatic_settings)
websocket_api.async_register_command(hass, handle_delete)
websocket_api.async_register_command(hass, handle_restore)
websocket_api.async_register_command(hass, handle_subscribe_events)
@@ -51,9 +51,9 @@ async def handle_info(
"agent_errors": {
agent_id: str(err) for agent_id, err in agent_errors.items()
},
"backups": list(backups.values()),
"last_attempted_strategy_backup": manager.config.data.last_attempted_strategy_backup,
"last_completed_strategy_backup": manager.config.data.last_completed_strategy_backup,
"backups": [backup.as_frontend_json() for backup in backups.values()],
"last_attempted_automatic_backup": manager.config.data.last_attempted_automatic_backup,
"last_completed_automatic_backup": manager.config.data.last_completed_automatic_backup,
},
)
@@ -81,7 +81,7 @@ async def handle_details(
"agent_errors": {
agent_id: str(err) for agent_id, err in agent_errors.items()
},
"backup": backup,
"backup": backup.as_frontend_json() if backup else None,
},
)
@@ -131,16 +131,20 @@ async def handle_restore(
msg: dict[str, Any],
) -> None:
"""Restore a backup."""
await hass.data[DATA_MANAGER].async_restore_backup(
msg["backup_id"],
agent_id=msg["agent_id"],
password=msg.get("password"),
restore_addons=msg.get("restore_addons"),
restore_database=msg["restore_database"],
restore_folders=msg.get("restore_folders"),
restore_homeassistant=msg["restore_homeassistant"],
)
connection.send_result(msg["id"])
try:
await hass.data[DATA_MANAGER].async_restore_backup(
msg["backup_id"],
agent_id=msg["agent_id"],
password=msg.get("password"),
restore_addons=msg.get("restore_addons"),
restore_database=msg["restore_database"],
restore_folders=msg.get("restore_folders"),
restore_homeassistant=msg["restore_homeassistant"],
)
except IncorrectPasswordError:
connection.send_error(msg["id"], "password_incorrect", "Incorrect password")
else:
connection.send_result(msg["id"])
@websocket_api.require_admin
@@ -181,11 +185,11 @@ async def handle_create(
@websocket_api.require_admin
@websocket_api.websocket_command(
{
vol.Required("type"): "backup/generate_with_strategy_settings",
vol.Required("type"): "backup/generate_with_automatic_settings",
}
)
@websocket_api.async_response
async def handle_create_with_strategy_settings(
async def handle_create_with_automatic_settings(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
@@ -202,7 +206,7 @@ async def handle_create_with_strategy_settings(
include_homeassistant=True, # always include HA
name=config_data.create_backup.name,
password=config_data.create_backup.password,
with_strategy_settings=True,
with_automatic_settings=True,
)
connection.send_result(msg["id"], backup)
@@ -291,11 +295,15 @@ async def handle_config_info(
vol.Required("type"): "backup/config/update",
vol.Optional("create_backup"): vol.Schema(
{
vol.Optional("agent_ids"): vol.All(list[str]),
vol.Optional("include_addons"): vol.Any(list[str], None),
vol.Optional("agent_ids"): vol.All([str], vol.Unique()),
vol.Optional("include_addons"): vol.Any(
vol.All([str], vol.Unique()), None
),
vol.Optional("include_all_addons"): bool,
vol.Optional("include_database"): bool,
vol.Optional("include_folders"): vol.Any([vol.Coerce(Folder)], None),
vol.Optional("include_folders"): vol.Any(
vol.All([vol.Coerce(Folder)], vol.Unique()), None
),
vol.Optional("name"): vol.Any(str, None),
vol.Optional("password"): vol.Any(str, None),
},
@@ -34,7 +34,7 @@ class BangOlufsenData:
type BangOlufsenConfigEntry = ConfigEntry[BangOlufsenData]
PLATFORMS = [Platform.MEDIA_PLAYER]
PLATFORMS = [Platform.EVENT, Platform.MEDIA_PLAYER]
async def async_setup_entry(hass: HomeAssistant, entry: BangOlufsenConfigEntry) -> bool:
@@ -79,6 +79,7 @@ class WebsocketNotification(StrEnum):
"""Enum for WebSocket notification types."""
ACTIVE_LISTENING_MODE = "active_listening_mode"
BUTTON = "button"
PLAYBACK_ERROR = "playback_error"
PLAYBACK_METADATA = "playback_metadata"
PLAYBACK_PROGRESS = "playback_progress"
@@ -203,14 +204,60 @@ FALLBACK_SOURCES: Final[SourceArray] = SourceArray(
),
]
)
# Map for storing compatibility of devices.
MODEL_SUPPORT_DEVICE_BUTTONS: Final[str] = "device_buttons"
MODEL_SUPPORT_MAP = {
MODEL_SUPPORT_DEVICE_BUTTONS: (
BangOlufsenModel.BEOLAB_8,
BangOlufsenModel.BEOLAB_28,
BangOlufsenModel.BEOSOUND_2,
BangOlufsenModel.BEOSOUND_A5,
BangOlufsenModel.BEOSOUND_A9,
BangOlufsenModel.BEOSOUND_BALANCE,
BangOlufsenModel.BEOSOUND_EMERGE,
BangOlufsenModel.BEOSOUND_LEVEL,
BangOlufsenModel.BEOSOUND_THEATRE,
)
}
# Device events
BANG_OLUFSEN_WEBSOCKET_EVENT: Final[str] = f"{DOMAIN}_websocket_event"
# Dict used to translate native Bang & Olufsen event names to string.json compatible ones
EVENT_TRANSLATION_MAP: dict[str, str] = {
"shortPress (Release)": "short_press_release",
"longPress (Timeout)": "long_press_timeout",
"longPress (Release)": "long_press_release",
"veryLongPress (Timeout)": "very_long_press_timeout",
"veryLongPress (Release)": "very_long_press_release",
}
CONNECTION_STATUS: Final[str] = "CONNECTION_STATUS"
DEVICE_BUTTONS: Final[list[str]] = [
"Bluetooth",
"Microphone",
"Next",
"PlayPause",
"Preset1",
"Preset2",
"Preset3",
"Preset4",
"Previous",
"Volume",
]
DEVICE_BUTTON_EVENTS: Final[list[str]] = [
"short_press_release",
"long_press_timeout",
"long_press_release",
"very_long_press_timeout",
"very_long_press_release",
]
# Beolink Converter NL/ML sources need to be transformed to upper case
BEOLINK_JOIN_SOURCES_TO_UPPER = (
"aux_a",
@@ -0,0 +1,76 @@
"""Event entities for the Bang & Olufsen integration."""
from __future__ import annotations
from homeassistant.components.event import EventDeviceClass, EventEntity
from homeassistant.const import CONF_MODEL
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import BangOlufsenConfigEntry
from .const import (
CONNECTION_STATUS,
DEVICE_BUTTON_EVENTS,
DEVICE_BUTTONS,
MODEL_SUPPORT_DEVICE_BUTTONS,
MODEL_SUPPORT_MAP,
WebsocketNotification,
)
from .entity import BangOlufsenEntity
async def async_setup_entry(
hass: HomeAssistant,
config_entry: BangOlufsenConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Sensor entities from config entry."""
if config_entry.data[CONF_MODEL] in MODEL_SUPPORT_MAP[MODEL_SUPPORT_DEVICE_BUTTONS]:
async_add_entities(
BangOlufsenButtonEvent(config_entry, button_type)
for button_type in DEVICE_BUTTONS
)
class BangOlufsenButtonEvent(BangOlufsenEntity, EventEntity):
"""Event class for Button events."""
_attr_device_class = EventDeviceClass.BUTTON
_attr_entity_registry_enabled_default = False
_attr_event_types = DEVICE_BUTTON_EVENTS
def __init__(self, config_entry: BangOlufsenConfigEntry, button_type: str) -> None:
"""Initialize Button."""
super().__init__(config_entry, config_entry.runtime_data.client)
self._attr_unique_id = f"{self._unique_id}_{button_type}"
# Make the native button name Home Assistant compatible
self._attr_translation_key = button_type.lower()
self._button_type = button_type
async def async_added_to_hass(self) -> None:
"""Listen to WebSocket button events."""
self.async_on_remove(
async_dispatcher_connect(
self.hass,
f"{self._unique_id}_{CONNECTION_STATUS}",
self._async_update_connection_state,
)
)
self.async_on_remove(
async_dispatcher_connect(
self.hass,
f"{self._unique_id}_{WebsocketNotification.BUTTON}_{self._button_type}",
self._async_handle_event,
)
)
@callback
def _async_handle_event(self, event: str) -> None:
"""Handle event."""
self._trigger_event(event)
self.async_write_ha_state()
@@ -1,7 +1,12 @@
{
"common": {
"jid_options_description": "Advanced grouping options, where devices' unique Beolink IDs (Called JIDs) are used directly. JIDs can be found in the state attributes of the media player entity.",
"jid_options_name": "JID options",
"jid_options_description": "Advanced grouping options, where devices' unique Beolink IDs (Called JIDs) are used directly. JIDs can be found in the state attributes of the media player entity."
"long_press_release": "Release of long press",
"long_press_timeout": "Long press",
"short_press_release": "Release of short press",
"very_long_press_release": "Release of very long press",
"very_long_press_timeout": "Very long press"
},
"config": {
"error": {
@@ -29,6 +34,150 @@
}
}
},
"entity": {
"event": {
"bluetooth": {
"name": "Bluetooth",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"microphone": {
"name": "Microphone",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"next": {
"name": "Next",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"playpause": {
"name": "Play / Pause",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"preset1": {
"name": "Favourite 1",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"preset2": {
"name": "Favourite 2",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"preset3": {
"name": "Favourite 3",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"preset4": {
"name": "Favourite 4",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"previous": {
"name": "Previous",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
},
"volume": {
"name": "Volume",
"state_attributes": {
"event_type": {
"state": {
"short_press_release": "[%key:component::bang_olufsen::common::short_press_release%]",
"long_press_timeout": "[%key:component::bang_olufsen::common::long_press_timeout%]",
"long_press_release": "[%key:component::bang_olufsen::common::long_press_release%]",
"very_long_press_timeout": "[%key:component::bang_olufsen::common::very_long_press_timeout%]",
"very_long_press_release": "[%key:component::bang_olufsen::common::very_long_press_release%]"
}
}
}
}
}
},
"selector": {
"source_ids": {
"options": {
@@ -3,8 +3,10 @@
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from mozart_api.models import (
ButtonEvent,
ListeningModeProps,
PlaybackContentMetadata,
PlaybackError,
@@ -26,6 +28,7 @@ from homeassistant.util.enum import try_parse_enum
from .const import (
BANG_OLUFSEN_WEBSOCKET_EVENT,
CONNECTION_STATUS,
EVENT_TRANSLATION_MAP,
WebsocketNotification,
)
from .entity import BangOlufsenBase
@@ -54,6 +57,8 @@ class BangOlufsenWebsocket(BangOlufsenBase):
self._client.get_active_listening_mode_notifications(
self.on_active_listening_mode
)
self._client.get_button_notifications(self.on_button_notification)
self._client.get_playback_error_notifications(
self.on_playback_error_notification
)
@@ -104,6 +109,19 @@ class BangOlufsenWebsocket(BangOlufsenBase):
notification,
)
def on_button_notification(self, notification: ButtonEvent) -> None:
"""Send button dispatch."""
# State is expected to always be available.
if TYPE_CHECKING:
assert notification.state
# Send to event entity
async_dispatcher_send(
self.hass,
f"{self._unique_id}_{WebsocketNotification.BUTTON}_{notification.button}",
EVENT_TRANSLATION_MAP[notification.state],
)
def on_notification_notification(
self, notification: WebsocketNotificationTag
) -> None:
+5 -5
View File
@@ -84,16 +84,16 @@
}
},
"send_pin": {
"name": "Send pin",
"description": "Sends a new PIN to blink for 2FA.",
"name": "Send PIN",
"description": "Sends a new PIN to Blink for 2FA.",
"fields": {
"pin": {
"name": "Pin",
"description": "PIN received from blink. Leave empty if you only received a verification email."
"name": "PIN",
"description": "PIN received from Blink. Leave empty if you only received a verification email."
},
"config_entry_id": {
"name": "Integration ID",
"description": "The Blink Integration id."
"description": "The Blink Integration ID."
}
}
}
@@ -71,27 +71,6 @@ class BluesoundConfigFlow(ConfigFlow, domain=DOMAIN):
),
)
async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
"""Import bluesound config entry from configuration.yaml."""
session = async_get_clientsession(self.hass)
async with Player(
import_data[CONF_HOST], import_data[CONF_PORT], session=session
) as player:
try:
sync_status = await player.sync_status(timeout=1)
except PlayerUnreachableError:
return self.async_abort(reason="cannot_connect")
await self.async_set_unique_id(
format_unique_id(sync_status.mac, import_data[CONF_PORT])
)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=sync_status.name,
data=import_data,
)
async def async_step_zeroconf(
self, discovery_info: zeroconf.ZeroconfServiceInfo
) -> ConfigFlowResult:
@@ -15,7 +15,6 @@ import voluptuous as vol
from homeassistant.components import media_source
from homeassistant.components.media_player import (
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
BrowseMedia,
MediaPlayerEntity,
MediaPlayerEntityFeature,
@@ -23,16 +22,10 @@ from homeassistant.components.media_player import (
MediaType,
async_process_play_media_url,
)
from homeassistant.config_entries import SOURCE_IMPORT
from homeassistant.const import CONF_HOST, CONF_HOSTS, CONF_NAME, CONF_PORT
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import (
config_validation as cv,
entity_platform,
issue_registry as ir,
)
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
DeviceInfo,
@@ -43,10 +36,9 @@ from homeassistant.helpers.dispatcher import (
async_dispatcher_send,
)
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
import homeassistant.util.dt as dt_util
from .const import ATTR_BLUESOUND_GROUP, ATTR_MASTER, DOMAIN, INTEGRATION_TITLE
from .const import ATTR_BLUESOUND_GROUP, ATTR_MASTER, DOMAIN
from .utils import dispatcher_join_signal, dispatcher_unjoin_signal, format_unique_id
if TYPE_CHECKING:
@@ -71,64 +63,6 @@ SYNC_STATUS_INTERVAL = timedelta(minutes=5)
POLL_TIMEOUT = 120
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_HOSTS): vol.All(
cv.ensure_list,
[
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
}
],
)
}
)
async def _async_import(hass: HomeAssistant, config: ConfigType) -> None:
"""Import config entry from configuration.yaml."""
if not hass.config_entries.async_entries(DOMAIN):
# Start import flow
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=config
)
if (
result["type"] == FlowResultType.ABORT
and result["reason"] == "cannot_connect"
):
ir.async_create_issue(
hass,
DOMAIN,
f"deprecated_yaml_import_issue_{result['reason']}",
breaks_in_ha_version="2025.2.0",
is_fixable=False,
issue_domain=DOMAIN,
severity=ir.IssueSeverity.WARNING,
translation_key=f"deprecated_yaml_import_issue_{result['reason']}",
translation_placeholders={
"domain": DOMAIN,
"integration_title": INTEGRATION_TITLE,
},
)
return
ir.async_create_issue(
hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_yaml_{DOMAIN}",
breaks_in_ha_version="2025.2.0",
is_fixable=False,
issue_domain=DOMAIN,
severity=ir.IssueSeverity.WARNING,
translation_key="deprecated_yaml",
translation_placeholders={
"domain": DOMAIN,
"integration_title": INTEGRATION_TITLE,
},
)
async def async_setup_entry(
hass: HomeAssistant,
@@ -159,22 +93,6 @@ async def async_setup_entry(
async_add_entities([bluesound_player], update_before_add=True)
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None,
) -> None:
"""Trigger import flows."""
hosts = config.get(CONF_HOSTS, [])
for host in hosts:
import_data = {
CONF_HOST: host[CONF_HOST],
CONF_PORT: host.get(CONF_PORT, 11000),
}
hass.async_create_task(_async_import(hass, import_data))
class BluesoundPlayer(MediaPlayerEntity):
"""Representation of a Bluesound Player."""
@@ -20,6 +20,6 @@
"bluetooth-auto-recovery==1.4.2",
"bluetooth-data-tools==1.20.0",
"dbus-fast==2.24.3",
"habluetooth==3.6.0"
"habluetooth==3.7.0"
]
}
@@ -103,9 +103,10 @@ class BMWConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1
data: dict[str, Any] = {}
_existing_entry_data: Mapping[str, Any] | None = None
def __init__(self) -> None:
"""Initialize the config flow."""
self.data: dict[str, Any] = {}
self._existing_entry_data: dict[str, Any] = {}
async def async_step_user(
self, user_input: dict[str, Any] | None = None
@@ -175,19 +176,15 @@ class BMWConfigFlow(ConfigFlow, domain=DOMAIN):
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Show the change password step."""
existing_data = (
dict(self._existing_entry_data) if self._existing_entry_data else {}
)
if user_input is not None:
return await self.async_step_user(existing_data | user_input)
return await self.async_step_user(self._existing_entry_data | user_input)
return self.async_show_form(
step_id="change_password",
data_schema=RECONFIGURE_SCHEMA,
description_placeholders={
CONF_USERNAME: existing_data[CONF_USERNAME],
CONF_REGION: existing_data[CONF_REGION],
CONF_USERNAME: self._existing_entry_data[CONF_USERNAME],
CONF_REGION: self._existing_entry_data[CONF_REGION],
},
)
@@ -195,14 +192,14 @@ class BMWConfigFlow(ConfigFlow, domain=DOMAIN):
self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle configuration by re-auth."""
self._existing_entry_data = entry_data
self._existing_entry_data = dict(entry_data)
return await self.async_step_change_password()
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a reconfiguration flow initialized by the user."""
self._existing_entry_data = self._get_reconfigure_entry().data
self._existing_entry_data = dict(self._get_reconfigure_entry().data)
return await self.async_step_change_password()
async def async_step_captcha(
@@ -6,5 +6,6 @@
"documentation": "https://www.home-assistant.io/integrations/bring",
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["bring_api"],
"requirements": ["bring-api==0.9.1"]
}
@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/caldav",
"iot_class": "cloud_polling",
"loggers": ["caldav", "vobject"],
"requirements": ["caldav==1.3.9"]
"requirements": ["caldav==1.3.9", "icalendar==6.1.0"]
}
@@ -0,0 +1,85 @@
"""Support for media browsing."""
from aiostreammagic import StreamMagicClient
from aiostreammagic.models import Preset
from homeassistant.components.media_player import BrowseMedia, MediaClass
from homeassistant.core import HomeAssistant
async def async_browse_media(
hass: HomeAssistant,
client: StreamMagicClient,
media_content_id: str | None,
media_content_type: str | None,
) -> BrowseMedia:
"""Browse media."""
if media_content_type == "presets":
return await _presets_payload(client.preset_list.presets)
return await _root_payload(
hass,
client,
)
async def _root_payload(
hass: HomeAssistant,
client: StreamMagicClient,
) -> BrowseMedia:
"""Return root payload for Cambridge Audio."""
children: list[BrowseMedia] = []
if client.preset_list.presets:
children.append(
BrowseMedia(
title="Presets",
media_class=MediaClass.DIRECTORY,
media_content_id="",
media_content_type="presets",
thumbnail="https://brands.home-assistant.io/_/cambridge_audio/logo.png",
can_play=False,
can_expand=True,
)
)
return BrowseMedia(
title="Cambridge Audio",
media_class=MediaClass.DIRECTORY,
media_content_id="",
media_content_type="root",
can_play=False,
can_expand=True,
children=children,
)
async def _presets_payload(presets: list[Preset]) -> BrowseMedia:
"""Create payload to list presets."""
children: list[BrowseMedia] = []
for preset in presets:
if preset.state != "OK":
continue
children.append(
BrowseMedia(
title=preset.name,
media_class=MediaClass.MUSIC,
media_content_id=str(preset.preset_id),
media_content_type="preset",
can_play=True,
can_expand=False,
thumbnail=preset.art_url,
)
)
return BrowseMedia(
title="Presets",
media_class=MediaClass.DIRECTORY,
media_content_id="",
media_content_type="presets",
can_play=False,
can_expand=True,
children=children,
)
@@ -13,6 +13,7 @@ from aiostreammagic import (
)
from homeassistant.components.media_player import (
BrowseMedia,
MediaPlayerDeviceClass,
MediaPlayerEntity,
MediaPlayerEntityFeature,
@@ -24,7 +25,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import CambridgeAudioConfigEntry
from . import CambridgeAudioConfigEntry, media_browser
from .const import (
CAMBRIDGE_MEDIA_TYPE_AIRABLE,
CAMBRIDGE_MEDIA_TYPE_INTERNET_RADIO,
@@ -34,7 +35,8 @@ from .const import (
from .entity import CambridgeAudioEntity, command
BASE_FEATURES = (
MediaPlayerEntityFeature.SELECT_SOURCE
MediaPlayerEntityFeature.BROWSE_MEDIA
| MediaPlayerEntityFeature.SELECT_SOURCE
| MediaPlayerEntityFeature.TURN_OFF
| MediaPlayerEntityFeature.TURN_ON
| MediaPlayerEntityFeature.PLAY_MEDIA
@@ -338,3 +340,13 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
if media_type == CAMBRIDGE_MEDIA_TYPE_INTERNET_RADIO:
await self.client.play_radio_url("Radio", media_id)
async def async_browse_media(
self,
media_content_type: MediaType | str | None = None,
media_content_id: str | None = None,
) -> BrowseMedia:
"""Implement the media browsing helper."""
return await media_browser.async_browse_media(
self.hass, self.client, media_content_id, media_content_type
)
@@ -12,7 +12,7 @@
}
},
"discovery_confirm": {
"description": "Do you want to setup {name}?"
"description": "Do you want to set up {name}?"
},
"reconfigure": {
"description": "Reconfigure your Cambridge Audio Streamer.",
@@ -28,7 +28,7 @@
"cannot_connect": "Failed to connect to Cambridge Audio device. Please make sure the device is powered up and connected to the network. Try power-cycling the device if it does not connect."
},
"abort": {
"wrong_device": "This Cambridge Audio device does not match the existing device id. Please make sure you entered the correct IP address.",
"wrong_device": "This Cambridge Audio device does not match the existing device ID. Please make sure you entered the correct IP address.",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
+21 -5
View File
@@ -516,6 +516,19 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
"""Flag supported features."""
return self._attr_supported_features
@property
def supported_features_compat(self) -> CameraEntityFeature:
"""Return the supported features as CameraEntityFeature.
Remove this compatibility shim in 2025.1 or later.
"""
features = self.supported_features
if type(features) is int: # noqa: E721
new_features = CameraEntityFeature(features)
self._report_deprecated_supported_features_values(new_features)
return new_features
return features
@cached_property
def is_recording(self) -> bool:
"""Return true if the device is recording."""
@@ -569,7 +582,7 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
self._deprecate_attr_frontend_stream_type_logged = True
return self._attr_frontend_stream_type
if CameraEntityFeature.STREAM not in self.supported_features:
if CameraEntityFeature.STREAM not in self.supported_features_compat:
return None
if (
self._webrtc_provider
@@ -798,7 +811,9 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
async def async_internal_added_to_hass(self) -> None:
"""Run when entity about to be added to hass."""
await super().async_internal_added_to_hass()
self.__supports_stream = self.supported_features & CameraEntityFeature.STREAM
self.__supports_stream = (
self.supported_features_compat & CameraEntityFeature.STREAM
)
await self.async_refresh_providers(write_state=False)
async def async_refresh_providers(self, *, write_state: bool = True) -> None:
@@ -838,7 +853,7 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
self, fn: Callable[[HomeAssistant, Camera], Coroutine[None, None, _T | None]]
) -> _T | None:
"""Get first provider that supports this camera."""
if CameraEntityFeature.STREAM not in self.supported_features:
if CameraEntityFeature.STREAM not in self.supported_features_compat:
return None
return await fn(self.hass, self)
@@ -896,7 +911,7 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
def camera_capabilities(self) -> CameraCapabilities:
"""Return the camera capabilities."""
frontend_stream_types = set()
if CameraEntityFeature.STREAM in self.supported_features:
if CameraEntityFeature.STREAM in self.supported_features_compat:
if self._supports_native_sync_webrtc or self._supports_native_async_webrtc:
# The camera has a native WebRTC implementation
frontend_stream_types.add(StreamType.WEB_RTC)
@@ -916,7 +931,8 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
"""
super().async_write_ha_state()
if self.__supports_stream != (
supports_stream := self.supported_features & CameraEntityFeature.STREAM
supports_stream := self.supported_features_compat
& CameraEntityFeature.STREAM
):
self.__supports_stream = supports_stream
self._invalidate_camera_capabilities_cache()
+2 -2
View File
@@ -5,7 +5,7 @@ from __future__ import annotations
import configparser
from dataclasses import dataclass
import logging
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, ClassVar
from urllib.parse import urlparse
import aiohttp
@@ -129,7 +129,7 @@ class ChromecastInfo:
class ChromeCastZeroconf:
"""Class to hold a zeroconf instance."""
__zconf: zeroconf.HaZeroconf | None = None
__zconf: ClassVar[zeroconf.HaZeroconf | None] = None
@classmethod
def set_zeroconf(cls, zconf: zeroconf.HaZeroconf) -> None:
@@ -3,7 +3,6 @@
from __future__ import annotations
import logging
import re
from pexpect import pxssh
import voluptuous as vol
@@ -101,11 +100,11 @@ class CiscoDeviceScanner(DeviceScanner):
return False
def _get_arp_data(self):
def _get_arp_data(self) -> str | None:
"""Open connection to the router and get arp entries."""
try:
cisco_ssh = pxssh.pxssh()
cisco_ssh: pxssh.pxssh[str] = pxssh.pxssh(encoding="uft-8")
cisco_ssh.login(
self.host,
self.username,
@@ -115,12 +114,11 @@ class CiscoDeviceScanner(DeviceScanner):
)
# Find the hostname
initial_line = cisco_ssh.before.decode("utf-8").splitlines()
initial_line = (cisco_ssh.before or "").splitlines()
router_hostname = initial_line[len(initial_line) - 1]
router_hostname += "#"
# Set the discovered hostname as prompt
regex_expression = f"(?i)^{router_hostname}".encode()
cisco_ssh.PROMPT = re.compile(regex_expression, re.MULTILINE)
cisco_ssh.PROMPT = f"(?i)^{router_hostname}"
# Allow full arp table to print at once
cisco_ssh.sendline("terminal length 0")
cisco_ssh.prompt(1)
@@ -128,13 +126,11 @@ class CiscoDeviceScanner(DeviceScanner):
cisco_ssh.sendline("show ip arp")
cisco_ssh.prompt(1)
devices_result = cisco_ssh.before
return devices_result.decode("utf-8")
except pxssh.ExceptionPxssh as px_e:
_LOGGER.error("Failed to login via pxssh: %s", px_e)
return None
return None
return cisco_ssh.before
def _parse_cisco_mac_address(cisco_hardware_addr):
@@ -6,5 +6,5 @@
"iot_class": "local_polling",
"loggers": ["pexpect", "ptyprocess"],
"quality_scale": "legacy",
"requirements": ["pexpect==4.6.0"]
"requirements": ["pexpect==4.9.0"]
}
+8 -1
View File
@@ -36,7 +36,14 @@ from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass
from homeassistant.util.signal_type import SignalType
from . import account_link, http_api
# Pre-import backup to avoid it being imported
# later when the import executor is busy and delaying
# startup
from . import (
account_link,
backup, # noqa: F401
http_api,
)
from .client import CloudClient
from .const import (
CONF_ACCOUNT_LINK_SERVER,
+39 -25
View File
@@ -3,11 +3,12 @@
from __future__ import annotations
import base64
from collections.abc import AsyncIterator, Callable, Coroutine
from collections.abc import AsyncIterator, Callable, Coroutine, Mapping
import hashlib
from typing import Any, Self
import logging
from typing import Any
from aiohttp import ClientError, ClientTimeout, StreamReader
from aiohttp import ClientError, ClientTimeout
from hass_nabucasa import Cloud, CloudError
from hass_nabucasa.cloud_api import (
async_files_delete_file,
@@ -18,10 +19,13 @@ from hass_nabucasa.cloud_api import (
from homeassistant.components.backup import AgentBackup, BackupAgent, BackupAgentError
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.aiohttp_client import ChunkAsyncStreamIterator
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .client import CloudClient
from .const import DATA_CLOUD, DOMAIN
from .const import DATA_CLOUD, DOMAIN, EVENT_CLOUD_EVENT
_LOGGER = logging.getLogger(__name__)
_STORAGE_BACKUP = "backup"
@@ -45,29 +49,29 @@ async def async_get_backup_agents(
return [CloudBackupAgent(hass=hass, cloud=cloud)]
class ChunkAsyncStreamIterator:
"""Async iterator for chunked streams.
@callback
def async_register_backup_agents_listener(
hass: HomeAssistant,
*,
listener: Callable[[], None],
**kwargs: Any,
) -> Callable[[], None]:
"""Register a listener to be called when agents are added or removed."""
Based on aiohttp.streams.ChunkTupleAsyncStreamIterator, but yields
bytes instead of tuple[bytes, bool].
"""
@callback
def unsub() -> None:
"""Unsubscribe from events."""
unsub_signal()
__slots__ = ("_stream",)
@callback
def handle_event(data: Mapping[str, Any]) -> None:
"""Handle event."""
if data["type"] not in ("login", "logout"):
return
listener()
def __init__(self, stream: StreamReader) -> None:
"""Initialize."""
self._stream = stream
def __aiter__(self) -> Self:
"""Iterate."""
return self
async def __anext__(self) -> bytes:
"""Yield next chunk."""
rv = await self._stream.readchunk()
if rv == (b"", False):
raise StopAsyncIteration
return rv[0]
unsub_signal = async_dispatcher_connect(hass, EVENT_CLOUD_EVENT, handle_event)
return unsub
class CloudBackupAgent(BackupAgent):
@@ -110,7 +114,11 @@ class CloudBackupAgent(BackupAgent):
raise BackupAgentError("Failed to get download details") from err
try:
resp = await self._cloud.websession.get(details["url"])
resp = await self._cloud.websession.get(
details["url"],
timeout=ClientTimeout(connect=10.0, total=43200.0), # 43200s == 12h
)
resp.raise_for_status()
except ClientError as err:
raise BackupAgentError("Failed to download backup") from err
@@ -153,6 +161,11 @@ class CloudBackupAgent(BackupAgent):
headers=details["headers"] | {"content-length": str(backup.size)},
timeout=ClientTimeout(connect=10.0, total=43200.0), # 43200s == 12h
)
_LOGGER.log(
logging.DEBUG if upload_status.status < 400 else logging.WARNING,
"Backup upload status: %s",
upload_status.status,
)
upload_status.raise_for_status()
except (TimeoutError, ClientError) as err:
raise BackupAgentError("Failed to upload backup") from err
@@ -182,6 +195,7 @@ class CloudBackupAgent(BackupAgent):
"""List backups."""
try:
backups = await async_files_list(self._cloud, storage_type=_STORAGE_BACKUP)
_LOGGER.debug("Cloud backups: %s", backups)
except (ClientError, CloudError) as err:
raise BackupAgentError("Failed to list backups") from err
+1
View File
@@ -306,6 +306,7 @@ class CloudClient(Interface):
},
"version": HA_VERSION,
"instance_id": self.prefs.instance_id,
"name": self._hass.config.location_name,
}
async def async_alexa_message(self, payload: dict[Any, Any]) -> dict[Any, Any]:
+2
View File
@@ -18,6 +18,8 @@ DATA_CLOUD: HassKey[Cloud[CloudClient]] = HassKey(DOMAIN)
DATA_PLATFORMS_SETUP: HassKey[dict[str, asyncio.Event]] = HassKey(
"cloud_platforms_setup"
)
EVENT_CLOUD_EVENT = "cloud_event"
REQUEST_TIMEOUT = 10
PREF_ENABLE_ALEXA = "alexa_enabled"
@@ -34,6 +34,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.util.location import async_detect_location_info
from .alexa_config import entity_supported as entity_supported_by_alexa
@@ -41,6 +42,7 @@ from .assist_pipeline import async_create_cloud_pipeline
from .client import CloudClient
from .const import (
DATA_CLOUD,
EVENT_CLOUD_EVENT,
LOGIN_MFA_TIMEOUT,
PREF_ALEXA_REPORT_STATE,
PREF_DISABLE_2FA,
@@ -278,6 +280,8 @@ class CloudLoginView(HomeAssistantView):
new_cloud_pipeline_id = await async_create_cloud_pipeline(hass)
else:
new_cloud_pipeline_id = None
async_dispatcher_send(hass, EVENT_CLOUD_EVENT, {"type": "login"})
return self.json({"success": True, "cloud_pipeline": new_cloud_pipeline_id})
@@ -297,6 +301,7 @@ class CloudLogoutView(HomeAssistantView):
async with asyncio.timeout(REQUEST_TIMEOUT):
await cloud.logout()
async_dispatcher_send(hass, EVENT_CLOUD_EVENT, {"type": "logout"})
return self.json_message("ok")
@@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["aiocomelit"],
"requirements": ["aiocomelit==0.9.1"]
"requirements": ["aiocomelit==0.10.1"]
}
@@ -5,5 +5,5 @@
"documentation": "https://www.home-assistant.io/integrations/compensation",
"iot_class": "calculated",
"quality_scale": "legacy",
"requirements": ["numpy==2.2.0"]
"requirements": ["numpy==2.2.1"]
}
@@ -46,13 +46,6 @@ def async_setup(hass: HomeAssistant) -> bool:
hass.http.register_view(OptionManagerFlowIndexView(hass.config_entries.options))
hass.http.register_view(OptionManagerFlowResourceView(hass.config_entries.options))
hass.http.register_view(
SubentryManagerFlowIndexView(hass.config_entries.subentries)
)
hass.http.register_view(
SubentryManagerFlowResourceView(hass.config_entries.subentries)
)
websocket_api.async_register_command(hass, config_entries_get)
websocket_api.async_register_command(hass, config_entry_disable)
websocket_api.async_register_command(hass, config_entry_get_single)
@@ -61,9 +54,6 @@ def async_setup(hass: HomeAssistant) -> bool:
websocket_api.async_register_command(hass, config_entries_progress)
websocket_api.async_register_command(hass, ignore_config_flow)
websocket_api.async_register_command(hass, config_subentry_delete)
websocket_api.async_register_command(hass, config_subentry_list)
return True
@@ -295,63 +285,6 @@ class OptionManagerFlowResourceView(
return await super().post(request, flow_id)
class SubentryManagerFlowIndexView(
FlowManagerIndexView[config_entries.ConfigSubentryFlowManager]
):
"""View to create subentry flows."""
url = "/api/config/config_entries/subentries/flow"
name = "api:config:config_entries:subentries:flow"
@require_admin(
error=Unauthorized(perm_category=CAT_CONFIG_ENTRIES, permission=POLICY_EDIT)
)
@RequestDataValidator(
vol.Schema(
{
vol.Required("handler"): vol.All(vol.Coerce(tuple), (str, str)),
vol.Optional("show_advanced_options", default=False): cv.boolean,
},
extra=vol.ALLOW_EXTRA,
)
)
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
"""Handle a POST request.
handler in request is [entry_id, subentry_type].
"""
return await super()._post_impl(request, data)
def get_context(self, data: dict[str, Any]) -> dict[str, Any]:
"""Return context."""
context = super().get_context(data)
context["source"] = config_entries.SOURCE_USER
return context
class SubentryManagerFlowResourceView(
FlowManagerResourceView[config_entries.ConfigSubentryFlowManager]
):
"""View to interact with the subentry flow manager."""
url = "/api/config/config_entries/subentries/flow/{flow_id}"
name = "api:config:config_entries:subentries:flow:resource"
@require_admin(
error=Unauthorized(perm_category=CAT_CONFIG_ENTRIES, permission=POLICY_EDIT)
)
async def get(self, request: web.Request, /, flow_id: str) -> web.Response:
"""Get the current state of a data_entry_flow."""
return await super().get(request, flow_id)
@require_admin(
error=Unauthorized(perm_category=CAT_CONFIG_ENTRIES, permission=POLICY_EDIT)
)
async def post(self, request: web.Request, flow_id: str) -> web.Response:
"""Handle a POST request."""
return await super().post(request, flow_id)
@websocket_api.require_admin
@websocket_api.websocket_command({"type": "config_entries/flow/progress"})
def config_entries_progress(
@@ -655,62 +588,3 @@ async def _async_matching_config_entries_json_fragments(
)
or (filter_is_not_helper and entry.domain not in integrations)
]
@websocket_api.require_admin
@websocket_api.websocket_command(
{
"type": "config_entries/subentries/list",
"entry_id": str,
}
)
@websocket_api.async_response
async def config_subentry_list(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""List subentries of a config entry."""
entry = get_entry(hass, connection, msg["entry_id"], msg["id"])
if entry is None:
return
result = [
{
"subentry_id": subentry.subentry_id,
"title": subentry.title,
"unique_id": subentry.unique_id,
}
for subentry_id, subentry in entry.subentries.items()
]
connection.send_result(msg["id"], result)
@websocket_api.require_admin
@websocket_api.websocket_command(
{
"type": "config_entries/subentries/delete",
"entry_id": str,
"subentry_id": str,
}
)
@websocket_api.async_response
async def config_subentry_delete(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Delete a subentry of a config entry."""
entry = get_entry(hass, connection, msg["entry_id"], msg["id"])
if entry is None:
return
try:
hass.config_entries.async_remove_subentry(entry, msg["subentry_id"])
except config_entries.UnknownSubEntry:
connection.send_error(
msg["id"], websocket_api.const.ERR_NOT_FOUND, "Config subentry not found"
)
return
connection.send_result(msg["id"])
@@ -75,6 +75,7 @@ async def async_converse(
language: str | None = None,
agent_id: str | None = None,
device_id: str | None = None,
extra_system_prompt: str | None = None,
) -> ConversationResult:
"""Process text and get intent."""
agent = async_get_agent(hass, agent_id)
@@ -99,6 +100,7 @@ async def async_converse(
device_id=device_id,
language=language,
agent_id=agent_id,
extra_system_prompt=extra_system_prompt,
)
with async_conversation_trace() as trace:
trace.add_event(
@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/conversation",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["hassil==2.0.5", "home-assistant-intents==2024.12.9"]
"requirements": ["hassil==2.1.0", "home-assistant-intents==2025.1.1"]
}
@@ -40,6 +40,9 @@ class ConversationInput:
agent_id: str | None = None
"""Agent to use for processing."""
extra_system_prompt: str | None = None
"""Extra prompt to provide extra info to LLMs how to understand the command."""
def as_dict(self) -> dict[str, Any]:
"""Return input as a dict."""
return {
@@ -49,6 +52,7 @@ class ConversationInput:
"device_id": self.device_id,
"language": self.language,
"agent_id": self.agent_id,
"extra_system_prompt": self.extra_system_prompt,
}
@@ -2,7 +2,7 @@
from __future__ import annotations
from cookidoo_api import Cookidoo, CookidooConfig, CookidooLocalizationConfig
from cookidoo_api import Cookidoo, CookidooConfig, get_localization_options
from homeassistant.const import (
CONF_COUNTRY,
@@ -16,21 +16,23 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .coordinator import CookidooConfigEntry, CookidooDataUpdateCoordinator
PLATFORMS: list[Platform] = [Platform.TODO]
PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.TODO]
async def async_setup_entry(hass: HomeAssistant, entry: CookidooConfigEntry) -> bool:
"""Set up Cookidoo from a config entry."""
localizations = await get_localization_options(
country=entry.data[CONF_COUNTRY].lower(),
language=entry.data[CONF_LANGUAGE],
)
cookidoo = Cookidoo(
async_get_clientsession(hass),
CookidooConfig(
email=entry.data[CONF_EMAIL],
password=entry.data[CONF_PASSWORD],
localization=CookidooLocalizationConfig(
country_code=entry.data[CONF_COUNTRY].lower(),
language=entry.data[CONF_LANGUAGE],
),
localization=localizations[0],
),
)
@@ -0,0 +1,70 @@
"""Support for Cookidoo buttons."""
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from cookidoo_api import Cookidoo, CookidooException
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .coordinator import CookidooConfigEntry, CookidooDataUpdateCoordinator
from .entity import CookidooBaseEntity
PARALLEL_UPDATES = 0
@dataclass(frozen=True, kw_only=True)
class CookidooButtonEntityDescription(ButtonEntityDescription):
"""Describes cookidoo button entity."""
press_fn: Callable[[Cookidoo], Awaitable[None]]
TODO_CLEAR = CookidooButtonEntityDescription(
key="todo_clear",
translation_key="todo_clear",
press_fn=lambda client: client.clear_shopping_list(),
entity_registry_enabled_default=False,
)
async def async_setup_entry(
hass: HomeAssistant,
entry: CookidooConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Cookidoo button entities based on a config entry."""
coordinator = entry.runtime_data
async_add_entities([CookidooButton(coordinator, TODO_CLEAR)])
class CookidooButton(CookidooBaseEntity, ButtonEntity):
"""Defines an Cookidoo button."""
entity_description: CookidooButtonEntityDescription
def __init__(
self,
coordinator: CookidooDataUpdateCoordinator,
description: CookidooButtonEntityDescription,
) -> None:
"""Initialize cookidoo button."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.key}"
async def async_press(self) -> None:
"""Press the button."""
try:
await self.entity_description.press_fn(self.coordinator.cookidoo)
except CookidooException as e:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="button_clear_todo_failed",
) from e
await self.coordinator.async_refresh()
@@ -10,7 +10,6 @@ from cookidoo_api import (
Cookidoo,
CookidooAuthException,
CookidooConfig,
CookidooLocalizationConfig,
CookidooRequestException,
get_country_options,
get_localization_options,
@@ -219,18 +218,19 @@ class CookidooConfigFlow(ConfigFlow, domain=DOMAIN):
else:
data_input[CONF_LANGUAGE] = (
await get_localization_options(country=data_input[CONF_COUNTRY].lower())
)[0] # Pick any language to test login
)[0].language # Pick any language to test login
localizations = await get_localization_options(
country=data_input[CONF_COUNTRY].lower(),
language=data_input[CONF_LANGUAGE],
)
session = async_get_clientsession(self.hass)
cookidoo = Cookidoo(
session,
async_get_clientsession(self.hass),
CookidooConfig(
email=data_input[CONF_EMAIL],
password=data_input[CONF_PASSWORD],
localization=CookidooLocalizationConfig(
country_code=data_input[CONF_COUNTRY].lower(),
language=data_input[CONF_LANGUAGE],
),
localization=localizations[0],
),
)
try:
@@ -1,5 +1,10 @@
{
"entity": {
"button": {
"todo_clear": {
"default": "mdi:cart-off"
}
},
"todo": {
"ingredient_list": {
"default": "mdi:cart-plus"
@@ -6,6 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/cookidoo",
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["cookidoo_api"],
"quality_scale": "silver",
"requirements": ["cookidoo-api==0.10.0"]
"requirements": ["cookidoo-api==0.11.2"]
}
@@ -48,6 +48,11 @@
}
},
"entity": {
"button": {
"todo_clear": {
"name": "Clear shopping list and additional purchases"
}
},
"todo": {
"ingredient_list": {
"name": "Shopping list"
@@ -58,6 +63,9 @@
}
},
"exceptions": {
"button_clear_todo_failed": {
"message": "Failed to clear all items from the Cookidoo shopping list"
},
"todo_save_item_failed": {
"message": "Failed to save {name} to Cookidoo shopping list"
},
@@ -300,6 +300,10 @@ class CoverEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
def supported_features(self) -> CoverEntityFeature:
"""Flag supported features."""
if (features := self._attr_supported_features) is not None:
if type(features) is int: # noqa: E721
new_features = CoverEntityFeature(features)
self._report_deprecated_supported_features_values(new_features)
return new_features
return features
supported_features = (
@@ -2,6 +2,7 @@
from __future__ import annotations
from collections.abc import Sequence
import os
from serial.tools.list_ports_common import ListPortInfo
@@ -12,7 +13,7 @@ from .const import DONT_USE_USB, MANUAL_PATH, REFRESH_LIST
def list_ports_as_str(
serial_ports: list[ListPortInfo], no_usb_option: bool = True
serial_ports: Sequence[ListPortInfo], no_usb_option: bool = True
) -> list[str]:
"""Represent currently available serial ports as string.
+1 -1
View File
@@ -266,7 +266,7 @@ class DeconzBaseLight[_LightDeviceT: Group | Light](
@property
def color_temp_kelvin(self) -> int | None:
"""Return the CT color value."""
if self._device.color_temp is None:
if self._device.color_temp is None or self._device.color_temp == 0:
return None
return color_temperature_mired_to_kelvin(self._device.color_temp)
@@ -0,0 +1 @@
"""Virtual integration: Decorquip."""
@@ -0,0 +1,6 @@
{
"domain": "decorquip",
"name": "Decorquip Dream",
"integration_type": "virtual",
"supported_by": "motion_blinds"
}
@@ -50,7 +50,7 @@
"services": {
"get_command": {
"name": "Get command",
"description": "Send sa generic HTTP get command.",
"description": "Sends a generic HTTP get command.",
"fields": {
"command": {
"name": "Command",
@@ -81,14 +81,8 @@ class DevoloBinaryDeviceEntity(DevoloDeviceEntity, BinarySensorEntity):
or self._binary_sensor_property.sensor_type
)
if device_instance.binary_sensor_property[element_uid].sub_type != "":
self._attr_name = device_instance.binary_sensor_property[
element_uid
].sub_type.capitalize()
else:
self._attr_name = device_instance.binary_sensor_property[
element_uid
].sensor_type.capitalize()
if device_instance.binary_sensor_property[element_uid].sub_type == "overload":
self._attr_translation_key = "overload"
self._value = self._binary_sensor_property.state
@@ -129,7 +123,8 @@ class DevoloRemoteControl(DevoloDeviceEntity, BinarySensorEntity):
self._key = key
self._attr_is_on = False
self._attr_name = f"Button {key}"
self._attr_translation_key = "button"
self._attr_translation_placeholders = {"key": str(key)}
def _sync(self, message: tuple) -> None:
"""Update the binary sensor state."""
@@ -116,9 +116,11 @@ class DevoloGenericMultiLevelDeviceEntity(DevoloMultiLevelDeviceEntity):
self._multi_level_sensor_property.sensor_type
)
self._attr_native_unit_of_measurement = self._multi_level_sensor_property.unit
self._attr_name = self._multi_level_sensor_property.sensor_type.capitalize()
self._value = self._multi_level_sensor_property.value
if self._multi_level_sensor_property.sensor_type == "light":
self._attr_translation_key = "brightness"
if element_uid.startswith("devolo.VoltageMultiLevelSensor:"):
self._attr_entity_registry_enabled_default = False
@@ -128,7 +130,6 @@ class DevoloBatteryEntity(DevoloMultiLevelDeviceEntity):
_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_native_unit_of_measurement = PERCENTAGE
_attr_name = "Battery level"
_attr_device_class = SensorDeviceClass.BATTERY
_attr_state_class = SensorStateClass.MEASUREMENT
@@ -175,8 +176,6 @@ class DevoloConsumptionEntity(DevoloMultiLevelDeviceEntity):
device_instance.consumption_property[element_uid], consumption
)
self._attr_name = f"{consumption.capitalize()} consumption"
@property
def unique_id(self) -> str:
"""Return the unique ID of the entity.
@@ -30,5 +30,20 @@
}
}
}
},
"entity": {
"binary_sensor": {
"button": {
"name": "Button {key}"
},
"overload": {
"name": "Overload"
}
},
"sensor": {
"brightness": {
"name": "Brightness"
}
}
}
}
@@ -8,7 +8,7 @@
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
"iot_class": "local_push",
"loggers": ["async_upnp_client"],
"requirements": ["async-upnp-client==0.41.0", "getmac==0.9.4"],
"requirements": ["async-upnp-client==0.42.0", "getmac==0.9.4"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaRenderer:1",
@@ -7,7 +7,7 @@
"dependencies": ["ssdp"],
"documentation": "https://www.home-assistant.io/integrations/dlna_dms",
"iot_class": "local_polling",
"requirements": ["async-upnp-client==0.41.0"],
"requirements": ["async-upnp-client==0.42.0"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaServer:1",

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