Compare commits

...

1190 Commits

Author SHA1 Message Date
Paulus Schoutsen
17a5815ca1 Add AI Task prefs 2025-06-18 00:00:27 +00:00
Paulus Schoutsen
a8d4caab01 Remove GenTextTaskType 2025-06-17 12:54:49 -04:00
Paulus Schoutsen
2be6acec03 Add AI Task integration 2025-06-17 12:33:58 -04:00
Paulus Schoutsen
fa21269f0d Simplify ChatLog dependencies (#146351) 2025-06-15 17:41:15 -04:00
starkillerOG
5f5869ffc6 Bump reolink-aio to 0.14.1 (#146903) 2025-06-15 20:53:32 +02:00
Nathan Spencer
7a2d99a450 Bump pylitterbot to 2024.2.0 (#146901) 2025-06-15 20:41:07 +02:00
Andre Lengwenus
6b669ce40c Bump pypck to 0.8.8 (#146841) 2025-06-15 19:32:13 +02:00
Markus Adrario
fdf4ed2aa5 Homee add button_state to event entities (#146860)
* use entityDescription

* Add new event and adapt tests

* change translation

* use references in strings
2025-06-15 18:17:52 +02:00
Simone Chemelli
1361d10cd7 Bump aioamazondevices to 3.1.4 (#146883) 2025-06-15 08:30:19 -07:00
Marc Mueller
8c7ba11493 Fix telegram_bot RuntimeWarning in tests (#146781) 2025-06-15 11:23:17 +03:00
Marc Mueller
29ce17abf4 Update eq3btsmart to 2.1.0 (#146335)
* Update eq3btsmart to 2.1.0

* Update import names

* Update register callbacks

* Updated data model

* Update Thermostat set value methods

* Update Thermostat init

* Thermostat status and device_data are always given

* Minor compatibility fixes

---------

Co-authored-by: Lennard Beers <l.beers@outlook.de>
2025-06-15 10:17:01 +02:00
Markus Lanthaler
c988d1ce36 Add support for Gemini's new TTS capabilities (#145872)
* Add support for Gemini TTS

* Add tests

* Use wave library and update a few comments
2025-06-14 22:21:04 -07:00
Paulus Schoutsen
ec02f6d010 Extract Google LLM base entity class (#146817) 2025-06-14 22:17:52 -07:00
Simone Chemelli
9f19c4250a Bump aioamazondevices to 3.1.3 (#146828) 2025-06-15 01:45:28 +03:00
Marc Mueller
d7b583ae51 Update pydantic to 2.11.7 (#146835) 2025-06-14 23:31:09 +02:00
Maciej Bieniek
152e5254e2 Use Shelly main device area as suggested area for sub-devices (#146810) 2025-06-14 13:53:51 -04:00
starkillerOG
3f8f7cd578 Bump motion blinds to 0.6.28 (#146831) 2025-06-14 19:01:41 +02:00
Chris Talkington
ed3fb62ffc Update rokuecp to 0.19.5 (#146788) 2025-06-14 18:49:16 +02:00
J. Nick Koston
1d14e1f018 Bump aiohttp to 3.12.13 (#146830)
changelog: https://github.com/aio-libs/aiohttp/compare/v3.12.12...v3.12.13

Likely does not affect us at all but just in case, tagging
2025-06-14 17:13:20 +01:00
hahn-th
2ac8901a0d Improve code quality in async_setup_entry of switches in homematicip_cloud (#146816)
improve setup of switches
2025-06-14 17:26:08 +02:00
Joris Pelgröm
6204fd5363 Add polling to LetPot coordinator (#146823)
- Adds polling (update_interval) to the coordinator for the LetPot integration. Push remains the primary update mechanism for all entities, but:
   - Polling makes entities go unavailable when the device can't be reached, which otherwise won't happen.
   - Pump changes do not always trigger a status push by the device (not sure why), polling makes the integration catch up to reality.
2025-06-14 16:24:48 +02:00
Brett Adams
ce52ef64db Bump tesla-fleet-api to 1.1.3 (#146793) 2025-06-14 08:39:27 -05:00
Paulus Schoutsen
059c12798d Drop user prompt from LLMContext (#146787) 2025-06-13 22:01:39 -04:00
epenet
56aa809074 Simplify google_photos service actions (#146744) 2025-06-13 18:57:11 -07:00
Marc Mueller
3d2dca5f0c Adjust scripts for compatibility with Python 3.14 (#146774) 2025-06-13 21:54:25 -04:00
starkillerOG
cdb2b407be Add Reolink baby cry sensitivity (#146773)
* Add baby cry sensitivity

* Adjust tests
2025-06-14 00:11:13 +01:00
Ian
186ed451a9 Bump nextbus client to 2.3.0 (#146780) 2025-06-14 00:09:29 +01:00
hahn-th
761a0877e6 Fix throttling issue in HomematicIP Cloud (#146683)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-06-13 19:57:03 +02:00
J. Nick Koston
91bc56b15c Bump aiodns to 3.5.0 (#146758) 2025-06-13 19:12:52 +02:00
Paulus Schoutsen
d1e2c62433 Remove unnecessary string formatting. (#146762) 2025-06-13 10:10:47 -07:00
Duco Sebel
524c16fbe1 Bumb python-homewizard-energy to 9.1.1 (#146723)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-06-13 18:59:28 +02:00
Marc Mueller
2fdd3d66bc Update pydantic to 2.11.6 (#146745) 2025-06-13 18:53:05 +02:00
Simone Chemelli
6a1e3b60ee Filter speak notify entity for WHA devices in Alexa Devices (#146688) 2025-06-13 18:49:18 +02:00
DeerMaximum
434cd95a66 Use ConfigEntry.runtime_data to store runtime data in NINA (#146754)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-06-13 18:47:21 +02:00
Vasilis Valatsos
1a5bc2c7e0 Drop HostKeyAlgorithms in aruba (#146619) 2025-06-13 18:47:07 +02:00
epenet
a66e9a1a2c Simplify reolink service actions (#146751) 2025-06-13 18:08:59 +02:00
Paulus Schoutsen
d880ce6bb4 Clean up Google conversation entity (#146736) 2025-06-13 10:30:14 -04:00
Paulus Schoutsen
c96023dcae Clean up Anthropic conversation entity (#146737) 2025-06-13 10:29:26 -04:00
Paulus Schoutsen
2f8ad4d5bf Clean up Ollama conversation entity (#146738) 2025-06-13 10:29:19 -04:00
Marc Mueller
038a848d53 Fix androidtv isfile patcher in tests (#146696) 2025-06-13 16:25:09 +02:00
epenet
ff17d79e73 Bump wakeonlan to 3.1.0 (#146655)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-06-13 08:58:44 -05:00
tronikos
a8201009f3 Fix opower to work with aiohttp>=3.12.7 by disabling cookie quoting (#146697)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-06-13 08:58:27 -05:00
Simone Chemelli
a349653282 Bump aioamazondevices to 3.1.2 (#146690) 2025-06-13 16:53:18 +03:00
epenet
355ee1178e Add callback decorator to async_setup_services (#146729) 2025-06-13 15:16:55 +02:00
Marc Mueller
30c5df3eaa Adjust core create_task tests with event_loop patch (#146699) 2025-06-13 15:16:28 +02:00
Marc Mueller
10874af19a Ignore lingering pycares shutdown thread (#146733) 2025-06-13 15:09:37 +02:00
Marc Mueller
704118b3d0 Remove unnecessary patch from toon tests (#146691) 2025-06-13 12:53:33 +02:00
Marc Mueller
7c575d0316 Fix asuswrt test patch (#146692) 2025-06-13 12:52:56 +02:00
starkillerOG
ab3f11bfe7 Add Reolink IR brightness entity (#146717) 2025-06-13 12:50:12 +02:00
Allen Porter
f0357539ad Add myself as a remote calendar code owner (#146703) 2025-06-13 12:48:24 +02:00
Allen Porter
e70a2dd257 Partial revert of update to remote calendar to fix issue where calendar does not update (#146702)
Partial revert
2025-06-13 12:47:56 +02:00
Allen Porter
5ef99a15a5 Revert scan interval change in local calendar (#146700) 2025-06-13 12:46:01 +02:00
Marc Mueller
6421973cd6 Remove unnecessary patch from panel_custom tests (#146695) 2025-06-13 10:46:26 +02:00
Marc Mueller
7201171eb5 Replace unnecessary pydantic import in matrix tests (#146693) 2025-06-13 10:45:54 +02:00
Abílio Costa
1fb438fa6c Add missing mock value to Reolink test (#146689) 2025-06-13 07:43:21 +02:00
starkillerOG
89ae68c5af Reolink check if camera and motion supported (#146666) 2025-06-12 22:19:46 +01:00
Paul Bottein
c78b66d5d5 Update frontend to 20250531.3 (#146638) 2025-06-12 16:52:09 -04:00
starkillerOG
d756cf91ce Add model_id to Reolink IPC camera (#146664) 2025-06-12 20:41:13 +01:00
Simon Lamon
8d13bf93ab Bump linkplay to v0.2.12 (#146669) 2025-06-12 20:38:42 +01:00
Franck Nijhof
e86e793842 Tweak non-English issue detection (#146636) 2025-06-12 13:38:20 -04:00
Tsvi Mostovicz
7e6bb021ce Bump hdate to 1.1.2 (#146659) 2025-06-12 18:29:47 +01:00
starkillerOG
680b70aa29 Reolink add diagnostics for baichuan (#146667)
* Add baichuan diagnostics

* adjust tests
2025-06-12 19:26:37 +02:00
Andre Lengwenus
8eebebc586 Bump pypck to 0.8.7 (#146657) 2025-06-12 17:36:50 +01:00
epenet
48e4624ba0 Add basic xiaomi_miio fan tests (#146593) 2025-06-12 17:33:45 +01:00
epenet
b0cf974b34 Simplify swiss public transport service actions (#146611) 2025-06-12 16:27:20 +02:00
Simone Chemelli
171f7c5f81 Fix cookies with aiohttp >= 3.12.7 for Vodafone Station (#146647) 2025-06-12 16:24:10 +02:00
Avi Miller
8807c530a9 Fix palette handling for LIFX Ceiling SKY effect (#146582)
Signed-off-by: Avi Miller <me@dje.li>
2025-06-12 14:32:04 +02:00
dependabot[bot]
28bd90aeb0 Bump actions/attest-build-provenance from 2.3.0 to 2.4.0 (#146594)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 14:18:04 +02:00
dependabot[bot]
af1eccabce Bump github/codeql-action from 3.28.19 to 3.29.0 (#146595)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 14:17:36 +02:00
Pete Sage
afc0a2789d Update Sonos to use SonosConfigEntry and runtime data (#145512)
* fix: initial

* fix: cleanup

* fix: cleanup

* fix: cleanup

* fix: SonosConfigEntry

* add config_entry.py

* fix: sonos_data to runtime_data

* fix: move to helpers.py
2025-06-12 14:05:51 +02:00
epenet
78ed1097c4 Simplify netgear_lte service actions (#146606) 2025-06-12 14:02:17 +02:00
epenet
2991726d35 Simplify screenlogic service actions (#146609) 2025-06-12 14:02:06 +02:00
epenet
c34596e54d Simplify seventeentrack service actions (#146610)
* Simplify seventeentrack service actions

* callback
2025-06-12 14:01:53 +02:00
epenet
74a92e2cd8 Simplify tado service actions (#146614) 2025-06-12 14:01:45 +02:00
Franck Nijhof
e19f178864 Make duplicate issue detection more strict (#146633) 2025-06-12 13:55:26 +02:00
epenet
9dfbccf0cb Improve type hints in xiaomi_miio fan (#146596) 2025-06-12 12:18:46 +02:00
epenet
64e503bc27 Fix fan is_on status in xiaomi_miio (#146592) 2025-06-12 12:18:23 +02:00
epenet
9d1e60cf7e Simplify mealie service actions (#146601) 2025-06-12 12:17:27 +02:00
epenet
4160521349 Simplify overseerr service actions (#146607) 2025-06-12 12:17:00 +02:00
epenet
14c30ef2df Mark async_setup_services as callback (#146617) 2025-06-12 11:34:56 +02:00
epenet
e14cf8a5b9 Remove deprecated service in plex (#146608)
* Remove deprecated service in plex

* Update json/yaml
2025-06-12 10:43:03 +02:00
epenet
30dbd5a900 Simplify synology_dsm service actions (#146612) 2025-06-12 10:42:40 +02:00
G Johansson
25e6eab008 Not valid hvac modes now fails in Climate (#145242)
* Not valid hvac modes now fails

* Fix some tests

* Some more

* More

* fix ruff

* HVAC

* Fritzbox

* Clean up

* Use dict[key]

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-12 07:15:07 +02:00
Thomas55555
8bf562b7b6 Add strings for pick implementation (#146557)
* Add string for pick implementation

* add missing
2025-06-12 06:02:26 +02:00
rappenze
7cb3c397b2 Support more dimmer devices in fibaro (#145864) 2025-06-11 23:55:38 +02:00
Christopher Boyd
f44f2522ef Add 'AdvancedToggle' to list of supported Lutron button types (#145676) 2025-06-11 23:54:22 +02:00
Denis Shulyaka
8c9acf5a4d Separate steps for openai_conversation options flow (#141533) 2025-06-11 23:54:01 +02:00
starkillerOG
e46e7f5a81 Bump reolink-aio to 0.14.0 (#146566) 2025-06-11 23:52:31 +02:00
Calvin C
c01f521199 Bump hyperion-py to 0.7.6 and add switch for Audio Capture to Hyperion Integration (#145952)
Co-authored-by: ToniCipriani <ToniCipriani@users.noreply.github.com>
Co-authored-by: Robert Resch <robert@resch.dev>
2025-06-11 21:20:22 +02:00
Robert Resch
4a15f12a0b Add aiofiles to pyproject.toml (#146561) 2025-06-11 20:32:38 +02:00
Ståle Storø Hauknes
8d24d775f1 Set suggested precision for Airthings sensors (#145966) 2025-06-11 20:04:03 +02:00
epenet
aca0e69081 Simplify service registration in recorder (#146237) 2025-06-11 20:01:13 +02:00
G Johansson
f4e5036275 New helper for templating args in command_line (#145899) 2025-06-11 19:58:28 +02:00
rappenze
59aba339d8 Add support for more cover devices in Fibaro (#146486) 2025-06-11 19:56:38 +02:00
Joost Lekkerkerker
864e440685 Make issue creation check architecture instead of uname (#146537) 2025-06-11 18:39:46 +02:00
tronikos
2f6fcb5801 Rename Amazon Devices to Alexa Devices (#146362)
Co-authored-by: Simone Chemelli <simone.chemelli@gmail.com>
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-06-11 18:35:26 +02:00
G Johansson
bdb6124aa3 Remove previously deprecated cached_property (#146478)
Co-authored-by: Robert Resch <robert@resch.dev>
2025-06-11 18:22:11 +02:00
epenet
613e2fd4b3 Simplify google_mail service actions (#146511) 2025-06-11 18:19:57 +02:00
Kevin Stillhammer
0e71ef3861 Fix stale options in here_travel_time (#145911) 2025-06-11 18:17:11 +02:00
andreimoraru
5076c10959 Bump yt-dlp to 2025.06.09 (#146553)
* Bumped yt-dlp to 2025.06.09

* fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-06-11 17:53:25 +02:00
Shay Levy
ab2fc4e9a6 Remove stale Shelly BLU TRV devices (#145994)
* Remove stale Shelly BLU TRV devices

* Add test

* Remove config entry from device
2025-06-11 17:39:49 +02:00
Erik Montnemery
e39edcc234 Remove unused attribute EntityInfo.custom_component (#146550) 2025-06-11 17:27:17 +02:00
Paul Bottein
54c8e59bcd Update frontend to 20250531.2 (#146551) 2025-06-11 17:12:34 +02:00
Franck Nijhof
c806555879 Add non-English issue detection using GitHub AI models (#146547) 2025-06-11 16:52:35 +02:00
G Johansson
4836930cb1 Remove previously deprecated StrEnum backport (#146477) 2025-06-11 16:41:40 +02:00
epenet
4a8faad62e Simplify fully_kiosk service actions (#146509) 2025-06-11 16:34:48 +02:00
peteS-UK
ba69301dda Move available property to entity.py for Squeezebox (#146531) 2025-06-11 16:34:08 +02:00
Aidan Timson
724c349194 Add guide for Honeywell Lyric application credentials setup (#146281)
* Add guide for Honeywell Lyric application credentials setup

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-06-11 16:24:37 +02:00
epenet
9346f8d658 Simplify blink service actions (#146508) 2025-06-11 16:21:42 +02:00
hanwg
0af41d9cb1 Bug fix for Telegram bot integration: Handle plain text parse_mode (#146535) 2025-06-11 16:19:22 +02:00
Marc Mueller
b02c0419b4 Update types packages (#146546) 2025-06-11 16:15:54 +02:00
Marc Mueller
0bc6408137 Update pytest-unordered to 0.7.0 (#146545) 2025-06-11 15:01:27 +01:00
Tsvi Mostovicz
3f1d2b1b71 Bump hdate to 1.1.1 (#146536) 2025-06-11 15:46:52 +02:00
Paul Bottein
bcfdee23e3 Update frontend to 20250531.1 (#146542) 2025-06-11 15:46:19 +02:00
Franck Nijhof
4a50f4ffc1 Add duplicate issue detection using GitHub AI models (#146487) 2025-06-11 15:42:37 +02:00
Petar Petrov
9ee45518e9 Remove the Delete button on the ZwaveJS device page (#146544) 2025-06-11 15:39:02 +02:00
Erik Montnemery
09a5ac5979 Handle changes to source entities in generic_thermostat helper (#146541) 2025-06-11 15:26:52 +02:00
Erik Montnemery
296b5c627a Handle changes to source entities in generic_hygrostat helper (#146538) 2025-06-11 15:18:04 +02:00
Erik Montnemery
120338d510 Handle changes to source entity in utility_meter (#146526) 2025-06-11 15:17:52 +02:00
Erik Montnemery
9b4ab60adb Handle changes to source entity in trend helper (#146525) 2025-06-11 15:17:42 +02:00
Erik Montnemery
51b0642789 Handle changes to source entity in threshold helper (#146524) 2025-06-11 15:17:34 +02:00
Erik Montnemery
cb9c213496 Handle changes to source entity in statistics helper (#146523) 2025-06-11 15:17:19 +02:00
Erik Montnemery
cb42d99c28 Handle changes to source entity in integration helper (#146522) 2025-06-11 15:17:08 +02:00
Erik Montnemery
cf5cdf3cdb Handle changes to source entity in history_stats helper (#146521) 2025-06-11 15:16:51 +02:00
epenet
acf31f609a Adjust urllib3 constraint (#145485)
* Remove urllib3 upper bound constraint

* Disable neato

* Disable neato tests

* Simplify test ignore

* Add to PACKAGE_CHECK_VERSION_RANGE

* Adjust

* Adjust

* Force 2.0
2025-06-11 15:11:58 +02:00
Simon Lamon
42377ff7ac Bump linkplay to v0.2.11 (#146530) 2025-06-11 15:10:00 +02:00
Petro31
3e0aab55a8 Fix delay_on and delay_off restarting when a new trigger occurs during the delay (#145050) 2025-06-11 14:08:10 +01:00
Erik Montnemery
0362012bb3 Correct misleading comment for const.ATTR_RESTORED (#146528) 2025-06-11 13:29:16 +02:00
Jesse Hills
ba5d0f2723 Fix solax state class of Today's Generated Energy (#146492) 2025-06-11 12:46:40 +02:00
Erik Montnemery
167e688139 Allow removing entity registry items twice (#146519) 2025-06-11 12:42:09 +02:00
Martin Hjelmare
c49d95b230 Remove Z-Wave useless reconfigure options (#146520)
* Remove emulate hardware option

* Remove log level option
2025-06-11 13:31:07 +03:00
Erik Montnemery
c4c8f88765 Simplify helper_integration.async_handle_source_entity_changes (#146516) 2025-06-11 12:27:51 +02:00
epenet
f908e0cf4d Bump pybotvac to 0.0.28 (#146513) 2025-06-11 12:19:54 +02:00
epenet
29c720a66d Bump weheat to 2025.6.10 (#146515) 2025-06-11 12:19:06 +02:00
epenet
4e628dbd9f Bump sensorpush-api to 2.1.3 (#146514) 2025-06-11 12:18:55 +02:00
Petro31
37d904dfdc Add color_temp_kelvin to set_temperature action variables (#146448) 2025-06-11 11:58:07 +02:00
Åke Strandberg
a53997dfc7 Graceful handling of missing datapoint in myuplink (#146517) 2025-06-11 11:55:28 +02:00
Joost Lekkerkerker
dd216ac15b Split deprecated system issue in 2 places (#146453) 2025-06-11 11:35:14 +02:00
Erik Montnemery
2afdec4711 Do not remove derivative config entry when input sensor is removed (#146506)
* Do not remove derivative config entry when input sensor is removed

* Add comments

* Update homeassistant/helpers/helper_integration.py

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

---------

Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-11 11:19:44 +02:00
karwosts
5b4c309170 Create a deprecation/repair for sensor.sun_solar_rising (#146462)
* Create a deprecation/repair for `sensor.sun_solar_rising`

* test

* Update homeassistant/components/sun/strings.json
2025-06-11 11:02:14 +02:00
hanwg
8deec55204 Add service validation for send file for Telegram bot integration (#146192)
* added service validation for send file

* update strings

* Apply suggestions from code review

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

* updated exception in tests

* removed TypeError since it is not thrown

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-11 10:59:08 +02:00
Robert Resch
f0a2c4e30a Bump deebot-client to 13.3.0 (#146507) 2025-06-11 10:49:38 +02:00
Joost Lekkerkerker
e9a71a8d7f Explain Nest setup (#146217) 2025-06-11 10:31:08 +02:00
Felix Schneider
1462366764 Bump apsystems to 2.7.0 (#146485) 2025-06-11 10:26:01 +02:00
Artur Pragacz
33528eb6bd Update pywizlight to 0.6.3 (#146490) 2025-06-11 08:26:55 +02:00
epenet
776a014ab0 Drop deprecated add_event service in google (#146432) 2025-06-10 20:35:17 -07:00
Michael Hansen
ea202eff66 Bump intents to 2025.6.10 (#146491) 2025-06-10 18:16:18 -05:00
Tsvi Mostovicz
b7404f5a05 Fix Jewish calendar not updating (#146465) 2025-06-10 21:25:47 +02:00
Joost Lekkerkerker
d015dff855 Remove DHCP discovery from Amazon Devices (#146476) 2025-06-10 20:55:00 +02:00
Joost Lekkerkerker
2f1977fa0c Fix typo in hassio (#146474) 2025-06-10 20:52:43 +02:00
Erik Montnemery
26fe23eb5c Improve support for trigger platforms with multiple triggers (#144827)
* Improve support for trigger platforms with multiple triggers

* Adjust zwave_js

* Refactor the Trigger class

* Silence mypy

* Adjust

* Revert "Adjust"

This reverts commit 17b3d16a267d54c082b12f07550faa8ac4ac3a49.

* Revert "Silence mypy"

This reverts commit c2a011b16f9b02880fc3dc673b5b12501f7995fc.

* Reapply "Adjust"

This reverts commit c64ba202dd.

* Apply suggestions from code review

* Revert "Apply suggestions from code review"

This reverts commit 0314955c5a.
2025-06-10 20:48:51 +02:00
hahn-th
dbfecf99dc Bump homematicip to 2.0.4 (#144096)
* Bump to 2.0.2 with all necessary changes

* bump to prerelease

* add addiional tests

* Bump to homematicip 2.0.3

* do not delete device

* Setup BRAND_SWITCH_MEASURING as light

* bump to 2.0.4

* refactor test_remove_obsolete_entities

* move test

* use const from homematicip lib
2025-06-10 20:44:06 +02:00
hanwg
4d28992f2b Add Telegram bot webhooks tests (#146436)
* add tests for webhooks

* added asserts
2025-06-10 19:58:15 +02:00
Markus Adrario
7a428a66bd Add support for HeatIt Thermostat TF056 to homee (#145515)
* adapt climate for Heatit TF 056

* add sensors & numbers for Heatit TF056

* Add select for Heatit TF056

* Adapt climat tests for changes

* Fix sentence case

* fix review comments

* Update homeassistant/components/homee/climate.py

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

* fix tests

* update diagnostics snapshot for this change

---------

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-06-10 19:41:13 +02:00
G Johansson
481bf2694b Fix incorrect categories handling in holiday (#146470) 2025-06-10 19:28:48 +02:00
Simone Chemelli
5cc9cc3c99 Fix EntityCategory for binary_sensor platform in Amazon Devices (#146472)
* Fix EntityCategory for  binary_sensor platform in Amazon Devices

* update snapshots
2025-06-10 19:28:37 +02:00
Whitney Young
87ce683b39 Add tests for initial state of OpenUV sensors (#146464)
This is a followup to #146408 to add test coverage.
2025-06-10 19:28:29 +02:00
Simone Chemelli
936d56f9af Avoid closing shared aiohttp session in Vodafone Station (#146471) 2025-06-10 19:18:19 +02:00
starkillerOG
d71ddcf69e Reolink conserve battery (#145452) 2025-06-10 18:05:55 +02:00
Robert Resch
3af2746fea Update wording deprecated system package integration repair (#146450)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-10 18:04:22 +02:00
Joost Lekkerkerker
5b6d7142fb Bump pySmartThings to 3.2.4 (#146459) 2025-06-10 17:37:21 +02:00
Whitney Young
7aa9301038 Fix initial state of UV protection window (#146408)
The `binary_sensor` is created when the config entry is loaded after the
`async_config_entry_first_refresh` has completed (during the forward of
setup to platforms). Therefore, the update coordinator will already have
data and will not trigger the invocation of
`_handle_coordinator_update`.

Fixing this just means performing the same update at initialization.
2025-06-10 17:35:40 +02:00
hanwg
627831dfaf Fix Telegram bot leave_chat service action (#146139)
* bug fix for leave chat

* update strings
2025-06-10 17:33:54 +02:00
Joost Lekkerkerker
db8a6f8583 Catch exception before retrying in AirGradient (#146460) 2025-06-10 17:31:30 +02:00
Paulus Schoutsen
014010acbd Assist Pipeline: Intent progress event when we start streaming (#146388)
Intent progress event when we start streaming
2025-06-10 09:55:43 -05:00
Arie Catsman
9b90ed04e5 fix possible mac collision in enphase_envoy (#145549)
* fix possible mac collision in enphase_envoy

* remove redundant device registry async_get
2025-06-10 16:25:26 +02:00
hanwg
0f27d0bf4a Bug fix for Telegram bot integration: fix async_unload_entry error for polling bot (#146277)
* removed reload from update_listener

* removed reload from update_listener
2025-06-10 16:24:51 +02:00
Andrea Turri
1fa55f96f8 Add evaporate water program id for Miele oven (#145996) 2025-06-10 16:23:55 +02:00
Jamin
2d60115ec6 Check hangup error in voip (#146423)
Check hangup error

Prevent an error where the call end future may have already been set
when a hangup is detected.
2025-06-10 16:22:53 +02:00
Luca Schröder
3b81480091 Update caldav to 1.6.0 (#146456)
Fixes #140798
2025-06-10 16:20:35 +02:00
Will Schlitzer
255acfa8c0 Fix typo in overseerr component docstring (#146457)
Change 'airgradient' to 'overseerr' in sensor.py
2025-06-10 16:15:40 +02:00
Marc Mueller
4617cc4e0a Update awesomeversion to 25.5.0 (#146032) 2025-06-10 15:44:53 +02:00
tronikos
b9e8cfb291 Handle grpc errors in Google Assistant SDK (#146438) 2025-06-10 15:31:32 +02:00
J. Nick Koston
7da1671b06 Shift ESPHome log parsing to the library (#146349) 2025-06-10 15:30:19 +02:00
Marc Mueller
6c5f7eabff Fix RuntimeWarning in rest tests (#146452) 2025-06-10 15:26:07 +02:00
Ian
f448f488ba Throttle Nextbus if we are reaching the rate limit (#146064)
Co-authored-by: Josef Zweck <josef@zweck.dev>
Co-authored-by: Robert Resch <robert@resch.dev>
2025-06-10 15:03:20 +02:00
Marc Mueller
20b5d5a755 Add requests to hassfest requirements check (#146446) 2025-06-10 15:01:05 +02:00
Marc Mueller
bb38a3a8ac Update requests to 2.32.4 (#146445) 2025-06-10 15:00:41 +02:00
Brett Adams
d0d1fb2da7 Prevent energy history returning zero in Teslemetry (#146202) 2025-06-10 15:00:02 +02:00
Marc Mueller
d82be09ed4 Update aiomealie to 0.9.6 (#146447) 2025-06-10 14:53:56 +02:00
Joost Lekkerkerker
110627e16e Return expected state in SmartThings water heater (#146449) 2025-06-10 14:52:24 +02:00
Klaas Schoute
b77ef7304a Change interval for Powerfox integration (#146348) 2025-06-10 14:38:52 +02:00
Erik Montnemery
16a0b7f44e Handle changes to source entity in derivative helper (#146407)
* Handle changes to source entity in derivative helper

* Rename helper function, improve docstring

* Add tests

* Improve derivative tests

* Deduplicate tests

* Rename helpers/helper_entity.py to helpers/helper_integration.py

* Rename tests
2025-06-10 14:31:18 +02:00
Joost Lekkerkerker
4fdbb9c0e2 Remove __all__ from switch_as_x (#146331)
* Remove `__all__` from switch_as_x

* Update homeassistant/components/switch_as_x/__init__.py
2025-06-10 14:21:01 +02:00
J. Diego Rodríguez Royo
c32a988838 Improvements for Home Connect application credentials string (#146443) 2025-06-10 14:11:07 +02:00
Jan-Philipp Benecke
927c9d3480 Improve error logging in trend binary sensor (#146358) 2025-06-10 14:10:49 +02:00
Joost Lekkerkerker
bf776d33b2 Explain Withings setup (#146216) 2025-06-10 14:10:35 +02:00
epenet
279539265b Use async_load_fixture in modern_forms tests (#146011) 2025-06-10 12:38:25 +02:00
J. Diego Rodríguez Royo
4acad77437 Fix typo at application credentials string at Home Connect integration (#146442)
Fix typos
2025-06-10 11:56:24 +02:00
J. Nick Koston
0c5b7401b9 Use entity unique id for ESPHome media player formats (#146318) 2025-06-10 11:48:11 +02:00
Erik Montnemery
ce739fd9b6 Restore entity ID and user customizations of deleted entities (#145278)
* Restore entity ID and user customizations of deleted entities

* Clear removed areas, categories and labels from deleted entities

* Correct test

* Fix logic for disabled_by and hidden_by

* Improve test coverage

* Fix sorting

* Always restore disabled_by and hidden_by

* Update mqtt test

* Update pglab tests
2025-06-10 11:47:54 +02:00
Erik Montnemery
11d9014be0 Restore user customizations of deleted devices (#145191)
* Restore user customizations of deleted devices

* Apply suggestions from code review

* Improve test coverage

* Always restore disabled_by
2025-06-10 11:47:39 +02:00
J. Nick Koston
c9dcb1c11b Bump propcache to 0.3.2 (#146418) 2025-06-10 11:44:34 +02:00
J. Diego Rodríguez Royo
ef7f32a28d Explain Home Connect setup (#146356)
* Explain Home Connect setup

* Avoid using "we"

* Fix login spelling

* Fix signup spelling
2025-06-10 11:41:36 +02:00
J. Nick Koston
4f5cf5797f Bump yarl to 1.20.1 (#146424) 2025-06-10 11:26:29 +02:00
Retha Runolfsson
4c5485ad04 Bump pyswitchbot to 0.66.0 (#146430)
bump pyswitchbot to 0.66.0
2025-06-10 11:16:08 +02:00
Franck Nijhof
5ad96dedfa Reformat Dockerfile to reduce merge conflicts (#146435) 2025-06-10 11:14:31 +02:00
epenet
0c18fe35e5 Migrate cloudflare to use runtime data (#146429) 2025-06-10 09:50:31 +02:00
epenet
6a23ad96ca Move google assistant sdk services to separate module (#146434) 2025-06-10 00:49:56 -07:00
J. Nick Koston
def0384608 Bump aiohttp to 3.12.12 (#146426) 2025-06-10 09:39:53 +02:00
Raphael Hehl
a4d12694da Bump uiprotect to 7.13.0 (#146410) 2025-06-09 19:26:54 -05:00
J. Nick Koston
2278e3f06f Bump aioesphomeapi to 32.2.1 (#146375) 2025-06-09 19:25:29 -05:00
Will Schlitzer
0144a0bb1f Fix minor docstring typos in jellyfin component media_source.py (#146398) 2025-06-09 20:12:32 +02:00
Imeon-Energy
7cc8f91bf9 Basic entity class for Imeon inverter integration (#145778)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: TheBushBoy <theodavid@icloud.com>
2025-06-09 20:04:25 +02:00
hanwg
d58157ca9e Bug fix for Telegram bot integration: handle last message id (#146378) 2025-06-09 20:01:16 +02:00
David Knowles
f401ffb08c Bump pydrawise to 2025.6.0 (#146369) 2025-06-09 20:00:37 +02:00
Simone Chemelli
8f7b831b94 Bump aioamazondevices to 3.0.6 (#146385) 2025-06-09 19:59:02 +02:00
wittypluck
9ed6b591a5 Fix CO concentration unit in OpenWeatherMap (#146403) 2025-06-09 19:55:09 +02:00
Michael Davie
98ea067285 Bump env-canada to v0.11.2 (#146371) 2025-06-09 12:53:44 -05:00
G Johansson
7e507dd378 Bump pynordpool to 0.3.0 (#146396) 2025-06-09 19:51:46 +02:00
Erik Montnemery
8e87223c40 Update switch_as_x to handle wrapped switch moved to another device (#146387)
* Update switch_as_x to handle wrapped switch moved to another device

* Reload switch_as_x config entry after updating device

* Make sure the switch_as_x entity is not removed
2025-06-09 17:04:55 +02:00
Abílio Costa
0cce4d1b81 Test all device classes in Sensor device condition/trigger tests (#146366) 2025-06-09 14:22:58 +01:00
Erik Montnemery
46dcc91510 Fix switch_as_x entity_id tracking (#146386) 2025-06-09 13:24:40 +02:00
Markus Adrario
b1a2af9fd3 Add Homee diagnostics platform (#146340)
* Initial dignostics implementation

* Add diagnostics tests

* change data-set for device diagnostics

* adapt for upcoming pyHomee release

* other solution

* fix review and more
2025-06-09 13:24:07 +02:00
Michael Arthur
5d58cdd98e DNSIP: Add literal to querytype (#146367) 2025-06-09 09:36:17 +02:00
Simon Lamon
a8aebbce9a Bump python-linkplay to v0.2.10 (#146359) 2025-06-08 16:43:20 -05:00
tronikos
f1244c182a Allow different manufacturer than Amazon in Amazon Devices (#146333) 2025-06-08 11:47:46 -07:00
Simon Lamon
560eeac457 Do not probe linkplay device if another config entry already contains the host (#146305)
* Do not probe if config entry already contains the host

* Add unit test

* Use common fixture
2025-06-08 19:47:00 +02:00
J. Nick Koston
d33080d79e Bump aioesphomeapi to 32.2.0 (#146344) 2025-06-08 11:15:00 -05:00
Michael
25f02c5b38 Bump py-synologydsm-api to 2.7.3 (#146338)
bump py-synologydsm-api to 2.7.3
2025-06-08 17:02:06 +01:00
Raphael Hehl
cb01af9f92 Bump uiprotect to 7.12.0 (#146337) 2025-06-08 10:57:50 -05:00
Sanjay Govind
9a6ebb0848 Fix bosch alarm areas not correctly subscribing to alarms (#146322)
* Fix bosch alarm areas not correctly subscribing to alarms

* add test
2025-06-08 14:35:54 +02:00
Pete Sage
fd30dd0aee Add tests for sonos switch alarms on and off (#146314)
* fix: add tests for switch on/off

* fix: simplify

* fix: simplify

* fix: comment

* fix: comment
2025-06-08 11:45:20 +02:00
tronikos
4a5e261709 Fix typo in Utility Meter always_available (#146320) 2025-06-08 10:53:48 +03:00
Marc Mueller
2842f55460 Add additional package version range checks (#146299)
* Add additional package version range checks

* Add exception for scipy
2025-06-08 00:06:20 +02:00
J. Nick Koston
7573a74cb0 Migrate rest to use aiohttp (#146306) 2025-06-07 13:44:25 -05:00
J. Nick Koston
636b484d9d Migrate onvif to use onvif-zeep-async 4.0.1 with aiohttp (#146297) 2025-06-07 13:39:59 -05:00
G Johansson
a979f884f9 Bump holidays to 0.74 (#146290) 2025-06-07 20:18:24 +03:00
J. Nick Koston
990ea78dec Bump aiohttp to 3.12.11 (#146298) 2025-06-07 12:08:32 -05:00
Marc Mueller
ee6db3bd23 Update numpy to 2.3.0 (#146296) 2025-06-07 18:43:18 +02:00
Arie Catsman
ae5606aa2f Migrate Enphase envoy from httpx to aiohttp (#146283)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-06-07 10:52:54 -05:00
Marc Mueller
7f9f106729 Update airtouch5py to 0.3.0 (#146278) 2025-06-07 16:58:53 +02:00
J. Nick Koston
44c63ce6f1 Bump aiohttp-fast-zlib to 0.3.0 (#146285)
changelog: https://github.com/Bluetooth-Devices/aiohttp-fast-zlib/compare/v0.2.3...v0.3.0

proper aiohttp 3.12 support
2025-06-07 17:30:43 +03:00
hanwg
cbf7ca6a9a Add bronze quality scale for Telegram bot integration (#146148)
* added quality scale

* updated appropriate-polling comment

* Remove entities comment

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-07 14:47:48 +02:00
Brett Adams
eb892df65a Change default range sensors in Teslemetry (#146268) 2025-06-07 10:51:57 +02:00
Brett Adams
24b5886d88 Add missing write state to Teslemetry (#146267) 2025-06-07 04:43:16 +02:00
Willem-Jan van Rootselaar
d5e902a170 Update python-bsblan requirement to version 2.1.0 (#146253) 2025-06-06 22:47:44 +03:00
hanwg
d907e4c10b Handle error in setup_entry for Telegram Bot (#146242)
* handle error in setup_entry

* Update homeassistant/components/telegram_bot/__init__.py

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>

---------

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-06-06 15:00:48 +01:00
Robin Lintermann
c4be3c4de2 Smarla integration number platform (#145747)
Add number platform to smarla integration
2025-06-06 12:13:06 +02:00
Retha Runolfsson
626591f832 Fix unit test for switchbot integration (#146247)
fix unit test
2025-06-06 12:06:01 +02:00
epenet
2bd3196183 Move abode services to separate module (#146142)
* Move abode services to separate module

* Rename

* Adjust test imports
2025-06-06 10:20:57 +02:00
epenet
fd93cf375d Tweak zwave_js service registration (#146244) 2025-06-06 09:41:51 +02:00
epenet
6bf8b84d26 Rename service registration method (#146236) 2025-06-06 08:08:06 +02:00
Michael
c72fea57a1 Bump aioimmich to 0.9.1 (#146222)
bump aioimmich to 0.9.1
2025-06-05 21:50:19 +02:00
Renat Sibgatulin
17dad7d8ae Bump aioairq to v0.4.6 (#146169)
This version exposes an API to control LED brightness.
2025-06-05 18:27:20 +02:00
Joost Lekkerkerker
14664719d9 Remove zeroconf discovery from Spotify (#146213) 2025-06-05 18:02:11 +02:00
epenet
b14cd1e14b Move elkm1 services to separate module (#146147)
* Move elkm1 services to separate module

* Rename
2025-06-05 16:51:01 +02:00
Retha Runolfsson
fd38d9788d Bump pyswitchbot to 0.65.0 (#146133)
* update pyswitchbot to 0.65.0

* fix relay switch 1pm test

* fix ma to a
2025-06-05 16:42:24 +02:00
epenet
0b3b641328 Move services to separate module in opentherm_gw (#146098)
* Move services to separate module in opentherm_gw

* Rename
2025-06-05 16:40:18 +02:00
Brett Adams
6ef77f8243 Fix Export Rule Select Entity in Tessie (#146203)
Fix TessieExportRuleSelectEntity
2025-06-05 16:39:55 +02:00
Ludovic BOUÉ
3a27143012 Matter add Service Area Cluster to vacuum_cleaner fixture (#145743)
Update vacuum_cleaner.json

Service Area Cluster
2025-06-05 16:39:08 +02:00
Samuel Xiao
9a6c642bdf Bump switchbot-api to 2.5.0 (#146205)
* update switchbot-api to 2.5.0

* update switchbot-api to 2.5.0
2025-06-05 16:16:45 +02:00
epenet
38b8d0b018 Move google_sheets services to separate module (#146160)
* Move google_sheets services to separate module

* Move to async_setup

* Do not remove the services

* hassfest

* Rename
2025-06-05 15:07:15 +02:00
epenet
4d3443dbf5 Move amcrest services to separate module (#146144)
* Move amcrest services to separate module

* Rename
2025-06-05 14:43:22 +02:00
Marc Mueller
4f99e54402 Update pandas to 2.3.0 (#146206) 2025-06-05 14:42:21 +02:00
epenet
d6615e3d44 Move ffmpeg services to separate module (#146149)
* Move ffmpeg services to separate module

* Fix tests

* Rename
2025-06-05 14:39:44 +02:00
Willem-Jan van Rootselaar
9c23331ead Bump python-bsblan to version 2.0.1 (#146198)
* Bump python-bsblan to version 2.0.1

* Remove 'bsblan' exception for 'python-bsblan' from forbidden package exceptions
2025-06-05 13:07:16 +02:00
epenet
5fb2802bf4 Move zoneminder services to separate module (#146151) 2025-06-05 06:35:32 +02:00
epenet
b4864e6a8a Move matrix services to separate module (#146161) 2025-06-05 06:35:10 +02:00
Raphael Hehl
04c34877f4 Bump uiprotect to 7.11.0 (#146171)
Bump uiprotect to version 7.11.0
2025-06-04 23:32:44 +03:00
Ludovic BOUÉ
bdeb61fafc Matter Extractor hood fixture (#146174)
* Create extractor_hood.json

* Matter Extractor hood fixture

* Format document
2025-06-04 21:17:51 +02:00
J. Nick Koston
76d4257f51 Bump aiohttp to 3.12.9 (#146178) 2025-06-04 20:12:19 +02:00
Markus Adrario
c6c7e7eae1 Add homee reconfiguration flow (#146065)
* Add a reconfigure flow to homee

* Add tests for reconfiguration flow

* string refinement

* fix review comments

* more review fixes
2025-06-04 15:27:07 +02:00
Iskra kranj
07557e27b0 Bump pyiskra to 0.1.21 (#146156) 2025-06-04 14:51:40 +02:00
J. Nick Koston
f211da60e0 Bump aiohttp to 3.12.8 (#146153) 2025-06-04 12:57:40 +01:00
Michael
64b74d00f7 Bump aioimmich to 0.9.0 (#146154)
bump aioimmich to 0.9.0
2025-06-04 13:35:16 +02:00
J. Nick Koston
96cb645644 Bump aioesphomeapi to 32.0.0 (#146135) 2025-06-04 09:34:04 +01:00
Claudio Ruggeri - CR-Tech
9b0db3bd51 Bump pymodbus to 3.9.2 (#145948) 2025-06-04 10:28:34 +02:00
Robert Resch
ffdefd1e0f Deprecate eddystone temperature integration (#145833) 2025-06-04 10:00:50 +02:00
Max Velitchko
59ad0268a9 Bump pyvera to 0.3.16 (#146089)
* Update vera integration with the latest pyvera package

* python3 -m script.gen_requirements_all

* Fix license
2025-06-04 07:47:41 +01:00
dependabot[bot]
f28851e76f Bump github/codeql-action from 3.28.18 to 3.28.19 (#146131)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.18 to 3.28.19.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3.28.18...v3.28.19)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.28.19
  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>
2025-06-04 07:41:34 +01:00
J. Nick Koston
4f5c1d544b Bump protobuf to 6.31.1 (#146128)
changelog: https://github.com/protocolbuffers/protobuf/compare/v30.2...v31.1
2025-06-04 07:40:10 +01:00
Marc Mueller
a8ccf1c6fc Update pytest to 8.4.0 (#146114) 2025-06-04 08:09:19 +02:00
Ian
e3f7e5706b Add config option for controlling Ollama think parameter (#146000)
* Add config option for controlling Ollama think parameter

Allows enabling or disable thinking for supported models. Neither option
will dislay thinking content in the chat. Future support for displaying
think content will require frontend changes for formatting.

* Add thinking strings
2025-06-03 20:42:16 -07:00
Erwin Douna
7ad1e756e7 SMA fix strings (#146112)
* Fix

* Feedback
2025-06-03 21:54:44 +02:00
Norbert Rittel
8868f214f3 Replace "numbers" with "digits" in invalid_backbone_key message of knx (#146124)
The KNX Backbone Key has a length of 128 bits, so written as a hexadecimal number that yields 32 digits.

This fix thus replaces "numbers" with "digits" in the `invalid_backbone_key` message.
2025-06-03 20:47:54 +02:00
J. Nick Koston
3ecff19a45 Bump habluetooth to 3.49.0 (#146111)
* Bump habluetooth to 3.49.0

changelog: https://github.com/Bluetooth-Devices/habluetooth/compare/v3.48.2...v3.49.0

* update diag

* diag
2025-06-03 16:56:20 +02:00
Ian
74421db747 NextBus: Bump py_nextbusnext to 2.2.0 (#145904) 2025-06-03 13:20:14 +02:00
J. Nick Koston
1cccfac3dc Bump bleak-esphome to 2.16.0 (#146110) 2025-06-03 11:57:58 +01:00
David Bonnes
c254548a64 Add required_features to WaterHeater entity service registrations (#141873) 2025-06-03 12:51:46 +02:00
epenet
7f8b782e95 Adjust SamsungTV on/off logging (#146045)
* Adjust SamsungTV on/off logging

* Update coordinator.py
2025-06-03 12:30:18 +02:00
Erwin Douna
cd518d4a46 SMA add missing strings for DHCP (#145782) 2025-06-03 12:12:56 +02:00
Retha Runolfsson
c5db07e84d Fix nightlatch option for all switchbot locks (#146090) 2025-06-03 12:11:02 +02:00
epenet
d1e0225520 Adjust ConnectionFailure logging in SamsungTV (#146044) 2025-06-03 12:05:33 +02:00
Robin Lintermann
d439bb68eb Smarla integration improve tests (#145803)
* Improve smarla integration tests

* Do not import descriptions instead use seperate list
2025-06-03 11:49:24 +02:00
Matthias Alphart
980dbf364d Add exception translations for KNX services (#146104) 2025-06-03 11:31:32 +02:00
SNoof85
842e7ce171 Add state class measurement to Freebox temperature sensors (#146074) 2025-06-03 11:23:52 +02:00
epenet
8afec8ada9 Use async_load_fixture in youtube tests (#146018) 2025-06-03 11:07:56 +02:00
Simone Chemelli
7b699f7733 Avoid services unload for Homematicip Cloud (#146050)
* Avoid services unload

* fix tests

* apply review comments

* cleanup

* apply review comment
2025-06-03 11:01:23 +02:00
Noah Groß
d448ef9f16 Bump python-picnic-api2 to 1.3.1 (#145962) 2025-06-03 10:57:59 +02:00
epenet
03912a1704 Use async_load_fixture in tplink_omada tests (#146014) 2025-06-03 10:54:22 +02:00
epenet
54c20d5d5a Use async_load_fixture in remaining tests (#146021) 2025-06-03 10:52:51 +02:00
epenet
2dbf24e798 Use async_load_fixture in skybell tests (#146017) 2025-06-03 10:47:03 +02:00
epenet
791654a420 Move services to separate module in nzbget (#146093) 2025-06-03 10:41:40 +02:00
epenet
5fe07e49e4 Move services to separate module in insteon (#146094) 2025-06-03 10:41:13 +02:00
epenet
0bd287788c Move service registration to async_setup in icloud (#146095) 2025-06-03 10:40:48 +02:00
Brett Adams
40e0c0f98d Fix BMS and Charge states in Teslemetry (#146091)
Fix BMS and Charge states
2025-06-03 10:40:20 +02:00
Pär Holmdahl
85b608912b Add energy sensor to adax (#145995)
* 2nd attempt to add energysensors to Adax component

* Ruff format changes

* I did not reuse the first call for information.. Now i do..

* Fixed some tests after the last change

* Remove extra attributes

* Dont use info logger

* aggregate if not rooms

* Raise error if no rooms are discovered

* Move code out of try catch

* Catch more specific errors

* removed platforms from manifest.json

* remove attribute translation key

* Getting rid of the summation of energy used..

* Fixed errorness in test

* set roomproperty in Init

* concatenated the two functions

* use raw Wh values and suggest a konversion for HomeAssistant

* Use snapshot testing

* Update homeassistant/components/adax/coordinator.py

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

* Update homeassistant/components/adax/strings.json

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

* Update homeassistant/components/adax/sensor.py

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

* Update homeassistant/components/adax/sensor.py

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

* Update homeassistant/components/adax/sensor.py

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

* Update homeassistant/components/adax/sensor.py

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

* Removing un needed logg

* Removing initial value

* Changing tests to snapshot_platform

* Removing available property from sensor.py and doing a ruff formating..

* Fix a broken indent

* Add fix for coordinator updates in Adax energisensor and namesetting

* Update homeassistant/components/adax/sensor.py

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

* Update homeassistant/components/adax/coordinator.py

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

* Update homeassistant/components/adax/coordinator.py

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

* Update homeassistant/components/adax/sensor.py

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

* generated snapshots

* Ruff changes

* Even more ruff changes, that did not appear on ruff command locally

* Trying to fix CI updates

* Update homeassistant/components/adax/sensor.py

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

* Improve AdaxEnergySensor by simplifying code and ensuring correct handling of energy values. Adjust how room and device information is retrieved to avoid duplication and improve readability.

* Removed a test för device_id as per request..

* Make supersure that value is int and not "Any"

* removing executable status

* Update tests/components/adax/test_sensor.py

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

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-06-03 10:36:43 +02:00
Pete Sage
987753dd1c Bump aiokem to 1.0.1 (#146085) 2025-06-03 10:16:08 +02:00
epenet
5df05fb6dd Move async_register_services to async_setup (#146092) 2025-06-03 08:38:02 +02:00
Simone Chemelli
f295ca27af Bump aioamazondevices to 3.0.5 (#146073) 2025-06-03 01:18:49 +03:00
Marc Mueller
8f75cc6a33 Update pyatmo to 9.2.1 (#146077) 2025-06-02 23:47:50 +02:00
Marc Mueller
19c71f0f49 Update python-homewizard-energy to 8.3.3 (#146076) 2025-06-02 23:34:50 +02:00
Marc Mueller
22c2028c00 Update typing-extensions to 4.14.0 (#146054) 2025-06-02 23:15:53 +02:00
Ian
39f687e3a3 Bump ollama to 0.5.1 (#146063)
* Bump ollama to 0.5.1
* Add ollama to license exceptions
2025-06-02 22:43:00 +02:00
Shay Levy
6692b9b71f Fix Shelly BLU TRV calibrate button (#146066) 2025-06-02 22:38:17 +03:00
J. Nick Koston
2f5787e7be Bump aiohttp to 3.12.7 (#146028) 2025-06-02 21:27:08 +02:00
Simone Chemelli
bbda1761bf Avoid services unload for Isy994 (#146069)
* Avoid services unload for Isy994

* cleanup
2025-06-02 21:19:10 +02:00
Robert Resch
ecc10e9793 Bump go2rtc-client to 0.2.1 (#146019)
* Bump go2rtc-client to 0.2.0

* Bump go2rtc-client to 0.2.1

* Clean up hassfest exception

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-02 20:48:40 +02:00
Simone Chemelli
9e1e889fd7 Rename mispelled services python files (#146049) 2025-06-02 20:41:31 +02:00
Michael
eefe1e6f0f Don't use multi-line conditionals in immich (#146062) 2025-06-02 19:58:54 +02:00
Marc Mueller
397ed87f2d Update aiohomekit to 3.2.15 (#146059)
* Update aiohomekit to 3.2.15

* Remove Python version exception for homekit_controller
2025-06-02 18:23:04 +01:00
Marc Mueller
15830f383e Update pyoverkiz to 1.17.2 (#146056) 2025-06-02 18:21:26 +01:00
epenet
87395efc6e Add awesomeversion to dependency version checks (#146047) 2025-06-02 17:28:13 +02:00
Marc Mueller
27d79bb10a Update yamllint to 1.37.1 (#146038) 2025-06-02 16:35:31 +02:00
Simone Chemelli
7427db70aa Move async_setup_services to async_setup (#146048)
* Moved async_setup_services to async_setup

* fix schema missing
2025-06-02 16:23:20 +02:00
Marc Mueller
77d5bffa85 Update pytest warnings filter (#146024) 2025-06-02 16:01:23 +02:00
Marc Mueller
ab7c7b8d89 Update ruff to 0.11.12 (#146037)
* Update ruff to 0.11.12
* Replace ruff legacy alias with ruff-check
2025-06-02 16:01:10 +02:00
Simon Lamon
93b8cc38d8 Small nmbs sensor attributes refactoring (#145956)
Attributes refactoring
2025-06-02 15:13:23 +02:00
Pete Sage
e5f95b3aff Add diagnostics tests for Sonos (#146040)
* fix: add tests for diagnostics

* fix: add new files

* fix: add new files
2025-06-02 15:12:34 +02:00
starkillerOG
613728ad3b Improve debug logging Reolink (#146033)
Add debug logging
2025-06-02 15:12:13 +02:00
starkillerOG
cb1bfe6ebe Bump reolink-aio to 0.13.5 (#145974)
* Add debug logging

* Bump reolink-aio to 0.13.5

* Revert "Add debug logging"

This reverts commit f96030a6c8.
2025-06-02 15:11:56 +02:00
Joost Lekkerkerker
434179ab3f Remove NMBS YAML import (#145733)
* Remove NMBS YAML import

* Remove NMBS YAML import
2025-06-02 15:10:46 +02:00
TimL
eb53277fcc Bump pysmlight to 0.2.6 (#146039)
Co-authored-by: Tim Lunn <tim@feathertop.org>
2025-06-02 15:04:34 +02:00
J. Nick Koston
850ddb3667 Bump grpcio to 1.72.1 (#146029) 2025-06-02 15:04:02 +02:00
epenet
5a727a4fa3 Avoid constant alias for integration DOMAIN (#145788)
* Avoid constant alias for integration DOMAIN

* Tweak

* Improve

* Three more

---------

Co-authored-by: Shay Levy <levyshay1@gmail.com>
2025-06-02 10:37:29 +02:00
karwosts
33fc700952 Make sun solar_rising a binary_sensor (#140956)
* Make sun solar_rising a binary_sensor.

* Add a state translation

* code review

* fix test

* move PLATFORMS

* Update strings.json
2025-06-02 10:32:48 +02:00
Joakim Sørensen
ad493e077e Submit legacy integrations for analytics (#145787)
* Submit legacy integrations for analytics

* adjustments
2025-06-02 10:29:17 +02:00
Marc Mueller
a2b2f6f20a Update pre-commit to 4.2.0 (#145986) 2025-06-02 09:56:20 +02:00
Marc Mueller
ee57fd413a Update freezegun to 1.5.2 (#145982) 2025-06-02 09:53:12 +02:00
Martin Hjelmare
f5d585e0f0 Fix removal of devices during Z-Wave migration (#145867) 2025-06-02 09:52:02 +02:00
Simone Chemelli
1899388f35 Add diagnostics to Amazon devices (#145964) 2025-06-02 09:48:42 +02:00
Allen Porter
4d833e9b1c Bump ical to 10.0.0 (#145954) 2025-06-02 09:47:05 +02:00
Robert Resch
6d827cd412 Deprecate hddtemp (#145850) 2025-06-02 09:45:14 +02:00
epenet
ebfbea39ff Use async_load_fixture in twitch tests (#146016) 2025-06-02 09:27:53 +02:00
dependabot[bot]
89a40f1c48 Bump dawidd6/action-download-artifact from 9 to 10 (#146015) 2025-06-02 09:21:26 +02:00
epenet
664eb7af10 Use async_load_fixture in moehlenhoff_alpha2 tests (#146012) 2025-06-02 08:59:19 +02:00
epenet
33b99b6627 Use async_load_fixture in netatmo tests (#146013) 2025-06-02 08:59:11 +02:00
epenet
0cf2ee0bcb Remove unnecessary DOMAIN alias in tests (l-r) (#146009)
* Remove unnecessary DOMAIN alias in tests (l-r)

* Keep late import in lirc
2025-06-02 08:54:55 +02:00
hanwg
85a86c3f11 Add config flow for telegram bot integration (#144617)
* added config flow for telegram integration

* added chat id in config entry title and added config flow tests

* fix import issue when there are no notifiers in configuration.yaml

* Revert "fix import issue when there are no notifiers in configuration.yaml"

This reverts commit b5b83e2a9a.

* Revert "added chat id in config entry title and added config flow tests"

This reverts commit 30c2bb4ae4.

* Revert "added config flow for telegram integration"

This reverts commit 1f44afcd45.

* added config and subentry flows

* added options flow to configure webhooks

* refactor module setup so it only load once

* moved service registration from async_setup_entry to async_setup

* Apply suggestions from code review

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

* import only last yaml config

* import only last yaml config

* reduced scope of try-block

* create issue when importing from yaml

* Apply suggestions from code review

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

* handle options update by reloading telegram bot

* handle import errors for create issue

* include bot's platform when creating issues

* handle options reload without needing HA restart

* moved url and trusted_networks inputs from options to new config flow step

* Apply suggestions from code review

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

* minor fixes

* refactor config flow

* moved constants to const.py

* Apply suggestions from code review

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

* Update homeassistant/components/telegram_bot/config_flow.py

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

* Update homeassistant/components/telegram_bot/config_flow.py

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

* Update homeassistant/components/telegram_bot/config_flow.py

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

* added options flow tests

* Update homeassistant/components/telegram_bot/__init__.py

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

* Update homeassistant/components/telegram_bot/__init__.py

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

* Update homeassistant/components/telegram_bot/__init__.py

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

* Update homeassistant/components/telegram_bot/config_flow.py

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

* Update homeassistant/components/telegram_bot/config_flow.py

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

* added reconfigure flow

* added reauth flow

* added tests for reconfigure flow

* added tests for reauth

* added tests for subentry flow

* added tests for user and webhooks flow with error scenarios

* added import flow tests

* handle webhook deregister exception

* added config entry id to all services

* fix leave chat bug

* Update homeassistant/components/telegram_bot/__init__.py

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

* removed leave chat bug fixes

* Update homeassistant/components/telegram_bot/strings.json

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

* handle other error types for import

* reuse translations

* added test for duplicated config entry for user step

* added tests

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-02 08:52:31 +02:00
epenet
de4a5fa30b Remove unnecessary DOMAIN alias in tests (s-z) (#146010) 2025-06-02 08:48:37 +02:00
Marc Mueller
43ac550ca0 Update pydantic to 2.11.5 (#145985)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-02 08:48:22 +02:00
Marc Mueller
c3c4d224b2 Update PyTurboJPEG to 1.8.0 (#145984)
Co-authored-by: Allen Porter <allen.porter@gmail.com>
2025-06-02 08:40:10 +02:00
Marc Mueller
6f865beacd Update attrs to 25.3.0 (#145977) 2025-06-02 07:58:35 +02:00
Marc Mueller
de25195383 Update bcrypt to 4.3.0 (#145978) 2025-06-02 07:56:51 +02:00
Marc Mueller
0139d2cabf Update cryptography to 45.0.3 (#145979) 2025-06-02 07:53:58 +02:00
Marc Mueller
17542614b5 Update aiohttp-cors to 0.8.1 (#145976)
* Update aiohttp-cors to 0.8.1

* Fix mypy
2025-06-02 07:52:23 +02:00
Marc Mueller
885367e690 Update coverage to 7.8.2 (#145983) 2025-06-02 07:47:56 +02:00
Marc Mueller
f8c44aad25 Update pytest-cov to 6.1.1 (#145989) 2025-06-02 07:34:11 +02:00
Marc Mueller
2323cc2869 Update numpy to 2.2.6 (#145981) 2025-06-01 21:23:30 -07:00
Marc Mueller
7f0249bbf7 Update pytest-timeout to 2.4.0 (#145990) 2025-06-02 06:17:39 +02:00
Marc Mueller
7a23b778a4 Update pytest-xdist to 3.7.0 (#145991) 2025-06-02 06:16:17 +02:00
Marc Mueller
d910924032 Update syrupy to 4.9.1 (#145992) 2025-06-02 06:14:52 +02:00
Marc Mueller
0b93a8c2f2 Update types packages (#145993) 2025-06-02 06:13:08 +02:00
Marc Mueller
5e377b89fc Update pytest-asyncio to 1.0.0 (#145988)
* Update pytest-asyncio to 1.0.0

* Remove event_loop fixture uses
2025-06-02 06:12:22 +02:00
Marc Mueller
dd85a1e5f0 Update mypy-dev to 1.17.0a2 (#146002)
* Update mypy-dev to 1.17.0a2

* Fix
2025-06-02 06:06:38 +02:00
Simone Chemelli
b96a7aebcd Bump aioamazondevices to 3.0.4 (#145971) 2025-06-01 21:15:18 +02:00
Michael
3cfcf382da Bump aioimmich to 0.8.0 (#145908) 2025-06-01 21:14:19 +02:00
epenet
ed9fd2c643 Use async_load_fixture in async test functions (b-i) (#145714)
* Use async_load_fixture in async test functions (b-i)

* Adjust
2025-06-01 06:31:37 -07:00
epenet
a007e8dc26 Use async_load_fixture in async test functions (l-z) (#145717)
* Use async_load_fixture in async test functions (l-z)

* Adjust
2025-06-01 06:29:17 -07:00
TimL
b318644998 Bump pysmlight to v0.2.5 (#145949) 2025-06-01 03:14:08 +02:00
Ståle Storø Hauknes
0434eea3ab Add sound pressure to Airthings (#145946)
Add sound pressure
2025-06-01 02:05:19 +02:00
Josef Zweck
c19b984660 Increase update intervals in lamarzocco (#145939) 2025-05-31 20:25:57 +02:00
Josef Zweck
0d6bb8a325 Bump pylamarzocco to 2.0.8 (#145938) 2025-05-31 20:25:47 +02:00
Joost Lekkerkerker
094b969301 Add more Amazon Devices DHCP matches (#145776) 2025-05-31 20:25:24 +02:00
Brett Adams
ddef6fdb98 Add streaming to charge cable connected in Teslemetry (#145880) 2025-05-31 20:01:10 +02:00
Robert Resch
cabf7860b3 Deprecate snips integration (#145784) 2025-05-31 20:00:34 +02:00
Bram Kragten
0c0a2403e5 Update frontend to 20250531.0 (#145933) 2025-05-31 17:54:36 +02:00
tronikos
be6c3d8bbd Bump opower to 0.12.3 (#145918) 2025-05-31 11:22:49 +02:00
Josef Zweck
c01536ee58 Move server device creation to init in jellyfin (#145910)
* Move server device creation to init in jellyfin

* move device creation to after coordinator refresh
2025-05-31 11:19:32 +02:00
J. Nick Koston
a9f36a50e4 Bump aiohttp to 3.12.6 (#145919)
* Bump aiohttp to 3.12.5

changelog: https://github.com/aio-libs/aiohttp/compare/v3.12.4...v3.12.5

* .6

* fix mock
2025-05-31 11:12:00 +02:00
Samuel Xiao
6d11c0395f Bump switchbot-api to 2.4.0 (#145786)
* update switchbot-api version to 2.4.0

* debug for test code
2025-05-30 20:22:40 +02:00
Brett Adams
66bb638dd0 Bump tesla-fleet-api to 1.1.1. (#145869)
bump
2025-05-30 20:21:51 +02:00
Iskra kranj
0d72bfef70 Bump pyiskra to 0.1.19 (#145889) 2025-05-30 20:21:14 +02:00
markhannon
6e44552d41 Minor cleanup of Zimi Integration (#144293) 2025-05-30 19:53:33 +02:00
Simon Lamon
9ec02633b3 Bump python-linkplay to v0.2.9 (#145892) 2025-05-30 19:35:08 +02:00
Jordan Harvey
5d340332bf Bump pyprobeplus to 1.0.1 (#145897) 2025-05-30 19:33:03 +02:00
J. Diego Rodríguez Royo
1e973c1d74 Bump aiohomeconnect to 0.17.1 (#145873) 2025-05-30 01:40:11 +02:00
starkillerOG
618ada64f8 Ensure Reolink host device is setup first (#145843) 2025-05-29 19:32:21 +02:00
Robert Resch
2d6802e06a Deprecate tensorflow (#145806)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-05-29 14:35:35 +01:00
starkillerOG
9687a34a70 Reolink fallback to download command for playback (#145842) 2025-05-29 15:31:50 +02:00
Michael
5ba0ceb6c2 Bump aioimmich to 0.7.0 (#145845) 2025-05-29 15:30:02 +02:00
G Johansson
d8e3e88c63 Fix language selections in workday (#145813) 2025-05-29 15:28:54 +02:00
Robert Resch
d1d1bca29d Deprecate sms integration (#145847) 2025-05-29 14:12:51 +02:00
Michael
80189495c5 Use mime type provided by Immich (#145830)
use mime type from immich instead of guessing it
2025-05-29 10:28:02 +02:00
Josef Zweck
cad6c72cfa Bump aiotedee to 0.2.23 (#145822)
* Bump aiotedee to 0.2.23

* update snapshot
2025-05-29 10:35:05 +03:00
J. Nick Koston
23ac22e213 Remove default args to ESPHome test fixture calls (#145840) 2025-05-29 01:45:37 -05:00
J. Nick Koston
55e664fc0d Bump aiohttp to 3.12.4 (#145838) 2025-05-28 21:08:01 -05:00
Brett Adams
881ce45afa Fix Tessie volume max and step (#145835)
* Use fixed volume max and step

* Update snapshot
2025-05-29 03:58:29 +02:00
André Lersveen
b80195df81 Set correct nobo_hub max temperature (#145751)
Max temperature 30°C is implemented upstream in pynobo and the Nobø Energy Hub app also stops at 30°C.
2025-05-29 03:52:05 +02:00
Matthew FitzGerald-Chamberlain
e57ce0a9df Bump pyaprilaire to 0.9.1 (#145836) 2025-05-29 03:43:28 +02:00
J. Nick Koston
ff66ad7705 Bump aiohttp to 3.12.3 (#145837) 2025-05-28 19:38:06 -05:00
Robert Resch
33e98ebffa Remove decora-wifi from excluded requirements (#145832) 2025-05-29 00:14:38 +02:00
Robert Resch
8fd9e2046e Deprecate decora integration (#145807) 2025-05-28 23:54:48 +02:00
Bram Kragten
32c2f47ab5 Update frontend to 20250528.0 (#145828)
Co-authored-by: Robert Resch <robert@resch.dev>
2025-05-28 23:17:14 +02:00
Ståle Storø Hauknes
e2fc2dce84 Move Airthings coordinator to separate module (#145827)
* Create coordinator

* Fix sensor.py
2025-05-28 22:38:33 +02:00
Michael
afa97f8ec1 Add level of collections in Immich media source tree (#145734)
* add layer for collections in media source tree

* re-arange tests, add test for collection layer

* fix
2025-05-28 20:51:27 +02:00
Michael
2708c1c94c Fix Immich media source browsing with multiple config entries (#145823)
fix media source browsing with multiple config entries
2025-05-28 20:49:20 +02:00
Michael Hansen
d76ed6a3c2 Bump intents to 2025.5.28 (#145816) 2025-05-28 21:14:13 +03:00
epenet
695f69bd90 Remove unnecessary DOMAIN alias in tests (e-k) (#145818) 2025-05-28 21:06:25 +03:00
epenet
7da8e24e21 Remove unnecessary DOMAIN alias in tests (a-d) (#145817) 2025-05-28 21:00:38 +03:00
David Bonnes
9d0fc0d513 Fix HOMEASSISTANT_STOP unsubscribe in data update coordinator (#145809)
* initial commit

* a better approach

* Add comment
2025-05-28 17:52:51 +01:00
Robert Resch
ca567aa7fc Deprecate lirc integration (#145797) 2025-05-28 17:28:37 +01:00
Robert Resch
27af2d8ec6 Deprecate keyboard integration (#145805) 2025-05-28 17:22:18 +02:00
Lennart Nederstigt
59ea6f375a Add hardwired chime toggle to Reolink Battery Doorbell (#145779)
Co-authored-by: starkillerOG <starkiller.og@gmail.com>
2025-05-28 17:10:38 +02:00
Marc Mueller
6c365c94ed Update sqlalchemy to 2.0.41 (#145790) 2025-05-28 16:39:10 +02:00
Marc Mueller
6693fc764f Update httpcore to 1.0.9 and h11 to 0.16.0 (#145789) 2025-05-28 16:35:11 +02:00
starkillerOG
e855b6c2bc Bump reolink-aio to 0.13.4 (#145799) 2025-05-28 16:33:20 +02:00
Abílio Costa
23a1dddc23 Add Shelly zwave virtual integration (#145749) 2025-05-28 14:56:47 +01:00
epenet
bd5fef1ddb Use async_load_fixture in async test functions (a) (#145718) 2025-05-28 15:51:49 +02:00
epenet
c3ade400fb Use Platform constant in tests (#145801)
* Use Platform constant in tests

* spelling

* Fix platform
2025-05-28 15:51:37 +02:00
epenet
1889f0ef66 Use Platform constant in hue tests (#145798) 2025-05-28 14:43:48 +02:00
epenet
6b28af8282 Remove unnecessary DOMAIN alias in components (#145791) 2025-05-28 14:04:35 +02:00
Robert Resch
f59001d45f Deprecate pandora integration (#145785) 2025-05-28 13:12:55 +02:00
Erik Montnemery
a857461059 Handle late abort when creating subentry (#145765)
* Handle late abort when creating subentry

* Move error handling to the base class

* Narrow down expected error in test
2025-05-28 12:26:28 +02:00
epenet
e4cc842584 Use async_load_json_(array/object)_fixture in async test functions (#145773) 2025-05-28 12:09:05 +02:00
Robert Resch
bb52058920 Deprecate GStreamer integration (#145768) 2025-05-28 11:16:08 +02:00
J. Diego Rodríguez Royo
c1676570da Add more information about possible hostnames at Home Connect (#145770) 2025-05-28 10:57:01 +02:00
G Johansson
4858b2171e Modernize tests for smhi (#139334)
* Modernize tests for smhi

* Fixes

* Mods

* Fix weather

* Coverage 100%

* Fix init test

* Fixes

* Fixes

* Remove waits
2025-05-28 10:56:07 +02:00
Jan Bouwhuis
192aa76cd7 Ensure mqtt sensor unit of measurement validation for state class measurement_angle (#145648) 2025-05-28 10:16:40 +02:00
Josef Zweck
ddf611bfdf Fix uom for prebrew numbers in lamarzocco (#145772) 2025-05-28 10:15:24 +02:00
Robert Resch
3164394982 Deprecate dlib image processing integrations (#145767) 2025-05-28 09:58:44 +02:00
Josef Zweck
b250a03ff5 Bump pylamarzocco to 2.0.7 (#145763) 2025-05-28 09:39:33 +02:00
dependabot[bot]
2dd7f035f6 Bump docker/build-push-action from 6.17.0 to 6.18.0 (#145764)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 09:10:37 +02:00
Joost Lekkerkerker
2c08b3f30c Add more Amazon Devices DHCP matches (#145754) 2025-05-28 08:43:59 +02:00
Josef Zweck
c3ec30ce3b Update otp description for amazon_devices (#145701)
* Update otp description from amazon_devices

* separate

* Update strings.json
2025-05-28 08:13:28 +02:00
Erik Montnemery
9d4375ca76 Make async_remove_stale_devices_links_keep_entity_device move entities (#145719)
Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-27 23:00:52 +02:00
Raphael Hehl
3870b87db9 Bump uiprotect to version 7.10.1 (#145737)
Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>
2025-05-27 22:58:46 +02:00
Joost Lekkerkerker
ff2fd7e9ef Add DHCP discovery to LG ThinQ (#145746) 2025-05-27 16:45:30 -04:00
G Johansson
719dd09eb3 Fix dns resolver error in dnsip config flow validation (#145735)
Fix dns resolver error in dnsip
2025-05-27 22:17:34 +02:00
Bram Kragten
2cf2613dbd Update frontend to 20250527.0 (#145741) 2025-05-27 22:12:07 +02:00
Jan Bouwhuis
181a3d142e Revert "squeezebox Better result for testing (#144622)" (#145739)
This reverts commit 987af8f7df.
2025-05-27 21:36:51 +02:00
Elias Wernicke
c20ad5fde1 Add complete intent function for shopping list component (#128565)
* add intent

* add tests

* raise IntentHandleError

* add check for non completed

* Prefer completing non complete items

* cleanup

* cleanup tests

* rename test

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>

* remove duplicated test

* update test

* complete all items

* fix event

* remove type def

* return speech slots

---------

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-05-27 14:35:14 -05:00
Erwin Douna
4fcebf18dc Tado update mobile devices interval (#145738)
Update the mobile devices interval to five minutes
2025-05-27 21:27:52 +02:00
Joost Lekkerkerker
a6e04be076 Remove niko_home_control YAML import (#145732) 2025-05-27 19:58:05 +02:00
Erwin Douna
330a8e197d MELCloud remove deprecated YAML import strings (#145731)
Remove deprecated YAML import strings
2025-05-27 19:50:31 +02:00
Joost Lekkerkerker
4300e846e6 Fix unbound local variable in Acmeda config flow (#145729) 2025-05-27 19:29:04 +02:00
Kevin Stillhammer
07fd1f99df Support addresses with comma in google_travel_time (#145663)
Support addresses with comma
2025-05-27 18:53:45 +02:00
Kevin Stillhammer
481639bcf9 Catch PermissionDenied(Route API disabled) in google_travel_time (#145722)
Catch PermissionDenied(Route API disabled)
2025-05-27 18:45:49 +02:00
Martin Hjelmare
376008940b Disable advanced window cover position Matter sensor by default (#145713)
* Disable advanced window cover position Matter sensor by default

* Enanble disabled sensors in snapshot test
2025-05-27 17:46:21 +02:00
epenet
b2c2db3394 Add check for transient packages restricting Python version (#145695) 2025-05-27 17:45:51 +02:00
Kevin Stillhammer
a636e38d24 Debug log the update response in google_travel_time (#145725)
Debug log the update response
2025-05-27 17:44:48 +02:00
Martin Hjelmare
ae1294830c Remove static pin code length Matter sensors (#145711)
* Remove static Matter sensors

* Clean up translation strings
2025-05-27 17:35:11 +02:00
Robin Lintermann
d87fdf028b Improve smarla base entity (#145710) 2025-05-27 15:58:19 +02:00
Petar Petrov
6f5d5d4cdb Change text of installing and starting Z-WaveJs add-on steps (#145702) 2025-05-27 14:51:22 +02:00
epenet
12fdd7034a Simplify boolean check in onewire (#145700) 2025-05-27 13:30:44 +02:00
Martin Hjelmare
f295d72cd9 Fix error stack trace for HomeAssistantError in websocket service call (#145699)
* Add test

* Fix error stack trace for HomeAssistantError in websocket service call
2025-05-27 12:54:57 +02:00
Petar Petrov
2605fda185 Remove confirm screen after Z-Wave usb discovery (#145682)
* Remove confirm screen after Z-Wave usb discovery

* Simplify async_step_usb
2025-05-27 12:53:30 +02:00
Joost Lekkerkerker
2189dc3e2a Use string type for amazon devices OTP code (#145698) 2025-05-27 12:33:02 +02:00
Franck Nijhof
8364d8a2e3 Bump version to 2025.7.0dev0 (#145647)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-27 10:59:34 +02:00
epenet
96c9636086 Add check for packages restricting Python version (#145690)
* Add check for packages restricting Python version

* Apply suggestions from code review

* until

* until
2025-05-27 10:44:00 +02:00
Petar Petrov
7b1dfc35d1 Change description on recommended/custom Z-Wave install step (#145688)
Change description on recommended/custom Z-WaveJS step
2025-05-27 10:04:29 +02:00
Norbert Rittel
2e94730491 Replace "Invalid API key" with common string in overseerr (#145689)
Replace "Invalid API key" with common string
2025-05-27 09:56:16 +02:00
Markus Adrario
11c6998bf2 Add homee siren platform (#145675)
* port siren.py from custom component

* Add Siren Tests

* last small nits
2025-05-27 09:48:59 +02:00
epenet
055a024d10 Add async-timeout to forbidden packages (#145679) 2025-05-27 08:57:35 +02:00
Joost Lekkerkerker
f73afd71fd Fix Amazon devices offline handling (#145656) 2025-05-27 08:49:25 +02:00
Jan Bouwhuis
ec64194ab9 Fix justnimbus CI test (#145681) 2025-05-27 08:48:06 +02:00
karwosts
d49a613c62 Add read_only entity_id to Trend options flow (#145657) 2025-05-27 08:42:08 +02:00
Artur Pragacz
6fc064fa6a Test that recorder is not promoted to earlier stage in bootstrap (#142695)
Test that recorder is not promoted to earlier stage
2025-05-27 08:23:39 +02:00
Artur Pragacz
b36b591ccf Improve error message for global timeout (#141563)
* Improve error message for global timeout

* Add test

* Message works with zone too
2025-05-27 07:49:18 +02:00
J. Nick Koston
d25ba79427 Bump aiohttp to 3.12.2 (#145671) 2025-05-26 21:58:46 -05:00
Joost Lekkerkerker
df35f30321 Handle Google Nest DHCP flows (#145658)
* Handle Google Nest DHCP flows

* Handle Google Nest DHCP flows
2025-05-26 15:01:35 -07:00
Jan Bouwhuis
1e3d06a993 Fix translation for sensor measurement angle state class (#145649) 2025-05-26 22:47:53 +01:00
Florian von Garrel
2ee6bf7340 Add update platform to paperless integration (#145638)
* Add uüdate platform to paperless integration

* Add tests to paperless

* Add translation

* Fixed update unavailable

* Fetch remote version in update platform

* changed diagnostics

* changed diagnostic data

* Code quality

* revert changes

* code quality
2025-05-26 23:24:53 +02:00
Joost Lekkerkerker
13a8e5e021 Fix Aquacell snapshot (#145651) 2025-05-26 23:08:07 +02:00
Markus Jacobsen
9a73006681 Simplify Bang & Olufsen testing setup (#139830)
* Add and use integration fixture

* Simplify WebSocket testing

* Remove integration fixture return value

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 22:14:27 +02:00
Joost Lekkerkerker
4aade14c9e Fix CI (#145644)
* Fix CI

* Fix CI
2025-05-26 21:55:33 +02:00
epenet
8abbd35c54 Add ability to load test fixtures on the executor (#144534) 2025-05-26 21:50:28 +02:00
Allen Porter
34f92d584b Bump gcal_sync to 7.1.0 (#145642) 2025-05-26 21:48:13 +02:00
Guido Schmitz
a7919c5ce7 Move coordinator and getting data closer together in devolo Home Network (#144814) 2025-05-26 21:44:45 +02:00
ngolf
405725f8ee Add last update to aquacell (#143661) 2025-05-26 21:43:55 +02:00
Cerallin
393ea0251b Add add_package action to seventeentrack (#144488)
* Fix schema name, add_packages -> get_packages

* Add "add_package" service

* Update description

* Update descriptions
2025-05-26 21:40:12 +02:00
LG-ThinQ-Integration
cdd3ce428f Add select for ventilator's control (#140849)
* Add select for ventilator's control

* Removed wind_strength and it will be provided by fan

---------

Co-authored-by: yunseon.park <yunseon.park@lge.com>
2025-05-26 21:37:05 +02:00
wittypluck
b17d62177c Add Air Pollution support to OpenWeatherMap (#137949)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 21:34:48 +02:00
tdfountain
16394061cb Add additional outlet sensors to NUT (#143309)
Add outlet sensors for current, power, and real powre
2025-05-26 21:34:15 +02:00
Jan Bouwhuis
b1403838bb Add translation string and references for sensor Measurement Angle state class (#145639) 2025-05-26 21:22:10 +02:00
jukrebs
e857db281f Set new IOmeter datacoordinator debouncer cooldown (#143665) 2025-05-26 21:21:35 +02:00
Sören Beye
5f63612b66 Increase resolution of sun updates around sunrise/sundown (#140403) 2025-05-26 21:20:18 +02:00
Phill (pssc)
987af8f7df squeezebox Better result for testing (#144622) 2025-05-26 21:16:11 +02:00
Matthew FitzGerald-Chamberlain
0ab7d46d7c Support AprilAire humidifier auto mode (#144647) 2025-05-26 21:15:40 +02:00
peteS-UK
072d0dc567 Update coordinator logging levels for Squeezebox (#144620) 2025-05-26 21:14:15 +02:00
Jason Mahdjoub
9b9d4d7dab Set correct state_class for battery_stored and increase timeout to prevent Imeon integration disconnections (#144925) 2025-05-26 21:13:47 +02:00
Gaylord GIRARD
84305563ab Add state class measurement to Freebox rate sensors (#142757)
* Update sensor.py

Update sensor.py to add state_class=SensorStateClass.MEASUREMENT as per long-term-statistics requierment

* Update sensor.py

remove duplicate import of SensorStateClass in freebox sensor to satisfy ruff

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 21:13:35 +02:00
Brett Adams
db489a5069 Improve device tracker platform in Teslemetry (#145268) 2025-05-26 21:12:39 +02:00
Allen Porter
2ef0a8557f Bump ical to 9.2.5 (#145636) 2025-05-26 21:12:05 +02:00
Brett Adams
001164ce1b Remove available property for streaming in Teslemetry (#145352) 2025-05-26 21:11:35 +02:00
karwosts
848eb797e0 Add read_only selectors to Filter Options Flow (#145526) 2025-05-26 21:08:30 +02:00
asafhas
fd4dafaac5 Fix trigger condition and alarm message in Tuya Alarm (#132963)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-26 21:05:09 +02:00
Erwin Douna
0b6ea36e24 Add Tado user agent (#145637) 2025-05-26 21:04:46 +02:00
Claudio Ruggeri - CR-Tech
b667fb2728 Fix NaN values in Modbus slaves sensors (#139969)
* Fix NaN values in Modbus slaves sensors

* fixXbdraco
2025-05-26 21:04:38 +02:00
J. Diego Rodríguez Royo
2dc2b0ffac Delete Home Connect program switches related strings (#144610) 2025-05-26 21:02:27 +02:00
Dave Ingram
d6375a79a1 Expose filter/pump timers for Tuya pet fountains (#131863)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-26 21:01:45 +02:00
Speak to the Geek
c36f8c38ae YouTube Component - Enable SensorStateClass for Long Term Statistic Support (#142670)
* Youtube Component Support SensorStateClass in sensor.py

Added support for long term statistics by including the appropriate state class type for subscriber and view counts.

* Update sensor.py

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 20:59:07 +02:00
Chuck Deal
c4485c1814 Add Sunbeam Dual Zone Heated Bedding to Tuya integration (#135405) 2025-05-26 20:58:11 +02:00
Joost Lekkerkerker
e2a916ff9d Make sure we can set up OAuth based integrations via discovery (#145144) 2025-05-26 20:48:07 +02:00
Joost Lekkerkerker
a2b02537a6 Add deprecation issues for supervised and core installation methods (#145323)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-26 20:45:12 +02:00
thargor
b8a96d2a76 update pyfronius to 0.8.0 (#141984) 2025-05-26 20:23:41 +02:00
David Poll
670e8dd434 Add as_function to allow macros to return values (#142033) 2025-05-26 20:22:45 +02:00
Florian von Garrel
27b0488f05 Update Paperless strings (#145633)
* minor changed

* Update snapshots
2025-05-26 19:53:54 +02:00
Simone Chemelli
6003f3d135 Add action exceptions to UptimeRobot integration (#143587)
* Add action exceptions to UptimeRobot integration

* fix tests and strings
2025-05-26 19:47:46 +02:00
epenet
c3dec7fb2f Add ability to set exceptions in dependency version checks (#145442)
* Add ability to set exceptions in dependency version checks

* Fix message

* Improve

* Auto-load from requirements.txt

* Revert "Auto-load from requirements.txt"

This reverts commit f893d4611a4b6ebedccaa639622c3f8f4ea64005.
2025-05-26 19:45:26 +02:00
TheJulianJES
cfa4d37909 Add icons for ZHA fan modes (#145634) 2025-05-26 19:44:31 +02:00
Bram Kragten
8ce3ead782 Update frontend to 20250526.0 (#145628) 2025-05-26 19:44:22 +02:00
Abílio Costa
b626204f63 Add default device class display precision for Sensor (#145013)
* Add default device class display precision for Sensor

* Renaming, docstrings, cleanup

* Simplify units list

* Fix tests

* Fix missing precision when suggested is specified

* Update snapshots

* Fix when unit of measurement is not valid

* Fix tests

* Fix deprecated unit usage

* Fix goalzero tests

The sensor native_value method was accessing the data dict and trowing,
since the mock did not have any data for the sensors.

Since now the precision is always specified (it was missing for those
sensors), the throw was hitting async_update_entity_options in _update_suggested_precision.
Previously, async_update_entity_options was not called since it had no
precision.

* Fix metoffice

* Fix smartthings

* Add default sensor data for Tesla Wall Connector tests

* Update snapshots

* Revert spaces

* Update smartthings snapshots

* Add missing sensor mock for tesla wall connector

* Address review comments

* Add doc comment

* Add cap to doc comment

* Update comment

* Update snapshots

* Update comment
2025-05-26 19:40:29 +02:00
Joost Lekkerkerker
b15989f2bf Make tests less dependent on issue registry size (#145631)
* Make tests less dependent on issue registry size

* Make tests less dependent on issue registry size
2025-05-26 19:39:11 +02:00
Erik Montnemery
eec7666416 Update squeezebox test snapshots (#145632) 2025-05-26 19:35:07 +02:00
TheJulianJES
5ea6811d01 Add translation for ZHA light effect (#145630)
* Add translations for ZHA light effects

* Add icons for ZHA light effects

* Fix capitalization of "Color loop"

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

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-26 19:31:25 +02:00
Erik Montnemery
4e1d5fbeb0 Add WS command to help reset custom entity_id (#145504)
* Add WS command to help reset custom entity_id

* Calculate suggested object id from entity properties

* Fix logic and add additional tests

* Adjust test

* Update folder_watcher test

* Handle current entity id matches the automatic entity id

* Don't store calculated_object_id

* Update snapshots

* Update snapshots

* Update test

* Tweak logic for reusing current entity_id

* Improve test

* Don't assign same entity_id to several entities

* Prioritize custom entity name

* Update snapshots

* Update snapshots
2025-05-26 19:28:27 +02:00
Sid
bf92db6fd5 Add diagnostics to eheimdigital (#145382)
* Add diagnotics to eheimdigital

* Diagnostics are now with data in tests
2025-05-26 19:25:15 +02:00
Sid
03a26836ed Refactor eheimdigital tests to use fixtures (#145428) 2025-05-26 19:13:20 +02:00
Adrian Freund
99ebac5452 Add translation keys for zha fan states (#145629) 2025-05-26 19:02:52 +02:00
J. Nick Koston
01ea58eb9b Bump aiohttp to 3.12.1 (#145627)
changelog: https://github.com/aio-libs/aiohttp/compare/v3.12.1rc0...v3.12.1

No changes since 3.12.1rc0, only the version number
2025-05-26 11:54:00 -05:00
epenet
039383ab22 Add pyserial-asyncio to forbidden packages (#145625) 2025-05-26 18:40:13 +02:00
Perchun Pak
8fb4f1f7f9 Update mcstatus to 12.0.1 in Minecraft Server (#144704)
Update mcstatus to 12.0.1
2025-05-26 18:39:13 +02:00
Simone Chemelli
15a7d13768 Use model details data from library for Amazon Devices (#145601)
* Log warning for unknown models for Amazon Devices

* use method from library

* apply review comment

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 18:24:23 +02:00
J. Nick Koston
51562e5ab4 Bump aiohttp to 3.12.1rc0 (#145624) 2025-05-26 11:05:26 -05:00
peteS-UK
8623d96deb Squeezebox add alarms support - switch platform. Part 1 (#141055)
* initial

* remove dupe name definition

* snapshot update

* name def updates

* test update for new entity name

* remove attributes

* icon translations

* merge fixes

* Snapshot update post merge

* update to class initialisation

* move entity delete to coordinator

* remove some comments

* move known_alarms to coordinator

* test_switch update for syrupy change

* listener and sets

* check self.available

* remove refresh from conftest

* test update

* test tweak

* move listener to switch platform

* updates revew

* SWITCH_DOMAIN
2025-05-26 17:41:28 +02:00
Sören Beye
3dc7b75e4b Allow nested schema validation in event automation trigger (#126771)
* Allow nested schema validation in event automation trigger

* Fix rfxtrx device trigger

* Don't create nested voluptuous schemas

* Fix editing mistake

* Fix format

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-26 17:34:13 +02:00
Florian von Garrel
c14d17f88c Add status sensors to paperless (#145591)
* Add first status sensor and coordinator

* New snapshot

* Add comment

* Add test for forbidden status endpoint

* Changed comment

* Fixed translation

* Minor changes and code optimization

* Add common translation; minor tweaks

* Moved translation from common to integration
2025-05-26 17:24:23 +02:00
Simone Chemelli
b7ce0f63a9 Add notify platform to Amazon Devices (#145589)
* Add notify platform to Amazon Devices

* apply review comment

* leftover

* tests leftovers

* remove sound notification

* missing await
2025-05-26 17:17:32 +02:00
Marcel van der Veldt
c2a5e1aaf9 Prefer source name in Music Assistant integration (#145622)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-26 17:07:05 +02:00
David Poll
13d7234f97 Add apply to make macros/callables useful in filters and tests (#144227) 2025-05-26 17:00:07 +02:00
avee87
ca50fca738 Add twice-daily forecasts to MetOffice (#145472) 2025-05-26 16:56:15 +02:00
epenet
acbfe54c7b Drop obsolete IGNORE_PIN in gen_requirements_all.py (#145487)
Drop IGNORE_PIN in gen_requirements_all.py
2025-05-26 16:49:42 +02:00
Robert Resch
49f9166646 Deprecate cups integration (#145615) 2025-05-26 16:48:41 +02:00
Åke Strandberg
42cacd28e7 Add tests to miele fan entity and api push data pathway (#144481)
* Use device class transation

* WIP

* Test api push

* Use constants

* Use callbacks registered with mock

* Add comment

* Adress review comments

* Empty commit

* Fix tests

* Updates after review
2025-05-26 16:38:41 +02:00
Marcel van der Veldt
6f9a39ab89 Add select source action to Music Assistant (#145619) 2025-05-26 16:28:18 +02:00
starkillerOG
0d81694640 Add event browsing to Reolink recordings (#144259) 2025-05-26 16:20:55 +02:00
epenet
109bcf362a Use shorthand attributes in xiaomi_miio (part 3) (#145617) 2025-05-26 16:16:18 +02:00
Erik Montnemery
0260a03447 Store information about add-ons and folders which could not be backed up (#145367)
* Store information about add-ons and folders which could not be backed up

* Address review comments
2025-05-26 16:07:33 +02:00
Simone Chemelli
0802fc8a21 Add switch platform to Amazon Devices (#145588)
* Add switch platform to Amazon Devices

* apply review comment

* make logic generic

* test cleanup
2025-05-26 16:01:11 +02:00
epenet
c346b932f0 Use shorthand attributes in xiaomi_miio (part 2) (#145616)
* Use shorthand attributes in xiaomi_miio (part 2)

* Brightness

* Is_on
2025-05-26 15:57:01 +02:00
avee87
a14f3ab6b1 Fix clear night weather condition for metoffice (#145470) 2025-05-26 15:43:28 +02:00
dontinelli
14cd00a116 Add user picture to fyta (#140934)
* Add user picture

* FYTA integration: Add separate entities for both default and user plant images (#12)

* Refactor FYTA integration to provide both default and user plant images as separate entities

* Refactor FYTA tests by removing unused CONF_USER_IMAGE option and related test cases

* Update FytaPlantImageEntity to set entity name based on image type

* Refactor FYTA image tests to accommodate separate plant and user image entities, updating assertions and snapshots accordingly.

* Enhance FYTA image handling by introducing FytaImageEntityDescription for better separation of plant and user images, and update image URL retrieval logic. Additionally, add localized strings for image entities in strings.json.

* Correct typo

* Update FYTA image snapshots to reflect changes in translation keys for plant and user images.

* Update homeassistant/components/fyta/image.py

* Update homeassistant/components/fyta/image.py

---------

Co-authored-by: dontinelli <73341522+dontinelli@users.noreply.github.com>

* Update QS + ruff

* Revert MINOR_VERSION increase and remove obsolete migration test

* Update snapshot

* Resolve comments

* Update snapshot

* Fix

---------

Co-authored-by: Alexander <chimera88@gmx.de>
2025-05-26 15:40:15 +02:00
Thomas D
486535c189 Add scene platform to Qbus integration (#144032)
* Add scene platform

* Remove updating last_activated

* Simplify device info

* Move _attr_name to specific classes

* Refactor device info

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-26 15:37:07 +02:00
Abílio Costa
54dce53628 Add sensor tests for device class enums (#145523) 2025-05-26 14:28:30 +01:00
starkillerOG
a3b7cd7b4d Implement NVR download for Reolink recordings (#144121) 2025-05-26 15:23:11 +02:00
Robin Lintermann
dafda420e5 Add smarla integration (#143081)
* Added smarla integration

* Apply suggested changes

* Bump pysmarlaapi version and reevaluate quality scale

* Focus on switch platform

* Bump pysmarlaapi version

* Change default name of device

* Code refactoring

* Removed obsolete reload function

* Code refactoring and clean up

* Bump pysmarlaapi version

* Refactoring and changed access token format

* Fix tests for smarla config_flow

* Update quality_scale

* Major rework of tests and refactoring

* Bump pysmarlaapi version

* Use object equality operator when applicable

* Refactoring

* Patch both connection objects

* Refactor tests

* Fix leaking tests

* Implemented full test coverage

* Bump pysmarlaapi version

* Fix tests

* Improve tests

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 15:21:23 +02:00
Yuxin Wang
68a4e1a112 Add reconfigure config flow to APCUPSD (#143801)
* Add reconfigure config flow

* Add reconfigure config flow

* Add more subtests for wrong device

* Reduce the patch scopes

* Address comments

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 15:10:30 +02:00
epenet
d3275c3833 Use shorthand attributes in xiaomi_miio (#145614) 2025-05-26 15:07:05 +02:00
Retha Runolfsson
2d5867cab6 Add switchbot air purifier support (#144552)
* add support for air purifier

* add unit tests for air purifier

* fix aqi translation

* fix aqi translation

* add air purifier table

* fix air purifier

* remove init and add options for aqi level
2025-05-26 15:06:33 +02:00
Retha Runolfsson
49cf66269c Set quality scale to 🥇 gold for switchbot integration (#144608)
* update quality scale

* update to gold
2025-05-26 15:06:07 +02:00
G Johansson
5642d6450f Add template to command args in command_line notify (#125170)
* Add template to command args in command_line notify

* coverage

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-05-26 15:05:44 +02:00
Sid
6ddc2193d6 Add exception handler and exception translations to eheimdigital (#145476)
* Add exception handler and exception translations to eheimdigital

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 15:05:11 +02:00
Jeef
5202bbb6af Update Weatherflow wind direction icons to use Ranged Icon Translation (#140166)
* feat: Wind direction icons

* optimize funciton

* float to int

* no-verify

* pre-change for icon translation changes

---------

Co-authored-by: Jeff Stein <6491743+jeffor@users.noreply.github.com>
2025-05-26 15:05:00 +02:00
avee87
39906cf65b Add state_class to metoffice sensors (#145496)
* Add state_class to metoffice sensors

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-26 15:04:26 +02:00
peteS-UK
c7745e0d02 Add support for SEARCH_MEDIA feature (#143261)
* initial

* initial

* add tests

* Update for list return

* translate exception

* tests for errors

* review tweaks

* test fix

* force content_type to lowercase

* Allow media_content_type = None

* new test
2025-05-26 15:01:17 +02:00
Simone Chemelli
1c1f5a779b Cleanup non-existing climate and humidifier devices for Comelit (#144624)
* Cleanup non-existing climate and humidifier devices for Comelit

* skip removing main hub device

* add tests

* complete tests

* improve logging

* fix post rebase

* apply  review comments

* typos

* fix identifiers

* fix ruff post merge

* clean post merge
2025-05-26 14:59:01 +02:00
Jan Rieger
ba0f6c3ba2 Add translations to Unifi Protect (#145548)
* Add translations to Unifi Protect

* address comments

* change `CO` to `CO alarm`
2025-05-26 14:56:55 +02:00
Andrea Turri
150110e221 add/fix miele program ids mapping (#145577)
* add/fix miele program ids mapping

* fix mistyped keys and base translations
2025-05-26 14:56:16 +02:00
Sasha Hilton
e95e9e1a33 bump starlink-grpc-core to 1.2.3 due to API change upstream (#145261) 2025-05-26 14:47:00 +02:00
epenet
c68ab714b7 Add init type hints to XiaomiMiioEntity derived entities (#145611) 2025-05-26 14:46:07 +02:00
epenet
2d2e0d0fb9 Add init type hints to XiaomiCoordinatedMiioEntity derived entities (#145612) 2025-05-26 14:45:55 +02:00
G Johansson
970359c6a0 Empty response returns empty list in Nord Pool (#145514) 2025-05-26 14:25:07 +02:00
Markus Adrario
e22fbe553b Add Homee event platform (#145569)
* add event.py

* Add strings and code improvements

* Add tests for event

* last fixes

* fix review comments

* update test snapshot
2025-05-26 14:00:30 +02:00
Petar Petrov
87c3e2c7ce Download backup if restore fails in Z-Wave migration (#145434)
* ZWaveJS migration: Download backup if restore fails

* update test

* PR comment
2025-05-26 13:56:37 +02:00
Petro31
13a6c13b89 Allow base64_encode to support bytes and strings (#145227) 2025-05-26 13:56:11 +02:00
epenet
cc504da03a Improve type hints in XiaomiGatewayDevice derived entities (#145605) 2025-05-26 13:21:00 +02:00
Petro31
25f3ab3640 Add from_hex filter (#145229) 2025-05-26 13:16:56 +02:00
Åke Strandberg
2cf09abb4c Fulfilled quality rules - gold and platinum tiers for Miele integration (#144773)
Fulfilled quality rules - gold and platinum tiers
2025-05-26 11:24:01 +02:00
Maciej Bieniek
c1c74a6f61 Mark Shelly quality as silver (#145610) 2025-05-26 12:22:46 +03:00
Avi Miller
8f9f531dd7 Bump aiolifx to 1.1.5 to improve the identification of LIFX Luna (#145416)
Signed-off-by: Avi Miller <me@dje.li>
2025-05-26 11:22:11 +02:00
Jan Bouwhuis
34d11521c0 Fix reference to "tilt command topic" in MQTT translation strings (#145563)
* Fix reference to "tilt command topic" in MQTT translation strings

* Missed one
2025-05-26 11:13:24 +02:00
Josef Zweck
561be22a60 Disable last cleaning sensor for gs3mp model in lamarzocco (#145576)
* Disable last cleaning sensor for gs3mp model in lamarzocco

* is comparison
2025-05-26 11:13:15 +02:00
Jan Bouwhuis
301d308d5a Add payload ON and OFF options to MQTT switch subentry component (#144627)
* Add payload ON and OFF options to MQTT switch component

* Add `state_on` and `state_off` options
2025-05-26 11:12:42 +02:00
Simone Chemelli
d975135a7c Improve Bluetooth binary_sensor for Amazon Devices (#145600)
Improve blueetooth binary_sensor for Amazon Devices
2025-05-26 11:00:09 +02:00
Simone Chemelli
19ee8886d6 Add more mac-addresses for Amazon Devices autodiscovery (#145598)
* Add more mac-addresses for Amazon Devices autodiscovery

* some more
2025-05-26 10:59:13 +02:00
Maciej Bieniek
7f4cc99a3e Use sub-devices for Shelly multi-channel devices (#144100)
* Shelly RPC sub-devices

* Better varaible name

* Add get_rpc_device_info helper

* Revert channel name changes

* Use get_rpc_device_info

* Add get_rpc_device_info helper

* Use get_block_device_info

* Use helpers in the button platform

* Fix channel name and roller mode for block devices

* Fix EM3 gen1

* Fix channel name for RPC devices

* Revert test changes

* Fix/improve test_block_get_block_channel_name

* Fix test_get_rpc_channel_name_multiple_components

* Fix tests

* Fix tests

* Fix tests

* Use key instead of index to generate sub-device identifier

* Improve logic for Pro RGBWW PM

* Split channels for em1

* Better channel name

* Cleaning

* has_entity_name is True

* Add get_block_sub_device_name() function

* Improve block functions

* Add get_rpc_sub_device_name() function

* Remove _attr_name

* Remove name for button with device class

* Fix names of virtual components

* Better Input name

* Fix get_rpc_channel_name()

* Fix names for Inputs

* get_rpc_channel_name() improvement

* Better variable name

* Clean RPC functions

* Fix input_name type

* Fix test

* Fix entity_ids for Blu Trv

* Fix get_block_channel_name()

* Fix for Blu Trv, once again

* Revert name for reboot button

* Fix button tests

* Fix tests

* Fix coordinator tests

* Fix tests for cover platform

* Fix tests for event platform

* Fix entity_ids in init tests

* Fix get_block_channel_name() for lights

* Fix tests for light platform

* Fix test for logbook

* Update snapshots for number platform

* Fix tests for sensor platform

* Fix tests for switch platform

* Fix tests for utils

* Uncomment

* Fix tests for flood

* Fix Valve entity name

* Fix climate tests

* Fix test for diagnostics

* Fix tests for init

* Remove old snapshots

* Add tests for 2PM Gen3

* Add comment

* More tests

* Cleaning

* Clean fixtures

* Update tests

* Anonymize coordinates in fixtures

* Split Pro 3EM entities into sub-devices

* Make sub-device names more unique

* 3EM (gen1) does not support sub-devices

* Coverage

* Rename "device temperature" sensor to the "relay temperature"

* Update tests after rebase

* Support sub-devices for 3EM (gen1)

* Mark has-entity-name rule as done 🎉

* Rename `relay temperature` to `temperature`
2025-05-26 10:47:22 +02:00
epenet
d4333665fc Add issue trackers to requirements script exceptions (#145608) 2025-05-26 10:21:38 +02:00
TheJulianJES
ba0c03ddbb Bump ZHA to 0.0.59 (#145597) 2025-05-26 06:53:09 +02:00
Ivan Lopez Hernandez
32eb4af6ef Enable message Streaming in the Gemini integration. (#144937)
* Added streaming implementation

* Indicate the entity supports streaming

* Added tests

* Removed unused snapshots

---------

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2025-05-25 21:50:55 -04:00
Josef Zweck
e4b519d77a Bump pylamarzocco to 2.0.6 (#145595) 2025-05-25 23:59:06 +02:00
Raphael Hehl
14c4cf7b63 Bump uiprotect to version 7.10.0 (#145596) 2025-05-25 23:51:52 +02:00
Paulus Schoutsen
1cc2baa95e Pipeline to stream TTS on tool call (#145477) 2025-05-25 14:59:07 -05:00
Raphael Hehl
f472bf7c87 Bump uiprotect to version 7.9.2 (#145583) 2025-05-25 18:42:02 +02:00
Joost Lekkerkerker
bc9683312e Change cooler name to fridge in SmartThings (#145590) 2025-05-25 18:40:04 +02:00
Joost Lekkerkerker
6634efa3aa Add DHCP discovery to Amazon Devices (#145587)
* Add DHCP discovery to Amazon Devices

* Add DHCP discovery to Amazon Devices

* Add DHCP discovery to Amazon Devices
2025-05-25 18:20:44 +02:00
Simone Chemelli
d0b2331a5f New integration Amazon Devices (#144422)
* New integration Amazon Devices

* apply review comments

* bump aioamazondevices

* Add notify platform

* pylance

* full coverage for coordinator tests

* cleanup imports

* Add switch platform

* update quality scale: docs items

* update quality scale: brands

* apply review comments

* fix new ruff rule

* simplify EntityDescription code

* remove additional platforms for first PR

* apply review comments

* update IQS

* apply last review comments

* snapshot update

* apply review comments

* apply review comments
2025-05-25 17:42:07 +02:00
Maciej Bieniek
46951bf223 Add returned energy sensor for Shelly RPC switch component (#145490)
* Add returned energy sensor for switch component

* Add test

* More tests

* Make returned energy sensor disabled by default
2025-05-25 16:16:55 +02:00
Marc Mueller
565f051ffc Fix aiohttp MockPayloadWriter (#145579) 2025-05-25 14:38:08 +02:00
Florian von Garrel
8c971904ca Add reauth and reconfigure to paperless (#145469)
* Add reauth and reconfigure

* Reauth and reconfigure in different functions

* Add duplicate check

* Add test for reconfigure duplicate

* Removed seconds config entry fixture
2025-05-25 14:03:13 +02:00
Josef Zweck
d0bc71752b Safe get for backflush status in lamarzocco (#145559)
* Safe get for backflush status in lamarzocco

* add correct default
2025-05-25 14:01:15 +02:00
Franck Nijhof
6b1484a7f0 Merge branch 'master' into dev 2025-05-25 10:40:31 +00:00
Joost Lekkerkerker
5eebadc730 Add SmartThings freezer and cooler temperatures (#145468) 2025-05-25 10:38:57 +02:00
tronikos
fa37bc272e Bump opower to 0.12.2 (#145573) 2025-05-25 10:37:50 +02:00
Simone Chemelli
535d128f8a Remove global registry reference in coordinator for UptimeRobot (#142938)
* Remove global registry reference in coordinator for UptimeRobot

* rework current_monitors listing

* fix logic
2025-05-25 02:03:07 +02:00
J. Nick Koston
13d530d110 Bump aiohttp to 3.12.0 (#145570) 2025-05-24 18:10:58 -05:00
Pete Sage
57f754b42b Bump aiokem to 0.5.12 (#145565) 2025-05-24 18:04:26 -05:00
Josef Zweck
1e0a2b704f Bump pylamarzocco to 2.0.5 (#145560) 2025-05-24 23:46:51 +02:00
Simone Chemelli
526a8ee31f Add preset mode to Comelit climate (#145195) 2025-05-25 00:37:21 +03:00
J. Nick Koston
ce02a5544d Bump aiohttp to 3.12.0rc1 (#145562) 2025-05-24 16:12:16 -05:00
Simon Lamon
1044a5341d Bump python-linkplay to v0.2.8 (#145550)
* Bump linkplay to v0.2.7

* Bump linkplay to v0.2.8
2025-05-24 21:53:41 +02:00
Jan Bouwhuis
a707cbc51b Fix translation strings for MQTT subentries (#145529) 2025-05-24 21:26:49 +02:00
tronikos
adf8e50313 Add data descriptions in the Android TV Remote Configure Android apps (#145537)
* Add data descriptions in the Android TV Remote Configure Android apps

* Update homeassistant/components/androidtv_remote/strings.json

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-05-24 21:20:04 +02:00
tronikos
8356bdb506 Bump androidtvremote2 to 0.2.2 (#145542) 2025-05-24 17:41:40 +02:00
Abílio Costa
5c7aa833ec Simplify ZBT-1 setup string (#145532) 2025-05-24 11:41:16 +02:00
Jan Bouwhuis
f92d14d87c Bump incomfort-client to v0.6.9 (#145546) 2025-05-24 10:53:08 +02:00
J. Nick Koston
2d3a6d780c Bump aiohttp to 3.12.0rc0 (#145540)
changelog: https://github.com/aio-libs/aiohttp/compare/v3.12.0b3...v3.12.0rc0
2025-05-24 09:52:48 +02:00
Petro31
c359765a29 Remove inactive codeowner from template integration (#145535) 2025-05-23 23:59:22 +02:00
Michael
d8ed10bcc7 Use _handle_coordinator_update() instead of own callback in Feedreader event entity (#145520)
use _handle_coordinator_update() instead of own callback
2025-05-23 21:10:26 +02:00
karwosts
19259d5cad Add read_only selectors to Statistics Options Flow (#145522) 2025-05-23 17:58:45 +02:00
epenet
102230bf9d Remove repoze.lru from license exceptions (#145519)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-23 17:46:09 +02:00
Jan Bouwhuis
2a38f03ec9 Add MQTT fan as entity platform on MQTT subentries (#144698) 2025-05-23 17:40:54 +02:00
Ludovic BOUÉ
e22ea85e84 Add Matter Pump device type (#145335)
* Pump status

* Pump speed

* PumpStatusRunning

* ControlModeEnum

* Add tests

* Clean code

* Update tests and sensors

* Review fixes

* Add RPM unit

* Fix for unknown value

* Update snapshot

* OperationMode

* Update snapshots

* Update snapshot

* Update tests/components/matter/test_select.py

Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>

* Handle SupplyFault bit enabled too

* Review fix

* Unmove

* Remove pump_operation_mode

* Update snapshot

---------

Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
2025-05-23 17:20:27 +02:00
Michael
ed0ff93d1e Bump py-sucks to 0.9.11 (#145518)
bump py-sucks to 0.9.11
2025-05-23 17:12:43 +02:00
Franck Nijhof
3e6473d130 2025.5.3 (#145516) 2025-05-23 17:09:32 +02:00
karwosts
7af731694f Support readonly selectors in config_flows (#129456)
* Allow disabled selectors in config flows. Show hidden options for history_stats.

* fix tests

* use optional instead of required

* rename flag to readonly

* rename to read_only

* Update to use read_only field as part of selector definition

* lint fix

* Fix test

* All selectors
2025-05-23 17:05:43 +02:00
epenet
83ec45e4fc Use runtime_data in xiaomi_miio (#145517)
* Use runtime_data in xiaomi_miio

* Reduce changes
2025-05-23 17:03:33 +02:00
Michael
086e97821f Add automatic backup event entity to Home Assistant Backup system (#145350)
* add automatic backup event entity

* add tests

* fix test

* Apply suggestions from code review

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

* implement _handle_coordinator_update

* add translations for event attributes

* simplify condition

* Apply suggestions from code review

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

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-23 17:01:57 +02:00
Petro31
5048d1512c Add trigger based template cover (#145455)
* Add trigger based template cover

* address comments

* update position template in test
2025-05-23 16:32:21 +02:00
Denis Shulyaka
199c565bf2 Add Anthropic Claude 4 support (#145505)
Add Claude 4 support

Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-23 10:31:44 -04:00
epenet
cbeefdaf26 Mark humidifier methods and properties as mandatory in pylint plugin (#145507) 2025-05-23 16:26:22 +02:00
Michael
4747de4703 Don't manipulate hvac modes based on device active mode in AVM Fritz!SmartHome (#145513) 2025-05-23 16:12:13 +02:00
Franck Nijhof
9a183bc16a Bump version to 2025.5.3 2025-05-23 14:03:47 +00:00
Robert Resch
e540247c14 Bump deebot-client to 13.2.1 (#145492) 2025-05-23 14:03:02 +00:00
rappenze
0aef8b58d8 Bump pyfibaro to 0.8.3 (#145488) 2025-05-23 14:03:01 +00:00
tronikos
f0501f917b Fix strings related to Google search tool in Google AI (#145480) 2025-05-23 14:02:59 +00:00
tronikos
97004e13cb Make Gemma models work in Google AI (#145479)
* Make Gemma models work in Google AI

* move one line to be improve readability
2025-05-23 14:02:58 +00:00
tronikos
f867a0af24 Bump opower to 0.12.1 (#145464) 2025-05-23 14:02:57 +00:00
Joost Lekkerkerker
d3b3839ffa Bump pysmartthings to 3.2.3 (#145444) 2025-05-23 14:02:56 +00:00
starkillerOG
1a227d6a10 Reolink fix device migration (#145443) 2025-05-23 14:02:54 +00:00
Joost Lekkerkerker
fc8c403a3a Bump yt-dlp to 2025.05.22 (#145441) 2025-05-23 14:02:53 +00:00
Josef Zweck
c1bf596eba Mark backflush binary sensor not supported for GS3 MP in lamarzocco (#145406) 2025-05-23 14:02:52 +00:00
Michael
63f69a9e3d Bump py-synologydsm-api to 2.7.2 (#145403)
bump py-synologydsm-api to 2.7.2
2025-05-23 14:02:51 +00:00
Josef Zweck
e13b014b6f Bump pylamarzocco to 2.0.4 (#145402) 2025-05-23 14:02:49 +00:00
c0ffeeca7
be0d4d926c OTBR: remove links to obsolete multiprotocol docs (#145394) 2025-05-23 14:02:48 +00:00
Raj Laud
2403fff81f Bump pysqueezebox to v0.12.1 (#145384) 2025-05-23 14:02:47 +00:00
Andy
8c475787cc Fix: Revert Ecovacs mower total_stats_area unit to square meters (#145380) 2025-05-23 14:02:45 +00:00
peteS-UK
d9fe1edd82 Add initial coordinator refresh for players in Squeezebox (#145347)
* initial

* add test for new player
2025-05-23 14:02:44 +00:00
Michael
f5cf64700a Fix limit of shown backups on Synology DSM location (#145342) 2025-05-23 14:02:43 +00:00
Josef Zweck
777b04d7a5 Handle more exceptions in azure_storage (#145320) 2025-05-23 14:02:41 +00:00
Josef Zweck
9fc78ed4e2 Add cloud as after_dependency to onedrive (#145301) 2025-05-23 14:02:40 +00:00
Matthew FitzGerald-Chamberlain
d03af549d4 Bump pyaprilaire to 0.9.0 (#145260) 2025-05-23 14:02:39 +00:00
G Johansson
d91f01243c Bump holidays to 0.73 (#145238) 2025-05-23 14:02:38 +00:00
Martin Hjelmare
5094208db6 Fix Z-Wave config entry unique id after NVM restore (#145221)
* Fix Z-Wave config entry unique id after NVM restore

* Remove stale comment
2025-05-23 14:01:37 +00:00
Simone Chemelli
006f66a841 Bump aiocomelit to 0.12.3 (#145209) 2025-05-23 14:01:36 +00:00
Maikel Punie
64b7d77840 Bump velbusaio to 2025.5.0 (#145198) 2025-05-23 14:01:35 +00:00
Martin Hjelmare
abf6a809b8 Fix Z-Wave unique id update during controller migration (#145185) 2025-05-23 14:01:33 +00:00
Martin Hjelmare
1b7dd205c7 Improve Z-Wave config flow tests (#144871)
* Improve Z-Wave config flow tests

* Fix test

* Use identify check for result type
2025-05-23 14:01:32 +00:00
Keilin Bickar
3e00366a61 Bump sense-energy to 0.13.8 (#145156) 2025-05-23 13:50:34 +00:00
karwosts
a17275b559 Fix history_stats with sliding window that ends before now (#145117) 2025-05-23 13:50:33 +00:00
Jan-Philipp Benecke
9534a919ce Add missing device condition translations to lock component (#145104) 2025-05-23 13:45:44 +00:00
Joost Lekkerkerker
422dbfef88 Map auto to heat_cool for thermostat in SmartThings (#145098) 2025-05-23 13:45:43 +00:00
Robert Resch
8e44684a61 Fix proberly Ecovacs mower area sensors (#145078) 2025-05-23 13:45:41 +00:00
Manu
642e7fd487 Bump aiontfy to 0.5.2 (#145044) 2025-05-23 13:45:40 +00:00
peteS-UK
9bb9132e7b Fix album and artist returning "None" rather than None for Squeezebox media player. (#144971)
* fix

* snapshot update

* cast type
2025-05-23 13:45:39 +00:00
J. Nick Koston
41be82f167 Bump ESPHome stable BLE version to 2025.5.0 (#144857) 2025-05-23 13:45:37 +00:00
Marc Hörsken
47140e14d9 Postpone update in WMSPro after service call (#144836)
* Reduce stress on WMS WebControl pro with higher scan interval

Avoid delays and connection issues due to overloaded hub.
Fixes #133832 and #134413

* Schedule an entity state update after performing an action

Avoid delaying immediate status updates, e.g. on/off changes.

* Replace scheduled state updates with delayed action completion

Suggested-by: joostlek
2025-05-23 13:45:36 +00:00
TheOneValen
926502b0f1 Allow image send with read-only access (matrix notify) (#144819) 2025-05-23 13:45:35 +00:00
disforw
78351ff7a7 Fix QNAP fail to load (#144675)
* Update coordinator.py

* Update coordinator.py

@peternash

* Update coordinator.py

* Update coordinator.py

* Update coordinator.py

* Update coordinator.py
2025-05-23 13:45:33 +00:00
wuede
c333726867 Netatmo: do not fail on schedule updates (#142933)
* do not fail on schedule updates

* add test to check that the store data remains unchanged
2025-05-23 13:45:32 +00:00
starkillerOG
fc2fe32f34 Reolink fix device migration (#145443) 2025-05-23 15:33:03 +02:00
epenet
528a509479 Mark light methods and properties as mandatory in pylint plugin (#145510) 2025-05-23 14:28:41 +01:00
Franck Nijhof
bca4793c69 Add concentration conversion support for mg/m³ (#145325) 2025-05-23 14:24:18 +01:00
Josef Zweck
0c9b1b5c58 Add cloud as after_dependency to onedrive (#145301) 2025-05-23 15:07:06 +02:00
Robert Resch
7bf4239789 Bump deebot-client to 13.2.1 (#145492) 2025-05-23 14:54:18 +02:00
epenet
71ac2d3d75 Improve type hints in xiaomi_miio humidifier (#145506) 2025-05-23 14:54:09 +02:00
Denis Shulyaka
f019e8a36c Bump Anthropic library to 0.52.0 (#145494) 2025-05-23 14:48:54 +02:00
J. Nick Koston
44560dd298 Bump aiohttp to 3.12.0b3 (#145358) 2025-05-23 14:44:47 +02:00
Jan Bouwhuis
e8ea5c9d62 Add MQTT cover as entity platform on MQTT subentries (#144381)
* Add MQTT cover as entity platform on MQTT subentries

* Revert change vol.Coerce wrappers on cover schema

* Fix template validator and cleanup redundant validators

* Cleanup more redundant validators
2025-05-23 14:25:00 +02:00
Jan Bouwhuis
17297ab929 Improve mqtt subentry selector validation and remove redundant validators (#145499) 2025-05-23 13:23:36 +02:00
rappenze
041c09380b Bump pyfibaro to 0.8.3 (#145488) 2025-05-23 12:05:13 +02:00
Markus Lanthaler
553d420db9 Add support for Tuya Wireless Switch entity (#123284)
Add support for Tuya Wireless Switch entity
2025-05-23 08:42:09 +02:00
Joost Lekkerkerker
3f99a0bb65 Add diagnostics to Paperless-ngx (#145465)
* Add diagnostics to Paperless-ngx

* Add diagnostics to Paperless-ngx
2025-05-23 08:09:54 +02:00
Joost Lekkerkerker
c3d318ff51 Add paperless-ngx to strict typing (#145466) 2025-05-23 08:08:44 +02:00
Erik Montnemery
19345b0e18 Prefer to create backups in local storage if selected (#145331) 2025-05-23 08:00:35 +02:00
tronikos
e13abf2034 Make Gemma models work in Google AI (#145479)
* Make Gemma models work in Google AI

* move one line to be improve readability
2025-05-22 22:02:30 -07:00
tronikos
61248c561d Fix strings related to Google search tool in Google AI (#145480) 2025-05-22 22:01:48 -07:00
epenet
8561721faf Add pytest/codecov to forbidden runtime dependencies (#145447)
Add pytest/codecov to forbidden runtime packages
2025-05-22 23:15:21 +02:00
Manu
2f318927bc Add pending damage and pending quest items sensors (#145449)
Add pending damage and quest items sensors
2025-05-22 23:10:49 +02:00
tronikos
a15572bb8c Bump opower to 0.12.1 (#145464) 2025-05-22 22:22:20 +02:00
Bonne Eggleston
b532776d78 Make Powerwall energy sensors TOTAL_INCREASING to fix hardware swaps (#145165) 2025-05-22 14:49:39 -05:00
Abílio Costa
4ad34c57b5 Replace empty mock in GoalZero tests (#145463) 2025-05-22 20:22:09 +01:00
Abílio Costa
228beacca8 Add default sensor data for Tesla Wall Connector tests (#145462) 2025-05-22 21:20:57 +02:00
Norbert Rittel
c130a9f31c Fix typo in reauth_confirm description of metoffice (#145458) 2025-05-22 21:12:37 +02:00
Michael
622ab922b5 Add configuration url to Immich device info (#145456)
add configuration url to device info
2025-05-22 21:09:28 +02:00
epenet
6de2258325 Mark device_tracker methods and properties as mandatory in pylint plugin (#145309) 2025-05-22 19:15:00 +01:00
jz-v
d8e0be69d1 Add HomeKit thermostat fan state mapping for preheating, defrosting (#145353)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-05-22 11:57:01 -05:00
Petro31
4ee9fdc9fb Add AbstractTemplateVacuum to prepare for trigger based template vacuums (#144990)
* Add AbstractTemplateVacuum

* fix typo from copypaste

* update after rebase
2025-05-22 17:50:26 +02:00
Petro31
a8823cc1d1 Add AbstractTempleAlarmControlPanel class to prepare for trigger based template alarm control panels (#144974)
* Add AbstractTempleAlarmControlPanel class

* update after rebase

* remove unused list
2025-05-22 17:50:15 +02:00
Petro31
83ee9e9540 Add AbstractTemplate cover to prepare for trigger based template covers (#144907)
* Add AbstractTemplate cover to prepare for trigger based template covers

* add reflection and improve test coverage

* update class after rebase

* remove test
2025-05-22 17:49:50 +02:00
Petro31
9a74390143 Add AbstractTemplateLock to prepare for trigger based template locks (#144978)
* Add AbstractTemplateLock

* update after rebase
2025-05-22 17:33:57 +02:00
Joost Lekkerkerker
64d6552890 Bump pysmartthings to 3.2.3 (#145444) 2025-05-22 17:26:59 +02:00
Joost Lekkerkerker
65ebdb4292 Bump yt-dlp to 2025.05.22 (#145441) 2025-05-22 17:26:04 +02:00
Petro31
7a55abaa42 Add AbstractTemplateFan class in preparation for trigger based entity (#144968)
* Add AbstractTemplateFan class in preparation for trigger based entity

* update after rebase
2025-05-22 17:18:48 +02:00
dalan
8f05a639f3 HomeKit Bridge integration: Adding h264_qsv as valid VIDEO_CODEC option (#145448) 2025-05-22 09:52:58 -05:00
TimL
917b467b85 Add SMLIGHT button entities for second radio (#141463)
* Add button entities for second radio

* Update tests for second router reconnect button
2025-05-22 14:50:22 +02:00
J. Diego Rodríguez Royo
a938001805 Don't add dynamically Home Connect event sensors and disable them by default (#144757)
* Don't add dynamically Home Connect sensors and disable them by default

* Fix test

* Check for None

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-22 12:55:11 +02:00
Ludovic BOUÉ
9e6de48a22 Matter Device Energy Management cluster ESAState attribute (#144430)
* ESAState

* Update strings.json

* Add test
2025-05-22 12:53:08 +02:00
jvmahon
569aeff054 Add matter attributes (#140843)
* Add Matter attributes

* Add Matter attributes

* Add Matter attributes

* Add Matter attributes

* Update strings.json

* Update homeassistant/components/matter/select.py

Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>

* Update select.py

Deleted items to be added as switch entities instead.

* Update strings.json

* Update select.py

* Update strings.json

* Fix

* Update strings.json

* Update strings.json

* Fix

* Update select.py

---------

Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-22 12:42:05 +02:00
Joost Lekkerkerker
c86ba49a79 Add Matter test to select attribute (#145440) 2025-05-22 12:40:56 +02:00
epenet
3b4004607d Mark image_processing methods and properties as mandatory in pylint plugin (#145435) 2025-05-22 12:19:22 +02:00
Gigatrappeur
c68e663a1c Add webhook in switchbot cloud integration (#132882)
* add webhook in switchbot cloud integration

* Rename _need_initialized to _is_initialized and reduce nb line in async_setup_entry

* Add unit tests

* Enhance poll management

* fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-22 12:19:08 +02:00
Tamer Wahba
d870410413 Quantum Gateway device tracker tests (#145161)
* move constants to central const file

* add none return type to device scanner constructor

* add quantum gateway device tracker tests

* fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-22 12:18:56 +02:00
Florian von Garrel
9a8c29e05d Add paperless integration (#145239)
* add paperless integration - config flow and initialisation

* Add first sensors - documents, inbox, storage total and available

* Add status sensors with error attributes

* add status coordinator and organized code

* Fixed None error

* Organized code and moved requests to coordinator

* Organized code

* optimized code

* Add statustype state strings

* Error handling

* Organized code

* Add update sensor and one coordinator for integration

* add sanity sensor and timer for version request

* Add sensors and icons.json. better errorhandling

* Add tests and error handling

* FIxed tests

* Add tests for coverage

* Quality scale

* Stuff

* Improved code structure

* Removed sensor platform and reauth / reconfigure flow

* bump pypaperless to 4.1.0

* Optimized tests; update sensor as update platform; little optimizations

* Code optimizations with update platform

* Add sensor platform

* Removed update platform

* quality scale

* removed unused const

* Removed update snapshot; better code

* Changed name of entry

* Fixed bugs

* Minor changes

* Minor changed and renamed sensors

* Sensors to measurement

* Fixed snapshot; test data to json; minor changes

* removed mypy errors

* Changed translation

* minor changes

* Update homeassistant/components/paperless_ngx/strings.json

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-22 12:17:38 +02:00
epenet
a54c8a88ff Improve type hints in microsoft_face_detect (#145421)
* Improve type hints in microsoft_face_detect

* Improve
2025-05-22 11:52:26 +02:00
Manuel Rüger
ca914d8e4f switchbot_cloud: Add Smart Lock door and calibration state (#143695)
* switchbot_cloud: Add Smart Lock door and calibration state

* Incorporate review
2025-05-22 11:51:28 +02:00
epenet
687bedd251 Improve type hints in sighthound (#145432)
* Improve type hints in sighthound

* More
2025-05-22 11:35:06 +02:00
Franck Nijhof
5ddadcbd65 Add range support to icon translations (#145340) 2025-05-22 11:32:33 +02:00
epenet
981842ee87 Improve type hints in seven_segments (#145431)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-22 11:31:17 +02:00
epenet
ab69223d75 Improve type hints in openalpr_cloud (#145429)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-22 11:30:53 +02:00
epenet
69f0f38a09 Improve type hints in qrcode (#145430)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-22 11:30:38 +02:00
epenet
40267760fd Improve type hints in tensorflow (#145433)
* Improve type hints in tensorflow

* Use ANTIALIAS again

* Use Image.Resampling.LANCZOS
2025-05-22 11:23:33 +02:00
marc7s
6e74b56649 Catch invalid settings error in geocaching (#139944)
Refactoring and preparation for other sensor types
2025-05-22 11:22:33 +02:00
epenet
d35802a996 Improve type hints in microsoft_face (#145417)
* Improve type hints in microsoft_face

* Remove hass from init
2025-05-22 11:21:45 +02:00
Martin Hjelmare
c007286fd6 Improve Z-Wave config flow test typing (#145438) 2025-05-22 11:11:38 +02:00
Joost Lekkerkerker
b5a3cedacd Move to explicit exports in test helpers (#145392) 2025-05-22 10:44:31 +02:00
epenet
3d53bdc6c5 Improve type hints in dlib_face_identify (#145423) 2025-05-22 10:37:44 +02:00
epenet
a7f6a6f22c Improve type hints in dlib_face_detect (#145422) 2025-05-22 10:37:03 +02:00
epenet
7893eaa389 Improve type hints in microsoft_face_identify (#145419) 2025-05-22 10:36:12 +02:00
Lektri.co
e410977e64 Add new button to the Lektrico integration (#145420) 2025-05-22 10:34:14 +02:00
peteS-UK
d48ca1d858 Hotfix for incorrect bracket in messages for Squeezebox (#145418)
hotfix for wrong bracket
2025-05-22 10:07:10 +02:00
epenet
8758a086c1 Improve type hints in doods (#145426) 2025-05-22 09:18:28 +02:00
Pete Sage
1db5c514e6 Add binary_sensor platform to Rehlko (#145391)
* feat: add binary_sensor platform to Rehlko

* feat: add binary sensor platform

* fix: simplify availability logic

* fix: simplify availability logic

* fix: simplify

* fix: rename sensor

* fix: rename sensor

* fix: rename sensor

* fix: remove unneeded type

* fix: rename sensor to 'Auto run'

* fix: use device_class name
2025-05-22 09:07:38 +02:00
Joost Lekkerkerker
613aa9b2cf Add climate entity for heatpump zones in SmartThings (#144991)
* Add climate entity for heatpump zones in SmartThings

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Sync SmartThings EHS fixture
2025-05-22 08:27:01 +02:00
Joost Lekkerkerker
4c6e854cad Add valve position capability to SmartThings (#144923)
* Add another EHS SmartThings fixture

* Add another EHS

* Add valve position capability to SmartThings

* Fix

* Fix
2025-05-22 08:25:41 +02:00
Michael
66a6e55310 Centralise MockStreamReaderChunked helper (#145404)
centralize MockStreamReaderChunked helper
2025-05-22 08:22:02 +02:00
Pete Sage
bffbd5607b Remove unneeded parenthesis in comparison for Sonos (#145413)
fix: remove unneeded paren
2025-05-22 08:17:31 +02:00
Ludovic BOUÉ
12b5dbdd83 Add CancelBoost for Matter Water heater (#145316)
* Update water_heater.py

Add CancelBoost

* Add test for CancelBoost

* Update water_heater.py
2025-05-22 08:01:42 +02:00
epenet
9e7ae1daa4 Catch blocking version pinning in dependencies early (#145364)
* Catch upper bindings in dependencies early

* One more

* Apply suggestions from code review
2025-05-22 07:56:18 +02:00
Petro31
f36ee88a87 Clean up AbstractTemplateEntity (#145409)
Clean up abstract templates
2025-05-22 07:23:44 +02:00
Manu
8b3bad1f54 Bump habiticalib to v.0.4.0 (#145414)
Bump habiticalib to v0.4.0
2025-05-22 07:22:50 +02:00
epenet
b407792bd1 Mark geo_location methods and properties as mandatory in pylint plugin (#145313) 2025-05-22 01:57:39 +03:00
Paulus Schoutsen
12376a2338 Mark LLMs that support streaming as such (#145405) 2025-05-22 01:54:29 +03:00
epenet
088cfc3576 Mark fan methods and properties as mandatory in pylint plugin (#145311) 2025-05-21 23:29:33 +02:00
epenet
01b8f97201 Mark cover methods and properties as mandatory in pylint plugin (#145308) 2025-05-21 22:27:53 +01:00
Lektri.co
195e34cc09 Bump lektricowifi to 0.1 (#145393)
Use lektricowifi 0.1: add a new command
2025-05-21 22:43:42 +02:00
peteS-UK
fbab6741af Update exception handling for initialization for Squeezebox (#144674)
* initial

* tests

* translate exceptions

* updates

* tests updates

* remove bare exception

* merge fix
2025-05-21 22:37:07 +02:00
J. Nick Koston
e2b9e21c6a Bump ESPHome stable BLE version to 2025.5.0 (#144857) 2025-05-21 16:23:04 -04:00
Michael
4a26352c50 Bump py-synologydsm-api to 2.7.2 (#145403)
bump py-synologydsm-api to 2.7.2
2025-05-21 22:22:33 +02:00
Josef Zweck
d43371ed2f Bump pylamarzocco to 2.0.4 (#145402) 2025-05-21 22:02:14 +02:00
avee87
4f24d63de1 Update metoffice to use DataHub API (#131425)
* Update metoffice to use DataHub API

* Reauth test

* Updated to datapoint 0.11.0

* Less hacky check for day/night in twice-daily forecasts

* Updated to datapoint 0.12.1, added daily forecast

* addressed review comments

* one more nit

* validate credewntials in reauth flow

* Addressed review comments

* Attempt to improve coverage

* Addressed comments

* Reverted unnecessary reordering

* Update homeassistant/components/metoffice/sensor.py

* Update tests/components/metoffice/test_sensor.py

* Update homeassistant/components/metoffice/sensor.py

---------

Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-21 21:56:32 +02:00
Joost Lekkerkerker
cd9339903f Add thermostat fixture to SmartThings (#145407) 2025-05-21 21:17:03 +02:00
Josef Zweck
ca01bdc481 Mark backflush binary sensor not supported for GS3 MP in lamarzocco (#145406) 2025-05-21 21:12:43 +02:00
Joost Lekkerkerker
39a5341ab8 Add SmartThings capability for Washer soil level (#145041) 2025-05-21 20:27:38 +02:00
c0ffeeca7
3c93f6e3f9 ZHA repairs: remove links to obsolete docs (#145398) 2025-05-21 20:23:05 +02:00
Tsvi Mostovicz
13ce4322ac Reword sunset event exception (#145400) 2025-05-21 20:21:06 +02:00
Jeremiah Paige
b3ba506e6c wsdot component adopts wsdot package (#144914)
* wsdot component adopts wsdot package

* update generated files

* format code

* move wsdot to async_setup_platform

* Fix tests

* cast wsdot travel id

* bump wsdot to 0.0.1

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-21 20:15:26 +02:00
Joost Lekkerkerker
ea9fc6052d Add power cool and power freeze to SmartThings (#145102) 2025-05-21 20:14:13 +02:00
Joost Lekkerkerker
c8ceea4be8 Add SmartThings capability for Washer spin level (#145039) 2025-05-21 20:01:12 +02:00
Marc Mueller
3df993b9a4 Update igloohome-api to 0.1.1 (#145401) 2025-05-21 19:42:13 +02:00
Marc Mueller
980f19173f Update sensorpro-ble to 0.7.1 (#145397) 2025-05-21 18:40:32 +02:00
Marc Mueller
b1da600269 Update inkbird-ble to 0.16.2 (#145396) 2025-05-21 18:40:24 +02:00
Marc Mueller
34c5f79983 Update bluetooth-auto-recovery to 1.5.2 (#145395) 2025-05-21 18:40:18 +02:00
Joost Lekkerkerker
4cd3527761 Enable B009 (#144192) 2025-05-21 16:37:51 +01:00
TheOneValen
1dbe1955eb Allow image send with read-only access (matrix notify) (#144819) 2025-05-21 17:18:34 +02:00
c0ffeeca7
743abadfcf OTBR: remove links to obsolete multiprotocol docs (#145394) 2025-05-21 17:11:19 +02:00
Tsvi Mostovicz
bbd223af1f Jewish Calendar: Make exception translatable (#145376) 2025-05-21 17:07:36 +02:00
Martin Hjelmare
cb717c0ec6 Improve Z-Wave config flow test fixtures (#145378) 2025-05-21 17:06:36 +02:00
Martin Hjelmare
4956cf3727 Fix Z-Wave installation type string (#145390) 2025-05-21 17:04:48 +02:00
epenet
f76165e761 Prevent types-*/setuptools/wheel runtime requirements in dependencies (#145381)
Prevent setuptools/wheel runtime requirements in dependencies
2025-05-21 16:17:24 +02:00
Erik Montnemery
dd00d0daad Improve failing backup repair messages (#145388) 2025-05-21 16:16:50 +02:00
Andre Lengwenus
77ec87d0ac Bump lcn-frontend to 0.2.5 (#144983) 2025-05-21 16:10:25 +02:00
Raj Laud
2209f0b884 Bump pysqueezebox to v0.12.1 (#145384) 2025-05-21 15:17:51 +02:00
Andy
61fd073a5c Fix: Revert Ecovacs mower total_stats_area unit to square meters (#145380) 2025-05-21 14:19:37 +02:00
Petar Petrov
efa7fe0dc9 Recommended installation option for Z-Wave (#145327)
Recommended installation option for ZWave
2025-05-21 13:30:59 +02:00
Erik Montnemery
00a1d9d1b0 Improve comment explaining planned backup store version bump (#145368) 2025-05-21 13:22:05 +02:00
Retha Runolfsson
630c438834 Add lock ultra and lock lite for switchbot integration (#145373) 2025-05-21 12:37:47 +02:00
Sid
3ada93b293 Bump eheimdigital to 1.2.0 (#145372) 2025-05-21 12:35:10 +02:00
c0ffeeca7
291499d5e1 Update links to user docs: Connect-ZBT-1, Green, Yellow (#145374) 2025-05-21 10:57:20 +01:00
Retha Runolfsson
08c453581c Add hub3 support for switchbot integration (#145371)
add support for hub3
2025-05-21 11:12:08 +02:00
Michael
5e25bbba2d Fix limit of shown backups on Synology DSM location (#145342) 2025-05-21 10:22:47 +02:00
Erik Montnemery
eb85185072 Minor code deduplication in backup manager (#145366) 2025-05-21 10:19:53 +02:00
Retha Runolfsson
3f72030d5f Bump pyswitchbot to 0.64.1 (#145360) 2025-05-21 10:08:32 +02:00
peteS-UK
69a4d2107f Add initial coordinator refresh for players in Squeezebox (#145347)
* initial

* add test for new player
2025-05-20 23:29:55 +02:00
Joris Drenth
46fe132e83 Add sensors to Wallbox (#145247) 2025-05-20 22:02:07 +01:00
Ernst Klamer
c60f19b35b Bump xiaomi-ble to 0.39.0 (#145348) 2025-05-20 22:37:27 +02:00
Petar Petrov
ba44986524 Remove the old ZWave controller from the list of migration targets (#145281)
* Remove the old ZWave controller from the list of migration targets

* ensure addon device path is serial/by_id

* Use executor

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-20 22:11:03 +02:00
Pete Sage
73811eac0a Add support for music library folder to Sonos (#139554)
* initial prototype

* use constants

* make playing work

* remove unneeded code

* remove unneeded code

* fix regressions issues

* refactor add_to_queue

* refactor add_to_queue

* refactor add_to_queue

* simplify

* add tests

* remove bad test

* rename constants

* comments

* comments

* comments

* use snapshot

* refactor to use add_to_queue

* refactor to use add_to_queue

* add comments, redo snapshots

* update comment

* merge formatting

* code review changes

* fix: merge issue

* fix: update snapshot to include new can_search field
2025-05-20 21:48:33 +02:00
Pete Sage
3ff3cb975b Add date sensors to Rehlko (#145314)
* feat: add datetime sensors

* fix: constants

* fix: constants

* fix: move tz conversion to api

* fix: update typing
2025-05-20 21:47:45 +02:00
Lode Smets
8ec5472b79 Added support for shared spaces in Synology DSM (Photo Station) (#144044)
* Added shared space to the list of all the albums

* Added tests

* added more tests

* Apply suggestions from code review

---------

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
2025-05-20 21:17:43 +02:00
Michael
b0415588d7 Add support for videos in Immich media source (#145254)
add support for videos
2025-05-20 20:40:22 +02:00
Paulus Schoutsen
abcf925b79 Assist Pipeline stream TTS when supported and long response (#145264)
* Assist Pipeline stream TTS when supported and long response

* Indicate in run-start if streaming supported

* Simplify a little bit

* Trigger streaming based on characters

* 60
2025-05-20 13:00:27 -05:00
Josef Zweck
37e13505cf Handle more exceptions in azure_storage (#145320) 2025-05-20 19:42:10 +02:00
Pete Sage
5d76d92bcf bump aiokem to 0.5.11 (#145332)
fix: bump aiokem
2025-05-20 19:13:40 +02:00
Tsvi Mostovicz
b71870aba3 Jewish calendar: move value calculation to entity description (1/3) (#144272)
* Move make_zmanim() method to entity

* Move enum values to setup

* Create a Jewish Calendar Sensor Description

* Hold a single variable for the runtime data in the entity

* Move value calculation to sensor description

* Use a base class to keep timestamp sensor inheritance

* Move attr to entity description as well

* Move options to entity description as well

* Fix tests after merge

* Put multiline in parentheses

* Fix diagnostics tests
2025-05-20 19:01:24 +02:00
Michael
734d6cd247 bump aioimmich to 0.6.0 (#145334) 2025-05-20 18:52:52 +02:00
Tsvi Mostovicz
40faa156e2 Jewish calendar : icon translations (#145329)
* Move icons to icons.json

* Fix tests
2025-05-20 17:35:24 +02:00
jb101010-2
4737091722 Suez water: fetch historical data in statistics (#131166)
* Suez water: fetch historical data in statistics

* test review

* wip: fix few things

* Python is smarter than me

* use snapshots for statistics and add hard limit for historical stats

* refactor refresh + handle missing price

* No more auth error raised

* fix after rebase

* Review - much cleaner <3

* fix changes

* test without snapshots

* fix imports
2025-05-20 16:22:35 +02:00
Bram Kragten
4160ed190c Add Albanian (Shqip) language (#145324) 2025-05-20 16:20:06 +02:00
Erik Montnemery
8e74f63d47 Create repair issue if not all add-ons or folders were backed up (#144999)
* Create repair issue if not all add-ons or folders were backed up

* Fix spelling

* Fix _collect_errors

* Make time patching by freezegun work with mashumaro

* Addd test to hassio

* Add fixture

* Fix generating list of folders

* Add issue creation tests

* Include name of failing add-on in message

* Improve code formatting

* Rename AddonError to AddonErrorData
2025-05-20 15:23:52 +02:00
Joris Drenth
fc62bc5fc1 Add solar charging options to Wallbox integration (#139286)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-05-20 14:19:48 +01:00
G Johansson
010b4f6b15 Remove deprecated aux heat from Climate Entity component (#145151) 2025-05-20 14:48:33 +02:00
Norbert Rittel
b16d4dd94b Use preferred spelling of "setpoint" in smartthings (#145319)
* Use preferred spelling of "setpoint" in `smartthings`

Change three occurrences of "set point" to "setpoint" to match the preferred spelling in Home Assistant.

* Update test_sensor.ambr

* Update test_sensor.ambr (2)
2025-05-20 14:31:51 +02:00
Sanjay Govind
0813adc327 Update binary sensor translations for bosch_alarm (#145315)
update binary sensor translations
2025-05-20 14:19:51 +02:00
Norbert Rittel
e68cf80531 Make spelling of "setpoint" consistent in opentherm_gw (#145318) 2025-05-20 15:07:57 +03:00
epenet
258c91d483 Mark climate methods and properties as mandatory in pylint plugin (#145280)
* Mark climate methods and properties as mandatory in pylint plugin

* One more
2025-05-20 13:40:17 +02:00
epenet
64d6101fb7 Mark camera methods and properties as mandatory in pylint plugin (#145272) 2025-05-20 12:30:22 +01:00
Franck Nijhof
fb0cb7cad6 Add Wh/km unit for energy distance (#145243) 2025-05-20 12:16:27 +01:00
Brett Adams
a3c0b83dee Bump teslemetry_stream to 0.7.9 in Teslemetry (#145303)
Bump stream to 0.7.9
2025-05-20 12:33:49 +02:00
Sanjay Govind
1ff5dd8ef5 Fix issues with bosch alarm dhcp discovery (#145034)
* fix issues with checking mac address for panels added manually

* add test

* don't allow discovery to pick up a host twice

* make sure we validate tests without a mac address

* check entry is loaded

* Update config_flow.py

* apply changes from review

* assert unique id

* assert unique id
2025-05-20 12:26:41 +02:00
epenet
f3f5fca0b9 Mark turn_on/turn_off/toggle as mandatory in pylint plugin (#145249)
* Mark turn_on/turn_off/toggle as mandatory in pylint plugin

* Fixes
2025-05-20 12:00:10 +02:00
Sanjay Govind
d15a1a6711 Tidy up service call for bosch_alarm (#145306)
tidy up service call for bosch_alarm
2025-05-20 11:56:53 +02:00
epenet
e39c8e350c Add class init type hint to xiaomi_aqara (#145255) 2025-05-20 11:56:17 +02:00
epenet
c1da554eb1 Mark calendar methods and properties as mandatory in pylint plugin (#145271) 2025-05-20 11:50:31 +02:00
epenet
1f1fd8de87 Mark alarm_control_panel methods and properties as mandatory in pylint plugin (#145270) 2025-05-20 11:50:22 +02:00
Norbert Rittel
cf6cb0bd39 Fix typos in user-facing strings of zha (#145305) 2025-05-20 11:49:50 +02:00
epenet
a8264ae8ae Mark button methods and properties as mandatory in pylint plugin (#145269) 2025-05-20 11:48:33 +02:00
epenet
642dc5b49c Use shorthand attributes in rpi_camera camera (#145274)
* Use shorthand attributes in rpi_camera camera

* Improve
2025-05-20 11:47:49 +02:00
epenet
43ae0f2541 Use shorthand attributes in xiaomi_aqara (#145253)
* Use shorthand attributes for is_on/is_locked in xiaomi_aqara

* Use _attr_changed_by

* Use _attr_device_class

* Remove unused class variable

* More
2025-05-20 11:47:26 +02:00
epenet
f2233b3034 Refactor set_temperature in venstar climate (#145297)
Clarify logic in venstar climate set_temperature
2025-05-20 11:46:53 +02:00
Sanjay Govind
c3fe5f012e add date and time service to bosch_alarm (#142243)
* add date and time service

* update quality scale

* add changes from review

* fix issues after merge

* fix icons

* apply changes from review

* remove list from service schema

* update quality scale

* update strings

* Update homeassistant/components/bosch_alarm/services.py

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

* apply changes from review

* apply changes from review

* Update tests/components/bosch_alarm/test_services.py

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

* validate exception messages

* use schema to validate service call

* update docstring

* update error message

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-20 11:09:46 +02:00
epenet
7f9b454922 Improve type hints in xs1 entities (#145299) 2025-05-20 10:44:34 +02:00
epenet
15915680b5 Use shorthand attributes in xs1 climate (#145298)
* Use shorthand attributes in xs1 climate

* Improve
2025-05-20 10:42:41 +02:00
epenet
2e4226d7d3 Use shorthand attributes in venstar climate (#145294) 2025-05-20 10:25:22 +02:00
epenet
0cd93e7e65 Use shorthand attributes in vivotek camera (#145275) 2025-05-20 10:15:04 +02:00
epenet
611d5be40a Use shorthand attributes in touchline climate (#145292) 2025-05-20 10:12:20 +02:00
epenet
072bf75d71 Improve type hints in homematic climate (#145283) 2025-05-20 10:11:23 +02:00
epenet
f9000ae08c Use shorthand attributes in push camera (#145273)
* Use shorthand attributes in push camera

* Improve
2025-05-20 10:10:42 +02:00
epenet
c8183bd35a Use shorthand attributes in intesishome climate (#145285) 2025-05-20 10:10:24 +02:00
epenet
99f91003d8 Use shorthand attributes in melissa climate (#145286) 2025-05-20 10:10:12 +02:00
epenet
ed2024e67a Drop useless unit conversion in smarttub (#145287) 2025-05-20 10:09:47 +02:00
epenet
cd91aca3b5 Use shorthand attributes in tfiac climate (#145289) 2025-05-20 10:09:25 +02:00
Matthew FitzGerald-Chamberlain
77ea654a1f Bump pyaprilaire to 0.9.0 (#145260) 2025-05-20 09:51:29 +02:00
Manu
ef6d3a5236 Bump aiontfy to 0.5.3 (#145263) 2025-05-20 09:49:27 +02:00
epenet
502574e86f Use shorthand attributes in yi camera (#145276) 2025-05-20 09:32:50 +02:00
epenet
fd1ddbd93d Improve type hints in blebox climate (#145282) 2025-05-20 09:31:42 +02:00
epenet
a12bc70543 Use runtime_data in smarttub (#145279) 2025-05-20 09:15:26 +02:00
Petar Petrov
b84e93f462 Sort usb ports in Z-Wave flow so unknown devices are last (#145211)
* Sort usb ports in Z-Wave flow so unknown devices are last

* tweak

* Apply suggestions from code review

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

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-20 08:25:44 +03:00
epenet
f4b0baecd3 Improve type hints in omnilogic (#145259) 2025-05-20 00:21:44 +02:00
epenet
f700a1faa3 Use shorthand attributes in raspyrfm (#145250) 2025-05-20 00:11:52 +02:00
epenet
eb90f5a581 Improve type hints in xiaomi_aqara light turn_on (#145257) 2025-05-20 00:11:34 +02:00
Jordan Harvey
20ce879471 Add new Probe Plus integration (#143424)
* Add probe_plus integration

* Changes for quality scale

* sentence-casing

* Update homeassistant/components/probe_plus/config_flow.py

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

* Update homeassistant/components/probe_plus/config_flow.py

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

* Update tests/components/probe_plus/test_config_flow.py

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

* Update tests/components/probe_plus/test_config_flow.py

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

* remove version from configflow

* remove address var from async_step_bluetooth_confirm

* move timedelta to SCAN_INTERVAL in coordinator

* update tests

* updates from review

* add voltage device class

* remove unused logger

* remove names

* update tests

* Update config flow tests

* Update unit tests

* Reorder successful tests

* Update config entry typing

* Remove icons

* ruff

* Update async_add_entities logic

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

* sensor platform formatting

---------

Co-authored-by: Erwin Douna <e.douna@gmail.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-19 22:50:09 +02:00
epenet
df3688ef08 Mark entity methods and properties as mandatory in pylint plugin (#145210)
* Mark entity methods and properties as mandatory in pylint plugin

* Fixes
2025-05-19 22:47:24 +02:00
Michael
e76bd1bbb9 Add media_source platform to Immich integration (#145159)
* add media_source platform

* fix error messages

* use mime-type from asset info, instead of guessing it

* add dependency for http

* add tests

* use direct imports and set can_play=False for images

* fix tests
2025-05-19 22:39:04 +02:00
Nick Kuiper
d580f8a8a2 Updated code owners for the blue current integration. (#144962)
Changed code owners for the blue current integration.
2025-05-19 22:21:06 +02:00
Brett Adams
ffb485aa87 Fix streaming window cover entity in Teslemetry (#145012) 2025-05-19 22:13:15 +02:00
Paulus Schoutsen
741cb23776 Only pass serializable data to media player intent (#145244) 2025-05-19 15:03:21 -05:00
Tsvi Mostovicz
6afb60d31b Jewish Calendar - quality scale - use specific config flow (#144408) 2025-05-19 21:52:06 +02:00
disforw
761bb65ac6 Fix QNAP fail to load (#144675)
* Update coordinator.py

* Update coordinator.py

@peternash

* Update coordinator.py

* Update coordinator.py

* Update coordinator.py

* Update coordinator.py
2025-05-19 21:47:01 +02:00
Tsvi Mostovicz
7464e3944e Jewish calendar: set parallel updates to 0 (#144986)
* Set all Jewish calendar parallel updates to 0

* Update homeassistant/components/jewish_calendar/service.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-19 21:44:28 +02:00
Tsvi Mostovicz
e2f2c13e5e Jewish calendar - quality scale - fix missing translations (#144410) 2025-05-19 21:44:13 +02:00
Åke Strandberg
0ee0b2fcba Add missing Miele tumble dryer program codes (#145236) 2025-05-19 21:34:36 +02:00
G Johansson
1e9c585e8b Bump holidays to 0.73 (#145238) 2025-05-19 21:12:51 +02:00
Paulus Schoutsen
e78f4d2a29 TTS to only use stream entity method when streaming request comes in (#145167)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-19 20:54:21 +02:00
Tsvi Mostovicz
1f6faaacab Jewish Calendar: Implement diagnostics (#145180)
* Implement diagnostics

* Add testing

* Remove implicitly tested code
2025-05-19 20:41:00 +02:00
karwosts
7e895f7d10 Fix history_stats with sliding window that ends before now (#145117) 2025-05-19 20:03:59 +02:00
Norbert Rittel
5031ffe767 Fix wording of "Estimated power production" sensors in forecast_solar (#145201) 2025-05-19 20:02:37 +02:00
Paulus Schoutsen
37fe25cfdc Add support_streaming to ConversationEntity (#144998)
* Add support_streaming to ConversationEntity

* pipeline tests
2025-05-19 13:43:06 -04:00
epenet
cff7aa229e Add missing type hint in plex (#145217) 2025-05-19 19:18:22 +02:00
Paulus Schoutsen
e09dde2ea9 Allow TTS streams to generate temporary media source IDs (#145080)
* Allow TTS streams to generate temporary media source IDs

* Update tests/components/tts/test_media_source.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update assist snapshots

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-19 12:04:19 -04:00
epenet
cadbe885d1 Add missing type hint in homematic (#145214) 2025-05-19 17:52:35 +02:00
epenet
366f592a8a Fix invalid type hints in netgear switch (#145226)
* Fix invalid type hints in netgear switch

* Adjust
2025-05-19 17:52:23 +02:00
epenet
e491629143 Split update method in pioneer media player (#145212)
Split method in pioneer media player
2025-05-19 17:40:12 +02:00
Simone Chemelli
f44cb9b03e Add action exceptions to Comelit integration (#143581)
* Add action exceptions to Comelit integration

* missing decorator

* update quality scale
2025-05-19 17:30:34 +02:00
Petro31
752c73a2ed Add trigger_variables to template trigger 'for' field (#136672)
* Add trigger_variables to template trigger for

* address comments
2025-05-19 17:26:42 +02:00
Simone Chemelli
a8ecdb3bff Finish reconfigure test for Vodafone Station (#145230) 2025-05-19 16:34:41 +02:00
Simone Chemelli
9c798cbb5d Add device reconfigure to Comelit config flow (#142866)
* Add device reconfigure to Comelit config flow

* tweak

* tweak

* update quality scale

* apply review comment

* apply review comment

* review comment

* complete test
2025-05-19 16:12:27 +02:00
Erik Montnemery
8938c109c2 Improve entity registry restore test (#145220) 2025-05-19 16:09:23 +02:00
Martin Hjelmare
85448ea903 Fix Z-Wave config entry unique id after NVM restore (#145221)
* Fix Z-Wave config entry unique id after NVM restore

* Remove stale comment
2025-05-19 17:05:48 +03:00
epenet
e3d2f917e2 Use shorthand attributes in yandex transport sensor (#145225) 2025-05-19 15:58:34 +02:00
epenet
05795d0ad8 Use _attr_native_value in repetier (#145219) 2025-05-19 15:56:27 +02:00
epenet
a38e033e13 Improve type hints in rtorrent (#145222) 2025-05-19 15:53:41 +02:00
epenet
8df447091d Add missing type hint in vlc (#145223) 2025-05-19 15:52:40 +02:00
Simone Chemelli
760f2d1959 Remove pylance warnings for Comelit tests (#145199) 2025-05-19 15:27:41 +02:00
Simone Chemelli
e64f76bebe Add full test coverage for Comelit cover (#144761) 2025-05-19 15:01:41 +02:00
epenet
7c5090d627 Add missing type hint in zestimate (#145218) 2025-05-19 14:55:48 +02:00
Robert Resch
f6a0d630c3 Fix typo in Ecovacs get_supported_entities (#145215) 2025-05-19 14:45:30 +02:00
markhannon
880f5faeec Add cover entity to Zimi integration (#144330) 2025-05-19 14:24:25 +02:00
Retha Runolfsson
0cf503d871 Add exception translation for switchbot device initialization (#144828) 2025-05-19 14:22:10 +02:00
epenet
9d050360c8 Prevent import from syrupy.SnapshotAssertion (#145208) 2025-05-19 14:18:35 +02:00
Simone Chemelli
0c0c61f9e0 Bump aiocomelit to 0.12.3 (#145209) 2025-05-19 14:16:12 +02:00
Erik Montnemery
e868b3e8ff Sort and simplify DeletedRegistryEntry (#145207) 2025-05-19 14:13:57 +02:00
Simone Chemelli
555215a848 Update quality_scale rules status for Comelit (#143592) 2025-05-19 14:05:08 +02:00
Simone Chemelli
484a547758 Fix pylance warning on SnapshotAssertion import (#145206) 2025-05-19 13:55:48 +02:00
wuede
7d25f68fa5 update pyatmo to version 9.2.0 (#145203) 2025-05-19 13:21:19 +02:00
Maikel Punie
8b22ab93c1 Bump velbusaio to 2025.5.0 (#145198) 2025-05-19 13:20:02 +02:00
epenet
78e3a2d0c6 Mark all _CLASS_MATCH as mandatory in pylint plugin (#145200) 2025-05-19 12:12:17 +01:00
Robert Resch
241c89e885 Bump go2rtc-client to 0.1.3b0 (#145192) 2025-05-19 12:11:07 +01:00
Marc Mueller
7d96a2a620 [ci] Skip step if coverage is skipped (#145202) 2025-05-19 12:46:38 +02:00
Martin Hjelmare
08104eec56 Fix Z-Wave unique id update during controller migration (#145185) 2025-05-19 13:43:06 +03:00
Michael
0fc81d6b33 Add diagnostics platform to Immich integration (#145162)
* add diagnostics platform

* also redact host
2025-05-19 12:23:04 +02:00
Joost Lekkerkerker
cb84e55c34 Map auto to heat_cool for thermostat in SmartThings (#145098) 2025-05-19 12:09:27 +02:00
Joost Lekkerkerker
68c3d5a159 Add lamp capability for hood component in SmartThings (#145036) 2025-05-19 12:07:50 +02:00
epenet
77bab39ed0 Move downloader service to separate module (#145183) 2025-05-19 12:05:33 +02:00
Maciej Bieniek
92e570ffc1 Revert "Link Shelly device entry with Shelly BT scanner entry (#144626)" (#145177)
This reverts commit b15c9ad130.
2025-05-19 13:01:54 +03:00
Paulus Schoutsen
919684e20a Minor cleanup for pipeline tts stream test (#145146) 2025-05-19 11:58:58 +02:00
G Johansson
a1d6df6ce9 Remove deprecated aux heat from ephember (#145152) 2025-05-19 11:58:35 +02:00
epenet
07c3c3bba8 Mark type hint as compulsory for entity.assumed_state property (#145187) 2025-05-19 11:56:05 +02:00
epenet
f11e040662 Mark all _FUNCTION_MATCH as mandatory in pylint plugin (#145194) 2025-05-19 11:55:15 +02:00
epenet
8d83341308 Mark type hint as compulsory for entity.available property (#145189) 2025-05-19 11:50:41 +02:00
Erik Montnemery
f27b2c4df1 Improve device registry restore tests (#145186) 2025-05-19 11:06:16 +02:00
Matrix
717b84bab9 Add battery entity for LockV2 in yolink (#145169)
Add battery entity for LockV2
2025-05-19 11:01:30 +02:00
epenet
a34bce6202 Fix runtime_data in iqvia (#145181) 2025-05-19 10:59:46 +02:00
epenet
bd190b9b4c Use runtime_data in icloud (#145179) 2025-05-19 10:59:06 +02:00
epenet
da6c6c5201 Use runtime_data in ialarm (#145178) 2025-05-19 10:58:34 +02:00
epenet
f50afae1c3 Use runtime_data in hvv_departures (#144951) 2025-05-19 10:58:01 +02:00
epenet
177afea5ad Use runtime_data in huisbaasje (#144953) 2025-05-19 10:57:22 +02:00
Joost Lekkerkerker
a3aae68229 Add athmospheric pressure capability to SmartThings (#145103) 2025-05-19 10:41:22 +02:00
Robert Resch
9ff9d9230e Fix test results parsing error (#145077) 2025-05-19 10:40:03 +02:00
epenet
2bb0843c30 Add ability to mark type hints as compulsory on specific functions (#139730) 2025-05-19 10:27:07 +02:00
Joakim Sørensen
5f2425f421 Bump hass-nabucasa from 0.100.0 to 0.101.0 (#145172) 2025-05-19 10:24:08 +02:00
J. Nick Koston
e46ca41697 Bump aioesphomeapi to 31.1.0 (#145170) 2025-05-19 10:22:47 +02:00
dependabot[bot]
fa5a7aea7e Bump github/codeql-action from 3.28.17 to 3.28.18 (#145173)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 10:14:37 +02:00
Tsvi Mostovicz
030681a443 Jewish calendar: use const in action code (#145007)
* Use const defines in code

* Added exception raises

* Revert "Added exception raises"

This reverts commit e8849e586c.
2025-05-19 10:14:22 +02:00
epenet
aa3cbf2473 Cleanup unused string in samsungtv (#145174) 2025-05-19 09:10:01 +02:00
Erik Montnemery
ce71f6444c Sort and simplify DeletedDeviceEntry (#145171)
* Sort and simplify DeletedDeviceEntry

* Fix sort

* Fix sort
2025-05-19 08:40:22 +02:00
J. Nick Koston
eb4d561b96 Bump grpcio to 1.72.0 and protobuf to 6.30.2 (#143633) 2025-05-18 20:10:38 -04:00
peteS-UK
075a41c69a Fix album and artist returning "None" rather than None for Squeezebox media player. (#144971)
* fix

* snapshot update

* cast type
2025-05-18 23:37:06 +02:00
G Johansson
2ba2248f67 Remove deprecated aux heat from econet (#145149) 2025-05-18 23:03:13 +02:00
starkillerOG
ff5ed82de8 Add Kaiser Nienhaus virtual motionblinds integration (#145096)
* Add Kaiser Nienhaus virtual motionblinds integration

* fix typo
2025-05-18 23:01:02 +02:00
wuede
541b969d3b Netatmo: do not fail on schedule updates (#142933)
* do not fail on schedule updates

* add test to check that the store data remains unchanged
2025-05-18 23:00:36 +02:00
javicalle
3d83c6299b Enable RFDEBUG on RFLink "Enable debug logging" (#138571)
* Enable RFDEBUG on "Enable debug logging"

* fix checks

* fix checks

* one more lap

* fix test

* wait to init rflink 

In my dev env this is not needed

* use hass.async_create_task(handle_logging_changed())

instead async_at_started(hass, handle_logging_changed)

* revert unneeded async_block_till_done

* Remove the startup management

There's a race condition at startup that can't be managed nicely
2025-05-18 22:51:42 +02:00
generically-named
3ecde49dca Add energy/water forecast for Miele integration (#144822)
* Add energy/water forecast & fix drying_step error

Adding the energy forecast and water forecast entities that are present in the HACS version of this integration but absent in the HA Core implantation. 

Also fixed the state_drying_step sensor which wasn't handling casting of the API value to an int correctly due to the API sometimes giving a None value.

* Fix formatting issues from previous commit

* Fix missing translation_key line 202

* Remove icon entries

* Update icons.json

* Update strings.json

* Update strings.json (correcting mixed up energy/water forecast names)

* Update homeassistant/components/miele/strings.json

Co-authored-by: Åke Strandberg <ake@strandberg.eu>

* Update homeassistant/components/miele/strings.json

Co-authored-by: Åke Strandberg <ake@strandberg.eu>

* Fix tests

---------

Co-authored-by: Åke Strandberg <ake@strandberg.eu>
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-18 22:33:27 +02:00
Nils Müller
c1fcd8ea7f Fix Nanoleaf light state propagation after change from home asisstant (#144291)
* Fix Nanoleaf light state propagation after change from home asisstant

* Add tests to check if nanoleaf light is triggering async_write_ha_state

* Fix pylint for test case

* Fix use coordinator.async_refresh instead of async_write_ha_state

* Fix tests

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-18 22:26:02 +02:00
G Johansson
78ac8ba841 Remove deprecated aux heat from Nexia (#145147) 2025-05-18 16:14:22 -04:00
Keilin Bickar
d9cfab4c8e Bump sense-energy to 0.13.8 (#145156) 2025-05-18 21:45:11 +02:00
Oliver
4c10502b0e Update denonavr to 1.1.1 (#145155) 2025-05-18 21:44:53 +02:00
Michael
a576f7baf3 Add Immich integration (#145125)
* add immich integration

* bump aioimmich==0.3.1

* rework to require an url as input and pare it afterwards

* fix doc strings

* remove name attribute from deviceinfo as it is default behaviour

* add translated uom for count sensors

* explicitly pass in the config_entry in coordinator

* fix url in strings to uppercase

* use data_updates attribute instead of data

* remove left over

* match entries only by host

* remove quotes

* import SOURCE_USER directly, instead of config_entries

* split happy and sad flow tests

* remove unneccessary async_block_till_done() calls

* replace url example by "full URL"

* bump aioimmich==0.4.0

* bump aioimmich==0.5.0

* allow multiple users for same immich instance

* Fix tests

* limit entities when user has no admin rights

* Fix tests

* Fix tests

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-18 21:28:15 +02:00
G Johansson
520c964656 Remove deprecated aux heat from elkm1 (#145148) 2025-05-18 20:50:33 +02:00
Matrix
3f59b1c376 Add YoLink new device types support 5009 & 5029 (#144323)
* Leak Stop

* Fix as suggested.
2025-05-18 19:59:19 +02:00
Markus Adrario
3ff095cc51 Add Homee alarm-control-panel platform (#140041)
* Add alarm control panel

* Add alarm control panel tests

* add disarm function

* reuse state setting code

* change sleeping to night

* review change 1

* fix review comments

* fix review comments
2025-05-18 17:25:09 +02:00
Marc Hörsken
aa4c41abe8 Postpone update in WMSPro after service call (#144836)
* Reduce stress on WMS WebControl pro with higher scan interval

Avoid delays and connection issues due to overloaded hub.
Fixes #133832 and #134413

* Schedule an entity state update after performing an action

Avoid delaying immediate status updates, e.g. on/off changes.

* Replace scheduled state updates with delayed action completion

Suggested-by: joostlek
2025-05-18 17:23:21 +02:00
Sid
906b3901fb Add select platform to eheimdigital (#145031)
* Add select platform to eheimdigital

* Review

* Review

* Fix tests
2025-05-18 16:52:27 +02:00
Andre Lengwenus
2aba4f261f Add has_entity_name attribute to LCN entities (#145045)
* Add _attr_has_entity_name

* Fix tests
2025-05-18 16:48:44 +02:00
elmurato
3eb0c8ddff Add Pterodactyl binary sensor tests (#142401)
* Add binary sensor tests

* Wait for background tasks as well in test_binary_sensor_update_failure

* Fix module docstring

* Use snapshot_platform, move constants to const.py, do not use snapshot for testing state updates

* Use JSON fixtures

* Use helper for loading JSON fixtures, remove unneeded mock in setup_integration

* Move mocks to pytest markers where possible
2025-05-18 16:46:11 +02:00
Andrea Turri
705a987547 Fix enum values for program phases by appliance type on Miele appliances (#144916) 2025-05-18 11:00:21 +02:00
J. Nick Koston
888f17c504 Bump google-maps-routing to 0.6.15 (#145130) 2025-05-18 09:11:13 +02:00
markhannon
2f4d0ede0f Bump zcc-helper to 3.5.2 (#144926) 2025-05-18 07:13:23 +02:00
Paulus Schoutsen
6fd9857666 OpenAI Conversation split out chat log processing (#145129) 2025-05-17 22:00:24 -07:00
XiaoXianNv-boot
f07265ece4 Set the default upgrade icon for the MQTT device to the default icon for Home Assistant instead of the icon for the MQTT integration (#144295)
* Set the default upgrade icon for the MQTT device to the default icon for Home Assistant instead of the icon for the MQTT integration

* Set the default upgrade icon for the MQTT device to the default icon for Home Assistant instead of the icon for the MQTT integration

* Set the default upgrade icon for the MQTT device to the default icon for Home Assistant instead of the icon for the MQTT integration

* Set the default upgrade icon for the MQTT device to the default icon for Home Assistant instead of the icon for the MQTT integration

* Fix failed tests

* Fix failed tests

* Cleanup unused helper option

* ruff

---------

Co-authored-by: jbouwh <jan@jbsoft.nl>
2025-05-18 01:30:04 +02:00
J. Nick Koston
a169d6ca97 Bump cryptography to 45.0.1 and pyopenssl to 25.1.0 (#145121) 2025-05-17 23:57:28 +02:00
Joost Lekkerkerker
ebed38c1dc Add Steam closet sanitize to SmartThings (#145110) 2025-05-17 21:03:24 +02:00
Joost Lekkerkerker
5619042fe7 Add Steam closet auto cycle link to SmartThings (#145111) 2025-05-17 20:39:17 +02:00
Joost Lekkerkerker
67b3428b07 Add Steam closet keep fresh mode to SmartThings (#145107) 2025-05-17 20:19:31 +02:00
Jan-Philipp Benecke
2302a3bb33 Add missing device condition translations to lock component (#145104) 2025-05-17 20:18:14 +02:00
Åke Strandberg
a83eafd949 Fix mapping from program_phase to vacuum_activity for Miele integration (#145115) 2025-05-17 20:17:15 +02:00
Paulus Schoutsen
2956f4fea1 Ensure that OpenAI tool call deltas have a role (#145085) 2025-05-17 09:36:14 -07:00
Robert Resch
180e1f462c Fix proberly Ecovacs mower area sensors (#145078) 2025-05-17 16:44:53 +02:00
cdnninja
2dc63eb8c5 Refactor fan in vesync (#135744)
* Refactor Fan

* Add tower fan tests and mode

* Schedule update after turn off

* Adjust updates to refresh library

* correct off command

* Revert changes

* Merge corrections

* Remove unused code to increase test coverage

* Ruff

* Tests

* Test for preset mode

* Adjust to increase coverage

* Test Corrections

* tests to match other PR

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-17 15:57:55 +02:00
Manu
4c40ec4948 Bump aiontfy to 0.5.2 (#145044) 2025-05-17 13:06:02 +02:00
starkillerOG
56b3dc02a7 Bump motionblinds to 0.6.27 (#145094) 2025-05-17 12:45:18 +02:00
Franck Nijhof
f66feabaaf 2025.5.2 (#145072)
Co-authored-by: Shay Levy <levyshay1@gmail.com>
Co-authored-by: Allen Porter <allen.porter@gmail.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: TimL <tl@smlight.tech>
Co-authored-by: Seweryn Zeman <seweryn.zeman@jazzy.pro>
Co-authored-by: hahn-th <15319212+hahn-th@users.noreply.github.com>
Co-authored-by: Luke Lashley <conway220@gmail.com>
Co-authored-by: starkillerOG <starkiller.og@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Arie Catsman <120491684+catsmanac@users.noreply.github.com>
Co-authored-by: Josef Zweck <josef@zweck.dev>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
Co-authored-by: Ruben van Dijk <15885455+RubenNL@users.noreply.github.com>
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
Co-authored-by: Simone Chemelli <simone.chemelli@gmail.com>
Co-authored-by: Thomas55555 <59625598+Thomas55555@users.noreply.github.com>
Co-authored-by: Øyvind Matheson Wergeland <oyvind@wergeland.org>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>
Co-authored-by: Brett Adams <Bre77@users.noreply.github.com>
Co-authored-by: rjblake <richard.blake@gmail.com>
Co-authored-by: Daniel Hjelseth Høyer <github@dahoiv.net>
Co-authored-by: Matthias Alphart <farmio@alphart.net>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: Robert Resch <robert@resch.dev>
Co-authored-by: Odd Stråbø <oddstr13@openshell.no>
Co-authored-by: puddly <32534428+puddly@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
fix privacy mode availability for NVR IPC cams (#144569)
fix enphase_envoy diagnostics home endpoint name (#144634)
Close Octoprint aiohttp session on unload (#144670)
Fix strings typo for Comelit (#144672)
Fix wrong state in Husqvarna Automower (#144684)
Fix Netgear handeling of missing MAC in device registry (#144722)
Fix blocking call in azure storage (#144803)
Fix Z-Wave unique id after controller reset (#144813)
Fix blocking call in azure_storage config flow (#144818)
Fix wall connector states in Teslemetry (#144855)
Fix Reolink setup when ONVIF push is unsupported (#144869)
Fix some Home Connect translation strings (#144905)
Fix unknown Pure AQI in Sensibo (#144924)
Fix Home Assistant Yellow config entry data (#144948)
Fix ESPHome entities unavailable if deep sleep enabled after entry setup (#144970)
fix from ZHA event `unique_id` (#145006)
Fix climate idle state for Comelit (#145059)
Fix fan AC mode in SmartThings AC (#145064)
Fix Ecovacs mower area sensors (#145071)
2025-05-16 23:08:52 +02:00
Franck Nijhof
0ef098a9f3 Pin rpds-py to 0.24.0 (#145074) 2025-05-16 20:40:02 +00:00
Franck Nijhof
db5bcd9fc4 Pin rpds-py to 0.24.0 (#145074) 2025-05-16 22:39:05 +02:00
jb101010-2
c845f4e9b2 Bump pysuezV2 to 2.0.5 (#145047) 2025-05-16 22:33:14 +02:00
Joost Lekkerkerker
5aff3499a0 Add number entities for freezer setpoint in SmartThings (#145069) 2025-05-16 22:29:00 +02:00
Andre Lengwenus
a501451038 Remove address parameter from services.yaml (#145052) 2025-05-16 22:27:09 +02:00
Paulus Schoutsen
0deed82bea OpenAI prompt is optional (#145065) 2025-05-16 22:22:46 +02:00
starkillerOG
f9231de824 Add additional explanation for Reolink password requirements (#145000) 2025-05-16 22:12:59 +02:00
Joost Lekkerkerker
757c66613d Deprecate SmartThings water heater sensors (#145060) 2025-05-16 21:59:12 +02:00
epenet
9d2302f2f5 Use runtime_data in homeworks (#144944) 2025-05-16 21:57:36 +02:00
epenet
0bbbd2cd54 Use runtime_data in hydrawise (#144950) 2025-05-16 21:45:11 +02:00
Franck Nijhof
02b028add3 Bump version to 2025.5.2 2025-05-16 19:31:36 +00:00
Robert Resch
34455f9743 Fix Ecovacs mower area sensors (#145071) 2025-05-16 19:31:15 +00:00
Joost Lekkerkerker
8c4eec231f Don't create entities for Smartthings smarttags (#145066) 2025-05-16 19:31:14 +00:00
Joost Lekkerkerker
621a14d7cc Fix fan AC mode in SmartThings AC (#145064) 2025-05-16 19:31:12 +00:00
Joost Lekkerkerker
4906e78a5c Only set suggested area for new SmartThings devices (#145063) 2025-05-16 19:31:11 +00:00
Bram Kragten
146e440d59 Update frontend to 20250516.0 (#145062) 2025-05-16 19:31:10 +00:00
Joost Lekkerkerker
e2ede3ed19 Map SmartThings auto mode correctly (#145061) 2025-05-16 19:31:09 +00:00
Simone Chemelli
b76ac68fb1 Fix climate idle state for Comelit (#145059) 2025-05-16 19:31:07 +00:00
Joost Lekkerkerker
0691ad9362 Set SmartThings oven setpoint to unknown if its 1 Fahrenheit (#145038) 2025-05-16 19:31:06 +00:00
Joost Lekkerkerker
715f116954 Bump pySmartThings to 3.2.2 (#145033) 2025-05-16 19:31:05 +00:00
puddly
9f0db98745 Strip _CLIENT suffix from ZHA event unique_id (#145006) 2025-05-16 19:31:03 +00:00
Odd Stråbø
0ba55c31e8 Fix ESPHome entities unavailable if deep sleep enabled after entry setup (#144970) 2025-05-16 19:31:02 +00:00
Robert Resch
19b7cfbd4a Bump deebot-client to 13.2.0 (#144957) 2025-05-16 19:31:01 +00:00
Erik Montnemery
a9520888cf Fix Home Assistant Yellow config entry data (#144948) 2025-05-16 19:31:00 +00:00
Matthias Alphart
f086f4a955 Ignore Fronius Gen24 firmware 1.35.4-1 SSL verification issue for new setups (#144940) 2025-05-16 19:30:59 +00:00
G Johansson
a657964c25 Fix unknown Pure AQI in Sensibo (#144924)
* Fix unknown Pure AQI in Sensibo

* Fix mypy
2025-05-16 19:30:57 +00:00
Daniel Hjelseth Høyer
543104b36c Update mill library 0.12.5 (#144911)
* Update mill library 0.12.5

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

* Update mill library 0.12.5

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

---------

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2025-05-16 19:30:56 +00:00
Daniel Hjelseth Høyer
bf1d2069e4 Update Tibber lib 0.31.2 (#144908)
Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2025-05-16 19:30:55 +00:00
rjblake
e5e1c9fb05 Fix some Home Connect translation strings (#144905)
* Update strings.json

Corrected program names:
changed "Pre_rinse" to "Pre-Rinse"
changed "Kurz 60°C" to "Speed 60°C"

Both match the Home Connect app; although the UK documentation refers to "Speed 60°C" as "Quick 60°C"

* Adjust casing

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-16 19:30:53 +00:00
starkillerOG
4c4be88323 Fix Reolink setup when ONVIF push is unsupported (#144869)
* Fix setup when ONVIF push is not supported

* fix styling
2025-05-16 19:30:52 +00:00
Brett Adams
5a83627dc5 Fix wall connector states in Teslemetry (#144855)
* Fix wall connector

* Update snapshot
2025-05-16 19:30:51 +00:00
Allen Porter
3123a7b168 Bump ical to 9.2.4 (#144852) 2025-05-16 19:30:50 +00:00
Luke Lashley
8161ce6ea8 Bump python-snoo to 0.6.6 (#144849) 2025-05-16 19:30:49 +00:00
Josef Zweck
d9cbd1b65f Bump pylamarzocco to 2.0.3 (#144825) 2025-05-16 19:30:47 +00:00
Josef Zweck
b7c07209b8 Fix blocking call in azure_storage config flow (#144818)
* Fix blocking call in azure_storage config flow

* Fix blocking call in azure_storage config_flow as well

* move session getting to event flow
2025-05-16 19:30:46 +00:00
Martin Hjelmare
6c3a4f17f0 Fix Z-Wave unique id after controller reset (#144813) 2025-05-16 19:30:45 +00:00
Josef Zweck
d82feb807f Fix blocking call in azure storage (#144803) 2025-05-16 19:30:43 +00:00
Jan Bouwhuis
c373fa9296 Do not show an empty component name on MQTT device subentries not as None if it is not set (#144792) 2025-05-16 19:30:42 +00:00
starkillerOG
139b48440f Cleanup wrongly combined Reolink devices (#144771) 2025-05-16 19:30:41 +00:00
Joost Lekkerkerker
9de1d3b143 Fill in Plaato URL via placeholders (#144754) 2025-05-16 19:29:35 +00:00
Martin Hjelmare
b69ebdaecb Repair Z-Wave unknown controller (#144738)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-16 19:23:25 +00:00
starkillerOG
f25e50b017 Fix Netgear handeling of missing MAC in device registry (#144722) 2025-05-16 19:23:24 +00:00
Simone Chemelli
a4a7601f9f Bump aiocomelit to 0.12.1 (#144720) 2025-05-16 19:23:22 +00:00
Øyvind Matheson Wergeland
41a503f76f Bump gcal-sync to 7.0.1 (#144718)
Co-authored-by: Allen Porter <allen.porter@gmail.com>
2025-05-16 19:23:21 +00:00
Allen Porter
f1a3d62db2 Bump ical to 9.2.2 (#144713) 2025-05-16 19:23:20 +00:00
Allen Porter
e465276464 Bump voluptuous-openapi to 0.1.0 (#144703) 2025-05-16 19:23:18 +00:00
Robert Resch
dbc15a2dda Fix Ecovacs mower area sensors (#145071) 2025-05-16 21:22:43 +02:00
Thomas55555
47b45444eb Fix wrong state in Husqvarna Automower (#144684) 2025-05-16 19:22:02 +00:00
Simone Chemelli
cf0911cc56 Avoid closing shared session for Comelit (#144682) 2025-05-16 19:22:00 +00:00
Simone Chemelli
da79d5b2e3 Fix strings typo for Comelit (#144672) 2025-05-16 19:21:59 +00:00
G Johansson
358b0c1c17 Bump holidays to 0.72 (#144671) 2025-05-16 19:21:58 +00:00
Ruben van Dijk
543348fe58 Close Octoprint aiohttp session on unload (#144670) 2025-05-16 19:21:57 +00:00
Simon Lamon
0635856761 Bump python-linkplay to v0.2.5 (#144666)
Bump linkplay to 0.2.5
2025-05-16 19:21:55 +00:00
Allen Porter
081afe6034 Bump ical to 9.2.1 (#144642) 2025-05-16 19:21:54 +00:00
Arie Catsman
ca14322227 bump pyenphase to 1.26.1 (#144641) 2025-05-16 19:21:53 +00:00
Josef Zweck
a54816a6e5 Bump pylamarzocco to 2.0.2 (#144635)
Co-authored-by: Shay Levy <levyshay1@gmail.com>
2025-05-16 19:21:51 +00:00
Arie Catsman
27db4e90b5 fix enphase_envoy diagnostics home endpoint name (#144634) 2025-05-16 19:21:50 +00:00
J. Nick Koston
e9cc624d93 Mark inkbird coordinator as not needing connectable (#144584) 2025-05-16 19:19:59 +00:00
starkillerOG
5a95f43992 Bump reolink_aio to 0.13.3 (#144583) 2025-05-16 19:19:58 +00:00
J. Nick Koston
36a35132c0 Bump aiodiscover to 2.7.0 (#144571) 2025-05-16 19:19:57 +00:00
starkillerOG
2fbc75f89b Reolink fix privacy mode availability for NVR IPC cams (#144569)
* Correct "available" for IPC cams

* Check privacy mode when updating
2025-05-16 19:19:56 +00:00
Luke Lashley
48aa6be889 Don't scale Roborock mop Path (#144421)
don't scale mop path
2025-05-16 19:19:55 +00:00
hahn-th
bde04bc47b Doorbell Event is fired just once in homematicip_cloud (#144357)
* fire event if event type if correct

* Fix requested changes
2025-05-16 19:19:53 +00:00
Seweryn Zeman
7d163aa659 Removed unused file_id param from open_ai_conversation request (#143878) 2025-05-16 19:19:52 +00:00
TimL
010b044379 Allow dns hostnames to be retained for SMLIGHT user flow. (#142514)
* Dont overwrite host with local IP

* adjust test for user flow change
2025-05-16 19:19:50 +00:00
Joost Lekkerkerker
7fefd58b84 Don't create entities for Smartthings smarttags (#145066) 2025-05-16 21:17:07 +02:00
Joost Lekkerkerker
87b60967a6 Map SmartThings auto mode correctly (#145061) 2025-05-16 20:14:41 +02:00
Joost Lekkerkerker
e80069545f Only set suggested area for new SmartThings devices (#145063) 2025-05-16 19:53:46 +02:00
Joost Lekkerkerker
be5685695e Fix fan AC mode in SmartThings AC (#145064) 2025-05-16 19:38:18 +02:00
Bram Kragten
6b769ac263 Update frontend to 20250516.0 (#145062) 2025-05-16 19:37:22 +02:00
Simone Chemelli
9114816384 Fix climate idle state for Comelit (#145059) 2025-05-16 18:51:30 +02:00
Ludovic BOUÉ
db3e596e48 Update Matter MicrowaveOven fixture (#145057)
Update microwave_oven.json

PowerInWatts feature
2025-05-16 18:19:36 +02:00
Joost Lekkerkerker
bdc21da076 Sync SmartThings EHS fixture (#145042) 2025-05-16 15:08:24 +02:00
epenet
a500eeb831 Use runtime_data in hue (#144946)
* Use runtime_data in hue

* More

* Tests
2025-05-16 08:35:46 -04:00
Joost Lekkerkerker
119d0c576a Add hood fan speed capability to SmartThings (#144919) 2025-05-16 13:39:03 +02:00
Bouwe Westerdijk
38cee53999 Small code optimization for Plugwise (#145037) 2025-05-16 13:28:31 +02:00
Joost Lekkerkerker
2ca9d4689e Set SmartThings oven setpoint to unknown if its 1 Fahrenheit (#145038) 2025-05-16 13:17:56 +02:00
Joost Lekkerkerker
8a32ffc7b9 Bump pySmartThings to 3.2.2 (#145033) 2025-05-16 13:10:58 +02:00
Matthias Alphart
6475b1a446 Ignore Fronius Gen24 firmware 1.35.4-1 SSL verification issue for new setups (#144940) 2025-05-16 12:58:59 +02:00
starkillerOG
07db244f91 Cleanup wrongly combined Reolink devices (#144771) 2025-05-16 12:58:28 +02:00
Joost Lekkerkerker
ff4aed1f6e Fix errors in strings in SmartThings (#145030) 2025-05-16 12:22:17 +02:00
Joost Lekkerkerker
3208815e10 Fix non-DHW heat pump in SmartThings (#145008) 2025-05-16 12:08:32 +02:00
epenet
b4a1bdcb83 Move huisbaasje coordinator to separate module (#144955) 2025-05-16 12:07:19 +02:00
epenet
97869636f8 Use typed config entry in Habitica coordinator (#144956) 2025-05-16 11:59:11 +02:00
epenet
cbb092f792 Move icloud services to separate module (#144980) 2025-05-16 11:56:07 +02:00
Sanjay Govind
0c5ee37721 Update bosch_alarm door switch strings so they are more user friendly (#144607)
* Update door switch strings so they are more user friendly

* Update door switch strings so they are more user friendly

* Update door switch strings so they are more user friendly

* update strings

* update strings
2025-05-16 11:43:31 +02:00
epenet
e74aeeab1a Use runtime_data in iaqualink (#144988) 2025-05-16 11:41:16 +02:00
Sanjay Govind
b8df9c7e97 Set parallel_updates for bosch_alarm (#145028) 2025-05-16 11:26:22 +02:00
epenet
82a9e67b7e Use generic in iaqualink entity (#144989) 2025-05-16 10:53:24 +02:00
Joost Lekkerkerker
7410b8778a Deprecate DHW switch for SmartThings (#145011) 2025-05-16 10:47:23 +02:00
epenet
3e92f23680 Cleanup huisbaasje tests (#144954) 2025-05-16 10:38:17 +02:00
rjblake
3942e6a841 Fix some Home Connect translation strings (#144905)
* Update strings.json

Corrected program names:
changed "Pre_rinse" to "Pre-Rinse"
changed "Kurz 60°C" to "Speed 60°C"

Both match the Home Connect app; although the UK documentation refers to "Speed 60°C" as "Quick 60°C"

* Adjust casing

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-16 10:37:11 +02:00
Joost Lekkerkerker
e76b483067 Add lamp capability to SmartThings (#144918) 2025-05-16 10:36:58 +02:00
Retha Runolfsson
3de740ed1e Bump PySwitchbot to 0.62.2 (#145018) 2025-05-16 10:30:30 +02:00
Bouwe Westerdijk
bbe975baef Bump plugwise to v1.7.4 (#145021) 2025-05-16 10:28:57 +02:00
Sid
6dff975711 Initialize select _attr_current_option with None (#145026) 2025-05-16 10:27:59 +02:00
Jan Bouwhuis
71108d9ca0 Do not show an empty component name on MQTT device subentries not as None if it is not set (#144792) 2025-05-16 10:26:00 +02:00
puddly
053e5417a7 Strip _CLIENT suffix from ZHA event unique_id (#145006) 2025-05-16 10:25:24 +02:00
Sanjay Govind
9bbc49e842 Add DHCP discovery flow to bosch_alarm (#142250)
* Add dhcp discovery

* Update homeassistant/components/bosch_alarm/config_flow.py

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

* put mac address in entry instead of unique id

* Update host and mac via dhcp discovery

* add mac to connections

* Abort dhcp flow if there is already an ongoing flow

* apply changes from review

* apply change from review

* remove outdated test

* fix snapshots

* apply change from review

* clean definition for connections

* update quality scale

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-16 10:21:41 +02:00
dependabot[bot]
270780ef5f Bump docker/build-push-action from 6.16.0 to 6.17.0 (#145022)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-16 09:42:24 +02:00
dependabot[bot]
e15963b422 Bump codecov/codecov-action from 5.4.2 to 5.4.3 (#145023)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-16 08:54:13 +02:00
starkillerOG
52e8196d0a Mark Reolink doorbell visitor sensor as always available (#145002)
Mark doorbell visitor sensor as always available
2025-05-15 20:34:55 -04:00
Odd Stråbø
cc62943835 Fix ESPHome entities unavailable if deep sleep enabled after entry setup (#144970) 2025-05-15 18:57:16 -05:00
epenet
d195726ed2 Use runtime_data in isy994 (#144961) 2025-05-15 13:50:48 -05:00
epenet
50e6c83dd8 Fix missing mock in hue v2 bridge tests (#144947) 2025-05-15 13:53:12 -04:00
alorente
3a58d97496 Fix wrong UNIT_CLASS for reactive energy converter (#144982) 2025-05-15 18:27:16 +01:00
epenet
ace12958d1 Use runtime_data in iqvia (#144984) 2025-05-15 17:48:02 +02:00
Joost Lekkerkerker
d33a0f75fd Add water heater support to SmartThings (#144927)
* Add another EHS SmartThings fixture

* Add another EHS

* Add water heater support to SmartThings

* Add water heater support to SmartThings

* Add water heater support to SmartThings

* Add water heater support to SmartThings

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Add more tests

* Make target temp setting conditional

* Make target temp setting conditional

* Finish tests

* Fix
2025-05-15 17:42:38 +02:00
Erik Montnemery
d24a60777b Fix Home Assistant Yellow config entry data (#144948) 2025-05-15 10:07:53 -04:00
epenet
f2a3a5cbbd Move iqvia coordinator to separate module (#144969)
* Move iqvia coordinator to separate module

* Adjust
2025-05-15 15:50:46 +02:00
Petro31
3bf9908789 Add template vacuum modern style (#144843)
* Add template vacuum modern style

* address comments and add tests for coverage

* address comments

* update vacuum and sort domains
2025-05-15 15:46:00 +02:00
epenet
912798ee34 Use runtime_data in intellifire (#144979) 2025-05-15 14:57:26 +02:00
epenet
28990e1db5 Use runtime_data in ipma (#144972)
* Use runtime_data in ipma

* Cleanup const
2025-05-15 14:43:58 +02:00
epenet
e8281bb009 Use runtime_data in iotawatt (#144977) 2025-05-15 14:43:35 +02:00
Robert Resch
334f9deaec Bump deebot-client to 13.2.0 (#144957) 2025-05-15 13:46:15 +02:00
alorente
1d47dc41c9 Add reactive energy device class and units (#143941) 2025-05-15 12:05:46 +01:00
Petro31
66ecc4d69d Add modern configuration for template alarm control panel (#144834)
* Add modern configuration for template alarm control panel

* address comments and add tests for coverage

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-05-15 11:46:57 +02:00
starkillerOG
fa3edb5c01 Fix Netgear handeling of missing MAC in device registry (#144722) 2025-05-15 10:56:54 +02:00
Petro31
ea046f32be Add modern style template lock (#144756)
* Add modern style lock

* add tests

* Add tests and address comments

* Update homeassistant/components/template/lock.py

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-05-15 10:43:56 +02:00
markhannon
fd09476b28 Add sensor entity to Zimi integration (#144329)
* Import sensor.py

* Light design alignment

* Fix merge error

* Refactor with extend

* Update homeassistant/components/zimi/sensor.py

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

* value_fn and inline refactoring

* strings.json and translation_key

* Add sensor_name

* Revert "Add sensor_name"

This reverts commit ad3da048e9.

* Default naming for sensors

* Remove uneeded 'garage' and use default battery name

* Bump to zcc-helper 3.5.2 which maps "Garage Controller" tp "Garage" in device.name

* Update homeassistant/components/zimi/sensor.py

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

* Update homeassistant/components/zimi/sensor.py

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

* Update strings.json

* Revert "Bump to zcc-helper 3.5.2 which maps "Garage Controller" tp "Garage" in device.name"

This reverts commit 345ef8a485.

* Update homeassistant/components/zimi/sensor.py

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-05-15 10:12:18 +02:00
Alexandre CUER
7c306acd5d Emoncms remove useless var in tests (#144942) 2025-05-15 09:48:01 +02:00
G Johansson
9c4733595a Fix unknown Pure AQI in Sensibo (#144924)
* Fix unknown Pure AQI in Sensibo

* Fix mypy
2025-05-15 10:27:48 +03:00
Petro31
c7cf9585ae Add modern style configuration for template fan (#144751)
* add modern template fan

* address comments and add tests for coverage
2025-05-15 08:18:37 +02:00
J. Nick Koston
301ca88f41 Bump aioesphomeapi to 31.0.1 (#144939) 2025-05-14 22:27:25 -05:00
peteS-UK
9a0fed89bd Translate raised exceptions for Squeezebox (#144842)
* initial

* tweak

* review updates
2025-05-14 19:39:00 -04:00
Joost Lekkerkerker
2050b0b375 Add another EHS SmartThings fixture (#144920)
* Add another EHS SmartThings fixture

* Add another EHS
2025-05-14 23:23:18 +02:00
epenet
34c7c3f384 Use runtime_data in homematicip_cloud (#144892) 2025-05-14 23:14:02 +02:00
epenet
3b9d8e00bc Use runtime_data and HassKey in geofency (#144886) 2025-05-14 23:13:37 +02:00
Abílio Costa
6b35b069b2 Remove duplicated code in unit conversion util (#144912) 2025-05-14 22:05:29 +01:00
Paulus Schoutsen
9428127021 Add media search and play intent (#144269)
* Add media search intent

* Add PLAY_MEDIA as required feature and remove explicit responses

---------

Co-authored-by: Michael Hansen <mike@rhasspy.org>
2025-05-14 15:45:40 -04:00
Sanjay Govind
1e8843947c Add sensor for alarm status in bosch_alarm (#142564)
* Add sensor for alarm status

* style fixes

* fix icons

* style fixes

* update tests

* apply change from code review

* add alarm to alarm sensor state

* Apply changes from review
2025-05-14 21:00:41 +02:00
Sanjay Govind
dbdffbba23 Add binary sensors to bosch_alarm (#142147)
* Add binary sensors to bosch_alarm

* make one device per sensor, remove device class guessing

* fix tests

* update tests

* Apply suggested changes

* add binary sensors

* make fault sensors diagnostic

* update tests

* update binary sensors to use base entity

* fix strings

* fix icons

* add state translations for area ready sensors

* use constants in tests

* apply changes from review

* remove fault prefix, use default translation for battery low

* update tests
2025-05-14 20:56:08 +02:00
Daniel Hjelseth Høyer
460f02ede5 Update mill library 0.12.5 (#144911)
* Update mill library 0.12.5

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

* Update mill library 0.12.5

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

---------

Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2025-05-14 20:46:28 +02:00
Sid
0eb6c88bc5 Add system LED brightness to eheimdigital (#144915) 2025-05-14 20:45:58 +02:00
Nick Kuiper
4b7650f2d2 Add buttons to Blue current integration (#143964)
* Add buttons to Blue current integration

* Apply feedback

* Changed configEntry to use the BlueCurrentConfigEntry.

The connector is now accessed via the entry instead of hass.data.

* Changed test_buttons_created test to use the snapshot_platform function.

Also removed the entry.unique_id check in the test_charge_point_buttons function because this is not needed anymore, according to https://github.com/home-assistant/core/pull/114000#discussion_r1627201872

* Applied requested changes.

Changes requested by joostlek.

* Moved has_value from BlueCurrentEntity to class level.

This value was still inside the __init__ function, so the value was not overwritten by the ChargePointButton.

---------

Co-authored-by: Floris272 <florispuijk@outlook.com>
2025-05-14 19:37:16 +02:00
Daniel Hjelseth Høyer
8004c6605b Update Tibber lib 0.31.2 (#144908)
Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2025-05-14 19:25:01 +02:00
Marc Hörsken
9d451b6358 Add support for identify buttons to WMS WebControl pro (#143339)
* Remove _attr_name = None from generic base class

* Add support for identify buttons to WMS WebControl pro

* Fix PERF401 as suggested by joostlek

* Fix fixture name after rebase

* Split test

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-14 18:06:21 +02:00
LG-ThinQ-Integration
7963665c40 Add fan for ventilator (#142444)
Add ventilator device

Co-authored-by: yunseon.park <yunseon.park@lge.com>
2025-05-14 17:58:25 +02:00
Erik Montnemery
d44a34ce1e Refactor DeviceAutomationTriggerProtocol (#144888) 2025-05-14 17:24:19 +02:00
Joost Lekkerkerker
49b7559b1f Fix snapshots in APC (#144901) 2025-05-14 17:14:57 +02:00
Glenn Vandeuren (aka Iondependent)
43b1dd64a7 Handle unit conversion in lib for niko_home_control (#141837)
* handle unit conversion in lib

* bump lib

* Fix

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2025-05-14 17:13:06 +02:00
Matthias Alphart
2d0c1fac24 Fix "tunneling" spelling in KNX (#144895) 2025-05-14 17:05:45 +02:00
Andre Lengwenus
a0f35a84ae Positioning for LCN covers (#143588)
* Fix motor control function names

* Add position logic for BS4

* Use helper methods from pypck

* Add motor positioning to domain_data schema

* Fix tests

* Add motor positioning via module

* Invert motor cover positions

* Merge relay cover classes back into one class

* Update snapshot for covers

* Revert bump lcn-frontend to 0.2.4
2025-05-14 16:49:30 +02:00
epenet
4bc5987f36 Use runtime_data in rachio (#144896) 2025-05-14 16:46:36 +02:00
Yuxin Wang
11644d48ee Use snapshot testing for APCUPSD integration (#130770)
* First try to use snapshot testing for sensors

* Use snapshot testing

* Add ambr files

* Update comment

* Address review comments

* Remove duplicate async init integration call

* Add device test for cases w/o SERIALNO

* Use friendlier snapshot names

* Use * to mandate keyed argument for async_init_integration

* Always pass mock config entry ID

* Fix incorrect ID
2025-05-14 16:04:07 +02:00
Petro31
d273a92a19 Refactor template optional configuration attributes (#144887) 2025-05-14 15:54:40 +02:00
Brian Rogers
b0ff4b5841 Add flow detection to Rachio hose timer (#144075)
* flow binary sensor

* rename property

* Move const and update coordinator reference

* update controller descriptions

* Address review comments

* Use lookup for rain sensor

* Update online binary sensor

* make it a bit more readable

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2025-05-14 15:01:01 +02:00
epenet
ef99658919 Use runtime_data in gpslogger (#144884) 2025-05-14 14:59:10 +02:00
epenet
a9238c7577 Use entry.async_on_unload in gpslogger (#144883) 2025-05-14 14:31:50 +02:00
Brett Adams
993e98a43f Fix pin strings in Teslemetry (#144873)
pinstring
2025-05-14 14:31:41 +02:00
epenet
10dd11f257 Use HassKey in greeneye_monitor (#144878) 2025-05-14 14:30:45 +02:00
epenet
fb9be3da79 Use entry.async_on_unload in geofency (#144882) 2025-05-14 14:30:02 +02:00
Åke Strandberg
3b1a33d606 Fix substitutions in strings.json in Miele integration (#144881)
Fix substitutions in strings.json
2025-05-14 14:14:48 +02:00
epenet
710e18f399 Use runtime_data in gree (#144880) 2025-05-14 14:06:40 +02:00
Maximilian Arzberger
67b9904740 Add Kostal plenticore Installer login support (#133773)
* feat: Add Installer login, Add ManualCharge Switch

* remove unnecessary field

* replace strings with consts

* change to CONF and camel_case

* Improve existing code

* Add translation string

* format code

* add service code test

* format code

* format code

* remove manual charge switch

* add reconfigure config flow

* fix flow

* add return type

* add reconfigure strings

* adjust tests

* change string

* simlify tests

* add reconfigure test

* add more tests

* Fix

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-14 14:05:23 +02:00
Robert Resch
e413e9b93b Add mac address to airgradient devices (#144876) 2025-05-14 13:40:38 +02:00
Matthias Alphart
5c86042b31 Add Fronius current and voltage for up to 4 MPP trackers (#140120)
Support current and voltage of up to 4 MPP trackers
2025-05-14 13:37:02 +02:00
Martin Hjelmare
e89333811e Improve Z-Wave config flow tests (#144871)
* Improve Z-Wave config flow tests

* Fix test

* Use identify check for result type
2025-05-14 13:08:26 +02:00
Dmytro Tkach
4f723232e3 Add modbus light brightness and color temperature (#139703)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-05-14 12:07:19 +01:00
Åke Strandberg
48520d90ef Add plate sensors for Miele hobs (#144400)
* Add plate sensors for miele hobs

* Address review comments

* Update snapshot
2025-05-14 13:02:05 +02:00
Jeremiah Paige
2fdda91cb8 Fix pandora.media_player to not sleep during event loop (#141957)
* Fix pandora.media_player to not sleep during event loop

* factor out pianobar spawn

* linting cleanup

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-14 12:34:40 +02:00
Sören Beye
c023f610dd Introduce recorder.get_statistics service (#142602)
Co-authored-by: abmantis <amfcalt@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-05-14 11:28:32 +01:00
epenet
161b62d8fa Drop alias from local DOMAIN import (#144867) 2025-05-14 12:24:46 +02:00
Brett Adams
8ccedd4064 Add credit balance sensor to Teslemetry (#144365)
* Add credits

* Credits string and icon

* Add test

* tests and fixes

* Add units

* Update homeassistant/components/teslemetry/sensor.py

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

* Update snapshot with unit

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-14 12:21:45 +02:00
Rob Bierbooms
9a06584a1d Bump influxdb-client to 1.48.0 (#144845)
* Bump influxdb-client to 1.48.0

* Adjust typing, fix mypy

* Update homeassistant/components/influxdb/__init__.py

* Update homeassistant/components/influxdb/__init__.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-14 12:21:26 +02:00
Daniël van den Berg
a21e586140 Show Sonos playlists under favorites (#142357)
* Update media_browser.py

* Update favorites.py

* Update media_player.py

* Update media_browser.py

* Update media_player.py

* Update favorites.py

* Update media_browser.py

* Update media_player.py

* Update favorites.py

* Added/fixed testing for showing sonos native playlists in the media browser

* Create a DidlFavorite to wrap playlists.

* Processed PR feedback
2025-05-14 12:14:20 +02:00
epenet
91f01d660f Move ps4 services to separate module (#144870) 2025-05-14 12:04:43 +02:00
peteS-UK
1748dbd60f Add parallel_updates to new updates platform for Squeezebox (#144864)
initial
2025-05-14 11:59:28 +02:00
starkillerOG
5acae7f86d Fix Reolink setup when ONVIF push is unsupported (#144869)
* Fix setup when ONVIF push is not supported

* fix styling
2025-05-14 11:58:29 +02:00
epenet
30ecba9944 Finish cleaning up SamsungTV init tests (#144865)
FInish cleaning up SamsungTV init tests
2025-05-14 11:58:01 +02:00
epenet
4287df5f3d Use HassKey in ps4 (#144868) 2025-05-14 11:51:32 +02:00
hahn-th
063deab3cb Doorbell Event is fired just once in homematicip_cloud (#144357)
* fire event if event type if correct

* Fix requested changes
2025-05-14 11:44:59 +02:00
dependabot[bot]
27798a6004 Bump actions/dependency-review-action from 4.7.0 to 4.7.1 (#144856)
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/v4.7.0...v4.7.1)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.7.1
  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>
2025-05-14 11:43:14 +02:00
Luke Lashley
577ddd9021 Bump python-snoo to 0.6.6 (#144849) 2025-05-14 11:42:43 +02:00
Allen Porter
34663e160d Bump ical to 9.2.4 (#144852) 2025-05-14 11:42:22 +02:00
Norbert Rittel
ac54b81289 Fix spelling of "IP address" in plugwise (#144861) 2025-05-14 11:01:14 +03:00
Penny Wood
67174fb07e Remove myself as code owner of sun component (#144854)
* Remove myself as code owner

I'm haven't actively been working on this for some time. Have removed myself as a code owner.

* cleanup

* cleanup

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
2025-05-14 09:37:51 +03:00
Brett Adams
d2a692393f Fix wall connector states in Teslemetry (#144855)
* Fix wall connector

* Update snapshot
2025-05-14 08:08:24 +02:00
Åke Strandberg
9aa2664188 Change unknown to unknown_code for missing Miele codes to avoid confusion (#144699)
* Change unknown to unknown_code

* Update snapshot

* Automatically replace missing codes with None

* Update snapshot
2025-05-14 08:07:38 +02:00
David Rapan
ab5d60e33d Make DHCP discovery aware of the network integration (#144767)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-05-14 00:59:48 -05:00
epenet
31847d8cfb Adjust handling of SamsungTV misaligned MAC (#144810)
* Cleanup SamsungTV misaligned MAC formatting

* Simplify

* One more

* Revert and add comment

* Adjust comment

* One more
2025-05-14 07:57:33 +02:00
John Hillery
9729f1f38b Provide ability to select nexia RoomIQ sensors (#144278)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-05-13 23:16:05 -05:00
peteS-UK
6bc6733c40 Add config flow data descriptions to Squeezebox (#144619)
* add data_descriptions

* tweaks

* review updates
2025-05-13 21:10:47 -07:00
Tsvi Mostovicz
b1ffcb4245 Jewish calendar - Fix Parasha values (#144646)
* Fix Parasha values

* Fix test

* Update sensor.py
2025-05-13 21:08:47 -07:00
Josef Zweck
f0c5fbfb8a Bump pylamarzocco to 2.0.3 (#144825) 2025-05-13 21:04:38 -07:00
J. Nick Koston
c76239806d Bump aioesphomeapi to 31.0.0 (#144778)
* aioesphomeapi update

* Bump aioesphomeapi to 31.0.0

There are some breaking changes with the protobuf naming and types
required some refactoring

changelog: https://github.com/esphome/aioesphomeapi/compare/v30.2.0...v31.0.0

* actually include the commit to bump the lib
2025-05-13 20:39:53 -04:00
Abílio Costa
6d809b0b5a Add service response support to admin services (#144837) 2025-05-13 21:57:15 +01:00
Norbert Rittel
de2cbb7f5c Improve user-facing strings of incomfort (#144844)
* Improvements in user-facing strings of `incomfort`

Fix spelling of "IP address" and "timeout"

Remove "temperature" from "Shortcut outside sensor temperature" as this makes no sense and leads to completely wrong translations. This is to indicate an electrical shortcut on the sensor so this should be the last word.

This also matches the naming in the user manual.

* Suggestion from review

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

---------

Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>
2025-05-13 22:47:21 +02:00
Erik Montnemery
cd61f37df7 Remove support for condition platforms defining only a CONDITION_SCHEMA (#144832) 2025-05-13 20:53:08 +02:00
epenet
26796f87cd Add device registry snapshots to samsungtv tests (#144804)
* Add device registry snapshots to samsungtv tests

* Simplify

* Adjust

* Reduce
2025-05-13 18:20:43 +02:00
Åke Strandberg
e2dd897ac7 Bump dependency pymiele -> 0.5.2 (#144758) 2025-05-13 18:19:49 +02:00
Retha Runolfsson
3bbe4baaf7 Update codeowner for switchbot Integration (#144829)
update codeowners
2025-05-13 18:16:05 +02:00
Alistair Francis
d409b86217 Bump automower-ble to 0.2.1 (#144817) 2025-05-13 14:21:56 +01:00
Josef Zweck
7928c15849 Fix blocking call in azure_storage config flow (#144818)
* Fix blocking call in azure_storage config flow

* Fix blocking call in azure_storage config_flow as well

* move session getting to event flow
2025-05-13 14:23:41 +02:00
epenet
d197debbc0 Improve SamsungTV config flow type hints (#144820) 2025-05-13 14:02:07 +02:00
Martin Hjelmare
55b9dee448 Fix Z-Wave unique id after controller reset (#144813) 2025-05-13 14:12:00 +03:00
epenet
5c6984d326 Do not abort on invalid host in SamsungTV user flow (#144794) 2025-05-13 10:47:26 +02:00
Josef Zweck
a7787d6080 Fix blocking call in azure storage (#144803) 2025-05-13 10:46:46 +02:00
Jeremiah Paige
2db60340c2 Add typing to wsdot (#143117)
* increase wsdot typing

* remove Final types

* help out mypy

* simplify wsdot types

* minor wsdot type changes

* type wsdot state
2025-05-13 10:43:03 +02:00
Mick Vleeshouwer
c121631fef Refactor config flow tests to improve result variable usage in Overkiz (#143374)
* Refactor test setup for unique ID migration in Overkiz integration

* Refactor test cases to unify result variable usage in Overkiz config flow tests (resultn -> result)

* Revert change in test_init
2025-05-13 10:35:32 +02:00
epenet
b0fb16d48d Remove obsolete compatibility code from SamsungTV (#144800) 2025-05-13 09:54:26 +02:00
Franck Nijhof
3e07f6543e Update debugpy to v1.8.14 (#144755) 2025-05-13 08:14:55 +02:00
Brett Adams
d4c2356c70 Create stream on demand in Teslemetry (#144777)
Create stream on demand
2025-05-13 08:05:33 +02:00
epenet
eec617b391 Add comments to samsungtv config flow tests (#144787) 2025-05-13 07:54:37 +02:00
Maciej Bieniek
b15c9ad130 Link Shelly device entry with Shelly BT scanner entry (#144626)
* Add BT address to DeviceInfo.connections

* Cleaning

* Use bluetooth_source property

* Add test

* Add connections property
2025-05-13 07:19:07 +02:00
Erik Montnemery
0128d85999 Move sun conditions to the sun integration (#144742) 2025-05-12 23:03:37 +01:00
David Rapan
e69ca0cf80 Bump aiodhcpwatcher to 1.2.0 (#144769) 2025-05-12 17:00:17 -05:00
Åke Strandberg
0719753be3 Set PARALLEL_UPDATES and update quality_scale for Miele integration (#144770)
Set PARALLEL_UPDATES and update quality_scale
2025-05-12 23:53:54 +02:00
Franck Nijhof
ba3181d4e7 Update pipdeptree to 2.26.1 (#144775) 2025-05-12 23:52:27 +02:00
Guido Schmitz
e58750555e Rework platform setup tests for devolo Home Network (#143114)
* Rework platform setup tests for devolo Home Network

* Fix sensor test

* Remove unload
2025-05-12 23:21:14 +02:00
Guido Schmitz
026687299d Assert resulting data in devolo Home Network test_form_reauth (#144760) 2025-05-12 21:28:40 +02:00
Martin Hjelmare
3eed552c56 Repair Z-Wave unknown controller (#144738)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-12 21:18:55 +02:00
J. Diego Rodríguez Royo
15a4514c7d Add MAC connection through DHCP discovery to Home Connect devices (#144611)
* Add MAC connection through DHCP discovery to Home Connect devices

* Update snapshots
2025-05-12 21:11:12 +02:00
Joakim Sørensen
b5445c0061 Allow subscription_expired repair issue in cloud (#144316)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-05-12 19:48:20 +02:00
Øyvind Matheson Wergeland
1d0584a90d Bump gcal-sync to 7.0.1 (#144718)
Co-authored-by: Allen Porter <allen.porter@gmail.com>
2025-05-12 19:45:34 +02:00
Matthias Alphart
158b795c70 Update xknx to 3.8.0 (#144753) 2025-05-12 19:45:02 +02:00
Paulus Schoutsen
4994229215 Track if TTS entity supports streaming input (#144697)
* Track if entity supports streaming

* Make class method
2025-05-12 13:44:39 -04:00
Andre Lengwenus
c022c32d2f Simplify unique config_entry check for LCN (#135756)
* Simplify check for unique config_entry

* Fix tests

* Fix reconfigure flow

* Add check for unchanging IP/port combination

* Remove explicit check for unchanged IP/port combination
2025-05-12 19:44:24 +02:00
Joost Lekkerkerker
d2ef3ca100 Fill in Plaato URL via placeholders (#144754) 2025-05-12 19:37:45 +02:00
Manu
00faadcfea Improve config flow description in ntfy integration (#144581) 2025-05-12 19:36:53 +02:00
Norbert Rittel
a6ff52b300 Fix outdated help center URL in plaato (#144748)
* Fix outdated help center URL in `plaato`

* Remove excessive space character
2025-05-12 19:12:49 +02:00
Joakim Sørensen
da0d65ca5b Log instead of ValueError for missing cloud translation key (#144732)
* Log instead of ValueError for missing translation key

* Update homeassistant/components/cloud/client.py
2025-05-12 18:59:38 +02:00
Paulus Schoutsen
2266e97417 Add a test for Assist Pipeline streaming deltas to TTS (#144711)
* Add a test for Assist Pipeline streaming deltas to TTS

* Adjust tests to new TTS engine
2025-05-12 12:15:05 -04:00
Norbert Rittel
d471de5645 Spelling fixes in user-facing strings of fronius (#144744) 2025-05-12 16:54:22 +02:00
Norbert Rittel
38674f0dc2 Add missing hyphen to "password-protected" in Shelly (#144746) 2025-05-12 17:47:14 +03:00
Erik Montnemery
b192ca4bad Make it possible to subscribe to frontend user store (#144724) 2025-05-12 16:01:42 +02:00
epenet
73a59523f5 Merge websocket test constants in samsungtv tests (#144741) 2025-05-12 15:51:21 +02:00
Erik Montnemery
05324dedd0 Deduplicate condition schemas (#144739) 2025-05-12 15:38:31 +02:00
Norbert Rittel
f1e5f73d7e Improve user-facing strings of velbus (#144716)
- add the missing hyphen to "password-protected"
- resolve missing genitive in `sync_clock` action description
- resolve singular/plural mismatch in `set_memo_text` action description
2025-05-12 16:35:06 +03:00
Robert Resch
7b23f21712 Remove deprecated camera async_handle_web_rtc_offer function (#144561) 2025-05-12 14:47:49 +02:00
epenet
4dde314338 Remove obsolete tests in SamsungTV (#144735) 2025-05-12 13:45:20 +02:00
Erik Montnemery
cba12fb598 Refactor frontend user store (#144723)
* Refactor frontend user store

* Address review comments
2025-05-12 12:00:32 +02:00
epenet
63e38b4d8d Rename samsung encrypted websocket test fixtures and constants (#144726)
* Rename samsung encrypted websocket test fixtures and constants

* More

* More
2025-05-12 11:36:22 +02:00
Simone Chemelli
7eded95315 Bump aiocomelit to 0.12.1 (#144720) 2025-05-12 11:23:44 +02:00
epenet
e493fe1105 Rename samsung websocket test fixtures and constants (#144719) 2025-05-12 10:27:29 +02:00
Åke Strandberg
646c230940 Add target temp sensor to Miele washing machines (#144507) 2025-05-12 09:42:27 +02:00
Thomas55555
5276a3688e Fix wrong state in Husqvarna Automower (#144684) 2025-05-12 09:39:30 +02:00
Allen Porter
0616bf16f4 Bump ical to 9.2.2 (#144713) 2025-05-12 09:37:57 +02:00
epenet
fbe1811e2b Improve SamsungTV test coverage (#144717) 2025-05-12 09:23:55 +02:00
epenet
2333c10915 Rename samsung legacy test fixtures and constants (#144715)
* Rename samsung legacy test fixtures and constants

* More
2025-05-12 09:13:23 +02:00
Franck Nijhof
00627b82e0 2025.5.1 (#144564) 2025-05-09 17:03:40 +02:00
Franck Nijhof
13aba6201e Bump version to 2025.5.1 2025-05-09 13:29:29 +00:00
starkillerOG
f392e0c1c7 Prevent errors during cleaning of connections/identifiers in device registry (#144558) 2025-05-09 13:28:33 +00:00
starkillerOG
181eca6c82 Reolink clean device registry mac (#144554) 2025-05-09 13:28:32 +00:00
Bram Kragten
196d923ac6 Update frontend to 20250509.0 (#144549) 2025-05-09 13:28:30 +00:00
Josef Zweck
4ad387c967 Fix statistics coordinator subscription for lamarzocco (#144541) 2025-05-09 13:28:29 +00:00
J. Nick Koston
cb475bf153 Bump aiodns to 3.4.0 (#144511) 2025-05-09 13:28:28 +00:00
Michael
47acceea08 Fix removing of smarthome templates on startup of AVM Fritz!SmartHome integration (#144506) 2025-05-09 13:28:26 +00:00
J. Nick Koston
fd6fb7e3bc Bump forecast-solar to 4.2.0 (#144502) 2025-05-09 13:28:25 +00:00
Erik Montnemery
30f7e9b441 Don't encrypt or decrypt unknown files in backup archives (#144495) 2025-05-09 13:28:24 +00:00
Matthias Alphart
a8beec2691 Ignore Fronius Gen24 firmware 1.35.4-1 SSL verification issue (#144463) 2025-05-09 13:28:23 +00:00
Fredrik Erlandsson
23244fb79f Fix point import error (#144462)
* fix import error

* fix failing tests

* Apply suggestions from code review

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-05-09 13:28:22 +00:00
Martin Hjelmare
e5c56629e2 Fix Z-Wave reset accumulated values button entity category (#144459) 2025-05-09 13:28:20 +00:00
Josef Zweck
a793503c8a Bump pylamarzocco to 2.0.1 (#144454) 2025-05-09 13:28:19 +00:00
DukeChocula
054c7a0adc Add LAP-V102S-AUSR to VeSync (#144437)
Update const.py

Added LAP-V102S-AUSR to Vital 100S
2025-05-09 13:28:18 +00:00
Tamer Wahba
6eb2d1aa7c fix homekit air purifier temperature sensor to convert unit (#144435) 2025-05-09 13:28:16 +00:00
Martin Hjelmare
619fdea5df Fix Z-Wave restore nvm command to wait for driver ready (#144413) 2025-05-09 13:28:15 +00:00
3334 changed files with 120852 additions and 30739 deletions

View File

@@ -94,7 +94,7 @@ jobs:
- name: Download nightly wheels of frontend
if: needs.init.outputs.channel == 'dev'
uses: dawidd6/action-download-artifact@v9
uses: dawidd6/action-download-artifact@v10
with:
github_token: ${{secrets.GITHUB_TOKEN}}
repo: home-assistant/frontend
@@ -105,7 +105,7 @@ jobs:
- name: Download nightly wheels of intents
if: needs.init.outputs.channel == 'dev'
uses: dawidd6/action-download-artifact@v9
uses: dawidd6/action-download-artifact@v10
with:
github_token: ${{secrets.GITHUB_TOKEN}}
repo: home-assistant/intents-package
@@ -509,7 +509,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker image
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: . # So action will not pull the repository again
file: ./script/hassfest/docker/Dockerfile
@@ -522,7 +522,7 @@ jobs:
- name: Push Docker image
if: needs.init.outputs.channel != 'dev' && needs.init.outputs.publish == 'true'
id: push
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: . # So action will not pull the repository again
file: ./script/hassfest/docker/Dockerfile
@@ -531,7 +531,7 @@ jobs:
- name: Generate artifact attestation
if: needs.init.outputs.channel != 'dev' && needs.init.outputs.publish == 'true'
uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with:
subject-name: ${{ env.HASSFEST_IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}

View File

@@ -40,7 +40,7 @@ env:
CACHE_VERSION: 2
UV_CACHE_VERSION: 1
MYPY_CACHE_VERSION: 1
HA_SHORT_VERSION: "2025.6"
HA_SHORT_VERSION: "2025.7"
DEFAULT_PYTHON: "3.13"
ALL_PYTHON_VERSIONS: "['3.13']"
# 10.3 is the oldest supported version
@@ -360,7 +360,7 @@ jobs:
- name: Run ruff
run: |
. venv/bin/activate
pre-commit run --hook-stage manual ruff --all-files --show-diff-on-failure
pre-commit run --hook-stage manual ruff-check --all-files --show-diff-on-failure
env:
RUFF_OUTPUT_FORMAT: github
@@ -653,7 +653,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.2
- name: Dependency review
uses: actions/dependency-review-action@v4.7.0
uses: actions/dependency-review-action@v4.7.1
with:
license-check: false # We use our own license audit checks
@@ -944,7 +944,8 @@ jobs:
bluez \
ffmpeg \
libturbojpeg \
libgammu-dev
libgammu-dev \
libxml2-utils
- name: Check out code from GitHub
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ matrix.python-version }}
@@ -1020,6 +1021,12 @@ jobs:
name: coverage-${{ matrix.python-version }}-${{ matrix.group }}
path: coverage.xml
overwrite: true
- name: Beautify test results
# For easier identification of parsing errors
if: needs.info.outputs.skip_coverage != 'true'
run: |
xmllint --format "junit.xml" > "junit.xml-tmp"
mv "junit.xml-tmp" "junit.xml"
- name: Upload test results artifact
if: needs.info.outputs.skip_coverage != 'true' && !cancelled()
uses: actions/upload-artifact@v4.6.2
@@ -1070,7 +1077,8 @@ jobs:
bluez \
ffmpeg \
libturbojpeg \
libmariadb-dev-compat
libmariadb-dev-compat \
libxml2-utils
- name: Check out code from GitHub
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ matrix.python-version }}
@@ -1154,6 +1162,12 @@ jobs:
steps.pytest-partial.outputs.mariadb }}
path: coverage.xml
overwrite: true
- name: Beautify test results
# For easier identification of parsing errors
if: needs.info.outputs.skip_coverage != 'true'
run: |
xmllint --format "junit.xml" > "junit.xml-tmp"
mv "junit.xml-tmp" "junit.xml"
- name: Upload test results artifact
if: needs.info.outputs.skip_coverage != 'true' && !cancelled()
uses: actions/upload-artifact@v4.6.2
@@ -1202,7 +1216,8 @@ jobs:
sudo apt-get -y install \
bluez \
ffmpeg \
libturbojpeg
libturbojpeg \
libxml2-utils
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
sudo apt-get -y install \
postgresql-server-dev-14
@@ -1290,6 +1305,12 @@ jobs:
steps.pytest-partial.outputs.postgresql }}
path: coverage.xml
overwrite: true
- name: Beautify test results
# For easier identification of parsing errors
if: needs.info.outputs.skip_coverage != 'true'
run: |
xmllint --format "junit.xml" > "junit.xml-tmp"
mv "junit.xml-tmp" "junit.xml"
- name: Upload test results artifact
if: needs.info.outputs.skip_coverage != 'true' && !cancelled()
uses: actions/upload-artifact@v4.6.2
@@ -1320,7 +1341,7 @@ jobs:
pattern: coverage-*
- name: Upload coverage to Codecov
if: needs.info.outputs.test_full_suite == 'true'
uses: codecov/codecov-action@v5.4.2
uses: codecov/codecov-action@v5.4.3
with:
fail_ci_if_error: true
flags: full-suite
@@ -1357,7 +1378,8 @@ jobs:
bluez \
ffmpeg \
libturbojpeg \
libgammu-dev
libgammu-dev \
libxml2-utils
- name: Check out code from GitHub
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ matrix.python-version }}
@@ -1436,6 +1458,12 @@ jobs:
name: coverage-${{ matrix.python-version }}-${{ matrix.group }}
path: coverage.xml
overwrite: true
- name: Beautify test results
# For easier identification of parsing errors
if: needs.info.outputs.skip_coverage != 'true'
run: |
xmllint --format "junit.xml" > "junit.xml-tmp"
mv "junit.xml-tmp" "junit.xml"
- name: Upload test results artifact
if: needs.info.outputs.skip_coverage != 'true' && !cancelled()
uses: actions/upload-artifact@v4.6.2
@@ -1463,7 +1491,7 @@ jobs:
pattern: coverage-*
- name: Upload coverage to Codecov
if: needs.info.outputs.test_full_suite == 'false'
uses: codecov/codecov-action@v5.4.2
uses: codecov/codecov-action@v5.4.3
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}

View File

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

View File

@@ -0,0 +1,385 @@
name: Auto-detect duplicate issues
# yamllint disable-line rule:truthy
on:
issues:
types: [labeled]
permissions:
issues: write
models: read
jobs:
detect-duplicates:
runs-on: ubuntu-latest
steps:
- name: Check if integration label was added and extract details
id: extract
uses: actions/github-script@v7.0.1
with:
script: |
// Debug: Log the event payload
console.log('Event name:', context.eventName);
console.log('Event action:', context.payload.action);
console.log('Event payload keys:', Object.keys(context.payload));
// Check the specific label that was added
const addedLabel = context.payload.label;
if (!addedLabel) {
console.log('No label found in labeled event payload');
core.setOutput('should_continue', 'false');
return;
}
console.log(`Label added: ${addedLabel.name}`);
if (!addedLabel.name.startsWith('integration:')) {
console.log('Added label is not an integration label, skipping duplicate detection');
core.setOutput('should_continue', 'false');
return;
}
console.log(`Integration label added: ${addedLabel.name}`);
let currentIssue;
let integrationLabels = [];
try {
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number
});
currentIssue = issue.data;
// Check if potential-duplicate label already exists
const hasPotentialDuplicateLabel = currentIssue.labels
.some(label => label.name === 'potential-duplicate');
if (hasPotentialDuplicateLabel) {
console.log('Issue already has potential-duplicate label, skipping duplicate detection');
core.setOutput('should_continue', 'false');
return;
}
integrationLabels = currentIssue.labels
.filter(label => label.name.startsWith('integration:'))
.map(label => label.name);
} catch (error) {
core.error(`Failed to fetch issue #${context.payload.issue.number}:`, error.message);
core.setOutput('should_continue', 'false');
return;
}
// Check if we've already posted a duplicate detection comment recently
let comments;
try {
comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
per_page: 10
});
} catch (error) {
core.error('Failed to fetch comments:', error.message);
// Continue anyway, worst case we might post a duplicate comment
comments = { data: [] };
}
// Check if we've already posted a duplicate detection comment
const recentDuplicateComment = comments.data.find(comment =>
comment.user && comment.user.login === 'github-actions[bot]' &&
comment.body.includes('<!-- workflow: detect-duplicate-issues -->')
);
if (recentDuplicateComment) {
console.log('Already posted duplicate detection comment, skipping');
core.setOutput('should_continue', 'false');
return;
}
core.setOutput('should_continue', 'true');
core.setOutput('current_number', currentIssue.number);
core.setOutput('current_title', currentIssue.title);
core.setOutput('current_body', currentIssue.body);
core.setOutput('current_url', currentIssue.html_url);
core.setOutput('integration_labels', JSON.stringify(integrationLabels));
console.log(`Current issue: #${currentIssue.number}`);
console.log(`Integration labels: ${integrationLabels.join(', ')}`);
- name: Fetch similar issues
id: fetch_similar
if: steps.extract.outputs.should_continue == 'true'
uses: actions/github-script@v7.0.1
env:
INTEGRATION_LABELS: ${{ steps.extract.outputs.integration_labels }}
CURRENT_NUMBER: ${{ steps.extract.outputs.current_number }}
with:
script: |
const integrationLabels = JSON.parse(process.env.INTEGRATION_LABELS);
const currentNumber = parseInt(process.env.CURRENT_NUMBER);
if (integrationLabels.length === 0) {
console.log('No integration labels found, skipping duplicate detection');
core.setOutput('has_similar', 'false');
return;
}
// Use GitHub search API to find issues with matching integration labels
console.log(`Searching for issues with integration labels: ${integrationLabels.join(', ')}`);
// Build search query for issues with any of the current integration labels
const labelQueries = integrationLabels.map(label => `label:"${label}"`);
// Calculate date 6 months ago
const sixMonthsAgo = new Date();
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
const dateFilter = `created:>=${sixMonthsAgo.toISOString().split('T')[0]}`;
let searchQuery;
if (labelQueries.length === 1) {
searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:issue ${labelQueries[0]} ${dateFilter}`;
} else {
searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:issue (${labelQueries.join(' OR ')}) ${dateFilter}`;
}
console.log(`Search query: ${searchQuery}`);
let result;
try {
result = await github.rest.search.issuesAndPullRequests({
q: searchQuery,
per_page: 15,
sort: 'updated',
order: 'desc'
});
} catch (error) {
core.error('Failed to search for similar issues:', error.message);
if (error.status === 403 && error.message.includes('rate limit')) {
core.error('GitHub API rate limit exceeded');
}
core.setOutput('has_similar', 'false');
return;
}
// Filter out the current issue, pull requests, and newer issues (higher numbers)
const similarIssues = result.data.items
.filter(item =>
item.number !== currentNumber &&
!item.pull_request &&
item.number < currentNumber // Only include older issues (lower numbers)
)
.map(item => ({
number: item.number,
title: item.title,
body: item.body,
url: item.html_url,
state: item.state,
createdAt: item.created_at,
updatedAt: item.updated_at,
comments: item.comments,
labels: item.labels.map(l => l.name)
}));
console.log(`Found ${similarIssues.length} issues with matching integration labels`);
console.log('Raw similar issues:', JSON.stringify(similarIssues.slice(0, 3), null, 2));
if (similarIssues.length === 0) {
console.log('No similar issues found, setting has_similar to false');
core.setOutput('has_similar', 'false');
return;
}
console.log('Similar issues found, setting has_similar to true');
core.setOutput('has_similar', 'true');
// Clean the issue data to prevent JSON parsing issues
const cleanedIssues = similarIssues.slice(0, 15).map(item => {
// Handle body with improved truncation and null handling
let cleanBody = '';
if (item.body && typeof item.body === 'string') {
// Remove control characters
const cleaned = item.body.replace(/[\u0000-\u001F\u007F-\u009F]/g, '');
// Truncate to 1000 characters and add ellipsis if needed
cleanBody = cleaned.length > 1000
? cleaned.substring(0, 1000) + '...'
: cleaned;
}
return {
number: item.number,
title: item.title.replace(/[\u0000-\u001F\u007F-\u009F]/g, ''), // Remove control characters
body: cleanBody,
url: item.url,
state: item.state,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
comments: item.comments,
labels: item.labels
};
});
console.log(`Cleaned issues count: ${cleanedIssues.length}`);
console.log('First cleaned issue:', JSON.stringify(cleanedIssues[0], null, 2));
core.setOutput('similar_issues', JSON.stringify(cleanedIssues));
- name: Detect duplicates using AI
id: ai_detection
if: steps.extract.outputs.should_continue == 'true' && steps.fetch_similar.outputs.has_similar == 'true'
uses: actions/ai-inference@v1.1.0
with:
model: openai/gpt-4o
system-prompt: |
You are a Home Assistant issue duplicate detector. Your task is to identify TRUE DUPLICATES - issues that report the EXACT SAME problem, not just similar or related issues.
CRITICAL: An issue is ONLY a duplicate if:
- It describes the SAME problem with the SAME root cause
- Issues about the same integration but different problems are NOT duplicates
- Issues with similar symptoms but different causes are NOT duplicates
Important considerations:
- Open issues are more relevant than closed ones for duplicate detection
- Recently updated issues may indicate ongoing work or discussion
- Issues with more comments are generally more relevant and active
- Older closed issues might be resolved differently than newer approaches
- Consider the time between issues - very old issues may have different contexts
Rules:
1. ONLY mark as duplicate if the issues describe IDENTICAL problems
2. Look for issues that report the same problem or request the same functionality
3. Different error messages = NOT a duplicate (even if same integration)
4. For CLOSED issues, only mark as duplicate if they describe the EXACT same problem
5. For OPEN issues, use a lower threshold (90%+ similarity)
6. Prioritize issues with higher comment counts as they indicate more activity/relevance
7. When in doubt, do NOT mark as duplicate
8. Return ONLY a JSON array of issue numbers that are duplicates
9. If no duplicates are found, return an empty array: []
10. Maximum 5 potential duplicates, prioritize open issues with comments
11. Consider the age of issues - prefer recent duplicates over very old ones
Example response format:
[1234, 5678, 9012]
prompt: |
Current issue (just created):
Title: ${{ steps.extract.outputs.current_title }}
Body: ${{ steps.extract.outputs.current_body }}
Other issues to compare against (each includes state, creation date, last update, and comment count):
${{ steps.fetch_similar.outputs.similar_issues }}
Analyze these issues and identify which ones describe IDENTICAL problems and thus are duplicates of the current issue. When sorting them, consider their state (open/closed), how recently they were updated, and their comment count (higher = more relevant).
max-tokens: 100
- name: Post duplicate detection results
id: post_results
if: steps.extract.outputs.should_continue == 'true' && steps.fetch_similar.outputs.has_similar == 'true'
uses: actions/github-script@v7.0.1
env:
AI_RESPONSE: ${{ steps.ai_detection.outputs.response }}
SIMILAR_ISSUES: ${{ steps.fetch_similar.outputs.similar_issues }}
with:
script: |
const aiResponse = process.env.AI_RESPONSE;
console.log('Raw AI response:', JSON.stringify(aiResponse));
let duplicateNumbers = [];
try {
// Clean the response of any potential control characters
const cleanResponse = aiResponse.trim().replace(/[\u0000-\u001F\u007F-\u009F]/g, '');
console.log('Cleaned AI response:', cleanResponse);
duplicateNumbers = JSON.parse(cleanResponse);
// Ensure it's an array and contains only numbers
if (!Array.isArray(duplicateNumbers)) {
console.log('AI response is not an array, trying to extract numbers');
const numberMatches = cleanResponse.match(/\d+/g);
duplicateNumbers = numberMatches ? numberMatches.map(n => parseInt(n)) : [];
}
// Filter to only valid numbers
duplicateNumbers = duplicateNumbers.filter(n => typeof n === 'number' && !isNaN(n));
} catch (error) {
console.log('Failed to parse AI response as JSON:', error.message);
console.log('Raw response:', aiResponse);
// Fallback: try to extract numbers from the response
const numberMatches = aiResponse.match(/\d+/g);
duplicateNumbers = numberMatches ? numberMatches.map(n => parseInt(n)) : [];
console.log('Extracted numbers as fallback:', duplicateNumbers);
}
if (!Array.isArray(duplicateNumbers) || duplicateNumbers.length === 0) {
console.log('No duplicates detected by AI');
return;
}
console.log(`AI detected ${duplicateNumbers.length} potential duplicates: ${duplicateNumbers.join(', ')}`);
// Get details of detected duplicates
const similarIssues = JSON.parse(process.env.SIMILAR_ISSUES);
const duplicates = similarIssues.filter(issue => duplicateNumbers.includes(issue.number));
if (duplicates.length === 0) {
console.log('No matching issues found for detected numbers');
return;
}
// Create comment with duplicate detection results
const duplicateLinks = duplicates.map(issue => `- [#${issue.number}: ${issue.title}](${issue.url})`).join('\n');
const commentBody = [
'<!-- workflow: detect-duplicate-issues -->',
'### 🔍 **Potential duplicate detection**',
'',
'I\'ve analyzed similar issues and found the following potential duplicates:',
'',
duplicateLinks,
'',
'**What to do next:**',
'1. Please review these issues to see if they match your issue',
'2. If you find an existing issue that covers your problem:',
' - Consider closing this issue',
' - Add your findings or 👍 on the existing issue instead',
'3. If your issue is different or adds new aspects, please clarify how it differs',
'',
'This helps keep our issues organized and ensures similar issues are consolidated for better visibility.',
'',
'*This message was generated automatically by our duplicate detection system.*'
].join('\n');
try {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
body: commentBody
});
console.log(`Posted duplicate detection comment with ${duplicates.length} potential duplicates`);
// Add the potential-duplicate label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
labels: ['potential-duplicate']
});
console.log('Added potential-duplicate label to the issue');
} catch (error) {
core.error('Failed to post duplicate detection comment or add label:', error.message);
if (error.status === 403) {
core.error('Permission denied or rate limit exceeded');
}
// Don't throw - we've done the analysis, just couldn't post the result
}

View File

@@ -0,0 +1,193 @@
name: Auto-detect non-English issues
# yamllint disable-line rule:truthy
on:
issues:
types: [opened]
permissions:
issues: write
models: read
jobs:
detect-language:
runs-on: ubuntu-latest
steps:
- name: Check issue language
id: detect_language
uses: actions/github-script@v7.0.1
env:
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_BODY: ${{ github.event.issue.body }}
ISSUE_USER_TYPE: ${{ github.event.issue.user.type }}
with:
script: |
// Get the issue details from environment variables
const issueNumber = process.env.ISSUE_NUMBER;
const issueTitle = process.env.ISSUE_TITLE || '';
const issueBody = process.env.ISSUE_BODY || '';
const userType = process.env.ISSUE_USER_TYPE;
// Skip language detection for bot users
if (userType === 'Bot') {
console.log('Skipping language detection for bot user');
core.setOutput('should_continue', 'false');
return;
}
console.log(`Checking language for issue #${issueNumber}`);
console.log(`Title: ${issueTitle}`);
// Combine title and body for language detection
const fullText = `${issueTitle}\n\n${issueBody}`;
// Check if the text is too short to reliably detect language
if (fullText.trim().length < 20) {
console.log('Text too short for reliable language detection');
core.setOutput('should_continue', 'false'); // Skip processing for very short text
return;
}
core.setOutput('issue_number', issueNumber);
core.setOutput('issue_text', fullText);
core.setOutput('should_continue', 'true');
- name: Detect language using AI
id: ai_language_detection
if: steps.detect_language.outputs.should_continue == 'true'
uses: actions/ai-inference@v1.1.0
with:
model: openai/gpt-4o-mini
system-prompt: |
You are a language detection system. Your task is to determine if the provided text is written in English or another language.
Rules:
1. Analyze the text and determine the primary language of the USER'S DESCRIPTION only
2. IGNORE markdown headers (lines starting with #, ##, ###, etc.) as these are from issue templates, not user input
3. IGNORE all code blocks (text between ``` or ` markers) as they may contain system-generated error messages in other languages
4. IGNORE error messages, logs, and system output even if not in code blocks - these often appear in the user's system language
5. Consider technical terms, code snippets, URLs, and file paths as neutral (they don't indicate non-English)
6. Focus ONLY on the actual sentences and descriptions written by the user explaining their issue
7. If the user's explanation/description is in English but includes non-English error messages or logs, consider it ENGLISH
8. Return ONLY a JSON object with two fields:
- "is_english": boolean (true if the user's description is primarily in English, false otherwise)
- "detected_language": string (the name of the detected language, e.g., "English", "Spanish", "Chinese", etc.)
9. Be lenient - if the user's explanation is in English with non-English system output, it's still English
10. Common programming terms, error messages, and technical jargon should not be considered as non-English
11. If you cannot reliably determine the language, set detected_language to "undefined"
Example response:
{"is_english": false, "detected_language": "Spanish"}
prompt: |
Please analyze the following issue text and determine if it is written in English:
${{ steps.detect_language.outputs.issue_text }}
max-tokens: 50
- name: Process non-English issues
if: steps.detect_language.outputs.should_continue == 'true'
uses: actions/github-script@v7.0.1
env:
AI_RESPONSE: ${{ steps.ai_language_detection.outputs.response }}
ISSUE_NUMBER: ${{ steps.detect_language.outputs.issue_number }}
with:
script: |
const issueNumber = parseInt(process.env.ISSUE_NUMBER);
const aiResponse = process.env.AI_RESPONSE;
console.log('AI language detection response:', aiResponse);
let languageResult;
try {
languageResult = JSON.parse(aiResponse.trim());
// Validate the response structure
if (!languageResult || typeof languageResult.is_english !== 'boolean') {
throw new Error('Invalid response structure');
}
} catch (error) {
core.error(`Failed to parse AI response: ${error.message}`);
console.log('Raw AI response:', aiResponse);
// Log more details for debugging
core.warning('Defaulting to English due to parsing error');
// Default to English if we can't parse the response
return;
}
if (languageResult.is_english) {
console.log('Issue is in English, no action needed');
return;
}
// If language is undefined or not detected, skip processing
if (!languageResult.detected_language || languageResult.detected_language === 'undefined') {
console.log('Language could not be determined, skipping processing');
return;
}
console.log(`Issue detected as non-English: ${languageResult.detected_language}`);
// Post comment explaining the language requirement
const commentBody = [
'<!-- workflow: detect-non-english-issues -->',
'### 🌐 Non-English issue detected',
'',
`This issue appears to be written in **${languageResult.detected_language}** rather than English.`,
'',
'The Home Assistant project uses English as the primary language for issues to ensure that everyone in our international community can participate and help resolve issues. This allows any of our thousands of contributors to jump in and provide assistance.',
'',
'**What to do:**',
'1. Re-create the issue using the English language',
'2. If you need help with translation, consider using:',
' - Translation tools like Google Translate',
' - AI assistants like ChatGPT or Claude',
'',
'This helps our community provide the best possible support and ensures your issue gets the attention it deserves from our global contributor base.',
'',
'Thank you for your understanding! 🙏'
].join('\n');
try {
// Add comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: commentBody
});
console.log('Posted language requirement comment');
// Add non-english label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: ['non-english']
});
console.log('Added non-english label');
// Close the issue
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
state: 'closed',
state_reason: 'not_planned'
});
console.log('Closed the issue');
} catch (error) {
core.error('Failed to process non-English issue:', error.message);
if (error.status === 403) {
core.error('Permission denied or rate limit exceeded');
}
}

View File

@@ -1,8 +1,8 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.0
rev: v0.11.12
hooks:
- id: ruff
- id: ruff-check
args:
- --fix
- id: ruff-format
@@ -30,7 +30,7 @@ repos:
- --branch=master
- --branch=rc
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.35.1
rev: v1.37.1
hooks:
- id: yamllint
- repo: https://github.com/pre-commit/mirrors-prettier

View File

@@ -65,6 +65,7 @@ homeassistant.components.aladdin_connect.*
homeassistant.components.alarm_control_panel.*
homeassistant.components.alert.*
homeassistant.components.alexa.*
homeassistant.components.alexa_devices.*
homeassistant.components.alpha_vantage.*
homeassistant.components.amazon_polly.*
homeassistant.components.amberelectric.*
@@ -270,6 +271,7 @@ homeassistant.components.image_processing.*
homeassistant.components.image_upload.*
homeassistant.components.imap.*
homeassistant.components.imgw_pib.*
homeassistant.components.immich.*
homeassistant.components.incomfort.*
homeassistant.components.input_button.*
homeassistant.components.input_select.*
@@ -385,6 +387,7 @@ homeassistant.components.overseerr.*
homeassistant.components.p1_monitor.*
homeassistant.components.pandora.*
homeassistant.components.panel_custom.*
homeassistant.components.paperless_ngx.*
homeassistant.components.peblar.*
homeassistant.components.peco.*
homeassistant.components.pegel_online.*

2
.vscode/tasks.json vendored
View File

@@ -45,7 +45,7 @@
{
"label": "Ruff",
"type": "shell",
"command": "pre-commit run ruff --all-files",
"command": "pre-commit run ruff-check --all-files",
"group": {
"kind": "test",
"isDefault": true

34
CODEOWNERS generated
View File

@@ -57,6 +57,8 @@ build.json @home-assistant/supervisor
/tests/components/aemet/ @Noltari
/homeassistant/components/agent_dvr/ @ispysoftware
/tests/components/agent_dvr/ @ispysoftware
/homeassistant/components/ai_task/ @home-assistant/core
/tests/components/ai_task/ @home-assistant/core
/homeassistant/components/air_quality/ @home-assistant/core
/tests/components/air_quality/ @home-assistant/core
/homeassistant/components/airgradient/ @airgradienthq @joostlek
@@ -89,6 +91,8 @@ build.json @home-assistant/supervisor
/tests/components/alert/ @home-assistant/core @frenck
/homeassistant/components/alexa/ @home-assistant/cloud @ochlocracy @jbouwh
/tests/components/alexa/ @home-assistant/cloud @ochlocracy @jbouwh
/homeassistant/components/alexa_devices/ @chemelli74
/tests/components/alexa_devices/ @chemelli74
/homeassistant/components/amazon_polly/ @jschlyter
/homeassistant/components/amberelectric/ @madpilot
/tests/components/amberelectric/ @madpilot
@@ -202,8 +206,8 @@ build.json @home-assistant/supervisor
/tests/components/blebox/ @bbx-a @swistakm
/homeassistant/components/blink/ @fronzbot @mkmer
/tests/components/blink/ @fronzbot @mkmer
/homeassistant/components/blue_current/ @Floris272 @gleeuwen
/tests/components/blue_current/ @Floris272 @gleeuwen
/homeassistant/components/blue_current/ @gleeuwen @NickKoepr @jtodorova23
/tests/components/blue_current/ @gleeuwen @NickKoepr @jtodorova23
/homeassistant/components/bluemaestro/ @bdraco
/tests/components/bluemaestro/ @bdraco
/homeassistant/components/blueprint/ @home-assistant/core
@@ -303,6 +307,7 @@ build.json @home-assistant/supervisor
/homeassistant/components/crownstone/ @Crownstone @RicArch97
/tests/components/crownstone/ @Crownstone @RicArch97
/homeassistant/components/cups/ @fabaff
/tests/components/cups/ @fabaff
/homeassistant/components/daikin/ @fredrike
/tests/components/daikin/ @fredrike
/homeassistant/components/date/ @home-assistant/core
@@ -710,6 +715,8 @@ build.json @home-assistant/supervisor
/tests/components/imeon_inverter/ @Imeon-Energy
/homeassistant/components/imgw_pib/ @bieniu
/tests/components/imgw_pib/ @bieniu
/homeassistant/components/immich/ @mib1185
/tests/components/immich/ @mib1185
/homeassistant/components/improv_ble/ @emontnemery
/tests/components/improv_ble/ @emontnemery
/homeassistant/components/incomfort/ @jbouwh
@@ -1138,6 +1145,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/paperless_ngx/ @fvgarrel
/tests/components/paperless_ngx/ @fvgarrel
/homeassistant/components/peblar/ @frenck
/tests/components/peblar/ @frenck
/homeassistant/components/peco/ @IceBotYT
@@ -1176,6 +1185,8 @@ build.json @home-assistant/supervisor
/tests/components/powerwall/ @bdraco @jrester @daniel-simpson
/homeassistant/components/private_ble_device/ @Jc2k
/tests/components/private_ble_device/ @Jc2k
/homeassistant/components/probe_plus/ @pantherale0
/tests/components/probe_plus/ @pantherale0
/homeassistant/components/profiler/ @bdraco
/tests/components/profiler/ @bdraco
/homeassistant/components/progettihwsw/ @ardaseremet
@@ -1222,6 +1233,7 @@ build.json @home-assistant/supervisor
/homeassistant/components/qnap_qsw/ @Noltari
/tests/components/qnap_qsw/ @Noltari
/homeassistant/components/quantum_gateway/ @cisasteelersfan
/tests/components/quantum_gateway/ @cisasteelersfan
/homeassistant/components/qvr_pro/ @oblogic7
/homeassistant/components/qwikswitch/ @kellerza
/tests/components/qwikswitch/ @kellerza
@@ -1264,8 +1276,8 @@ build.json @home-assistant/supervisor
/tests/components/rehlko/ @bdraco @peterager
/homeassistant/components/remote/ @home-assistant/core
/tests/components/remote/ @home-assistant/core
/homeassistant/components/remote_calendar/ @Thomas55555
/tests/components/remote_calendar/ @Thomas55555
/homeassistant/components/remote_calendar/ @Thomas55555 @allenporter
/tests/components/remote_calendar/ @Thomas55555 @allenporter
/homeassistant/components/renault/ @epenet
/tests/components/renault/ @epenet
/homeassistant/components/renson/ @jimmyd-be
@@ -1410,6 +1422,8 @@ build.json @home-assistant/supervisor
/tests/components/sma/ @kellerza @rklomp @erwindouna
/homeassistant/components/smappee/ @bsmappee
/tests/components/smappee/ @bsmappee
/homeassistant/components/smarla/ @explicatis @rlint-explicatis
/tests/components/smarla/ @explicatis @rlint-explicatis
/homeassistant/components/smart_meter_texas/ @grahamwetzler
/tests/components/smart_meter_texas/ @grahamwetzler
/homeassistant/components/smartthings/ @joostlek
@@ -1484,8 +1498,8 @@ build.json @home-assistant/supervisor
/tests/components/subaru/ @G-Two
/homeassistant/components/suez_water/ @ooii @jb101010-2
/tests/components/suez_water/ @ooii @jb101010-2
/homeassistant/components/sun/ @Swamp-Ig
/tests/components/sun/ @Swamp-Ig
/homeassistant/components/sun/ @home-assistant/core
/tests/components/sun/ @home-assistant/core
/homeassistant/components/supla/ @mwegrzynek
/homeassistant/components/surepetcare/ @benleb @danielhiversen
/tests/components/surepetcare/ @benleb @danielhiversen
@@ -1498,8 +1512,8 @@ build.json @home-assistant/supervisor
/tests/components/switch_as_x/ @home-assistant/core
/homeassistant/components/switchbee/ @jafar-atili
/tests/components/switchbee/ @jafar-atili
/homeassistant/components/switchbot/ @danielhiversen @RenierM26 @murtas @Eloston @dsypniewski
/tests/components/switchbot/ @danielhiversen @RenierM26 @murtas @Eloston @dsypniewski
/homeassistant/components/switchbot/ @danielhiversen @RenierM26 @murtas @Eloston @dsypniewski @zerzhang
/tests/components/switchbot/ @danielhiversen @RenierM26 @murtas @Eloston @dsypniewski @zerzhang
/homeassistant/components/switchbot_cloud/ @SeraphicRav @laurence-presland @Gigatrappeur
/tests/components/switchbot_cloud/ @SeraphicRav @laurence-presland @Gigatrappeur
/homeassistant/components/switcher_kis/ @thecode @YogevBokobza
@@ -1539,8 +1553,8 @@ build.json @home-assistant/supervisor
/tests/components/tedee/ @patrickhilker @zweckj
/homeassistant/components/tellduslive/ @fredrike
/tests/components/tellduslive/ @fredrike
/homeassistant/components/template/ @Petro31 @PhracturedBlue @home-assistant/core
/tests/components/template/ @Petro31 @PhracturedBlue @home-assistant/core
/homeassistant/components/template/ @Petro31 @home-assistant/core
/tests/components/template/ @Petro31 @home-assistant/core
/homeassistant/components/tesla_fleet/ @Bre77
/tests/components/tesla_fleet/ @Bre77
/homeassistant/components/tesla_wall_connector/ @einarhauks

View File

@@ -1,29 +0,0 @@
"""Enum backports from standard lib.
This file contained the backport of the StrEnum of Python 3.11.
Since we have dropped support for Python 3.10, we can remove this backport.
This file is kept for now to avoid breaking custom components that might
import it.
"""
from __future__ import annotations
from enum import StrEnum as _StrEnum
from functools import partial
from homeassistant.helpers.deprecation import (
DeprecatedAlias,
all_with_deprecated_constants,
check_if_deprecated_constant,
dir_with_deprecated_constants,
)
# StrEnum deprecated as of 2024.5 use enum.StrEnum instead.
_DEPRECATED_StrEnum = DeprecatedAlias(_StrEnum, "enum.StrEnum", "2025.5")
__getattr__ = partial(check_if_deprecated_constant, module_globals=globals())
__dir__ = partial(
dir_with_deprecated_constants, module_globals_keys=[*globals().keys()]
)
__all__ = all_with_deprecated_constants(globals())

View File

@@ -1,31 +0,0 @@
"""Functools backports from standard lib.
This file contained the backport of the cached_property implementation of Python 3.12.
Since we have dropped support for Python 3.11, we can remove this backport.
This file is kept for now to avoid breaking custom components that might
import it.
"""
from __future__ import annotations
# pylint: disable-next=hass-deprecated-import
from functools import cached_property as _cached_property, partial
from homeassistant.helpers.deprecation import (
DeprecatedAlias,
all_with_deprecated_constants,
check_if_deprecated_constant,
dir_with_deprecated_constants,
)
# cached_property deprecated as of 2024.5 use functools.cached_property instead.
_DEPRECATED_cached_property = DeprecatedAlias(
_cached_property, "functools.cached_property", "2025.5"
)
__getattr__ = partial(check_if_deprecated_constant, module_globals=globals())
__dir__ = partial(
dir_with_deprecated_constants, module_globals_keys=[*globals().keys()]
)
__all__ = all_with_deprecated_constants(globals())

View File

@@ -171,8 +171,6 @@ FRONTEND_INTEGRATIONS = {
# Stage 0 is divided into substages. Each substage has a name, a set of integrations and a timeout.
# The substage containing recorder should have no timeout, as it could cancel a database migration.
# Recorder freezes "recorder" timeout during a migration, but it does not freeze other timeouts.
# The substages preceding it should also have no timeout, until we ensure that the recorder
# is not accidentally promoted as a dependency of any of the integrations in them.
# If we add timeouts to the frontend substages, we should make sure they don't apply in recovery mode.
STAGE_0_INTEGRATIONS = (
# Load logging and http deps as soon as possible
@@ -929,7 +927,11 @@ async def _async_set_up_integrations(
await _async_setup_multi_components(hass, stage_all_domains, config)
continue
try:
async with hass.timeout.async_timeout(timeout, cool_down=COOLDOWN_TIME):
async with hass.timeout.async_timeout(
timeout,
cool_down=COOLDOWN_TIME,
cancel_message=f"Bootstrap stage {name} timeout",
):
await _async_setup_multi_components(hass, stage_all_domains, config)
except TimeoutError:
_LOGGER.warning(
@@ -941,7 +943,11 @@ async def _async_set_up_integrations(
# Wrap up startup
_LOGGER.debug("Waiting for startup to wrap up")
try:
async with hass.timeout.async_timeout(WRAP_UP_TIMEOUT, cool_down=COOLDOWN_TIME):
async with hass.timeout.async_timeout(
WRAP_UP_TIMEOUT,
cool_down=COOLDOWN_TIME,
cancel_message="Bootstrap startup wrap up timeout",
):
await hass.async_block_till_done()
except TimeoutError:
_LOGGER.warning(

View File

@@ -3,6 +3,7 @@
"name": "Amazon",
"integrations": [
"alexa",
"alexa_devices",
"amazon_polly",
"aws",
"aws_s3",

View File

@@ -0,0 +1,6 @@
{
"domain": "shelly",
"name": "shelly",
"integrations": ["shelly"],
"iot_standards": ["zwave"]
}

View File

@@ -14,30 +14,24 @@ from jaraco.abode.exceptions import (
)
from jaraco.abode.helpers.timeline import Groups as GROUPS
from requests.exceptions import ConnectTimeout, HTTPError
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_DATE,
ATTR_DEVICE_ID,
ATTR_ENTITY_ID,
ATTR_TIME,
CONF_PASSWORD,
CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP,
Platform,
)
from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, ServiceCall
from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.helpers.typing import ConfigType
from .const import CONF_POLLING, DOMAIN, LOGGER
SERVICE_SETTINGS = "change_setting"
SERVICE_CAPTURE_IMAGE = "capture_image"
SERVICE_TRIGGER_AUTOMATION = "trigger_automation"
from .services import async_setup_services
ATTR_DEVICE_NAME = "device_name"
ATTR_DEVICE_TYPE = "device_type"
@@ -45,22 +39,12 @@ ATTR_EVENT_CODE = "event_code"
ATTR_EVENT_NAME = "event_name"
ATTR_EVENT_TYPE = "event_type"
ATTR_EVENT_UTC = "event_utc"
ATTR_SETTING = "setting"
ATTR_USER_NAME = "user_name"
ATTR_APP_TYPE = "app_type"
ATTR_EVENT_BY = "event_by"
ATTR_VALUE = "value"
CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
CHANGE_SETTING_SCHEMA = vol.Schema(
{vol.Required(ATTR_SETTING): cv.string, vol.Required(ATTR_VALUE): cv.string}
)
CAPTURE_IMAGE_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
AUTOMATION_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
PLATFORMS = [
Platform.ALARM_CONTROL_PANEL,
Platform.BINARY_SENSOR,
@@ -85,7 +69,7 @@ class AbodeSystem:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Abode component."""
setup_hass_services(hass)
async_setup_services(hass)
return True
@@ -138,60 +122,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return unload_ok
def setup_hass_services(hass: HomeAssistant) -> None:
"""Home Assistant services."""
def change_setting(call: ServiceCall) -> None:
"""Change an Abode system setting."""
setting = call.data[ATTR_SETTING]
value = call.data[ATTR_VALUE]
try:
hass.data[DOMAIN].abode.set_setting(setting, value)
except AbodeException as ex:
LOGGER.warning(ex)
def capture_image(call: ServiceCall) -> None:
"""Capture a new image."""
entity_ids = call.data[ATTR_ENTITY_ID]
target_entities = [
entity_id
for entity_id in hass.data[DOMAIN].entity_ids
if entity_id in entity_ids
]
for entity_id in target_entities:
signal = f"abode_camera_capture_{entity_id}"
dispatcher_send(hass, signal)
def trigger_automation(call: ServiceCall) -> None:
"""Trigger an Abode automation."""
entity_ids = call.data[ATTR_ENTITY_ID]
target_entities = [
entity_id
for entity_id in hass.data[DOMAIN].entity_ids
if entity_id in entity_ids
]
for entity_id in target_entities:
signal = f"abode_trigger_automation_{entity_id}"
dispatcher_send(hass, signal)
hass.services.async_register(
DOMAIN, SERVICE_SETTINGS, change_setting, schema=CHANGE_SETTING_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_CAPTURE_IMAGE, capture_image, schema=CAPTURE_IMAGE_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_TRIGGER_AUTOMATION, trigger_automation, schema=AUTOMATION_SCHEMA
)
async def setup_hass_events(hass: HomeAssistant) -> None:
"""Home Assistant start and stop callbacks."""

View File

@@ -0,0 +1,90 @@
"""Support for the Abode Security System."""
from __future__ import annotations
from jaraco.abode.exceptions import Exception as AbodeException
import voluptuous as vol
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import dispatcher_send
from .const import DOMAIN, LOGGER
SERVICE_SETTINGS = "change_setting"
SERVICE_CAPTURE_IMAGE = "capture_image"
SERVICE_TRIGGER_AUTOMATION = "trigger_automation"
ATTR_SETTING = "setting"
ATTR_VALUE = "value"
CHANGE_SETTING_SCHEMA = vol.Schema(
{vol.Required(ATTR_SETTING): cv.string, vol.Required(ATTR_VALUE): cv.string}
)
CAPTURE_IMAGE_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
AUTOMATION_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
def _change_setting(call: ServiceCall) -> None:
"""Change an Abode system setting."""
setting = call.data[ATTR_SETTING]
value = call.data[ATTR_VALUE]
try:
call.hass.data[DOMAIN].abode.set_setting(setting, value)
except AbodeException as ex:
LOGGER.warning(ex)
def _capture_image(call: ServiceCall) -> None:
"""Capture a new image."""
entity_ids = call.data[ATTR_ENTITY_ID]
target_entities = [
entity_id
for entity_id in call.hass.data[DOMAIN].entity_ids
if entity_id in entity_ids
]
for entity_id in target_entities:
signal = f"abode_camera_capture_{entity_id}"
dispatcher_send(call.hass, signal)
def _trigger_automation(call: ServiceCall) -> None:
"""Trigger an Abode automation."""
entity_ids = call.data[ATTR_ENTITY_ID]
target_entities = [
entity_id
for entity_id in call.hass.data[DOMAIN].entity_ids
if entity_id in entity_ids
]
for entity_id in target_entities:
signal = f"abode_trigger_automation_{entity_id}"
dispatcher_send(call.hass, signal)
@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Home Assistant services."""
hass.services.async_register(
DOMAIN, SERVICE_SETTINGS, _change_setting, schema=CHANGE_SETTING_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_CAPTURE_IMAGE, _capture_image, schema=CAPTURE_IMAGE_SCHEMA
)
hass.services.async_register(
DOMAIN,
SERVICE_TRIGGER_AUTOMATION,
_trigger_automation,
schema=AUTOMATION_SCHEMA,
)

View File

@@ -40,9 +40,10 @@ class AcmedaFlowHandler(ConfigFlow, domain=DOMAIN):
entry.unique_id for entry in self._async_current_entries()
}
hubs: list[aiopulse.Hub] = []
with suppress(TimeoutError):
async with timeout(5):
hubs: list[aiopulse.Hub] = [
hubs = [
hub
async for hub in aiopulse.Hub.discover()
if hub.id not in already_configured

View File

@@ -8,7 +8,7 @@ from homeassistant.core import HomeAssistant
from .const import CONNECTION_TYPE, LOCAL
from .coordinator import AdaxCloudCoordinator, AdaxConfigEntry, AdaxLocalCoordinator
PLATFORMS = [Platform.CLIMATE]
PLATFORMS = [Platform.CLIMATE, Platform.SENSOR]
async def async_setup_entry(hass: HomeAssistant, entry: AdaxConfigEntry) -> bool:

View File

@@ -41,7 +41,30 @@ class AdaxCloudCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]]):
async def _async_update_data(self) -> dict[str, dict[str, Any]]:
"""Fetch data from the Adax."""
rooms = await self.adax_data_handler.get_rooms() or []
try:
if hasattr(self.adax_data_handler, "fetch_rooms_info"):
rooms = await self.adax_data_handler.fetch_rooms_info() or []
_LOGGER.debug("fetch_rooms_info returned: %s", rooms)
else:
_LOGGER.debug("fetch_rooms_info method not available, using get_rooms")
rooms = []
if not rooms:
_LOGGER.debug(
"No rooms from fetch_rooms_info, trying get_rooms as fallback"
)
rooms = await self.adax_data_handler.get_rooms() or []
_LOGGER.debug("get_rooms fallback returned: %s", rooms)
if not rooms:
raise UpdateFailed("No rooms available from Adax API")
except OSError as e:
raise UpdateFailed(f"Error communicating with API: {e}") from e
for room in rooms:
room["energyWh"] = int(room.get("energyWh", 0))
return {r["id"]: r for r in rooms}

View File

@@ -0,0 +1,77 @@
"""Support for Adax energy sensors."""
from __future__ import annotations
from typing import cast
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
from homeassistant.const import UnitOfEnergy
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import AdaxConfigEntry
from .const import CONNECTION_TYPE, DOMAIN, LOCAL
from .coordinator import AdaxCloudCoordinator
async def async_setup_entry(
hass: HomeAssistant,
entry: AdaxConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Adax energy sensors with config flow."""
if entry.data.get(CONNECTION_TYPE) != LOCAL:
cloud_coordinator = cast(AdaxCloudCoordinator, entry.runtime_data)
# Create individual energy sensors for each device
async_add_entities(
AdaxEnergySensor(cloud_coordinator, device_id)
for device_id in cloud_coordinator.data
)
class AdaxEnergySensor(CoordinatorEntity[AdaxCloudCoordinator], SensorEntity):
"""Representation of an Adax energy sensor."""
_attr_has_entity_name = True
_attr_translation_key = "energy"
_attr_device_class = SensorDeviceClass.ENERGY
_attr_native_unit_of_measurement = UnitOfEnergy.WATT_HOUR
_attr_suggested_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
_attr_state_class = SensorStateClass.TOTAL_INCREASING
_attr_suggested_display_precision = 3
def __init__(
self,
coordinator: AdaxCloudCoordinator,
device_id: str,
) -> None:
"""Initialize the energy sensor."""
super().__init__(coordinator)
self._device_id = device_id
room = coordinator.data[device_id]
self._attr_unique_id = f"{room['homeId']}_{device_id}_energy"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, device_id)},
name=room["name"],
manufacturer="Adax",
)
@property
def available(self) -> bool:
"""Return True if entity is available."""
return (
super().available and "energyWh" in self.coordinator.data[self._device_id]
)
@property
def native_value(self) -> int:
"""Return the native value of the sensor."""
return int(self.coordinator.data[self._device_id]["energyWh"])

View File

@@ -15,7 +15,7 @@ from homeassistant.helpers.entity_platform import (
)
from . import AgentDVRConfigEntry
from .const import ATTRIBUTION, CAMERA_SCAN_INTERVAL_SECS, DOMAIN as AGENT_DOMAIN
from .const import ATTRIBUTION, CAMERA_SCAN_INTERVAL_SECS, DOMAIN
SCAN_INTERVAL = timedelta(seconds=CAMERA_SCAN_INTERVAL_SECS)
@@ -82,7 +82,7 @@ class AgentCamera(MjpegCamera):
still_image_url=f"{device.client._server_url}{device.still_image_url}&size={device.mjpegStreamWidth}x{device.mjpegStreamHeight}", # noqa: SLF001
)
self._attr_device_info = DeviceInfo(
identifiers={(AGENT_DOMAIN, self.unique_id)},
identifiers={(DOMAIN, self.unique_id)},
manufacturer="Agent",
model="Camera",
name=f"{device.client.name} {device.name}",

View File

@@ -0,0 +1,99 @@
"""Integration to offer AI tasks to Home Assistant."""
import logging
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, storage
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import UNDEFINED, ConfigType, UndefinedType
from .const import DATA_COMPONENT, DATA_PREFERENCES, DOMAIN
from .entity import AITaskEntity
from .http import async_setup as async_setup_conversation_http
from .task import GenTextTask, GenTextTaskResult, async_generate_text
__all__ = [
"DOMAIN",
"AITaskEntity",
"GenTextTask",
"GenTextTaskResult",
"async_generate_text",
"async_setup",
"async_setup_entry",
"async_unload_entry",
]
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Register the process service."""
entity_component = EntityComponent[AITaskEntity](_LOGGER, DOMAIN, hass)
hass.data[DATA_COMPONENT] = entity_component
hass.data[DATA_PREFERENCES] = AITaskPreferences(hass)
await hass.data[DATA_PREFERENCES].async_load()
async_setup_conversation_http(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a config entry."""
return await hass.data[DATA_COMPONENT].async_setup_entry(entry)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.data[DATA_COMPONENT].async_unload_entry(entry)
class AITaskPreferences:
"""AI Task preferences."""
gen_text_entity_id: str | None = None
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize the preferences."""
self._store: storage.Store[dict[str, str | None]] = storage.Store(
hass, 1, DOMAIN
)
async def async_load(self) -> None:
"""Load the data from the store."""
data = await self._store.async_load()
if data is None:
return
self.gen_text_entity_id = data.get("gen_text_entity_id")
@callback
def async_set_preferences(
self,
*,
gen_text_entity_id: str | None | UndefinedType = UNDEFINED,
) -> None:
"""Set the preferences."""
changed = False
for key, value in (("gen_text_entity_id", gen_text_entity_id),):
if value is not UNDEFINED:
if getattr(self, key) != value:
setattr(self, key, value)
changed = True
if not changed:
return
self._store.async_delay_save(
lambda: {
"gen_text_entity_id": self.gen_text_entity_id,
},
10,
)
@callback
def as_dict(self) -> dict[str, str | None]:
"""Get the current preferences."""
return {
"gen_text_entity_id": self.gen_text_entity_id,
}

View File

@@ -0,0 +1,21 @@
"""Constants for the AI Task integration."""
from __future__ import annotations
from typing import TYPE_CHECKING
from homeassistant.util.hass_dict import HassKey
if TYPE_CHECKING:
from homeassistant.helpers.entity_component import EntityComponent
from . import AITaskPreferences
from .entity import AITaskEntity
DOMAIN = "ai_task"
DATA_COMPONENT: HassKey[EntityComponent[AITaskEntity]] = HassKey(DOMAIN)
DATA_PREFERENCES: HassKey[AITaskPreferences] = HassKey(f"{DOMAIN}_preferences")
DEFAULT_SYSTEM_PROMPT = (
"You are a Home Assistant expert and help users with their tasks."
)

View File

@@ -0,0 +1,95 @@
"""Entity for the AI Task integration."""
from collections.abc import AsyncGenerator
import contextlib
from typing import final
from homeassistant.components.conversation import (
ChatLog,
UserContent,
async_get_chat_log,
)
from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN
from homeassistant.helpers import llm
from homeassistant.helpers.chat_session import async_get_chat_session
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.util import dt as dt_util
from .const import DEFAULT_SYSTEM_PROMPT, DOMAIN
from .task import GenTextTask, GenTextTaskResult
class AITaskEntity(RestoreEntity):
"""Entity that supports conversations."""
_attr_should_poll = False
__last_activity: str | None = None
@property
@final
def state(self) -> str | None:
"""Return the state of the entity."""
if self.__last_activity is None:
return None
return self.__last_activity
async def async_internal_added_to_hass(self) -> None:
"""Call when the entity is added to hass."""
await super().async_internal_added_to_hass()
state = await self.async_get_last_state()
if (
state is not None
and state.state is not None
and state.state not in (STATE_UNAVAILABLE, STATE_UNKNOWN)
):
self.__last_activity = state.state
@final
@contextlib.asynccontextmanager
async def _async_get_ai_task_chat_log(
self,
task: GenTextTask,
) -> AsyncGenerator[ChatLog]:
"""Context manager used to manage the ChatLog used during an AI Task."""
# pylint: disable-next=contextmanager-generator-missing-cleanup
with (
async_get_chat_session(self.hass) as session,
async_get_chat_log(
self.hass,
session,
None,
) as chat_log,
):
await chat_log.async_provide_llm_data(
llm.LLMContext(
platform=self.platform.domain,
context=None,
language=None,
assistant=DOMAIN,
device_id=None,
),
user_llm_prompt=DEFAULT_SYSTEM_PROMPT,
)
chat_log.async_add_user_content(UserContent(task.instructions))
yield chat_log
@final
async def internal_async_generate_text(
self,
task: GenTextTask,
) -> GenTextTaskResult:
"""Run a gen text task."""
self.__last_activity = dt_util.utcnow().isoformat()
self.async_write_ha_state()
async with self._async_get_ai_task_chat_log(task) as chat_log:
return await self._async_generate_text(task, chat_log)
async def _async_generate_text(
self,
task: GenTextTask,
chat_log: ChatLog,
) -> GenTextTaskResult:
"""Handle a gen text task."""
raise NotImplementedError

View File

@@ -0,0 +1,82 @@
"""HTTP endpoint for AI Task integration."""
from typing import Any
import voluptuous as vol
from homeassistant.components import websocket_api
from homeassistant.core import HomeAssistant, callback
from .const import DATA_PREFERENCES
from .task import async_generate_text
@callback
def async_setup(hass: HomeAssistant) -> None:
"""Set up the HTTP API for the conversation integration."""
websocket_api.async_register_command(hass, websocket_generate_text)
websocket_api.async_register_command(hass, websocket_get_preferences)
websocket_api.async_register_command(hass, websocket_set_preferences)
@websocket_api.websocket_command(
{
vol.Required("type"): "ai_task/generate_text",
vol.Required("task_name"): str,
vol.Optional("entity_id"): str,
vol.Required("instructions"): str,
}
)
@websocket_api.require_admin
@websocket_api.async_response
async def websocket_generate_text(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Run a generate text task."""
msg.pop("type")
msg_id = msg.pop("id")
try:
result = await async_generate_text(hass=hass, **msg)
except ValueError as err:
connection.send_error(msg_id, websocket_api.const.ERR_UNKNOWN_ERROR, str(err))
return
connection.send_result(msg_id, result.as_dict())
@websocket_api.websocket_command(
{
vol.Required("type"): "ai_task/preferences/get",
}
)
@callback
def websocket_get_preferences(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Get AI task preferences."""
preferences = hass.data[DATA_PREFERENCES]
connection.send_result(msg["id"], preferences.as_dict())
@websocket_api.websocket_command(
{
vol.Required("type"): "ai_task/preferences/set",
vol.Optional("gen_text_entity_id"): vol.Any(str, None),
}
)
@websocket_api.require_admin
@callback
def websocket_set_preferences(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Set AI task preferences."""
preferences = hass.data[DATA_PREFERENCES]
msg.pop("type")
msg_id = msg.pop("id")
preferences.async_set_preferences(**msg)
connection.send_result(msg_id, preferences.as_dict())

View File

@@ -0,0 +1,9 @@
{
"domain": "ai_task",
"name": "AI Task",
"codeowners": ["@home-assistant/core"],
"dependencies": ["conversation"],
"documentation": "https://www.home-assistant.io/integrations/ai_task",
"integration_type": "system",
"quality_scale": "internal"
}

View File

@@ -0,0 +1,68 @@
"""AI tasks to be handled by agents."""
from __future__ import annotations
from dataclasses import dataclass
from homeassistant.core import HomeAssistant
from .const import DATA_COMPONENT, DATA_PREFERENCES
async def async_generate_text(
hass: HomeAssistant,
*,
task_name: str,
entity_id: str | None = None,
instructions: str,
) -> GenTextTaskResult:
"""Run a task in the AI Task integration."""
if entity_id is None:
entity_id = hass.data[DATA_PREFERENCES].gen_text_entity_id
if entity_id is None:
raise ValueError("No entity_id provided and no preferred entity set")
entity = hass.data[DATA_COMPONENT].get_entity(entity_id)
if entity is None:
raise ValueError(f"AI Task entity {entity_id} not found")
return await entity.internal_async_generate_text(
GenTextTask(
name=task_name,
instructions=instructions,
)
)
@dataclass(slots=True)
class GenTextTask:
"""Gen text task to be processed."""
name: str
"""Name of the task."""
instructions: str
"""Instructions on what needs to be done."""
def __str__(self) -> str:
"""Return task as a string."""
return f"<GenTextTask {self.name}: {id(self)}>"
@dataclass(slots=True)
class GenTextTaskResult:
"""Result of gen text task."""
conversation_id: str
"""Unique identifier for the conversation."""
result: str
"""Result of the task."""
def as_dict(self) -> dict[str, str]:
"""Return result as a dict."""
return {
"conversation_id": self.conversation_id,
"result": self.result,
}

View File

@@ -51,9 +51,16 @@ class AirGradientCoordinator(DataUpdateCoordinator[AirGradientData]):
async def _async_setup(self) -> None:
"""Set up the coordinator."""
self._current_version = (
await self.client.get_current_measures()
).firmware_version
try:
self._current_version = (
await self.client.get_current_measures()
).firmware_version
except AirGradientError as error:
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="update_error",
translation_placeholders={"error": str(error)},
) from error
async def _async_update_data(self) -> AirGradientData:
try:

View File

@@ -6,6 +6,7 @@ from typing import Any, Concatenate
from airgradient import AirGradientConnectionError, AirGradientError, get_model_name
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
@@ -29,6 +30,7 @@ class AirGradientEntity(CoordinatorEntity[AirGradientCoordinator]):
model_id=measures.model,
serial_number=coordinator.serial_number,
sw_version=measures.firmware_version,
connections={(dr.CONNECTION_NETWORK_MAC, coordinator.serial_number)},
)

View File

@@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["aioairq"],
"requirements": ["aioairq==0.4.4"]
"requirements": ["aioairq==0.4.6"]
}

View File

@@ -5,23 +5,22 @@ from __future__ import annotations
from datetime import timedelta
import logging
from airthings import Airthings, AirthingsDevice, AirthingsError
from airthings import Airthings
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import CONF_SECRET, DOMAIN
from .const import CONF_SECRET
from .coordinator import AirthingsDataUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
PLATFORMS: list[Platform] = [Platform.SENSOR]
SCAN_INTERVAL = timedelta(minutes=6)
type AirthingsDataCoordinatorType = DataUpdateCoordinator[dict[str, AirthingsDevice]]
type AirthingsConfigEntry = ConfigEntry[AirthingsDataCoordinatorType]
type AirthingsConfigEntry = ConfigEntry[AirthingsDataUpdateCoordinator]
async def async_setup_entry(hass: HomeAssistant, entry: AirthingsConfigEntry) -> bool:
@@ -32,21 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirthingsConfigEntry) ->
async_get_clientsession(hass),
)
async def _update_method() -> dict[str, AirthingsDevice]:
"""Get the latest data from Airthings."""
try:
return await airthings.update_devices() # type: ignore[no-any-return]
except AirthingsError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err
coordinator = AirthingsDataUpdateCoordinator(hass, airthings)
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
config_entry=entry,
name=DOMAIN,
update_method=_update_method,
update_interval=SCAN_INTERVAL,
)
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator

View File

@@ -0,0 +1,36 @@
"""The Airthings integration."""
from datetime import timedelta
import logging
from airthings import Airthings, AirthingsDevice, AirthingsError
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(minutes=6)
class AirthingsDataUpdateCoordinator(DataUpdateCoordinator[dict[str, AirthingsDevice]]):
"""Coordinator for Airthings data updates."""
def __init__(self, hass: HomeAssistant, airthings: Airthings) -> None:
"""Initialize the coordinator."""
super().__init__(
hass,
_LOGGER,
name=DOMAIN,
update_method=self._update_method,
update_interval=SCAN_INTERVAL,
)
self.airthings = airthings
async def _update_method(self) -> dict[str, AirthingsDevice]:
"""Get the latest data from Airthings."""
try:
return await self.airthings.update_devices() # type: ignore[no-any-return]
except AirthingsError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err

View File

@@ -19,6 +19,7 @@ from homeassistant.const import (
SIGNAL_STRENGTH_DECIBELS,
EntityCategory,
UnitOfPressure,
UnitOfSoundPressure,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -27,32 +28,44 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import AirthingsConfigEntry, AirthingsDataCoordinatorType
from . import AirthingsConfigEntry
from .const import DOMAIN
from .coordinator import AirthingsDataUpdateCoordinator
SENSORS: dict[str, SensorEntityDescription] = {
"radonShortTermAvg": SensorEntityDescription(
key="radonShortTermAvg",
native_unit_of_measurement="Bq/m³",
translation_key="radon",
suggested_display_precision=0,
),
"temp": SensorEntityDescription(
key="temp",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
),
"humidity": SensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"pressure": SensorEntityDescription(
key="pressure",
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
native_unit_of_measurement=UnitOfPressure.MBAR,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
),
"sla": SensorEntityDescription(
key="sla",
device_class=SensorDeviceClass.SOUND_PRESSURE,
native_unit_of_measurement=UnitOfSoundPressure.WEIGHTED_DECIBEL_A,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"battery": SensorEntityDescription(
key="battery",
@@ -60,40 +73,47 @@ SENSORS: dict[str, SensorEntityDescription] = {
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"co2": SensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"voc": SensorEntityDescription(
key="voc",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"light": SensorEntityDescription(
key="light",
native_unit_of_measurement=PERCENTAGE,
translation_key="light",
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"lux": SensorEntityDescription(
key="lux",
device_class=SensorDeviceClass.ILLUMINANCE,
native_unit_of_measurement=LIGHT_LUX,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"virusRisk": SensorEntityDescription(
key="virusRisk",
translation_key="virus_risk",
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"mold": SensorEntityDescription(
key="mold",
translation_key="mold",
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"rssi": SensorEntityDescription(
key="rssi",
@@ -102,18 +122,21 @@ SENSORS: dict[str, SensorEntityDescription] = {
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"pm1": SensorEntityDescription(
key="pm1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"pm25": SensorEntityDescription(
key="pm25",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
}
@@ -140,7 +163,7 @@ async def async_setup_entry(
class AirthingsHeaterEnergySensor(
CoordinatorEntity[AirthingsDataCoordinatorType], SensorEntity
CoordinatorEntity[AirthingsDataUpdateCoordinator], SensorEntity
):
"""Representation of a Airthings Sensor device."""
@@ -149,7 +172,7 @@ class AirthingsHeaterEnergySensor(
def __init__(
self,
coordinator: AirthingsDataCoordinatorType,
coordinator: AirthingsDataUpdateCoordinator,
airthings_device: AirthingsDevice,
entity_description: SensorEntityDescription,
) -> None:

View File

@@ -142,7 +142,7 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
return AT_TO_HA_STATE[self._airtouch.acs[self._ac_number].AcMode]
@property
def hvac_modes(self):
def hvac_modes(self) -> list[HVACMode]:
"""Return the list of available operation modes."""
airtouch_modes = self._airtouch.GetSupportedCoolingModesForAc(self._ac_number)
modes = [AT_TO_HA_STATE[mode] for mode in airtouch_modes]
@@ -226,12 +226,12 @@ class AirtouchGroup(CoordinatorEntity, ClimateEntity):
return super()._handle_coordinator_update()
@property
def min_temp(self):
def min_temp(self) -> float:
"""Return Minimum Temperature for AC of this group."""
return self._airtouch.acs[self._unit.BelongsToAc].MinSetpoint
@property
def max_temp(self):
def max_temp(self) -> float:
"""Return Max Temperature for AC of this group."""
return self._airtouch.acs[self._unit.BelongsToAc].MaxSetpoint

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/airtouch5",
"iot_class": "local_push",
"loggers": ["airtouch5py"],
"requirements": ["airtouch5py==0.2.11"]
"requirements": ["airtouch5py==0.3.0"]
}

View File

@@ -0,0 +1,32 @@
"""Alexa Devices integration."""
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from .coordinator import AmazonConfigEntry, AmazonDevicesCoordinator
PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.NOTIFY,
Platform.SWITCH,
]
async def async_setup_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bool:
"""Set up Alexa Devices platform."""
coordinator = AmazonDevicesCoordinator(hass, entry)
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bool:
"""Unload a config entry."""
await entry.runtime_data.api.close()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@@ -0,0 +1,74 @@
"""Support for binary sensors."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Final
from aioamazondevices.api import AmazonDevice
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import AmazonConfigEntry
from .entity import AmazonEntity
# Coordinator is used to centralize the data updates
PARALLEL_UPDATES = 0
@dataclass(frozen=True, kw_only=True)
class AmazonBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Alexa Devices binary sensor entity description."""
is_on_fn: Callable[[AmazonDevice], bool]
BINARY_SENSORS: Final = (
AmazonBinarySensorEntityDescription(
key="online",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_category=EntityCategory.DIAGNOSTIC,
is_on_fn=lambda _device: _device.online,
),
AmazonBinarySensorEntityDescription(
key="bluetooth",
entity_category=EntityCategory.DIAGNOSTIC,
translation_key="bluetooth",
is_on_fn=lambda _device: _device.bluetooth_state,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AmazonConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Alexa Devices binary sensors based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
AmazonBinarySensorEntity(coordinator, serial_num, sensor_desc)
for sensor_desc in BINARY_SENSORS
for serial_num in coordinator.data
)
class AmazonBinarySensorEntity(AmazonEntity, BinarySensorEntity):
"""Binary sensor device."""
entity_description: AmazonBinarySensorEntityDescription
@property
def is_on(self) -> bool:
"""Return True if the binary sensor is on."""
return self.entity_description.is_on_fn(self.device)

View File

@@ -0,0 +1,63 @@
"""Config flow for Alexa Devices integration."""
from __future__ import annotations
from typing import Any
from aioamazondevices.api import AmazonEchoApi
from aioamazondevices.exceptions import CannotAuthenticate, CannotConnect
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_CODE, CONF_COUNTRY, CONF_PASSWORD, CONF_USERNAME
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.selector import CountrySelector
from .const import CONF_LOGIN_DATA, DOMAIN
class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Alexa Devices."""
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors = {}
if user_input:
client = AmazonEchoApi(
user_input[CONF_COUNTRY],
user_input[CONF_USERNAME],
user_input[CONF_PASSWORD],
)
try:
data = await client.login_mode_interactive(user_input[CONF_CODE])
except CannotConnect:
errors["base"] = "cannot_connect"
except CannotAuthenticate:
errors["base"] = "invalid_auth"
else:
await self.async_set_unique_id(data["customer_info"]["user_id"])
self._abort_if_unique_id_configured()
user_input.pop(CONF_CODE)
return self.async_create_entry(
title=user_input[CONF_USERNAME],
data=user_input | {CONF_LOGIN_DATA: data},
)
finally:
await client.close()
return self.async_show_form(
step_id="user",
errors=errors,
data_schema=vol.Schema(
{
vol.Required(
CONF_COUNTRY, default=self.hass.config.country
): CountrySelector(),
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_CODE): cv.string,
}
),
)

View File

@@ -0,0 +1,8 @@
"""Alexa Devices constants."""
import logging
_LOGGER = logging.getLogger(__package__)
DOMAIN = "alexa_devices"
CONF_LOGIN_DATA = "login_data"

View File

@@ -0,0 +1,58 @@
"""Support for Alexa Devices."""
from datetime import timedelta
from aioamazondevices.api import AmazonDevice, AmazonEchoApi
from aioamazondevices.exceptions import (
CannotAuthenticate,
CannotConnect,
CannotRetrieveData,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_COUNTRY, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import _LOGGER, CONF_LOGIN_DATA
SCAN_INTERVAL = 30
type AmazonConfigEntry = ConfigEntry[AmazonDevicesCoordinator]
class AmazonDevicesCoordinator(DataUpdateCoordinator[dict[str, AmazonDevice]]):
"""Base coordinator for Alexa Devices."""
config_entry: AmazonConfigEntry
def __init__(
self,
hass: HomeAssistant,
entry: AmazonConfigEntry,
) -> None:
"""Initialize the scanner."""
super().__init__(
hass,
_LOGGER,
name=entry.title,
config_entry=entry,
update_interval=timedelta(seconds=SCAN_INTERVAL),
)
self.api = AmazonEchoApi(
entry.data[CONF_COUNTRY],
entry.data[CONF_USERNAME],
entry.data[CONF_PASSWORD],
entry.data[CONF_LOGIN_DATA],
)
async def _async_update_data(self) -> dict[str, AmazonDevice]:
"""Update device data."""
try:
await self.api.login_mode_stored_data()
return await self.api.get_devices_data()
except (CannotConnect, CannotRetrieveData) as err:
raise UpdateFailed(f"Error occurred while updating {self.name}") from err
except CannotAuthenticate as err:
raise ConfigEntryError("Could not authenticate") from err

View File

@@ -0,0 +1,66 @@
"""Diagnostics support for Alexa Devices integration."""
from __future__ import annotations
from typing import Any
from aioamazondevices.api import AmazonDevice
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntry
from .coordinator import AmazonConfigEntry
TO_REDACT = {CONF_PASSWORD, CONF_USERNAME, CONF_NAME, "title"}
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: AmazonConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
coordinator = entry.runtime_data
devices: list[dict[str, dict[str, Any]]] = [
build_device_data(device) for device in coordinator.data.values()
]
return {
"entry": async_redact_data(entry.as_dict(), TO_REDACT),
"device_info": {
"last_update success": coordinator.last_update_success,
"last_exception": repr(coordinator.last_exception),
"devices": devices,
},
}
async def async_get_device_diagnostics(
hass: HomeAssistant, entry: AmazonConfigEntry, device_entry: DeviceEntry
) -> dict[str, Any]:
"""Return diagnostics for a device."""
coordinator = entry.runtime_data
assert device_entry.serial_number
return build_device_data(coordinator.data[device_entry.serial_number])
def build_device_data(device: AmazonDevice) -> dict[str, Any]:
"""Build device data for diagnostics."""
return {
"account name": device.account_name,
"capabilities": device.capabilities,
"device family": device.device_family,
"device type": device.device_type,
"device cluster members": device.device_cluster_members,
"online": device.online,
"serial number": device.serial_number,
"software version": device.software_version,
"do not disturb": device.do_not_disturb,
"response style": device.response_style,
"bluetooth state": device.bluetooth_state,
}

View File

@@ -0,0 +1,57 @@
"""Defines a base Alexa Devices entity."""
from aioamazondevices.api import AmazonDevice
from aioamazondevices.const import SPEAKER_GROUP_MODEL
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import AmazonDevicesCoordinator
class AmazonEntity(CoordinatorEntity[AmazonDevicesCoordinator]):
"""Defines a base Alexa Devices entity."""
_attr_has_entity_name = True
def __init__(
self,
coordinator: AmazonDevicesCoordinator,
serial_num: str,
description: EntityDescription,
) -> None:
"""Initialize the entity."""
super().__init__(coordinator)
self._serial_num = serial_num
model_details = coordinator.api.get_model_details(self.device) or {}
model = model_details.get("model")
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, serial_num)},
name=self.device.account_name,
model=model,
model_id=self.device.device_type,
manufacturer=model_details.get("manufacturer", "Amazon"),
hw_version=model_details.get("hw_version"),
sw_version=(
self.device.software_version if model != SPEAKER_GROUP_MODEL else None
),
serial_number=serial_num if model != SPEAKER_GROUP_MODEL else None,
)
self.entity_description = description
self._attr_unique_id = f"{serial_num}-{description.key}"
@property
def device(self) -> AmazonDevice:
"""Return the device."""
return self.coordinator.data[self._serial_num]
@property
def available(self) -> bool:
"""Return True if entity is available."""
return (
super().available
and self._serial_num in self.coordinator.data
and self.device.online
)

View File

@@ -0,0 +1,12 @@
{
"entity": {
"binary_sensor": {
"bluetooth": {
"default": "mdi:bluetooth",
"state": {
"off": "mdi:bluetooth-off"
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
{
"domain": "alexa_devices",
"name": "Alexa Devices",
"codeowners": ["@chemelli74"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/alexa_devices",
"integration_type": "hub",
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "bronze",
"requirements": ["aioamazondevices==3.1.4"]
}

View File

@@ -0,0 +1,78 @@
"""Support for notification entity."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any, Final
from aioamazondevices.api import AmazonDevice, AmazonEchoApi
from aioamazondevices.const import SPEAKER_GROUP_FAMILY
from homeassistant.components.notify import NotifyEntity, NotifyEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import AmazonConfigEntry
from .entity import AmazonEntity
PARALLEL_UPDATES = 1
@dataclass(frozen=True, kw_only=True)
class AmazonNotifyEntityDescription(NotifyEntityDescription):
"""Alexa Devices notify entity description."""
is_supported: Callable[[AmazonDevice], bool] = lambda _device: True
method: Callable[[AmazonEchoApi, AmazonDevice, str], Awaitable[None]]
subkey: str
NOTIFY: Final = (
AmazonNotifyEntityDescription(
key="speak",
translation_key="speak",
subkey="AUDIO_PLAYER",
is_supported=lambda _device: _device.device_family != SPEAKER_GROUP_FAMILY,
method=lambda api, device, message: api.call_alexa_speak(device, message),
),
AmazonNotifyEntityDescription(
key="announce",
translation_key="announce",
subkey="AUDIO_PLAYER",
method=lambda api, device, message: api.call_alexa_announcement(
device, message
),
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AmazonConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Alexa Devices notification entity based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
AmazonNotifyEntity(coordinator, serial_num, sensor_desc)
for sensor_desc in NOTIFY
for serial_num in coordinator.data
if sensor_desc.subkey in coordinator.data[serial_num].capabilities
and sensor_desc.is_supported(coordinator.data[serial_num])
)
class AmazonNotifyEntity(AmazonEntity, NotifyEntity):
"""Binary sensor notify platform."""
entity_description: AmazonNotifyEntityDescription
async def async_send_message(
self, message: str, title: str | None = None, **kwargs: Any
) -> None:
"""Send a message."""
await self.entity_description.method(self.coordinator.api, self.device, message)

View File

@@ -0,0 +1,76 @@
rules:
# Bronze
action-setup:
status: exempt
comment: no 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: no actions
docs-high-level-description: done
docs-installation-instructions: done
docs-removal-instructions: done
entity-event-setup:
status: exempt
comment: entities do 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: todo
config-entry-unloading: done
docs-configuration-parameters: todo
docs-installation-parameters: todo
entity-unavailable: done
integration-owner: done
log-when-unavailable: done
parallel-updates: done
reauthentication-flow: todo
test-coverage:
status: todo
comment: all tests missing
# Gold
devices: done
diagnostics: todo
discovery-update-info:
status: exempt
comment: Network information not relevant
discovery:
status: exempt
comment: There are a ton of mac address ranges in use, but also by kindles which are not supported by this integration
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: todo
entity-category: done
entity-device-class: done
entity-disabled-by-default: done
entity-translations: done
exception-translations: todo
icon-translations: done
reconfiguration-flow: todo
repair-issues:
status: exempt
comment: no known use cases for repair issues or flows, yet
stale-devices:
status: todo
comment: automate the cleanup process
# Platinum
async-dependency: done
inject-websession: todo
strict-typing: done

View File

@@ -0,0 +1,60 @@
{
"common": {
"data_country": "Country code",
"data_code": "One-time password (OTP code)",
"data_description_country": "The country of your Amazon account.",
"data_description_username": "The email address of your Amazon account.",
"data_description_password": "The password of your Amazon account.",
"data_description_code": "The one-time password to log in to your account. Currently, only tokens from OTP applications are supported."
},
"config": {
"flow_title": "{username}",
"step": {
"user": {
"data": {
"country": "[%key:component::alexa_devices::common::data_country%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]",
"code": "[%key:component::alexa_devices::common::data_description_code%]"
},
"data_description": {
"country": "[%key:component::alexa_devices::common::data_description_country%]",
"username": "[%key:component::alexa_devices::common::data_description_username%]",
"password": "[%key:component::alexa_devices::common::data_description_password%]",
"code": "[%key:component::alexa_devices::common::data_description_code%]"
}
}
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"unknown": "[%key:common::config_flow::error::unknown%]"
}
},
"entity": {
"binary_sensor": {
"bluetooth": {
"name": "Bluetooth"
}
},
"notify": {
"speak": {
"name": "Speak"
},
"announce": {
"name": "Announce"
}
},
"switch": {
"do_not_disturb": {
"name": "Do not disturb"
}
}
}
}

View File

@@ -0,0 +1,84 @@
"""Support for switches."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Final
from aioamazondevices.api import AmazonDevice
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import AmazonConfigEntry
from .entity import AmazonEntity
PARALLEL_UPDATES = 1
@dataclass(frozen=True, kw_only=True)
class AmazonSwitchEntityDescription(SwitchEntityDescription):
"""Alexa Devices switch entity description."""
is_on_fn: Callable[[AmazonDevice], bool]
subkey: str
method: str
SWITCHES: Final = (
AmazonSwitchEntityDescription(
key="do_not_disturb",
subkey="AUDIO_PLAYER",
translation_key="do_not_disturb",
is_on_fn=lambda _device: _device.do_not_disturb,
method="set_do_not_disturb",
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AmazonConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Alexa Devices switches based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
AmazonSwitchEntity(coordinator, serial_num, switch_desc)
for switch_desc in SWITCHES
for serial_num in coordinator.data
if switch_desc.subkey in coordinator.data[serial_num].capabilities
)
class AmazonSwitchEntity(AmazonEntity, SwitchEntity):
"""Switch device."""
entity_description: AmazonSwitchEntityDescription
async def _switch_set_state(self, state: bool) -> None:
"""Set desired switch state."""
method = getattr(self.coordinator.api, self.entity_description.method)
if TYPE_CHECKING:
assert method is not None
await method(self.device, state)
await self.coordinator.async_request_refresh()
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
await self._switch_set_state(True)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
await self._switch_set_state(False)
@property
def is_on(self) -> bool:
"""Return True if switch is on."""
return self.entity_description.is_on_fn(self.device)

View File

@@ -16,10 +16,7 @@ from amcrest import AmcrestError, ApiWrapper, LoginError
import httpx
import voluptuous as vol
from homeassistant.auth.models import User
from homeassistant.auth.permissions.const import POLICY_CONTROL
from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_AUTHENTICATION,
CONF_BINARY_SENSORS,
CONF_HOST,
@@ -30,21 +27,17 @@ from homeassistant.const import (
CONF_SENSORS,
CONF_SWITCHES,
CONF_USERNAME,
ENTITY_MATCH_ALL,
ENTITY_MATCH_NONE,
HTTP_BASIC_AUTHENTICATION,
Platform,
)
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import Unauthorized, UnknownUser
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.helpers.dispatcher import async_dispatcher_send, dispatcher_send
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.service import async_extract_entity_ids
from homeassistant.helpers.typing import ConfigType
from .binary_sensor import BINARY_SENSOR_KEYS, BINARY_SENSORS, check_binary_sensors
from .camera import CAMERA_SERVICES, STREAM_SOURCE_LIST
from .camera import STREAM_SOURCE_LIST
from .const import (
CAMERAS,
COMM_RETRIES,
@@ -58,6 +51,7 @@ from .const import (
)
from .helpers import service_signal
from .sensor import SENSOR_KEYS
from .services import async_setup_services
from .switch import SWITCH_KEYS
_LOGGER = logging.getLogger(__name__)
@@ -455,47 +449,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
if not hass.data[DATA_AMCREST][DEVICES]:
return False
def have_permission(user: User | None, entity_id: str) -> bool:
return not user or user.permissions.check_entity(entity_id, POLICY_CONTROL)
async def async_extract_from_service(call: ServiceCall) -> list[str]:
if call.context.user_id:
user = await hass.auth.async_get_user(call.context.user_id)
if user is None:
raise UnknownUser(context=call.context)
else:
user = None
if call.data.get(ATTR_ENTITY_ID) == ENTITY_MATCH_ALL:
# Return all entity_ids user has permission to control.
return [
entity_id
for entity_id in hass.data[DATA_AMCREST][CAMERAS]
if have_permission(user, entity_id)
]
if call.data.get(ATTR_ENTITY_ID) == ENTITY_MATCH_NONE:
return []
call_ids = await async_extract_entity_ids(hass, call)
entity_ids = []
for entity_id in hass.data[DATA_AMCREST][CAMERAS]:
if entity_id not in call_ids:
continue
if not have_permission(user, entity_id):
raise Unauthorized(
context=call.context, entity_id=entity_id, permission=POLICY_CONTROL
)
entity_ids.append(entity_id)
return entity_ids
async def async_service_handler(call: ServiceCall) -> None:
args = [call.data[arg] for arg in CAMERA_SERVICES[call.service][2]]
for entity_id in await async_extract_from_service(call):
async_dispatcher_send(hass, service_signal(call.service, entity_id), *args)
for service, params in CAMERA_SERVICES.items():
hass.services.async_register(DOMAIN, service, async_service_handler, params[0])
async_setup_services(hass)
return True

View File

@@ -0,0 +1,62 @@
"""Support for Amcrest IP cameras."""
from __future__ import annotations
from homeassistant.auth.models import User
from homeassistant.auth.permissions.const import POLICY_CONTROL
from homeassistant.const import ATTR_ENTITY_ID, ENTITY_MATCH_ALL, ENTITY_MATCH_NONE
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import Unauthorized, UnknownUser
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.service import async_extract_entity_ids
from .camera import CAMERA_SERVICES
from .const import CAMERAS, DATA_AMCREST, DOMAIN
from .helpers import service_signal
@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Set up the Amcrest IP Camera services."""
def have_permission(user: User | None, entity_id: str) -> bool:
return not user or user.permissions.check_entity(entity_id, POLICY_CONTROL)
async def async_extract_from_service(call: ServiceCall) -> list[str]:
if call.context.user_id:
user = await hass.auth.async_get_user(call.context.user_id)
if user is None:
raise UnknownUser(context=call.context)
else:
user = None
if call.data.get(ATTR_ENTITY_ID) == ENTITY_MATCH_ALL:
# Return all entity_ids user has permission to control.
return [
entity_id
for entity_id in hass.data[DATA_AMCREST][CAMERAS]
if have_permission(user, entity_id)
]
if call.data.get(ATTR_ENTITY_ID) == ENTITY_MATCH_NONE:
return []
call_ids = await async_extract_entity_ids(hass, call)
entity_ids = []
for entity_id in hass.data[DATA_AMCREST][CAMERAS]:
if entity_id not in call_ids:
continue
if not have_permission(user, entity_id):
raise Unauthorized(
context=call.context, entity_id=entity_id, permission=POLICY_CONTROL
)
entity_ids.append(entity_id)
return entity_ids
async def async_service_handler(call: ServiceCall) -> None:
args = [call.data[arg] for arg in CAMERA_SERVICES[call.service][2]]
for entity_id in await async_extract_from_service(call):
async_dispatcher_send(hass, service_signal(call.service, entity_id), *args)
for service, params in CAMERA_SERVICES.items():
hass.services.async_register(DOMAIN, service, async_service_handler, params[0])

View File

@@ -24,7 +24,7 @@ from homeassistant.components.recorder import (
get_instance as get_recorder_instance,
)
from homeassistant.config_entries import SOURCE_IGNORE
from homeassistant.const import ATTR_DOMAIN, __version__ as HA_VERSION
from homeassistant.const import ATTR_DOMAIN, BASE_PLATFORMS, __version__ as HA_VERSION
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
@@ -225,7 +225,8 @@ class Analytics:
LOGGER.error(err)
return
configuration_set = set(yaml_configuration)
configuration_set = _domains_from_yaml_config(yaml_configuration)
er_platforms = {
entity.platform
for entity in ent_reg.entities.values()
@@ -370,3 +371,13 @@ class Analytics:
for entry in entries
if entry.source != SOURCE_IGNORE and entry.disabled_by is None
)
def _domains_from_yaml_config(yaml_configuration: dict[str, Any]) -> set[str]:
"""Extract domains from the YAML configuration."""
domains = set(yaml_configuration)
for platforms in conf_util.extract_platform_integrations(
yaml_configuration, BASE_PLATFORMS
).values():
domains.update(platforms)
return domains

View File

@@ -7,6 +7,6 @@
"integration_type": "device",
"iot_class": "local_push",
"loggers": ["androidtvremote2"],
"requirements": ["androidtvremote2==0.2.1"],
"requirements": ["androidtvremote2==0.2.2"],
"zeroconf": ["_androidtvremote2._tcp.local."]
}

View File

@@ -51,6 +51,10 @@
"app_id": "Application ID",
"app_icon": "Application icon",
"app_delete": "Check to delete this application"
},
"data_description": {
"app_id": "E.g. com.plexapp.android for https://play.google.com/store/apps/details?id=com.plexapp.android",
"app_icon": "Image URL. From the Play Store app page, right click on the icon and select 'Copy image address' and then paste it here. Alternatively, download the image, upload it under /config/www/ and use the URL /local/filename"
}
}
}

View File

@@ -17,4 +17,11 @@ CONF_THINKING_BUDGET = "thinking_budget"
RECOMMENDED_THINKING_BUDGET = 0
MIN_THINKING_BUDGET = 1024
THINKING_MODELS = ["claude-3-7-sonnet-20250219", "claude-3-7-sonnet-latest"]
THINKING_MODELS = [
"claude-3-7-sonnet-20250219",
"claude-3-7-sonnet-latest",
"claude-opus-4-20250514",
"claude-opus-4-0",
"claude-sonnet-4-20250514",
"claude-sonnet-4-0",
]

View File

@@ -294,6 +294,8 @@ async def _transform_stream( # noqa: C901 - This is complex, but better to have
elif isinstance(response, RawMessageDeltaEvent):
if (usage := response.usage) is not None:
chat_log.async_trace(_create_token_stats(input_usage, usage))
if response.delta.stop_reason == "refusal":
raise HomeAssistantError("Potential policy violation detected")
elif isinstance(response, RawMessageStopEvent):
if current_message is not None:
messages.append(current_message)
@@ -326,6 +328,7 @@ class AnthropicConversationEntity(
_attr_has_entity_name = True
_attr_name = None
_attr_supports_streaming = True
def __init__(self, entry: AnthropicConfigEntry) -> None:
"""Initialize the agent."""
@@ -363,15 +366,35 @@ class AnthropicConversationEntity(
options = self.entry.options
try:
await chat_log.async_update_llm_data(
DOMAIN,
user_input,
await chat_log.async_provide_llm_data(
user_input.as_llm_context(DOMAIN),
options.get(CONF_LLM_HASS_API),
options.get(CONF_PROMPT),
user_input.extra_system_prompt,
)
except conversation.ConverseError as err:
return err.as_conversation_result()
await self._async_handle_chat_log(chat_log)
response_content = chat_log.content[-1]
if not isinstance(response_content, conversation.AssistantContent):
raise TypeError("Last message must be an assistant message")
intent_response = intent.IntentResponse(language=user_input.language)
intent_response.async_set_speech(response_content.content or "")
return conversation.ConversationResult(
response=intent_response,
conversation_id=chat_log.conversation_id,
continue_conversation=chat_log.continue_conversation,
)
async def _async_handle_chat_log(
self,
chat_log: conversation.ChatLog,
) -> None:
"""Generate an answer for the chat log."""
options = self.entry.options
tools: list[ToolParam] | None = None
if chat_log.llm_api:
tools = [
@@ -421,7 +444,7 @@ class AnthropicConversationEntity(
[
content
async for content in chat_log.async_add_delta_content_stream(
user_input.agent_id,
self.entity_id,
_transform_stream(chat_log, stream, messages),
)
if not isinstance(content, conversation.AssistantContent)
@@ -432,17 +455,6 @@ class AnthropicConversationEntity(
if not chat_log.unresponded_tool_results:
break
response_content = chat_log.content[-1]
if not isinstance(response_content, conversation.AssistantContent):
raise TypeError("Last message must be an assistant message")
intent_response = intent.IntentResponse(language=user_input.language)
intent_response.async_set_speech(response_content.content or "")
return conversation.ConversationResult(
response=intent_response,
conversation_id=chat_log.conversation_id,
continue_conversation=chat_log.continue_conversation,
)
async def _async_entry_update_listener(
self, hass: HomeAssistant, entry: ConfigEntry
) -> None:

View File

@@ -8,5 +8,5 @@
"documentation": "https://www.home-assistant.io/integrations/anthropic",
"integration_type": "service",
"iot_class": "cloud_polling",
"requirements": ["anthropic==0.47.2"]
"requirements": ["anthropic==0.52.0"]
}

View File

@@ -46,11 +46,7 @@ class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
return self.async_show_form(step_id="user", data_schema=_SCHEMA)
host, port = user_input[CONF_HOST], user_input[CONF_PORT]
# Abort if an entry with same host and port is present.
self._async_abort_entries_match({CONF_HOST: host, CONF_PORT: port})
# Test the connection to the host and get the current status for serial number.
try:
async with asyncio.timeout(CONNECTION_TIMEOUT):
data = APCUPSdData(await aioapcaccess.request_status(host, port))
@@ -67,3 +63,30 @@ class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
title = data.name or data.model or data.serial_no or "APC UPS"
return self.async_create_entry(title=title, data=user_input)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle reconfiguration of an existing entry."""
if user_input is None:
return self.async_show_form(step_id="reconfigure", data_schema=_SCHEMA)
host, port = user_input[CONF_HOST], user_input[CONF_PORT]
self._async_abort_entries_match({CONF_HOST: host, CONF_PORT: port})
try:
async with asyncio.timeout(CONNECTION_TIMEOUT):
data = APCUPSdData(await aioapcaccess.request_status(host, port))
except (OSError, asyncio.IncompleteReadError, TimeoutError):
errors = {"base": "cannot_connect"}
return self.async_show_form(
step_id="reconfigure", data_schema=_SCHEMA, errors=errors
)
await self.async_set_unique_id(data.serial_no)
self._abort_if_unique_id_mismatch(reason="wrong_apcupsd_daemon")
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data_updates=user_input,
)

View File

@@ -1,7 +1,9 @@
{
"config": {
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"wrong_apcupsd_daemon": "The reconfigured APC UPS Daemon is not the same as the one already configured.",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"

View File

@@ -62,6 +62,8 @@ async def async_setup_entry(
target_humidity_key=Attribute.HUMIDIFICATION_SETPOINT,
min_humidity=10,
max_humidity=50,
auto_status_key=Attribute.HUMIDIFICATION_AVAILABLE,
auto_status_value=1,
default_humidity=30,
set_humidity_fn=coordinator.client.set_humidification_setpoint,
)
@@ -77,6 +79,8 @@ async def async_setup_entry(
action_map=DEHUMIDIFIER_ACTION_MAP,
current_humidity_key=Attribute.INDOOR_HUMIDITY_CONTROLLING_SENSOR_VALUE,
target_humidity_key=Attribute.DEHUMIDIFICATION_SETPOINT,
auto_status_key=None,
auto_status_value=None,
min_humidity=40,
max_humidity=90,
default_humidity=60,
@@ -100,6 +104,8 @@ class AprilaireHumidifierDescription(HumidifierEntityDescription):
target_humidity_key: str
min_humidity: int
max_humidity: int
auto_status_key: str | None
auto_status_value: int | None
default_humidity: int
set_humidity_fn: Callable[[int], Awaitable]
@@ -163,14 +169,31 @@ class AprilaireHumidifierEntity(BaseAprilaireEntity, HumidifierEntity):
def min_humidity(self) -> float:
"""Return the minimum humidity."""
if self.is_auto_humidity_mode():
return 1
return self.entity_description.min_humidity
@property
def max_humidity(self) -> float:
"""Return the maximum humidity."""
if self.is_auto_humidity_mode():
return 7
return self.entity_description.max_humidity
def is_auto_humidity_mode(self) -> bool:
"""Return whether the humidifier is in auto mode."""
if self.entity_description.auto_status_key is None:
return False
return (
self.coordinator.data.get(self.entity_description.auto_status_key)
== self.entity_description.auto_status_value
)
async def async_set_humidity(self, humidity: int) -> None:
"""Set the humidity."""

View File

@@ -7,5 +7,5 @@
"integration_type": "device",
"iot_class": "local_push",
"loggers": ["pyaprilaire"],
"requirements": ["pyaprilaire==0.8.1"]
"requirements": ["pyaprilaire==0.9.1"]
}

View File

@@ -7,5 +7,5 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["APsystemsEZ1"],
"requirements": ["apsystems-ez1==2.6.0"]
"requirements": ["apsystems-ez1==2.7.0"]
}

View File

@@ -1,6 +1,9 @@
{
"entity": {
"sensor": {
"last_update": {
"default": "mdi:update"
},
"salt_left_side_percentage": {
"default": "mdi:basket-fill"
},

View File

@@ -4,6 +4,7 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
from aioaquacell import Softener
@@ -28,7 +29,7 @@ PARALLEL_UPDATES = 1
class SoftenerSensorEntityDescription(SensorEntityDescription):
"""Describes Softener sensor entity."""
value_fn: Callable[[Softener], StateType]
value_fn: Callable[[Softener], StateType | datetime]
SENSORS: tuple[SoftenerSensorEntityDescription, ...] = (
@@ -77,6 +78,12 @@ SENSORS: tuple[SoftenerSensorEntityDescription, ...] = (
"low",
],
),
SoftenerSensorEntityDescription(
key="last_update",
translation_key="last_update",
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=lambda softener: softener.lastUpdate,
),
)
@@ -111,6 +118,6 @@ class SoftenerSensor(AquacellEntity, SensorEntity):
self.entity_description = description
@property
def native_value(self) -> StateType:
def native_value(self) -> StateType | datetime:
"""Return the state of the sensor."""
return self.entity_description.value_fn(self.softener)

View File

@@ -21,6 +21,9 @@
},
"entity": {
"sensor": {
"last_update": {
"name": "Last update"
},
"salt_left_side_percentage": {
"name": "Salt left side percentage"
},

View File

@@ -89,7 +89,7 @@ class ArubaDeviceScanner(DeviceScanner):
def get_aruba_data(self) -> dict[str, dict[str, str]] | None:
"""Retrieve data from Aruba Access Point and return parsed result."""
connect = f"ssh {self.username}@{self.host} -o HostKeyAlgorithms=ssh-rsa"
connect = f"ssh {self.username}@{self.host}"
ssh: pexpect.spawn[str] = pexpect.spawn(connect, encoding="utf-8")
query = ssh.expect(
[

View File

@@ -20,9 +20,6 @@ import hass_nabucasa
import voluptuous as vol
from homeassistant.components import conversation, stt, tts, wake_word, websocket_api
from homeassistant.components.tts import (
generate_media_source_id as tts_generate_media_source_id,
)
from homeassistant.const import ATTR_SUPPORTED_FEATURES, MATCH_ALL
from homeassistant.core import Context, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
@@ -92,6 +89,8 @@ KEY_ASSIST_PIPELINE: HassKey[PipelineData] = HassKey(DOMAIN)
KEY_PIPELINE_CONVERSATION_DATA: HassKey[dict[str, PipelineConversationData]] = HassKey(
"pipeline_conversation_data"
)
# Number of response parts to handle before streaming the response
STREAM_RESPONSE_CHARS = 60
def validate_language(data: dict[str, Any]) -> Any:
@@ -555,7 +554,7 @@ class PipelineRun:
event_callback: PipelineEventCallback
language: str = None # type: ignore[assignment]
runner_data: Any | None = None
intent_agent: str | None = None
intent_agent: conversation.AgentInfo | None = None
tts_audio_output: str | dict[str, Any] | None = None
wake_word_settings: WakeWordSettings | None = None
audio_settings: AudioSettings = field(default_factory=AudioSettings)
@@ -591,6 +590,9 @@ class PipelineRun:
_intent_agent_only = False
"""If request should only be handled by agent, ignoring sentence triggers and local processing."""
_streamed_response_text = False
"""If the conversation agent streamed response text to TTS result."""
def __post_init__(self) -> None:
"""Set language for pipeline."""
self.language = self.pipeline.language or self.hass.config.language
@@ -652,6 +654,11 @@ class PipelineRun:
"token": self.tts_stream.token,
"url": self.tts_stream.url,
"mime_type": self.tts_stream.content_type,
"stream_response": (
self.tts_stream.supports_streaming_input
and self.intent_agent
and self.intent_agent.supports_streaming
),
}
self.process_event(PipelineEvent(PipelineEventType.RUN_START, data))
@@ -899,12 +906,12 @@ class PipelineRun:
) -> str:
"""Run speech-to-text portion of pipeline. Returns the spoken text."""
# Create a background task to prepare the conversation agent
if self.end_stage >= PipelineStage.INTENT:
if self.end_stage >= PipelineStage.INTENT and self.intent_agent:
self.hass.async_create_background_task(
conversation.async_prepare_agent(
self.hass, self.intent_agent, self.language
self.hass, self.intent_agent.id, self.language
),
f"prepare conversation agent {self.intent_agent}",
f"prepare conversation agent {self.intent_agent.id}",
)
if isinstance(self.stt_provider, stt.Provider):
@@ -1045,7 +1052,7 @@ class PipelineRun:
message=f"Intent recognition engine {engine} is not found",
)
self.intent_agent = agent_info.id
self.intent_agent = agent_info
async def recognize_intent(
self,
@@ -1078,7 +1085,7 @@ class PipelineRun:
PipelineEvent(
PipelineEventType.INTENT_START,
{
"engine": self.intent_agent,
"engine": self.intent_agent.id,
"language": input_language,
"intent_input": intent_input,
"conversation_id": conversation_id,
@@ -1095,11 +1102,11 @@ class PipelineRun:
conversation_id=conversation_id,
device_id=device_id,
language=input_language,
agent_id=self.intent_agent,
agent_id=self.intent_agent.id,
extra_system_prompt=conversation_extra_system_prompt,
)
agent_id = self.intent_agent
agent_id = self.intent_agent.id
processed_locally = agent_id == conversation.HOME_ASSISTANT_AGENT
intent_response: intent.IntentResponse | None = None
if not processed_locally and not self._intent_agent_only:
@@ -1121,7 +1128,7 @@ class PipelineRun:
# If the LLM has API access, we filter out some sentences that are
# interfering with LLM operation.
if (
intent_agent_state := self.hass.states.get(self.intent_agent)
intent_agent_state := self.hass.states.get(self.intent_agent.id)
) and intent_agent_state.attributes.get(
ATTR_SUPPORTED_FEATURES, 0
) & conversation.ConversationEntityFeature.CONTROL:
@@ -1143,6 +1150,13 @@ class PipelineRun:
agent_id = conversation.HOME_ASSISTANT_AGENT
processed_locally = True
if self.tts_stream and self.tts_stream.supports_streaming_input:
tts_input_stream: asyncio.Queue[str | None] | None = asyncio.Queue()
else:
tts_input_stream = None
chat_log_role = None
delta_character_count = 0
@callback
def chat_log_delta_listener(
chat_log: conversation.ChatLog, delta: dict
@@ -1156,6 +1170,70 @@ class PipelineRun:
},
)
)
if tts_input_stream is None:
return
nonlocal chat_log_role
if role := delta.get("role"):
chat_log_role = role
# We are only interested in assistant deltas
if chat_log_role != "assistant":
return
if content := delta.get("content"):
tts_input_stream.put_nowait(content)
if self._streamed_response_text:
return
nonlocal delta_character_count
# Streamed responses are not cached. That's why we only start streaming text after
# we have received enough characters that indicates it will be a long response
# or if we have received text, and then a tool call.
# Tool call after we already received text
start_streaming = delta_character_count > 0 and delta.get("tool_calls")
# Count characters in the content and test if we exceed streaming threshold
if not start_streaming and content:
delta_character_count += len(content)
start_streaming = delta_character_count > STREAM_RESPONSE_CHARS
if not start_streaming:
return
self._streamed_response_text = True
self.process_event(
PipelineEvent(
PipelineEventType.INTENT_PROGRESS,
{
"tts_start_streaming": True,
},
)
)
async def tts_input_stream_generator() -> AsyncGenerator[str]:
"""Yield TTS input stream."""
while (tts_input := await tts_input_stream.get()) is not None:
yield tts_input
# Concatenate all existing queue items
parts = []
while not tts_input_stream.empty():
parts.append(tts_input_stream.get_nowait())
tts_input_stream.put_nowait(
"".join(
# At this point parts is only strings, None indicates end of queue
cast(list[str], parts)
)
)
assert self.tts_stream is not None
self.tts_stream.async_set_message_stream(tts_input_stream_generator())
with (
chat_session.async_get_chat_session(
@@ -1199,6 +1277,8 @@ class PipelineRun:
speech = conversation_result.response.speech.get("plain", {}).get(
"speech", ""
)
if tts_input_stream and self._streamed_response_text:
tts_input_stream.put_nowait(None)
except Exception as src_error:
_LOGGER.exception("Unexpected error during intent recognition")
@@ -1276,26 +1356,11 @@ class PipelineRun:
)
)
try:
# Synthesize audio and get URL
tts_media_id = tts_generate_media_source_id(
self.hass,
tts_input,
engine=self.tts_stream.engine,
language=self.tts_stream.language,
options=self.tts_stream.options,
)
except Exception as src_error:
_LOGGER.exception("Unexpected error during text-to-speech")
raise TextToSpeechError(
code="tts-failed",
message="Unexpected error during text-to-speech",
) from src_error
self.tts_stream.async_set_message(tts_input)
if not self._streamed_response_text:
self.tts_stream.async_set_message(tts_input)
tts_output = {
"media_id": tts_media_id,
"media_id": self.tts_stream.media_source_id,
"token": self.tts_stream.token,
"url": self.tts_stream.url,
"mime_type": self.tts_stream.content_type,

View File

@@ -6,6 +6,7 @@ from homeassistant.components.water_heater import (
STATE_ECO,
STATE_PERFORMANCE,
WaterHeaterEntity,
WaterHeaterEntityFeature,
)
from homeassistant.const import ATTR_TEMPERATURE, STATE_OFF, Platform, UnitOfTemperature
from homeassistant.core import HomeAssistant
@@ -32,6 +33,7 @@ class AtagWaterHeater(AtagEntity, WaterHeaterEntity):
"""Representation of an ATAG water heater."""
_attr_operation_list = OPERATION_LIST
_attr_supported_features = WaterHeaterEntityFeature.TARGET_TEMPERATURE
_attr_temperature_unit = UnitOfTemperature.CELSIUS
@property

View File

@@ -47,7 +47,7 @@ from .const import (
CONF_VIDEO_SOURCE,
DEFAULT_STREAM_PROFILE,
DEFAULT_VIDEO_SOURCE,
DOMAIN as AXIS_DOMAIN,
DOMAIN,
)
from .errors import AuthenticationRequired, CannotConnect
from .hub import AxisHub, get_axis_api
@@ -58,7 +58,7 @@ DEFAULT_PROTOCOL = "https"
PROTOCOL_CHOICES = ["https", "http"]
class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
class AxisFlowHandler(ConfigFlow, domain=DOMAIN):
"""Handle a Axis config flow."""
VERSION = 3
@@ -146,7 +146,7 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
model = self.config[CONF_MODEL]
same_model = [
entry.data[CONF_NAME]
for entry in self.hass.config_entries.async_entries(AXIS_DOMAIN)
for entry in self.hass.config_entries.async_entries(DOMAIN)
if entry.source != SOURCE_IGNORE and entry.data[CONF_MODEL] == model
]

View File

@@ -11,7 +11,7 @@ from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, format_mac
from homeassistant.helpers.dispatcher import async_dispatcher_send
from ..const import ATTR_MANUFACTURER, DOMAIN as AXIS_DOMAIN
from ..const import ATTR_MANUFACTURER, DOMAIN
from .config import AxisConfig
from .entity_loader import AxisEntityLoader
from .event_source import AxisEventSource
@@ -79,7 +79,7 @@ class AxisHub:
config_entry_id=self.config.entry.entry_id,
configuration_url=self.api.config.url,
connections={(CONNECTION_NETWORK_MAC, self.unique_id)},
identifiers={(AXIS_DOMAIN, self.unique_id)},
identifiers={(DOMAIN, self.unique_id)},
manufacturer=ATTR_MANUFACTURER,
model=f"{self.config.model} {self.product_type}",
name=self.config.name,

View File

@@ -2,8 +2,8 @@
from aiohttp import ClientTimeout
from azure.core.exceptions import (
AzureError,
ClientAuthenticationError,
HttpResponseError,
ResourceNotFoundError,
)
from azure.core.pipeline.transport._aiohttp import (
@@ -39,11 +39,20 @@ async def async_setup_entry(
session = async_create_clientsession(
hass, timeout=ClientTimeout(connect=10, total=12 * 60 * 60)
)
container_client = ContainerClient(
account_url=f"https://{entry.data[CONF_ACCOUNT_NAME]}.blob.core.windows.net/",
container_name=entry.data[CONF_CONTAINER_NAME],
credential=entry.data[CONF_STORAGE_ACCOUNT_KEY],
transport=AioHttpTransport(session=session),
def create_container_client() -> ContainerClient:
"""Create a ContainerClient."""
return ContainerClient(
account_url=f"https://{entry.data[CONF_ACCOUNT_NAME]}.blob.core.windows.net/",
container_name=entry.data[CONF_CONTAINER_NAME],
credential=entry.data[CONF_STORAGE_ACCOUNT_KEY],
transport=AioHttpTransport(session=session),
)
# has a blocking call to open in cpython
container_client: ContainerClient = await hass.async_add_executor_job(
create_container_client
)
try:
@@ -61,7 +70,7 @@ async def async_setup_entry(
translation_key="invalid_auth",
translation_placeholders={CONF_ACCOUNT_NAME: entry.data[CONF_ACCOUNT_NAME]},
) from err
except HttpResponseError as err:
except AzureError as err:
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="cannot_connect",

View File

@@ -8,7 +8,7 @@ import json
import logging
from typing import Any, Concatenate
from azure.core.exceptions import HttpResponseError
from azure.core.exceptions import AzureError, HttpResponseError, ServiceRequestError
from azure.storage.blob import BlobProperties
from homeassistant.components.backup import (
@@ -80,6 +80,20 @@ def handle_backup_errors[_R, **P](
f"Error during backup operation in {func.__name__}:"
f" Status {err.status_code}, message: {err.message}"
) from err
except ServiceRequestError as err:
raise BackupAgentError(
f"Timeout during backup operation in {func.__name__}"
) from err
except AzureError as err:
_LOGGER.debug(
"Error during backup in %s: %s",
func.__name__,
err,
exc_info=True,
)
raise BackupAgentError(
f"Error during backup operation in {func.__name__}: {err}"
) from err
return wrapper

View File

@@ -27,9 +27,25 @@ _LOGGER = logging.getLogger(__name__)
class AzureStorageConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for azure storage."""
def get_account_url(self, account_name: str) -> str:
"""Get the account URL."""
return f"https://{account_name}.blob.core.windows.net/"
async def get_container_client(
self, account_name: str, container_name: str, storage_account_key: str
) -> ContainerClient:
"""Get the container client.
ContainerClient has a blocking call to open in cpython
"""
session = async_get_clientsession(self.hass)
def create_container_client() -> ContainerClient:
return ContainerClient(
account_url=f"https://{account_name}.blob.core.windows.net/",
container_name=container_name,
credential=storage_account_key,
transport=AioHttpTransport(session=session),
)
return await self.hass.async_add_executor_job(create_container_client)
async def validate_config(
self, container_client: ContainerClient
@@ -58,11 +74,10 @@ class AzureStorageConfigFlow(ConfigFlow, domain=DOMAIN):
self._async_abort_entries_match(
{CONF_ACCOUNT_NAME: user_input[CONF_ACCOUNT_NAME]}
)
container_client = ContainerClient(
account_url=self.get_account_url(user_input[CONF_ACCOUNT_NAME]),
container_client = await self.get_container_client(
account_name=user_input[CONF_ACCOUNT_NAME],
container_name=user_input[CONF_CONTAINER_NAME],
credential=user_input[CONF_STORAGE_ACCOUNT_KEY],
transport=AioHttpTransport(session=async_get_clientsession(self.hass)),
storage_account_key=user_input[CONF_STORAGE_ACCOUNT_KEY],
)
errors = await self.validate_config(container_client)
@@ -99,12 +114,12 @@ class AzureStorageConfigFlow(ConfigFlow, domain=DOMAIN):
reauth_entry = self._get_reauth_entry()
if user_input is not None:
container_client = ContainerClient(
account_url=self.get_account_url(reauth_entry.data[CONF_ACCOUNT_NAME]),
container_client = await self.get_container_client(
account_name=reauth_entry.data[CONF_ACCOUNT_NAME],
container_name=reauth_entry.data[CONF_CONTAINER_NAME],
credential=user_input[CONF_STORAGE_ACCOUNT_KEY],
transport=AioHttpTransport(session=async_get_clientsession(self.hass)),
storage_account_key=user_input[CONF_STORAGE_ACCOUNT_KEY],
)
errors = await self.validate_config(container_client)
if not errors:
return self.async_update_reload_and_abort(
@@ -129,13 +144,10 @@ class AzureStorageConfigFlow(ConfigFlow, domain=DOMAIN):
reconfigure_entry = self._get_reconfigure_entry()
if user_input is not None:
container_client = ContainerClient(
account_url=self.get_account_url(
reconfigure_entry.data[CONF_ACCOUNT_NAME]
),
container_client = await self.get_container_client(
account_name=reconfigure_entry.data[CONF_ACCOUNT_NAME],
container_name=user_input[CONF_CONTAINER_NAME],
credential=user_input[CONF_STORAGE_ACCOUNT_KEY],
transport=AioHttpTransport(session=async_get_clientsession(self.hass)),
storage_account_key=user_input[CONF_STORAGE_ACCOUNT_KEY],
)
errors = await self.validate_config(container_client)
if not errors:

View File

@@ -23,6 +23,7 @@ from .const import DATA_MANAGER, DOMAIN
from .coordinator import BackupConfigEntry, BackupDataUpdateCoordinator
from .http import async_register_http_views
from .manager import (
AddonErrorData,
BackupManager,
BackupManagerError,
BackupPlatformEvent,
@@ -48,6 +49,7 @@ from .util import suggested_filename, suggested_filename_from_name_date
from .websocket import async_register_websocket_handlers
__all__ = [
"AddonErrorData",
"AddonInfo",
"AgentBackup",
"BackupAgent",
@@ -79,7 +81,7 @@ __all__ = [
"suggested_filename_from_name_date",
]
PLATFORMS = [Platform.SENSOR]
PLATFORMS = [Platform.EVENT, Platform.SENSOR]
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)

View File

@@ -33,6 +33,7 @@ class BackupCoordinatorData:
last_attempted_automatic_backup: datetime | None
last_successful_automatic_backup: datetime | None
next_scheduled_automatic_backup: datetime | None
last_event: ManagerStateEvent | BackupPlatformEvent | None
class BackupDataUpdateCoordinator(DataUpdateCoordinator[BackupCoordinatorData]):
@@ -60,11 +61,13 @@ class BackupDataUpdateCoordinator(DataUpdateCoordinator[BackupCoordinatorData]):
]
self.backup_manager = backup_manager
self._last_event: ManagerStateEvent | BackupPlatformEvent | None = None
@callback
def _on_event(self, event: ManagerStateEvent | BackupPlatformEvent) -> None:
"""Handle new event."""
LOGGER.debug("Received backup event: %s", event)
self._last_event = event
self.config_entry.async_create_task(self.hass, self.async_refresh())
async def _async_update_data(self) -> BackupCoordinatorData:
@@ -74,6 +77,7 @@ class BackupDataUpdateCoordinator(DataUpdateCoordinator[BackupCoordinatorData]):
self.backup_manager.config.data.last_attempted_automatic_backup,
self.backup_manager.config.data.last_completed_automatic_backup,
self.backup_manager.config.data.schedule.next_automatic_backup,
self._last_event,
)
@callback

View File

@@ -11,7 +11,7 @@ from .const import DOMAIN
from .coordinator import BackupDataUpdateCoordinator
class BackupManagerEntity(CoordinatorEntity[BackupDataUpdateCoordinator]):
class BackupManagerBaseEntity(CoordinatorEntity[BackupDataUpdateCoordinator]):
"""Base entity for backup manager."""
_attr_has_entity_name = True
@@ -19,12 +19,9 @@ class BackupManagerEntity(CoordinatorEntity[BackupDataUpdateCoordinator]):
def __init__(
self,
coordinator: BackupDataUpdateCoordinator,
entity_description: EntityDescription,
) -> None:
"""Initialize base entity."""
super().__init__(coordinator)
self.entity_description = entity_description
self._attr_unique_id = entity_description.key
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, "backup_manager")},
manufacturer="Home Assistant",
@@ -34,3 +31,17 @@ class BackupManagerEntity(CoordinatorEntity[BackupDataUpdateCoordinator]):
entry_type=DeviceEntryType.SERVICE,
configuration_url="homeassistant://config/backup",
)
class BackupManagerEntity(BackupManagerBaseEntity):
"""Entity for backup manager."""
def __init__(
self,
coordinator: BackupDataUpdateCoordinator,
entity_description: EntityDescription,
) -> None:
"""Initialize entity."""
super().__init__(coordinator)
self.entity_description = entity_description
self._attr_unique_id = entity_description.key

View File

@@ -0,0 +1,59 @@
"""Event platform for Home Assistant Backup integration."""
from __future__ import annotations
from typing import Final
from homeassistant.components.event import EventEntity
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import BackupConfigEntry, BackupDataUpdateCoordinator
from .entity import BackupManagerBaseEntity
from .manager import CreateBackupEvent, CreateBackupState
ATTR_BACKUP_STAGE: Final[str] = "backup_stage"
ATTR_FAILED_REASON: Final[str] = "failed_reason"
async def async_setup_entry(
hass: HomeAssistant,
config_entry: BackupConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Event set up for backup config entry."""
coordinator = config_entry.runtime_data
async_add_entities([AutomaticBackupEvent(coordinator)])
class AutomaticBackupEvent(BackupManagerBaseEntity, EventEntity):
"""Representation of an automatic backup event."""
_attr_event_types = [s.value for s in CreateBackupState]
_unrecorded_attributes = frozenset({ATTR_FAILED_REASON, ATTR_BACKUP_STAGE})
coordinator: BackupDataUpdateCoordinator
def __init__(self, coordinator: BackupDataUpdateCoordinator) -> None:
"""Initialize the automatic backup event."""
super().__init__(coordinator)
self._attr_unique_id = "automatic_backup_event"
self._attr_translation_key = "automatic_backup_event"
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
if (
not (data := self.coordinator.data)
or (event := data.last_event) is None
or not isinstance(event, CreateBackupEvent)
):
return
self._trigger_event(
event.state,
{
ATTR_BACKUP_STAGE: event.stage,
ATTR_FAILED_REASON: event.reason,
},
)
self.async_write_ha_state()

View File

@@ -1,4 +1,11 @@
{
"entity": {
"event": {
"automatic_backup_event": {
"default": "mdi:database"
}
}
},
"services": {
"create": {
"service": "mdi:cloud-upload"

View File

@@ -62,6 +62,7 @@ from .const import (
LOGGER,
)
from .models import (
AddonInfo,
AgentBackup,
BackupError,
BackupManagerError,
@@ -102,15 +103,27 @@ class ManagerBackup(BaseBackup):
"""Backup class."""
agents: dict[str, AgentBackupStatus]
failed_addons: list[AddonInfo]
failed_agent_ids: list[str]
failed_folders: list[Folder]
with_automatic_settings: bool | None
@dataclass(frozen=True, kw_only=True, slots=True)
class AddonErrorData:
"""Addon error class."""
addon: AddonInfo
errors: list[tuple[str, str]]
@dataclass(frozen=True, kw_only=True, slots=True)
class WrittenBackup:
"""Written backup class."""
addon_errors: dict[str, AddonErrorData]
backup: AgentBackup
folder_errors: dict[Folder, list[tuple[str, str]]]
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]]
release_stream: Callable[[], Coroutine[Any, Any, None]]
@@ -636,9 +649,13 @@ class BackupManager:
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_addons = known_backup.failed_addons
failed_agent_ids = known_backup.failed_agent_ids
failed_folders = known_backup.failed_folders
else:
failed_addons = []
failed_agent_ids = []
failed_folders = []
with_automatic_settings = self.is_our_automatic_backup(
agent_backup, await instance_id.async_get(self.hass)
)
@@ -649,7 +666,9 @@ class BackupManager:
date=agent_backup.date,
database_included=agent_backup.database_included,
extra_metadata=agent_backup.extra_metadata,
failed_addons=failed_addons,
failed_agent_ids=failed_agent_ids,
failed_folders=failed_folders,
folders=agent_backup.folders,
homeassistant_included=agent_backup.homeassistant_included,
homeassistant_version=agent_backup.homeassistant_version,
@@ -704,9 +723,13 @@ class BackupManager:
continue
if backup is None:
if known_backup := self.known_backups.get(backup_id):
failed_addons = known_backup.failed_addons
failed_agent_ids = known_backup.failed_agent_ids
failed_folders = known_backup.failed_folders
else:
failed_addons = []
failed_agent_ids = []
failed_folders = []
with_automatic_settings = self.is_our_automatic_backup(
result, await instance_id.async_get(self.hass)
)
@@ -717,7 +740,9 @@ class BackupManager:
date=result.date,
database_included=result.database_included,
extra_metadata=result.extra_metadata,
failed_addons=failed_addons,
failed_agent_ids=failed_agent_ids,
failed_folders=failed_folders,
folders=result.folders,
homeassistant_included=result.homeassistant_included,
homeassistant_version=result.homeassistant_version,
@@ -960,7 +985,7 @@ class BackupManager:
password=None,
)
await written_backup.release_stream()
self.known_backups.add(written_backup.backup, agent_errors, [])
self.known_backups.add(written_backup.backup, agent_errors, {}, {}, [])
return written_backup.backup.backup_id
async def async_create_backup(
@@ -1198,7 +1223,11 @@ class BackupManager:
finally:
await written_backup.release_stream()
self.known_backups.add(
written_backup.backup, agent_errors, unavailable_agents
written_backup.backup,
agent_errors,
written_backup.addon_errors,
written_backup.folder_errors,
unavailable_agents,
)
if not agent_errors:
if with_automatic_settings:
@@ -1208,7 +1237,9 @@ class BackupManager:
backup_success = True
if with_automatic_settings:
self._update_issue_after_agent_upload(agent_errors, unavailable_agents)
self._update_issue_after_agent_upload(
written_backup, agent_errors, unavailable_agents
)
# delete old backups more numerous than copies
# try this regardless of agent errors above
await delete_backups_exceeding_configured_count(self)
@@ -1354,8 +1385,10 @@ class BackupManager:
for subscription in self._backup_event_subscriptions:
subscription(event)
def _update_issue_backup_failed(self) -> None:
"""Update issue registry when a backup fails."""
def _create_automatic_backup_failed_issue(
self, translation_key: str, translation_placeholders: dict[str, str] | None
) -> None:
"""Create an issue in the issue registry for automatic backup failures."""
ir.async_create_issue(
self.hass,
DOMAIN,
@@ -1364,37 +1397,73 @@ class BackupManager:
is_persistent=True,
learn_more_url="homeassistant://config/backup",
severity=ir.IssueSeverity.WARNING,
translation_key="automatic_backup_failed_create",
translation_key=translation_key,
translation_placeholders=translation_placeholders,
)
def _update_issue_backup_failed(self) -> None:
"""Update issue registry when a backup fails."""
self._create_automatic_backup_failed_issue(
"automatic_backup_failed_create", None
)
def _update_issue_after_agent_upload(
self, agent_errors: dict[str, Exception], unavailable_agents: list[str]
self,
written_backup: WrittenBackup,
agent_errors: dict[str, Exception],
unavailable_agents: list[str],
) -> None:
"""Update issue registry after a backup is uploaded to agents."""
if not agent_errors and not unavailable_agents:
addon_errors = written_backup.addon_errors
failed_agents = unavailable_agents + [
self.backup_agents[agent_id].name for agent_id in agent_errors
]
folder_errors = written_backup.folder_errors
if not failed_agents and not addon_errors and not folder_errors:
# No issues to report, clear previous error
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(
chain(
(
self.backup_agents[agent_id].name
for agent_id in agent_errors
),
unavailable_agents,
if failed_agents and not (addon_errors or folder_errors):
# No issues with add-ons or folders, but issues with agents
self._create_automatic_backup_failed_issue(
"automatic_backup_failed_upload_agents",
{"failed_agents": ", ".join(failed_agents)},
)
elif addon_errors and not (failed_agents or folder_errors):
# No issues with agents or folders, but issues with add-ons
self._create_automatic_backup_failed_issue(
"automatic_backup_failed_addons",
{
"failed_addons": ", ".join(
val.addon.name or val.addon.slug
for val in addon_errors.values()
)
)
},
)
},
)
elif folder_errors and not (failed_agents or addon_errors):
# No issues with agents or add-ons, but issues with folders
self._create_automatic_backup_failed_issue(
"automatic_backup_failed_folders",
{"failed_folders": ", ".join(folder for folder in folder_errors)},
)
else:
# Issues with agents, add-ons, and/or folders
self._create_automatic_backup_failed_issue(
"automatic_backup_failed_agents_addons_folders",
{
"failed_agents": ", ".join(failed_agents) or "-",
"failed_addons": (
", ".join(
val.addon.name or val.addon.slug
for val in addon_errors.values()
)
or "-"
),
"failed_folders": ", ".join(f for f in folder_errors) or "-",
},
)
async def async_can_decrypt_on_download(
self,
@@ -1460,7 +1529,12 @@ class KnownBackups:
self._backups = {
backup["backup_id"]: KnownBackup(
backup_id=backup["backup_id"],
failed_addons=[
AddonInfo(name=a["name"], slug=a["slug"], version=a["version"])
for a in backup["failed_addons"]
],
failed_agent_ids=backup["failed_agent_ids"],
failed_folders=[Folder(f) for f in backup["failed_folders"]],
)
for backup in stored_backups
}
@@ -1473,12 +1547,16 @@ class KnownBackups:
self,
backup: AgentBackup,
agent_errors: dict[str, Exception],
failed_addons: dict[str, AddonErrorData],
failed_folders: dict[Folder, list[tuple[str, str]]],
unavailable_agents: list[str],
) -> None:
"""Add a backup."""
self._backups[backup.backup_id] = KnownBackup(
backup_id=backup.backup_id,
failed_addons=[val.addon for val in failed_addons.values()],
failed_agent_ids=list(chain(agent_errors, unavailable_agents)),
failed_folders=list(failed_folders),
)
self._manager.store.save()
@@ -1499,21 +1577,38 @@ class KnownBackup:
"""Persistent backup data."""
backup_id: str
failed_addons: list[AddonInfo]
failed_agent_ids: list[str]
failed_folders: list[Folder]
def to_dict(self) -> StoredKnownBackup:
"""Convert known backup to a dict."""
return {
"backup_id": self.backup_id,
"failed_addons": [
{"name": a.name, "slug": a.slug, "version": a.version}
for a in self.failed_addons
],
"failed_agent_ids": self.failed_agent_ids,
"failed_folders": [f.value for f in self.failed_folders],
}
class StoredAddonInfo(TypedDict):
"""Stored add-on info."""
name: str | None
slug: str
version: str | None
class StoredKnownBackup(TypedDict):
"""Stored persistent backup data."""
backup_id: str
failed_addons: list[StoredAddonInfo]
failed_agent_ids: list[str]
failed_folders: list[str]
class CoreBackupReaderWriter(BackupReaderWriter):
@@ -1677,7 +1772,11 @@ class CoreBackupReaderWriter(BackupReaderWriter):
raise BackupReaderWriterError(str(err)) from err
return WrittenBackup(
backup=backup, open_stream=open_backup, release_stream=remove_backup
addon_errors={},
backup=backup,
folder_errors={},
open_stream=open_backup,
release_stream=remove_backup,
)
finally:
# Inform integrations the backup is done
@@ -1816,7 +1915,11 @@ class CoreBackupReaderWriter(BackupReaderWriter):
await async_add_executor_job(temp_file.unlink, True)
return WrittenBackup(
backup=backup, open_stream=open_backup, release_stream=remove_backup
addon_errors={},
backup=backup,
folder_errors={},
open_stream=open_backup,
release_stream=remove_backup,
)
async def async_restore_backup(

View File

@@ -13,9 +13,9 @@ from homeassistant.exceptions import HomeAssistantError
class AddonInfo:
"""Addon information."""
name: str
name: str | None
slug: str
version: str
version: str | None
class Folder(StrEnum):

View File

@@ -16,7 +16,7 @@ if TYPE_CHECKING:
STORE_DELAY_SAVE = 30
STORAGE_KEY = DOMAIN
STORAGE_VERSION = 1
STORAGE_VERSION_MINOR = 6
STORAGE_VERSION_MINOR = 7
class StoredBackupData(TypedDict):
@@ -76,8 +76,16 @@ class _BackupStore(Store[StoredBackupData]):
# Version 1.6 adds agent retention settings
for agent in data["config"]["agents"]:
data["config"]["agents"][agent]["retention"] = None
if old_minor_version < 7:
# Version 1.7 adds failing addons and folders
for backup in data["backups"]:
backup["failed_addons"] = []
backup["failed_folders"] = []
# Note: We allow reading data with major version 2.
# Note: We allow reading data with major version 2 in which the unused key
# data["config"]["schedule"]["state"] will be removed. The bump to 2 is
# planned to happen after a 6 month quiet period with no minor version
# changes.
# Reject if major version is higher than 2.
if old_major_version > 2:
raise NotImplementedError

View File

@@ -11,6 +11,18 @@
"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."
},
"automatic_backup_failed_addons": {
"title": "Not all add-ons could be included in automatic backup",
"description": "Add-ons {failed_addons} could not be included in automatic backup. Please check the supervisor logs for more information. Another attempt will be made at the next scheduled time if a backup schedule is configured."
},
"automatic_backup_failed_agents_addons_folders": {
"title": "Automatic backup was created with errors",
"description": "The automatic backup was created with errors:\n* Locations which the backup could not be uploaded to: {failed_agents}\n* Add-ons which could not be backed up: {failed_addons}\n* Folders which could not be backed up: {failed_folders}\n\nPlease check the core and supervisor logs for more information. Another attempt will be made at the next scheduled time if a backup schedule is configured."
},
"automatic_backup_failed_folders": {
"title": "Not all folders could be included in automatic backup",
"description": "Folders {failed_folders} could not be included in automatic backup. Please check the supervisor logs for more information. Another attempt will be made at the next scheduled time if a backup schedule is configured."
}
},
"services": {
@@ -24,6 +36,22 @@
}
},
"entity": {
"event": {
"automatic_backup_event": {
"name": "Automatic backup",
"state_attributes": {
"event_type": {
"state": {
"completed": "Completed successfully",
"failed": "Failed",
"in_progress": "In progress"
}
},
"backup_stage": { "name": "Backup stage" },
"failed_reason": { "name": "Failure reason" }
}
}
},
"sensor": {
"backup_manager_state": {
"name": "Backup Manager state",

View File

@@ -21,7 +21,6 @@ from .entity import BleBoxEntity
SCAN_INTERVAL = timedelta(seconds=5)
BLEBOX_TO_HVACMODE = {
None: None,
0: HVACMode.OFF,
1: HVACMode.HEAT,
2: HVACMode.COOL,
@@ -59,12 +58,14 @@ class BleBoxClimateEntity(BleBoxEntity[blebox_uniapi.climate.Climate], ClimateEn
_attr_temperature_unit = UnitOfTemperature.CELSIUS
@property
def hvac_modes(self):
def hvac_modes(self) -> list[HVACMode]:
"""Return list of supported HVAC modes."""
if self._feature.mode is None:
return [HVACMode.OFF]
return [HVACMode.OFF, BLEBOX_TO_HVACMODE[self._feature.mode]]
@property
def hvac_mode(self):
def hvac_mode(self) -> HVACMode | None:
"""Return the desired HVAC mode."""
if self._feature.is_on is None:
return None
@@ -75,7 +76,7 @@ class BleBoxClimateEntity(BleBoxEntity[blebox_uniapi.climate.Climate], ClimateEn
return HVACMode.HEAT if self._feature.is_on else HVACMode.OFF
@property
def hvac_action(self):
def hvac_action(self) -> HVACAction | None:
"""Return the actual current HVAC action."""
if self._feature.hvac_action is not None:
if not self._feature.is_on:
@@ -88,22 +89,22 @@ class BleBoxClimateEntity(BleBoxEntity[blebox_uniapi.climate.Climate], ClimateEn
return HVACAction.HEATING if self._feature.is_heating else HVACAction.IDLE
@property
def max_temp(self):
def max_temp(self) -> float:
"""Return the maximum temperature supported."""
return self._feature.max_temp
@property
def min_temp(self):
def min_temp(self) -> float:
"""Return the maximum temperature supported."""
return self._feature.min_temp
@property
def current_temperature(self):
def current_temperature(self) -> float | None:
"""Return the current temperature."""
return self._feature.current
@property
def target_temperature(self):
def target_temperature(self) -> float | None:
"""Return the desired thermostat temperature."""
return self._feature.desired

View File

@@ -84,7 +84,7 @@ class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
return color_util.color_temperature_mired_to_kelvin(self._feature.color_temp)
@property
def color_mode(self):
def color_mode(self) -> ColorMode:
"""Return the color mode.
Set values to _attr_ibutes if needed.
@@ -92,7 +92,7 @@ class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
return COLOR_MODE_MAP.get(self._feature.color_mode, ColorMode.ONOFF)
@property
def supported_color_modes(self):
def supported_color_modes(self) -> set[ColorMode]:
"""Return supported color modes."""
return {self.color_mode}
@@ -107,7 +107,7 @@ class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
return self._feature.effect
@property
def rgb_color(self):
def rgb_color(self) -> tuple[int, int, int] | None:
"""Return value for rgb."""
if (rgb_hex := self._feature.rgb_hex) is None:
return None
@@ -118,14 +118,14 @@ class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
)
@property
def rgbw_color(self):
def rgbw_color(self) -> tuple[int, int, int, int] | None:
"""Return the hue and saturation."""
if (rgbw_hex := self._feature.rgbw_hex) is None:
return None
return tuple(blebox_uniapi.light.Light.rgb_hex_to_rgb_list(rgbw_hex)[0:4])
@property
def rgbww_color(self):
def rgbww_color(self) -> tuple[int, int, int, int, int] | None:
"""Return value for rgbww."""
if (rgbww_hex := self._feature.rgbww_hex) is None:
return None

View File

@@ -25,7 +25,7 @@ from homeassistant.helpers.typing import ConfigType
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN, PLATFORMS
from .coordinator import BlinkConfigEntry, BlinkUpdateCoordinator
from .services import setup_services
from .services import async_setup_services
_LOGGER = logging.getLogger(__name__)
@@ -72,7 +72,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> b
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up Blink."""
setup_services(hass)
async_setup_services(hass)
return True

View File

@@ -6,7 +6,7 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_PIN
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv
@@ -21,34 +21,36 @@ SERVICE_SEND_PIN_SCHEMA = vol.Schema(
)
def setup_services(hass: HomeAssistant) -> None:
"""Set up the services for the Blink integration."""
async def send_pin(call: ServiceCall):
"""Call blink to send new pin."""
config_entry: BlinkConfigEntry | None
for entry_id in call.data[ATTR_CONFIG_ENTRY_ID]:
if not (config_entry := hass.config_entries.async_get_entry(entry_id)):
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="integration_not_found",
translation_placeholders={"target": DOMAIN},
)
if config_entry.state != ConfigEntryState.LOADED:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="not_loaded",
translation_placeholders={"target": config_entry.title},
)
coordinator = config_entry.runtime_data
await coordinator.api.auth.send_auth_key(
coordinator.api,
call.data[CONF_PIN],
async def _send_pin(call: ServiceCall) -> None:
"""Call blink to send new pin."""
config_entry: BlinkConfigEntry | None
for entry_id in call.data[ATTR_CONFIG_ENTRY_ID]:
if not (config_entry := call.hass.config_entries.async_get_entry(entry_id)):
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="integration_not_found",
translation_placeholders={"target": DOMAIN},
)
if config_entry.state != ConfigEntryState.LOADED:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="not_loaded",
translation_placeholders={"target": config_entry.title},
)
coordinator = config_entry.runtime_data
await coordinator.api.auth.send_auth_key(
coordinator.api,
call.data[CONF_PIN],
)
@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Set up the services for the Blink integration."""
hass.services.async_register(
DOMAIN,
SERVICE_SEND_PIN,
send_pin,
_send_pin,
schema=SERVICE_SEND_PIN_SCHEMA,
)

View File

@@ -24,7 +24,7 @@ from .const import DOMAIN, EVSE_ID, LOGGER, MODEL_TYPE
type BlueCurrentConfigEntry = ConfigEntry[Connector]
PLATFORMS = [Platform.SENSOR]
PLATFORMS = [Platform.BUTTON, Platform.SENSOR]
CHARGE_POINTS = "CHARGE_POINTS"
DATA = "data"
DELAY = 5

View File

@@ -0,0 +1,89 @@
"""Support for Blue Current buttons."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from typing import Any
from bluecurrent_api.client import Client
from homeassistant.components.button import (
ButtonDeviceClass,
ButtonEntity,
ButtonEntityDescription,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import BlueCurrentConfigEntry, Connector
from .entity import ChargepointEntity
@dataclass(kw_only=True, frozen=True)
class ChargePointButtonEntityDescription(ButtonEntityDescription):
"""Describes a Blue Current button entity."""
function: Callable[[Client, str], Coroutine[Any, Any, None]]
CHARGE_POINT_BUTTONS = (
ChargePointButtonEntityDescription(
key="reset",
translation_key="reset",
function=lambda client, evse_id: client.reset(evse_id),
device_class=ButtonDeviceClass.RESTART,
),
ChargePointButtonEntityDescription(
key="reboot",
translation_key="reboot",
function=lambda client, evse_id: client.reboot(evse_id),
device_class=ButtonDeviceClass.RESTART,
),
ChargePointButtonEntityDescription(
key="stop_charge_session",
translation_key="stop_charge_session",
function=lambda client, evse_id: client.stop_session(evse_id),
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: BlueCurrentConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Blue Current buttons."""
connector: Connector = entry.runtime_data
async_add_entities(
ChargePointButton(
connector,
button,
evse_id,
)
for evse_id in connector.charge_points
for button in CHARGE_POINT_BUTTONS
)
class ChargePointButton(ChargepointEntity, ButtonEntity):
"""Define a charge point button."""
has_value = True
entity_description: ChargePointButtonEntityDescription
def __init__(
self,
connector: Connector,
description: ChargePointButtonEntityDescription,
evse_id: str,
) -> None:
"""Initialize the button."""
super().__init__(connector, evse_id)
self.entity_description = description
self._attr_unique_id = f"{description.key}_{evse_id}"
async def async_press(self) -> None:
"""Handle the button press."""
await self.entity_description.function(self.connector.client, self.evse_id)

View File

@@ -1,7 +1,5 @@
"""Entity representing a Blue Current charge point."""
from abc import abstractmethod
from homeassistant.const import ATTR_NAME
from homeassistant.core import callback
from homeassistant.helpers.device_registry import DeviceInfo
@@ -17,12 +15,12 @@ class BlueCurrentEntity(Entity):
_attr_has_entity_name = True
_attr_should_poll = False
has_value = False
def __init__(self, connector: Connector, signal: str) -> None:
"""Initialize the entity."""
self.connector = connector
self.signal = signal
self.has_value = False
async def async_added_to_hass(self) -> None:
"""Register callbacks."""
@@ -43,7 +41,6 @@ class BlueCurrentEntity(Entity):
return self.connector.connected and self.has_value
@callback
@abstractmethod
def update_from_latest_data(self) -> None:
"""Update the entity from the latest data."""

View File

@@ -19,6 +19,17 @@
"current_left": {
"default": "mdi:gauge"
}
},
"button": {
"reset": {
"default": "mdi:restart"
},
"reboot": {
"default": "mdi:restart-alert"
},
"stop_charge_session": {
"default": "mdi:stop"
}
}
}
}

View File

@@ -1,7 +1,7 @@
{
"domain": "blue_current",
"name": "Blue Current",
"codeowners": ["@Floris272", "@gleeuwen"],
"codeowners": ["@gleeuwen", "@NickKoepr", "@jtodorova23"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/blue_current",
"iot_class": "cloud_push",

View File

@@ -113,6 +113,17 @@
"grid_max_current": {
"name": "Max grid current"
}
},
"button": {
"stop_charge_session": {
"name": "Stop charge session"
},
"reboot": {
"name": "Reboot"
},
"reset": {
"name": "Reset"
}
}
}
}

View File

@@ -18,9 +18,9 @@
"bleak==0.22.3",
"bleak-retry-connector==3.9.0",
"bluetooth-adapters==0.21.4",
"bluetooth-auto-recovery==1.5.1",
"bluetooth-auto-recovery==1.5.2",
"bluetooth-data-tools==1.28.1",
"dbus-fast==2.43.0",
"habluetooth==3.48.2"
"habluetooth==3.49.0"
]
}

View File

@@ -22,13 +22,7 @@ from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util.ssl import get_default_context
from .const import (
CONF_GCID,
CONF_READ_ONLY,
CONF_REFRESH_TOKEN,
DOMAIN as BMW_DOMAIN,
SCAN_INTERVALS,
)
from .const import CONF_GCID, CONF_READ_ONLY, CONF_REFRESH_TOKEN, DOMAIN, SCAN_INTERVALS
_LOGGER = logging.getLogger(__name__)
@@ -63,7 +57,7 @@ class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]):
hass,
_LOGGER,
config_entry=config_entry,
name=f"{BMW_DOMAIN}-{config_entry.data[CONF_USERNAME]}",
name=f"{DOMAIN}-{config_entry.data[CONF_USERNAME]}",
update_interval=timedelta(
seconds=SCAN_INTERVALS[config_entry.data[CONF_REGION]]
),
@@ -81,26 +75,26 @@ class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]):
except MyBMWCaptchaMissingError as err:
# If a captcha is required (user/password login flow), always trigger the reauth flow
raise ConfigEntryAuthFailed(
translation_domain=BMW_DOMAIN,
translation_domain=DOMAIN,
translation_key="missing_captcha",
) from err
except MyBMWAuthError as err:
# Allow one retry interval before raising AuthFailed to avoid flaky API issues
if self.last_update_success:
raise UpdateFailed(
translation_domain=BMW_DOMAIN,
translation_domain=DOMAIN,
translation_key="update_failed",
translation_placeholders={"exception": str(err)},
) from err
# Clear refresh token and trigger reauth if previous update failed as well
self._update_config_entry_refresh_token(None)
raise ConfigEntryAuthFailed(
translation_domain=BMW_DOMAIN,
translation_domain=DOMAIN,
translation_key="invalid_auth",
) from err
except (MyBMWAPIError, RequestError) as err:
raise UpdateFailed(
translation_domain=BMW_DOMAIN,
translation_domain=DOMAIN,
translation_key="update_failed",
translation_placeholders={"exception": str(err)},
) from err

View File

@@ -6,21 +6,31 @@ from ssl import SSLError
from bosch_alarm_mode2 import Panel
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, Platform
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PASSWORD, CONF_PORT, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.typing import ConfigType
from .const import CONF_INSTALLER_CODE, CONF_USER_CODE, DOMAIN
from .services import setup_services
from .types import BoschAlarmConfigEntry
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
PLATFORMS: list[Platform] = [
Platform.ALARM_CONTROL_PANEL,
Platform.BINARY_SENSOR,
Platform.SENSOR,
Platform.SWITCH,
]
type BoschAlarmConfigEntry = ConfigEntry[Panel]
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up bosch alarm services."""
setup_services(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: BoschAlarmConfigEntry) -> bool:
@@ -52,8 +62,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: BoschAlarmConfigEntry) -
device_registry = dr.async_get(hass)
mac = entry.data.get(CONF_MAC)
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
connections={(CONNECTION_NETWORK_MAC, mac)} if mac else set(),
identifiers={(DOMAIN, entry.unique_id or entry.entry_id)},
name=f"Bosch {panel.model}",
manufacturer="Bosch Security Systems",

View File

@@ -12,8 +12,8 @@ from homeassistant.components.alarm_control_panel import (
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import BoschAlarmConfigEntry
from .entity import BoschAlarmAreaEntity
from .types import BoschAlarmConfigEntry
async def async_setup_entry(
@@ -34,6 +34,9 @@ async def async_setup_entry(
)
PARALLEL_UPDATES = 0
class AreaAlarmControlPanel(BoschAlarmAreaEntity, AlarmControlPanelEntity):
"""An alarm control panel entity for a bosch alarm panel."""
@@ -47,7 +50,7 @@ class AreaAlarmControlPanel(BoschAlarmAreaEntity, AlarmControlPanelEntity):
def __init__(self, panel: Panel, area_id: int, unique_id: str) -> None:
"""Initialise a Bosch Alarm control panel entity."""
super().__init__(panel, area_id, unique_id, False, False, True)
super().__init__(panel, area_id, unique_id, True, False, True)
self._attr_unique_id = self._area_unique_id
@property

View File

@@ -0,0 +1,220 @@
"""Support for Bosch Alarm Panel binary sensors."""
from __future__ import annotations
from dataclasses import dataclass
from bosch_alarm_mode2 import Panel
from bosch_alarm_mode2.const import ALARM_PANEL_FAULTS
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import BoschAlarmConfigEntry
from .entity import BoschAlarmAreaEntity, BoschAlarmEntity, BoschAlarmPointEntity
@dataclass(kw_only=True, frozen=True)
class BoschAlarmFaultEntityDescription(BinarySensorEntityDescription):
"""Describes Bosch Alarm sensor entity."""
fault: int
FAULT_TYPES = [
BoschAlarmFaultEntityDescription(
key="panel_fault_battery_low",
entity_registry_enabled_default=True,
device_class=BinarySensorDeviceClass.BATTERY,
fault=ALARM_PANEL_FAULTS.BATTERY_LOW,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_battery_mising",
translation_key="panel_fault_battery_mising",
entity_registry_enabled_default=True,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.BATTERY_MISING,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_ac_fail",
translation_key="panel_fault_ac_fail",
entity_registry_enabled_default=True,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.AC_FAIL,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_phone_line_failure",
translation_key="panel_fault_phone_line_failure",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.CONNECTIVITY,
fault=ALARM_PANEL_FAULTS.PHONE_LINE_FAILURE,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_parameter_crc_fail_in_pif",
translation_key="panel_fault_parameter_crc_fail_in_pif",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.PARAMETER_CRC_FAIL_IN_PIF,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_communication_fail_since_rps_hang_up",
translation_key="panel_fault_communication_fail_since_rps_hang_up",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.COMMUNICATION_FAIL_SINCE_RPS_HANG_UP,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_sdi_fail_since_rps_hang_up",
translation_key="panel_fault_sdi_fail_since_rps_hang_up",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.SDI_FAIL_SINCE_RPS_HANG_UP,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_user_code_tamper_since_rps_hang_up",
translation_key="panel_fault_user_code_tamper_since_rps_hang_up",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.USER_CODE_TAMPER_SINCE_RPS_HANG_UP,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_fail_to_call_rps_since_rps_hang_up",
translation_key="panel_fault_fail_to_call_rps_since_rps_hang_up",
entity_registry_enabled_default=False,
fault=ALARM_PANEL_FAULTS.FAIL_TO_CALL_RPS_SINCE_RPS_HANG_UP,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_point_bus_fail_since_rps_hang_up",
translation_key="panel_fault_point_bus_fail_since_rps_hang_up",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.POINT_BUS_FAIL_SINCE_RPS_HANG_UP,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_log_overflow",
translation_key="panel_fault_log_overflow",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.LOG_OVERFLOW,
),
BoschAlarmFaultEntityDescription(
key="panel_fault_log_threshold",
translation_key="panel_fault_log_threshold",
entity_registry_enabled_default=False,
device_class=BinarySensorDeviceClass.PROBLEM,
fault=ALARM_PANEL_FAULTS.LOG_THRESHOLD,
),
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: BoschAlarmConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up binary sensors for alarm points and the connection status."""
panel = config_entry.runtime_data
entities: list[BinarySensorEntity] = [
PointSensor(panel, point_id, config_entry.unique_id or config_entry.entry_id)
for point_id in panel.points
]
entities.extend(
PanelFaultsSensor(
panel,
config_entry.unique_id or config_entry.entry_id,
fault_type,
)
for fault_type in FAULT_TYPES
)
entities.extend(
AreaReadyToArmSensor(
panel, area_id, config_entry.unique_id or config_entry.entry_id, "away"
)
for area_id in panel.areas
)
entities.extend(
AreaReadyToArmSensor(
panel, area_id, config_entry.unique_id or config_entry.entry_id, "home"
)
for area_id in panel.areas
)
async_add_entities(entities)
PARALLEL_UPDATES = 0
class PanelFaultsSensor(BoschAlarmEntity, BinarySensorEntity):
"""A binary sensor entity for each fault type in a bosch alarm panel."""
_attr_entity_category = EntityCategory.DIAGNOSTIC
entity_description: BoschAlarmFaultEntityDescription
def __init__(
self,
panel: Panel,
unique_id: str,
entity_description: BoschAlarmFaultEntityDescription,
) -> None:
"""Set up a binary sensor entity for each fault type in a bosch alarm panel."""
super().__init__(panel, unique_id, True)
self.entity_description = entity_description
self._fault_type = entity_description.fault
self._attr_unique_id = f"{unique_id}_fault_{entity_description.key}"
@property
def is_on(self) -> bool:
"""Return if this fault has occurred."""
return self._fault_type in self.panel.panel_faults_ids
class AreaReadyToArmSensor(BoschAlarmAreaEntity, BinarySensorEntity):
"""A binary sensor entity showing if a panel is ready to arm."""
_attr_entity_category = EntityCategory.DIAGNOSTIC
def __init__(
self, panel: Panel, area_id: int, unique_id: str, arm_type: str
) -> None:
"""Set up a binary sensor entity for the arming status in a bosch alarm panel."""
super().__init__(panel, area_id, unique_id, False, False, True)
self.panel = panel
self._arm_type = arm_type
self._attr_translation_key = f"area_ready_to_arm_{arm_type}"
self._attr_unique_id = f"{self._area_unique_id}_ready_to_arm_{arm_type}"
@property
def is_on(self) -> bool:
"""Return if this panel is ready to arm."""
if self._arm_type == "away":
return self._area.all_ready
if self._arm_type == "home":
return self._area.all_ready or self._area.part_ready
return False
class PointSensor(BoschAlarmPointEntity, BinarySensorEntity):
"""A binary sensor entity for a point in a bosch alarm panel."""
_attr_name = None
def __init__(self, panel: Panel, point_id: int, unique_id: str) -> None:
"""Set up a binary sensor entity for a point in a bosch alarm panel."""
super().__init__(panel, point_id, unique_id)
self._attr_unique_id = self._point_unique_id
@property
def is_on(self) -> bool:
"""Return if this point sensor is on."""
return self._point.is_open()

View File

@@ -6,25 +6,30 @@ import asyncio
from collections.abc import Mapping
import logging
import ssl
from typing import Any
from typing import Any, Self
from bosch_alarm_mode2 import Panel
import voluptuous as vol
from homeassistant.config_entries import (
SOURCE_DHCP,
SOURCE_RECONFIGURE,
SOURCE_USER,
ConfigEntryState,
ConfigFlow,
ConfigFlowResult,
)
from homeassistant.const import (
CONF_CODE,
CONF_HOST,
CONF_MAC,
CONF_MODEL,
CONF_PASSWORD,
CONF_PORT,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
from .const import CONF_INSTALLER_CODE, CONF_USER_CODE, DOMAIN
@@ -88,6 +93,12 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
"""Init config flow."""
self._data: dict[str, Any] = {}
self.mac: str | None = None
self.host: str | None = None
def is_matching(self, other_flow: Self) -> bool:
"""Return True if other_flow is matching this flow."""
return self.mac == other_flow.mac or self.host == other_flow.host
async def async_step_user(
self, user_input: dict[str, Any] | None = None
@@ -96,9 +107,12 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
errors: dict[str, str] = {}
if user_input is not None:
self.host = user_input[CONF_HOST]
if self.source == SOURCE_USER:
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
try:
# Use load_selector = 0 to fetch the panel model without authentication.
(model, serial) = await try_connect(user_input, 0)
(model, _) = await try_connect(user_input, 0)
except (
OSError,
ConnectionRefusedError,
@@ -129,6 +143,70 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
errors=errors,
)
async def async_step_dhcp(
self, discovery_info: DhcpServiceInfo
) -> ConfigFlowResult:
"""Handle DHCP discovery."""
self.mac = format_mac(discovery_info.macaddress)
self.host = discovery_info.ip
if self.hass.config_entries.flow.async_has_matching_flow(self):
return self.async_abort(reason="already_in_progress")
for entry in self.hass.config_entries.async_entries(DOMAIN):
if entry.data.get(CONF_MAC) == self.mac:
result = self.hass.config_entries.async_update_entry(
entry,
data={
**entry.data,
CONF_HOST: discovery_info.ip,
},
)
if result:
self.hass.config_entries.async_schedule_reload(entry.entry_id)
return self.async_abort(reason="already_configured")
if entry.data[CONF_HOST] == discovery_info.ip:
if (
not entry.data.get(CONF_MAC)
and entry.state is ConfigEntryState.LOADED
):
result = self.hass.config_entries.async_update_entry(
entry,
data={
**entry.data,
CONF_MAC: self.mac,
},
)
if result:
self.hass.config_entries.async_schedule_reload(entry.entry_id)
return self.async_abort(reason="already_configured")
try:
# Use load_selector = 0 to fetch the panel model without authentication.
(model, _) = await try_connect(
{CONF_HOST: discovery_info.ip, CONF_PORT: 7700}, 0
)
except (
OSError,
ConnectionRefusedError,
ssl.SSLError,
asyncio.exceptions.TimeoutError,
):
return self.async_abort(reason="cannot_connect")
except Exception:
_LOGGER.exception("Unexpected exception")
return self.async_abort(reason="unknown")
self.context["title_placeholders"] = {
"model": model,
"host": discovery_info.ip,
}
self._data = {
CONF_HOST: discovery_info.ip,
CONF_MAC: self.mac,
CONF_MODEL: model,
CONF_PORT: 7700,
}
return await self.async_step_auth()
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
@@ -172,7 +250,7 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
else:
if serial_number:
await self.async_set_unique_id(str(serial_number))
if self.source == SOURCE_USER:
if self.source in (SOURCE_USER, SOURCE_DHCP):
if serial_number:
self._abort_if_unique_id_configured()
else:
@@ -184,6 +262,7 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
)
if serial_number:
self._abort_if_unique_id_mismatch(reason="device_mismatch")
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data=self._data,

View File

@@ -1,6 +1,9 @@
"""Constants for the Bosch Alarm integration."""
DOMAIN = "bosch_alarm"
HISTORY_ATTR = "history"
ATTR_HISTORY = "history"
CONF_INSTALLER_CODE = "installer_code"
CONF_USER_CODE = "user_code"
ATTR_DATETIME = "datetime"
SERVICE_SET_DATE_TIME = "set_date_time"
ATTR_CONFIG_ENTRY_ID = "config_entry_id"

View File

@@ -6,8 +6,8 @@ from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_PASSWORD
from homeassistant.core import HomeAssistant
from . import BoschAlarmConfigEntry
from .const import CONF_INSTALLER_CODE, CONF_USER_CODE
from .types import BoschAlarmConfigEntry
TO_REDACT = [CONF_INSTALLER_CODE, CONF_USER_CODE, CONF_PASSWORD]

View File

@@ -17,9 +17,13 @@ class BoschAlarmEntity(Entity):
_attr_has_entity_name = True
def __init__(self, panel: Panel, unique_id: str) -> None:
def __init__(
self, panel: Panel, unique_id: str, observe_faults: bool = False
) -> None:
"""Set up a entity for a bosch alarm panel."""
self.panel = panel
self._observe_faults = observe_faults
self._attr_should_poll = False
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)},
name=f"Bosch {panel.model}",
@@ -34,10 +38,14 @@ class BoschAlarmEntity(Entity):
async def async_added_to_hass(self) -> None:
"""Observe state changes."""
self.panel.connection_status_observer.attach(self.schedule_update_ha_state)
if self._observe_faults:
self.panel.faults_observer.attach(self.schedule_update_ha_state)
async def async_will_remove_from_hass(self) -> None:
"""Stop observing state changes."""
self.panel.connection_status_observer.detach(self.schedule_update_ha_state)
if self._observe_faults:
self.panel.faults_observer.attach(self.schedule_update_ha_state)
class BoschAlarmAreaEntity(BoschAlarmEntity):
@@ -88,6 +96,33 @@ class BoschAlarmAreaEntity(BoschAlarmEntity):
self._area.status_observer.detach(self.schedule_update_ha_state)
class BoschAlarmPointEntity(BoschAlarmEntity):
"""A base entity for point related entities within a bosch alarm panel."""
def __init__(self, panel: Panel, point_id: int, unique_id: str) -> None:
"""Set up a area related entity for a bosch alarm panel."""
super().__init__(panel, unique_id)
self._point_id = point_id
self._point_unique_id = f"{unique_id}_point_{point_id}"
self._point = panel.points[point_id]
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._point_unique_id)},
name=self._point.name,
manufacturer="Bosch Security Systems",
via_device=(DOMAIN, unique_id),
)
async def async_added_to_hass(self) -> None:
"""Observe state changes."""
await super().async_added_to_hass()
self._point.status_observer.attach(self.schedule_update_ha_state)
async def async_will_remove_from_hass(self) -> None:
"""Stop observing state changes."""
await super().async_added_to_hass()
self._point.status_observer.detach(self.schedule_update_ha_state)
class BoschAlarmDoorEntity(BoschAlarmEntity):
"""A base entity for area related entities within a bosch alarm panel."""

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