Compare commits

...

1191 Commits

Author SHA1 Message Date
Marc Mueller
8e9e304608
Update lxml to 6.0.0 (#149640) 2025-07-30 10:38:42 +02:00
dependabot[bot]
6b641411a0
Bump github/codeql-action from 3.29.4 to 3.29.5 (#149648)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-30 10:33:09 +02:00
Norbert Rittel
6f8214bbb4
Fix spelling mistakes in abort message of leaone (#149653) 2025-07-29 22:22:35 -10:00
Marcel van der Veldt
f66e83f33e
Add dynamic encryption key support to the ESPHome integration (#148746)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-07-29 21:54:00 -10:00
Robert Resch
2ee82e1d6f
Remove battery attribute from Ecovacs vacuums (#149581) 2025-07-30 09:24:16 +02:00
Jan Bouwhuis
0dd1e0cabb
Suppress exception stack trace when writing MQTT entity state if a ValueError occured (#149583) 2025-07-30 09:06:15 +02:00
Åke Strandberg
45ae34cc0e
Strip leading and trailing whitespace in program names in miele action response (#149643) 2025-07-30 00:23:03 +02:00
hypnosiss
73e578b168
Bump pymysensors library version (#149632) 2025-07-29 22:29:53 +01:00
Arie Catsman
52ee5d53ee
bump pyenphase to 2.2.3 (#149641) 2025-07-29 22:27:43 +01:00
Marc Mueller
62713b1371
Update pyblu to 2.0.4 (#149589) 2025-07-29 22:32:32 +02:00
Simone Chemelli
c4c4463c63
Update IQS for Alexa Devices (#149639) 2025-07-29 22:00:49 +02:00
Franck Nijhof
7e2fd6e47b
Merge branch 'master' into dev 2025-07-29 18:52:18 +00:00
karwosts
9f45801409
Remove advanced mode from group all option. (#149626) 2025-07-29 20:03:27 +02:00
J. Nick Koston
aaec243bf4
Properly cleanup ONVIF events to prevent log flooding on setup errors (#149603) 2025-07-29 19:49:20 +02:00
Tom
b67e85e8da
Introduce Ubiquiti UISP airOS (#148989)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-29 19:41:13 +02:00
J. Nick Koston
25407c0f4b
Bump aiohttp to 3.12.15 (#149609) 2025-07-29 19:21:31 +02:00
Stefan Agner
09e7d8d1a5
Increase open file descriptor limit on startup (#148940)
Co-authored-by: Jan Čermák <sairon@sairon.cz>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-07-29 17:42:26 +02:00
Markus Adrario
ff7c125334
Upgrade Homee quality scale to silver (#149194) 2025-07-29 15:19:08 +02:00
Martin Hjelmare
3d6f868cbc
Bump zwave-js-server-python to 0.67.0 (#149616) 2025-07-29 13:57:40 +02:00
Thomas D
378c3af9df
Bump qbusmqttapi to 1.4.2 (#149622) 2025-07-29 13:51:32 +02:00
osohotwateriot
c7271d1af9
Add OSO Energy Custom Away Mode Service (#149612) 2025-07-29 13:50:31 +02:00
Klaas Schoute
87400c6a17
Bump odp-amsterdam to v6.1.2 (#149617) 2025-07-29 12:59:30 +02:00
Christopher Fenner
692a1119a6
Adjust suggested display precision on Volvo distance sensors (#149593) 2025-07-29 12:29:07 +02:00
Thomas55555
2e728eb7de
Bump aioautomower to 2.1.1 (#149585) 2025-07-29 09:38:50 +02:00
Manu
45ec9c7dad
Refactor coordinator setup in Iron OS (#149600) 2025-07-29 09:37:32 +02:00
Manu
62ee1fbc64
Remove unnecessary CONF_NAME usage in Habitica integration (#149595) 2025-07-29 08:55:32 +02:00
Jan-Philipp Benecke
3c1aa9d9de
Make exceptions translatable in Tankerkoenig integration (#149611) 2025-07-29 08:52:42 +02:00
J. Nick Koston
bf568b22d7
Bump onvif-zeep-async to 4.0.2 (#149606) 2025-07-29 08:41:45 +02:00
Michael
596f6cd216
Add people and tags collections to Immich media source (#149340) 2025-07-28 23:21:04 +02:00
Åke Strandberg
cf05f1046d
Add action to retrieve list of programs on miele appliance (#149307) 2025-07-28 22:19:51 +02:00
Thomas55555
7f9be420d2
Add details to Husqvarna Automower restricted reason sensor (#147678)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-28 19:54:54 +01:00
Abílio Costa
dda46e7e0b
Use non-autospec mock in Reolink's remaining tests (#149565)
Co-authored-by: starkillerOG <starkiller.og@gmail.com>
2025-07-28 18:38:06 +01:00
Michael
b1dd742a57
Move battery properties from legacy Ecovacs vacuum entity to separate entities (#149084) 2025-07-28 18:49:12 +02:00
Simone Chemelli
5af4290b77
Update IQS for Alexa Devices (#149440) 2025-07-28 18:33:39 +02:00
Petro31
8339516fb4
Add optimistic option to alarm control panel yaml (#149334) 2025-07-28 17:44:43 +02:00
Matrix
aa1314c1d5
Add YoLink YS6614 support. (#149153) 2025-07-28 17:43:20 +02:00
epenet
92ad922ddc
Add fan mode support for Tuya air conditioner (aqoouq7x) (#149226) 2025-07-28 17:42:36 +02:00
epenet
e518e7beac
Add service tests to Tuya select platform (#149156)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-28 17:42:18 +02:00
Thomas D
483d814a8f
Add new Volvo integration (#142994)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-28 17:24:15 +02:00
Tom
8f795f021c
Bump Plugwise to v1.7.8 preventing rogue KeyError (#149000) 2025-07-28 17:19:43 +02:00
Petro31
d823b574c0
Add optimistic option to light yaml (#149395) 2025-07-28 16:59:57 +02:00
Petro31
49bd15718c
Add optimistic option to fan yaml (#149390) 2025-07-28 16:58:46 +02:00
Abílio Costa
d3f18c1678
Add quality scale to ring manifest (#149406) 2025-07-28 16:35:38 +02:00
Joost Lekkerkerker
5ef17c8588
Bump the required version of ruff to 0.12.1 (#149571) 2025-07-28 16:32:56 +02:00
Norbert Rittel
e8b8d31027
Make actions labels consistent for Template alarm control panel (#149574) 2025-07-28 16:31:13 +02:00
Manu
978ee3870c
Add notify platform to PlayStation Network integration (#149557) 2025-07-28 16:18:57 +02:00
Petro31
b3862591ea
Add optimism to vacuum platform (#149425) 2025-07-28 16:18:37 +02:00
Petro31
1895db0ddd
Add optimistic option to switch yaml (#149402) 2025-07-28 16:17:39 +02:00
Petro31
ee2cf961f6
Add assumed optimistic functionality to lock platform (#149397) 2025-07-28 16:17:09 +02:00
Martin Hjelmare
9a364ec729
Fix Z-Wave removal of devices when connected to unknown controller (#149339) 2025-07-28 16:13:39 +02:00
starkillerOG
96529ec245
Add Reolink pre-recording entities (#149522)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-28 16:12:53 +02:00
David Knowles
8fc8220924
Teach Hydrawise to auto-add/remove devices (#149547)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-28 16:06:15 +02:00
osohotwateriot
386f709fd3
Osoenergy holiday mode services (#149430)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-28 16:00:22 +02:00
alvi kazi 🇧🇩
d088fccb88
VeSync: add support for LAP-V102S-WJP air purifier (#149102) 2025-07-28 15:51:07 +02:00
jennoian
2a5448835f
Add Vacuum support to smartthings (#148724)
Co-authored-by: Joostlek <joostlek@outlook.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-28 15:37:37 +02:00
Avery
a71eecaaa4
Update datadog test logic (#149459)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-28 15:10:55 +02:00
hanwg
46d810b9f9
Better error handling when setting up config entry for Telegram bot (#149444) 2025-07-28 14:52:40 +02:00
Petro31
48c4240a5d
Delete unused switch platform code (#149468) 2025-07-28 14:48:45 +02:00
wittypluck
bf05c23414
Update OpenWeatherMap config step description to clarify API key documentation (#146843) 2025-07-28 14:40:00 +02:00
Michael
db1e6a0d98
Add quality scale and set Silver for Tankerkoenig (#143418) 2025-07-28 14:34:27 +02:00
Assaf Inbal
4ad35e8421
Add charging binary sensor to ituran (#149562)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-28 13:18:43 +02:00
wollew
850e04d9aa
Add binary sensor for rain detection for Velux windows that have them (#148275)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-28 13:15:59 +02:00
Manu
95c5a91f01
Refactor active session handling in PlaystationNetwork (#149559) 2025-07-28 13:13:08 +02:00
Petro31
140f56aeaa
Add common translation strings (#149472)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-07-28 13:12:52 +02:00
Michael
40ce228c9c
Add upload_file action to immich integration (#147295)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-28 13:12:16 +02:00
Abílio Costa
18c5437fe7
Revert "Make default title configurable in XMPP" (#149544) 2025-07-28 13:42:40 +03:00
Norbert Rittel
ebad1ff4cc
Fix capitalization of "IP address" in goalzero (#149563) 2025-07-28 11:59:11 +02:00
Ludovic BOUÉ
a68e722c92
Matter MicrowaveOven device (#148219)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-07-28 11:33:03 +02:00
Joakim Sørensen
05935bbc01
Bump hass-nabucasa from 0.108.0 to 0.110.0 (#149560) 2025-07-28 11:17:26 +02:00
Assaf Inbal
c67636b4f6
Add support for EVs in ituran (#149484) 2025-07-28 10:35:52 +02:00
Franck Nijhof
777b3128bb
2025.7.4 (#149526) 2025-07-28 10:15:08 +02:00
Shai Ungar
ab6cd0eb41
Bump israel-rail to 0.1.3 (#149555) 2025-07-28 08:42:40 +02:00
Brett Adams
f35558413a
Bump tesla-fleet-api to 1.2.3 (#149550) 2025-07-28 07:58:59 +02:00
Michael
e30d405625
Enable strict typing in Tankerkoenig (#149535) 2025-07-27 22:48:15 +02:00
Thomas55555
622cce03a1
Bump aioautomower to 2.1.0 (#149541) 2025-07-27 22:46:59 +02:00
Raphael Hehl
1fa9141ce1
Bump uiprotect to version 7.20.0 (#149533) 2025-07-27 21:52:53 +02:00
Norbert Rittel
a060f7486f
Replace duplicated strings and fix "street name" in waze_travel_time (#149512) 2025-07-27 21:36:25 +03:00
Manu
dbb5730389
Increase trophy titles retrieval page size to 500 for PlayStation Network (#149528) 2025-07-27 21:35:01 +03:00
Michael
431b2aa1d5
Add data description strings to Tankerkoenig (#149519)
Co-authored-by: Josef Zweck <josef@zweck.dev>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-27 20:13:05 +02:00
Michael
c99d81a554
Set PARALLEL_UPDATES in Tankerkoenig platforms (#149518) 2025-07-27 20:02:24 +02:00
starkillerOG
ff4dc393cf
Bump reolink-aio to 0.14.4 (#149521) 2025-07-27 20:00:50 +02:00
Franck Nijhof
d384bee576
Bump version to 2025.7.4 2025-07-27 17:35:19 +00:00
Manu
f0cb5d5480
Bump habiticalib to v0.4.1 (#149523) 2025-07-27 17:35:01 +00:00
jb101010-2
725799c73e
Bump pysuezV2 to 2.0.7 (#149436) 2025-07-27 17:34:59 +00:00
Simone Chemelli
dc6d2e3e84
Bump aioamazondevices to 3.5.1 (#149385) 2025-07-27 17:34:09 +00:00
Alex Hermann
4a7d06a68a
Update slixmpp to 1.10.0 (#149374) 2025-07-27 17:29:37 +00:00
Brett Adams
cd800da357
Update Tesla OAuth Server in Tesla Fleet (#149280) 2025-07-27 17:29:35 +00:00
Antoine Reversat
4c8ab8eb64
Add fan off mode to the supported fan modes to fujitsu_fglair (#149277) 2025-07-27 17:29:33 +00:00
Martin Hjelmare
60f4d29d60
Add Z-Wave USB migration confirm step (#149243) 2025-07-27 17:29:31 +00:00
Avi Miller
68b7d09476
Fix brightness_step and brightness_step_pct via lifx.set_state (#149217)
Signed-off-by: Avi Miller <me@dje.li>
2025-07-27 17:29:29 +00:00
jvmahon
c3eb6dea11
Fix Matter light get brightness (#149186) 2025-07-27 17:29:28 +00:00
David Knowles
f428ffde87
Bump pyschlage to 2025.7.2 (#149148) 2025-07-27 17:29:26 +00:00
hanwg
fa207860a0
Fix multiple webhook secrets for Telegram bot (#149103) 2025-07-27 17:29:24 +00:00
Allen Porter
959c3a8a99
Fix a bug in rainbird device migration that results in additional devices (#149078) 2025-07-27 17:29:23 +00:00
Marc Hörsken
254ccca4e5
Fix warning about failure to get action during setup phase (#148923) 2025-07-27 17:29:21 +00:00
AlCalzone
5b08724d81
Keep entities of dead Z-Wave devices available (#148611) 2025-07-27 17:29:20 +00:00
Marc Mueller
ea2b3b3ff3
Update ical + gcal-sync (#149413) 2025-07-27 19:22:01 +02:00
Alex Hermann
a33760bc1a
Update slixmpp to 1.10.0 (#149374) 2025-07-27 19:18:00 +02:00
Manu
4ea7ad52b1
Bump habiticalib to v0.4.1 (#149523) 2025-07-27 19:09:13 +02:00
Manu
dac75d1902
Add update platform to Uptime Kuma (#148973) 2025-07-27 18:02:33 +02:00
petep0p
0e9ced3c00
Correct core Purpleair integration's RSSI sensor to use RSSI value rather than barometric pressure (#149418) 2025-07-27 07:13:31 -06:00
Norbert Rittel
22d0fbcbd2
Fix spelling of "its" in mqtt (#149517) 2025-07-27 14:39:21 +02:00
Abílio Costa
57b641b97d
Use non-autospec mock in Reolink's media source, number, sensor and siren tests (#149396) 2025-07-27 12:43:48 +02:00
J. Nick Koston
27bd6d2e38
Bump aioesphomeapi to 37.1.2 (#149460) 2025-07-26 22:48:48 -10:00
Assaf Inbal
427e5d81df
Bump pyituran to 0.1.5 (#149486) 2025-07-26 19:03:51 +03:00
Shay Levy
b6bd92ed19
Shelly entity device info code quality (#149477) 2025-07-26 17:08:08 +03:00
Florian von Garrel
7976729e76
Paperless-ngx: Retry setup on initialization error (#149476) 2025-07-26 14:19:33 +02:00
Shay Levy
5aa0d0dc81
Remove Shelly redundant device info assignment in Button class (#149469) 2025-07-26 14:32:51 +03:00
jb101010-2
e1501d7510
Bump pysuezV2 to 2.0.7 (#149436) 2025-07-26 13:38:38 +03:00
Norbert Rittel
be5109fddf
Change spelling of "Favorite x" to intl. English in bang_olufsen (#149464) 2025-07-26 13:35:11 +03:00
Norbert Rittel
c5cf9b07b7
Replace HA alarm (control panel) states with references in risco (#149466) 2025-07-26 13:34:24 +03:00
Norbert Rittel
002b7c6789
Fix descriptions in home_connect.set_program_and_options action (#149462) 2025-07-26 09:47:26 +02:00
Paul Bottein
e017dc80a0
Allow to reorder members within a group (#149003) 2025-07-26 01:07:51 +02:00
Erik Montnemery
aab7381553
Add test of ConfigSubentryFlow._subentry_type (#147565) 2025-07-26 00:27:04 +02:00
Norbert Rittel
cbf4409db3
Fix inconsistent spelling of "Wi-Fi" in unifiprotect (#149311)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-07-25 09:51:01 -10:00
Raphael Hehl
56fb59e48e
Unifiprotect refactor device description ID retrieval in tests (#149445) 2025-07-25 09:21:57 -10:00
rappenze
971bd56bee
Add Z-Box Hub virtual integration (#146678) 2025-07-25 20:37:36 +02:00
Matt Zimmerman
b2710c1bce
Add smarttub cover sensor (#139134)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-25 20:10:39 +02:00
Petro31
a069b59efc
Transition template types from string to platform keys (#149434) 2025-07-25 19:55:40 +02:00
osohotwateriot
02eb1dd533
Bump pyosoenergyapi to 1.2.4 (#149439) 2025-07-25 19:30:58 +02:00
Thomas55555
b3130c7929
Bump aioautomower to 2.0.2 (#149441) 2025-07-25 19:29:40 +02:00
Norbert Rittel
aad1dbecb4
Fix spelling of "IP" and improve action descriptions in lcn (#149314) 2025-07-25 19:28:43 +02:00
jvmahon
65109ea000
Fix Matter light get brightness (#149186) 2025-07-25 19:09:58 +02:00
Marc Mueller
356ac74fa5
Update orjson to 3.11.1 (#149442) 2025-07-25 19:07:07 +02:00
Norbert Rittel
f3513f7f29
Add missing hyphen to "case-sensitive" in tplink (#149363) 2025-07-25 19:01:57 +02:00
Marc Mueller
4bbb94f43d
Update coverage to 7.10.0 (#149412) 2025-07-25 15:05:20 +02:00
Jan Bouwhuis
c1fa721a57
Revert "Use OptionsFlowWithReload in mqtt" (#149431) 2025-07-25 15:03:44 +02:00
Norbert Rittel
e3ffb41650
Improve some option and state names in home_connect (#149373) 2025-07-25 13:52:01 +02:00
Shay Levy
123cce6d96
Add configuration URL and model details to Shelly sub device info (#149404) 2025-07-25 14:26:32 +03:00
Guido Schmitz
6920dec352
Rework devolo Home Control config flow (#147121) 2025-07-25 12:55:42 +02:00
Guido Schmitz
f7cc260336
Add quality scale for devolo Home Network (#131510)
Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>
2025-07-25 12:20:33 +02:00
osohotwateriot
b7da31a021
Bump pyosoenergyapi to 1.2.3 (#149422) 2025-07-25 12:15:42 +02:00
Kevin Stillhammer
95d4dc678c
Add option traffic_mode in here_travel_time (#146676) 2025-07-25 12:14:36 +02:00
Álvaro Fernández Rojas
7e9da052ca
Update aioairzone-cloud to v0.7.1 (#149388)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2025-07-25 08:17:26 +02:00
Marc Mueller
59ece455d9
Update numpy to 2.3.2 (#149411) 2025-07-25 02:24:25 +02:00
Jake Martin
3ba144c8b2
Bump monzopy to 1.5.1 (#149410) 2025-07-25 02:38:48 +03:00
Petro31
4cc4bd3b9a
Remove redundant async_set_context from platforms (#149403) 2025-07-24 22:28:56 +01:00
Raphael Hehl
dbc2b1354b
UnifiProtect refactor sensor retrieval in tests to use get_sensor_by_key function (#149398) 2025-07-24 10:11:47 -10:00
Steven B.
fbe257f997
Add quality scale file to ring integration (#136454)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-24 20:19:30 +01:00
Alex Hermann
208dde10e6
Make default title configurable in XMPP (#149379) 2025-07-24 20:08:47 +01:00
Norbert Rittel
b7b733efc3
Use common state for "Normal" in switchbot (#149399) 2025-07-24 20:03:45 +01:00
Norbert Rittel
1d9f779b2a
Add missing hyphen to "case-sensitive" in tuya (#149400) 2025-07-24 20:03:36 +01:00
Maciej Bieniek
56c53fdb9b
Allow Bluetooth proxy for Shelly devices only if Zigbee firmware is not active (#149193)
Co-authored-by: Shay Levy <levyshay1@gmail.com>
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-24 21:14:44 +03:00
LG-ThinQ-Integration
5c4862ffe1
Fix Air Conditioner set temperature error in LG ThinQ (#147008)
Co-authored-by: yunseon.park <yunseon.park@lge.com>
2025-07-24 20:12:41 +02:00
Abílio Costa
5c7913c3bd
Remove door state from Whirlpool machine state sensor (#144078) 2025-07-24 20:07:57 +02:00
Norbert Rittel
36a98470cc
Remove excessive comma from dsmr_reader issue description (#149393) 2025-07-24 19:20:42 +02:00
Norbert Rittel
f2c995cf86
Fix sentence-casing of "DSMR options" string (#149392) 2025-07-24 19:20:28 +02:00
Matěj 'Horm' Horák
eeca5a8030
Improve Airthings test coverage (#144750)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-24 19:10:01 +02:00
Norbert Rittel
56d97f5545
Drop duplicated lower-case "qnap" from setup description (#149384) 2025-07-24 18:49:46 +02:00
Simone Chemelli
995a99e256
Bump aioamazondevices to 3.5.1 (#149385) 2025-07-24 16:54:00 +01:00
Abílio Costa
ef7cd815b2
Add list of targeted entities to target state event (#149203) 2025-07-24 16:52:12 +01:00
Paulus Schoutsen
8b8616182d
Allow downloading a device analytics dump (#149376) 2025-07-24 17:27:02 +02:00
Frank Wickström
760b69d458
Only send integers when setting Huum sauna temperature (#149380) 2025-07-24 17:13:54 +02:00
Norbert Rittel
6adcd34521
Remove space character from "autodetect" in xiaomi_miio (#149381) 2025-07-24 17:10:46 +02:00
Thomas55555
a0992498c6
Improve removal of stale entities/devices in Husqvarna Automower (#148428)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-24 15:52:43 +01:00
Marc Mueller
d6175fb383
Update mypy-dev to 1.18.0a3 (#149383) 2025-07-24 16:05:24 +02:00
G Johansson
dd3c9ab3af
Use OptionsFlowWithReload in mqtt (#149092) 2025-07-24 15:34:00 +02:00
Maciej Bieniek
fea2ef1ac1
Bump imgw_pib to version 1.5.1 (#149368) 2025-07-24 15:37:01 +03:00
Álvaro Fernández Rojas
326bcc3f05
Update aioairzone-cloud to v0.7.0 (#149369)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2025-07-24 15:32:51 +03:00
Andrew Jackson
feeef88710
Bump aiomealie to 0.10.0 (#149370) 2025-07-24 13:07:35 +02:00
LG-ThinQ-Integration
f481c1b92f
Add sensors for ventilator in LG ThinQ (#140846)
Co-authored-by: yunseon.park <yunseon.park@lge.com>
2025-07-24 12:33:34 +02:00
Avery
eea22d8079
Add config flow for datadog (#148104)
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2025-07-24 12:29:07 +02:00
Maciej Bieniek
393087cf50
Bump aioshelly to 13.8.0 (#149365) 2025-07-24 11:50:26 +02:00
Norbert Rittel
f5718e1df6
Fix spelling of "autoplay" in music_assistant (#149364) 2025-07-24 11:15:57 +02:00
Artur Pragacz
15f2ae3002
Mark Onkyo quality scale as bronze (#149362) 2025-07-24 11:03:02 +02:00
Norbert Rittel
f458ede468
Small fixes to user-facing strings of webostv (#149359) 2025-07-24 11:53:33 +03:00
dependabot[bot]
d85ffee27a
Bump github/codeql-action from 3.29.3 to 3.29.4 (#149354)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:29:34 +02:00
Norbert Rittel
2e12d67f2f
Improve id_missing abort message in samsungtv (#149357) 2025-07-24 10:23:30 +02:00
Norbert Rittel
46a01c2060
Fix config entry name and description in rainbird.set_rain_delay action (#149358) 2025-07-24 10:23:17 +02:00
tronikos
53d77c4c10
Fix Chinese in Google Cloud STT (#149155) 2025-07-24 01:08:58 -07:00
Norbert Rittel
fcd514a06b
Sentence-case "Still image URL" in mjpeg (#149356) 2025-07-24 09:23:21 +02:00
Norbert Rittel
049a698815
Add missing hyphen to "right-hand drive" in teslemetry (#149355) 2025-07-24 08:56:49 +02:00
Norbert Rittel
55f01e3485
Make descriptions of modbus.stop/restart actions consistent (#149341) 2025-07-24 08:23:42 +02:00
Artur Pragacz
c2b1932045
Bump aioonkyo to 0.3.0 (#149336) 2025-07-24 08:23:02 +02:00
Norbert Rittel
5543587527
Fix spelling of "sea level" in luftdaten (#149347) 2025-07-24 08:22:25 +02:00
J. Nick Koston
202d8ac802
Bump yalexs-ble to 3.1.0 (#149352) 2025-07-24 08:18:59 +02:00
Norbert Rittel
7613880645
Fix spelling of "the setup" in nest (#149345) 2025-07-24 02:50:39 +02:00
Norbert Rittel
3f77c13aad
Fix spelling of "re-authenticate" in devolo_home_control (#149342) 2025-07-24 02:46:20 +02:00
Raphael Hehl
b966b59c09
Unifiprotect public api snapshot (#149213) 2025-07-23 13:37:34 -10:00
Michael
40cf47ae5a
Bump aioimmich to 0.11.1 (#149335)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-23 20:48:04 +02:00
Norbert Rittel
da8ce52ed7
Fix grammar issues in re-interview description of zwave_js (#149337) 2025-07-23 19:00:55 +01:00
Norbert Rittel
b5190788ac
Fix missing sentence-casing of "MAC address" in anthemav (#149333) 2025-07-23 19:29:31 +02:00
Norbert Rittel
bfa7ff3ede
Make spelling of "Telldus Live" consistent (#149332) 2025-07-23 19:07:40 +02:00
Norbert Rittel
1312e04c57
Fix typos in update_failed message of fritz (#149330) 2025-07-23 18:53:19 +02:00
Matthias Alphart
d3771571cd
Bump knx-frontend (#149287) 2025-07-23 17:18:41 +01:00
Norbert Rittel
5aa629edd0
Fix typo in "re-authentication" in devolo_home_network (#149312) 2025-07-23 17:16:00 +01:00
Norbert Rittel
3ed297676f
Remove third "s" from "Home Assistant" in lametric (#149329) 2025-07-23 18:08:01 +02:00
Norbert Rittel
d735af505e
Sentence-case "app" in laundrify (#149328) 2025-07-23 18:04:47 +02:00
Norbert Rittel
e337abb12d
Clarify setup description in google_travel_time (#149327) 2025-07-23 17:57:45 +02:00
Maciej Bieniek
45edd12f13
Bump imgw_pib to version 1.5.0 (#149324) 2025-07-23 16:51:24 +01:00
Ludovic BOUÉ
5b94f5a99a
Add more types in TYPE_MAP for Matter Cover (#149188) 2025-07-23 17:33:24 +02:00
Norbert Rittel
8b7295cd26
Fix three spelling issues in lg_thinq (#149322) 2025-07-23 17:16:28 +02:00
Marc Hörsken
15f7dade5e
Fix warning about failure to get action during setup phase (#148923) 2025-07-23 17:05:35 +02:00
Norbert Rittel
61807412c4
Fix typo "optimisic" in mqtt (#149291) 2025-07-23 16:03:12 +01:00
Norbert Rittel
f679f33c56
Fix description of current field of keba.set_current action (#149326) 2025-07-23 17:02:59 +02:00
Sid
2abd203580
Bump eheimdigital quality scale to platinum (#148263) 2025-07-23 16:58:18 +02:00
Avi Miller
ccd22ce0d5
Fix brightness_step and brightness_step_pct via lifx.set_state (#149217)
Signed-off-by: Avi Miller <me@dje.li>
2025-07-23 16:55:44 +02:00
AlCalzone
391b144033
Update Z-Wave LED entity name for ZWA-2 (#149323) 2025-07-23 16:55:00 +02:00
tronikos
b6db10340e
Update supported languages for Google Generative AI TTS and STT (#149154) 2025-07-23 16:54:06 +02:00
epenet
23b2936174
Replace RuntimeError with custom ServiceValidationError in Tuya (#149175) 2025-07-23 16:53:36 +02:00
Petro31
fad5f7a47b
Move optimistic platform logic to AbstractTemplateEntity base class (#149245) 2025-07-23 14:52:25 +01:00
Marius
58ddf4ea95
Add note about re-interviewing Z-Wave battery powered devices (#149300) 2025-07-23 15:40:09 +02:00
AlCalzone
22fa863984
Discover ZWA-2 LED as a configuration entity in Z-Wave (#149298) 2025-07-23 15:33:52 +02:00
Imeon-Energy
d9b25770ad
Remove sensors from Imeon Inverter (#148542)
Co-authored-by: TheBushBoy <theodavid@icloud.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-23 15:32:32 +02:00
Nick Kuiper
1c8ae8a21b
Add switches for blue current integration. (#146210) 2025-07-23 15:12:53 +02:00
Norbert Rittel
6d3872252b
Fix one inconsistent spelling of "AppArmor" in hassio (#149310) 2025-07-23 15:09:17 +02:00
epenet
4730c5b831
Add logging to Tuya for devices that cannot be supported (#149192)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-23 15:07:37 +02:00
Artur Pragacz
9a9f65dc36
Improve config flow tests in Onkyo (#149199) 2025-07-23 15:06:25 +02:00
G Johansson
7c83fd0bf9
Add twice_daily forecast to SMHI (#148882) 2025-07-23 15:05:39 +02:00
johanzander
70e03cdd4e
Implements coordinator pattern for Growatt component data fetching (#143373) 2025-07-23 15:05:19 +02:00
J. Nick Koston
4d5c1b139b
Consolidate REST sensor encoding tests using pytest parametrize (#149279)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-23 14:57:07 +02:00
Antoine Reversat
6dc5c9beb7
Add fan off mode to the supported fan modes to fujitsu_fglair (#149277) 2025-07-23 14:52:14 +02:00
Brett Adams
47611619db
Update Tesla OAuth Server in Tesla Fleet (#149280) 2025-07-23 14:45:50 +02:00
Norbert Rittel
2a0a31bff8
Capitalize "HEPA" as an abbreviation in matter (#149306) 2025-07-23 14:27:49 +02:00
Joost Lekkerkerker
dcf29d12a7
Migrate Ollama to has entity name (#149303) 2025-07-23 14:27:32 +02:00
Norbert Rittel
edf6166a9f
Fix spelling of "Domino's Pizza" in dominos (#149308) 2025-07-23 13:58:24 +02:00
Joost Lekkerkerker
eb8ca53a03
Migrate Anthropic to has entity name (#149302) 2025-07-23 12:58:28 +02:00
Joost Lekkerkerker
3dffd74607
Migrate OpenAI to has entity name (#149301) 2025-07-23 12:58:15 +02:00
Thomas55555
b37273ed33
Makes entites available in Husqvarna Automower when mower is in error state (#149261) 2025-07-23 12:39:17 +02:00
David Ferguson
232b34609c
Avoid hardcoded max core climate timeout in SleepIQ (#149283) 2025-07-23 12:37:47 +02:00
Norbert Rittel
aeeabfcae7
Fix typo "hazlenut" in miele (#149299) 2025-07-23 11:55:35 +02:00
Vincent Wolsink
52abab8ae8
Use translation_key for entities in Huum (#149256) 2025-07-23 11:28:28 +02:00
Artur Pragacz
7aa4810b0a
Clean up internal_get_tts_audio in TTS entity (#148946) 2025-07-23 11:26:54 +02:00
Norbert Rittel
c4d742f549
Add missing hyphen to "auto-renew period" in whois (#149296) 2025-07-23 12:01:19 +03:00
Raphael Hehl
51a46a128c
Begin migrating unifiprotect to use the public API (#149126)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-07-22 22:46:52 -10:00
Norbert Rittel
9a6ba225e4
Fix typo "paela" in miele (#149295) 2025-07-23 10:33:31 +02:00
Norbert Rittel
a5ab523014
Fix sentence-casing in tomorrowio (#149293) 2025-07-23 10:03:04 +02:00
Norbert Rittel
40571dff3d
Replace typo "effect" with "affect" in insteon (#149292) 2025-07-23 09:33:27 +02:00
J. Nick Koston
5f2f038609
Bump dbus-fast to 2.44.2 (#149281) 2025-07-23 08:14:41 +02:00
Matthias Alphart
9fd2ad425c
Refactor KNX UI conditional selectors and migrate store data (#146067)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-23 07:22:48 +02:00
Michael
2f6c0a1b7f
Bump aioimmich to 0.11.0 (#149272) 2025-07-23 00:30:23 +02:00
Artur Pragacz
dde73c05cb
Order selectors alphabetically in helper (#149269) 2025-07-22 23:06:51 +02:00
Michael
993b0bbdd7
Use absolute humidity device class in HomematicIP Cloud (#148905) 2025-07-22 22:51:03 +02:00
Raphael Hehl
45dbf3ef1a
Bump uiprotect to version 7.19.0 (#149266) 2025-07-22 22:50:55 +02:00
Paulus Schoutsen
71c1837f39
Update OpenAI title to drop "conversation" (#149263) 2025-07-22 22:43:02 +02:00
epenet
34eb99530f
Use translation_placeholders in tuya cover descriptions (#149248)
Co-authored-by: Simone Chemelli <simone.chemelli@gmail.com>
2025-07-22 22:21:59 +02:00
Thomas55555
55ac4d8855
Bump aioautomower to 2.0.1 (#149262) 2025-07-22 21:17:59 +02:00
epenet
ef3fb50018
Use translation_placeholders in tuya light descriptions (#149249) 2025-07-22 19:44:51 +02:00
epenet
316ac6253b
Use translation_placeholders in tuya number descriptions (#149250) 2025-07-22 19:06:14 +02:00
epenet
252a46d141
Use translation_placeholders in tuya select descriptions (#149251) 2025-07-22 19:05:54 +02:00
Álvaro Fernández Rojas
969ad232aa
Update aioairzone-cloud to v0.6.16 (#149254) 2025-07-22 17:23:38 +01:00
Martin Hjelmare
828a47db06
Add Z-Wave USB migration confirm step (#149243) 2025-07-22 17:09:11 +03:00
G Johansson
3947569132
Bump holidays to 0.77 (#149246) 2025-07-22 15:50:38 +02:00
Joakim Sørensen
e5f9788d24
Refactor cloud backup agent to use updated file handling methods (#149231) 2025-07-22 15:15:56 +02:00
Erik Montnemery
dd399ef59f
Refactor EntityPlatform (#147927) 2025-07-22 14:35:57 +02:00
wedsa5
5a771b501d
Fix ColorMode.WHITE support in Tuya (#126242)
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-22 14:07:34 +02:00
hahn-th
3f67ba4c02
Add support for ELV-SH-WSM to homematicip (#149098) 2025-07-22 14:06:03 +02:00
Joost Lekkerkerker
c075134845
Use OpenRouterClient to get the models (#148903) 2025-07-22 13:58:33 +02:00
Joost Lekkerkerker
e5c7e04329
Introduce base entity in Open Router (#148910) 2025-07-22 13:43:41 +02:00
Åke Strandberg
49807c9fbe
Add set_program service to Miele (#143442) 2025-07-22 13:33:03 +02:00
Norbert Rittel
e79d42ecfc
Add missing hyphen to "post-heater" in vallox (#149222) 2025-07-22 13:32:45 +02:00
dependabot[bot]
1f07dd7946
Bump github/codeql-action from 3.29.2 to 3.29.3 (#149220)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 13:07:56 +02:00
epenet
8d1c789ca2
Replace RuntimeError with TYPE_CHECKING in Tuya (#149227) 2025-07-22 12:10:23 +02:00
Bram Kragten
456f992b7e
2025.7.3 (#149024) 2025-07-22 10:30:09 +02:00
Artur Pragacz
f5d68a4ea4
Simplify getting domains to resolve in bootstrap (#145829) 2025-07-22 10:10:59 +02:00
Artur Pragacz
2315bcbfe3
Set has_entity_name in Onkyo (#149223) 2025-07-22 10:02:15 +02:00
Raphael Hehl
df4e1411cc
Bump uiprotect to version 7.18.1 (#149209) 2025-07-22 09:00:25 +02:00
Norbert Rittel
3e7974a638
Add missing hyphen to "post-processing" in nzbget (#149205) 2025-07-22 08:58:32 +02:00
David Ferguson
48b8827390
Bump asyncsleepiq to 1.5.3 (#149215) 2025-07-22 08:56:54 +02:00
hanwg
42cf4e8db7
Fix multiple webhook secrets for Telegram bot (#149103) 2025-07-22 07:42:40 +02:00
Ville Skyttä
ef2531d28d
Add diagnostics support to Huawei LTE (#131085)
Co-authored-by: abmantis <amfcalt@gmail.com>
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-21 21:52:48 +01:00
Vincent Wolsink
79dd91ebc6
Add sauna light control in Huum (#149169) 2025-07-21 22:52:24 +02:00
starkillerOG
ecb6cc50b9
Add Reolink post recording time select entity (#149201)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-21 21:48:02 +01:00
starkillerOG
b6014da121
Add Reolink wifi signal sensor for IPC cams (#149200) 2025-07-21 21:35:28 +02:00
Erik Montnemery
941d3c2be4
Improve integration sensor tests (#149180) 2025-07-21 18:23:58 +02:00
starkillerOG
7d895653fb
Bump reolink-aio to 0.14.3 (#149191) 2025-07-21 18:19:56 +02:00
Erik Montnemery
3bd70a4698
Improve derivative sensor tests (#149179) 2025-07-21 17:51:26 +02:00
Petro31
b85ec55abb
Add availability template to template helper config flow (#147623)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
Co-authored-by: Joostlek <joostlek@outlook.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-21 17:41:56 +02:00
Michael Hansen
3f42911af4
Add streaming to cloud TTS (#148925) 2025-07-21 10:33:23 -05:00
G Johansson
3c70932357
Use OptionsFlowWithReload in enphase_envoy (#149171) 2025-07-21 16:52:25 +02:00
Artur Pragacz
40252763d7
Switch to a new library in Onkyo (#148613) 2025-07-21 16:31:28 +02:00
G Johansson
80b96b0007
Use OptionsFlowWithReload in roku (#149172) 2025-07-21 15:40:30 +02:00
David Knowles
f3db3ba3c8
Bump pyschlage to 2025.7.3 (#149184) 2025-07-21 14:36:12 +01:00
Joakim Sørensen
102ef257a0
Bump hass-nabucasa from 0.107.1 to 0.108.0 (#149189) 2025-07-21 14:35:35 +01:00
Joost Lekkerkerker
2476e7e47c
Revert setting a user to download translations (#149190) 2025-07-21 15:27:29 +02:00
G Johansson
671523feb3
Use OptionsFlowWithReload in hyperion (#149163) 2025-07-21 14:52:14 +02:00
G Johansson
54fa4d635b
Use OptionsFlowWithReload in sonarr (#149166) 2025-07-21 14:51:48 +02:00
G Johansson
af0480f2a4
Use OptionsFlowWithReload in slide_local (#149168) 2025-07-21 14:51:33 +02:00
Ludovic BOUÉ
64f190749a
Add Demo Vacuum in entity name (#148629) 2025-07-21 14:39:42 +02:00
dependabot[bot]
6b489e0ab6
Bump sigstore/cosign-installer from 3.9.1 to 3.9.2 (#148985)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 14:34:12 +02:00
Norbert Rittel
1315095b4a
Make spelling of "devolo Home Network" consistent (#149165) 2025-07-21 14:16:03 +02:00
David Ferguson
2d86fa079e
SleepIQ add core climate for SleepNumber Climate 360 beds (#134718) 2025-07-21 14:14:33 +02:00
Paul Bottein
875219ccb5
Adds support for hide_states options in state selector (#148959) 2025-07-21 13:02:04 +01:00
Luuk Dobber
bc0162cf85
Add select for heating circuit to Tado zones (#147902)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-21 12:45:57 +01:00
Marc Mueller
d774de79db
Update types packages (#149178) 2025-07-21 13:33:04 +02:00
G Johansson
be25a7bc70
Use OptionsFlowWithReload in ezviz (#149167) 2025-07-21 13:24:15 +02:00
Marc Mueller
05566e1621
Update websockets pin (#149004) 2025-07-21 13:23:42 +02:00
Erik Montnemery
b59d8b5730
Improve statistics sensor tests (#149181) 2025-07-21 13:20:04 +02:00
dependabot[bot]
75a90ab568
Bump actions/ai-inference from 1.1.0 to 1.2.3 (#149159)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:11:22 +02:00
Erik Montnemery
67c68dedba
Make async_track_state_change/report_event listeners fire in order (#148766) 2025-07-21 13:07:52 +02:00
Marc Mueller
1fba61973d
Update pytest-asyncio to 1.1.0 (#149177) 2025-07-21 12:03:53 +01:00
Simon Lamon
bf1a660dcb
Bump Lokalise docker image to v2.6.14 (#149031) 2025-07-21 13:02:50 +02:00
G Johansson
94d077ea41
Use OptionsFlowWithReload in honeywell (#149162) 2025-07-21 12:47:38 +02:00
G Johansson
c22f65bd87
Use OptionsFlowWithReload in isy994 (#149174) 2025-07-21 12:47:24 +02:00
G Johansson
0dba32dbcd
Use OptionsFlowWithReload in keenetic_ndms2 (#149173) 2025-07-21 12:47:11 +02:00
Elmo-S
8c964e64db
Add support for UV index attribute in template weather entity (#149015) 2025-07-21 11:39:46 +01:00
epenet
c08aa74496
Cleanup Tuya climate/cover tests (#149157) 2025-07-21 12:27:37 +02:00
G Johansson
ff9fb6228b
Use OptionsFlowWithReload in onewire (#149164) 2025-07-21 11:14:02 +02:00
Joost Lekkerkerker
6eab118a2d
Bump airgradient to platinum (#149014) 2025-07-21 08:26:20 +02:00
G Johansson
c1e35cc9cf
Use OptionsFlowWithReload in androidtv_remote (#149133) 2025-07-21 08:18:40 +02:00
G Johansson
11dd2dc374
Use OptionsFlowWithReload in file (#149108) 2025-07-21 08:17:12 +02:00
G Johansson
00c4b09773
Use OptionsFlowWithReload in motioneye (#149130) 2025-07-21 08:15:51 +02:00
Joakim Plate
bc9ad5eac6
Add device class to gardena (#149144) 2025-07-21 08:15:32 +02:00
Michael
eca80a1645
Use OptionsFlowWithReload in Feedreader (#149134) 2025-07-21 07:27:02 +02:00
Michael
bd7cef92c7
Use OptionsFlowWithReload in Proximity (#149136) 2025-07-21 07:26:29 +02:00
David Knowles
27787e0679
Bump pyschlage to 2025.7.2 (#149148) 2025-07-21 07:25:45 +02:00
Raphael Hehl
0a9fbb215d
Bump uiprotect to version 7.16.0 (#149146) 2025-07-21 02:22:32 +02:00
G Johansson
77a954df9b
Use OptionsFlowWithReload in reolink (#149132) 2025-07-20 23:44:39 +02:00
G Johansson
61ca0b6b86
Use OptionsFlowWithReload in vodafone_station (#149131) 2025-07-20 23:18:00 +02:00
G Johansson
e3577de9d8
Use OptionsFlowWithReload in onkyo (#149093) 2025-07-20 23:17:43 +02:00
J. Nick Koston
b8d45fba24
Bump aioesphomeapi to 37.0.2 (#149143) 2025-07-20 10:53:09 -10:00
Vincent Wolsink
44fec53bac
Add binary_sensor for door status in Huum (#149135) 2025-07-20 22:50:53 +02:00
Raphael Hehl
ca48b9e375
Bump uiprotect to version 7.15.1 (#149124) 2025-07-20 08:41:49 -10:00
Abílio Costa
216e89dc5e
Add battery charging state icons to Reolink (#149125) 2025-07-20 14:50:17 +02:00
Norbert Rittel
72d5578128
Fix typo in #device-discovery-payload anchor link of mqtt (#149116) 2025-07-20 14:29:18 +02:00
Thorsten
e3bdd12dad
Add Bauknecht virtual integration (#146801) 2025-07-20 13:13:24 +01:00
G Johansson
43dc73c2e1
Use OptionsFlowWithReload in forecast_solar (#149112) 2025-07-20 13:09:07 +02:00
G Johansson
302b6f03ba
Use OptionsFlowWithReload in speedtest (#149111) 2025-07-20 13:08:42 +02:00
G Johansson
b31e17f1f9
Use OptionsFlowWithReload in met (#149115) 2025-07-20 13:07:46 +02:00
G Johansson
1b8f3348b0
Use OptionsFlowWithReload in roborock (#149118) 2025-07-20 13:06:59 +02:00
G Johansson
0d42b24467
Use OptionsFlowWithReload in jewish_calendar (#149121) 2025-07-20 13:05:39 +02:00
G Johansson
0c858de1af
Use OptionsFlowWithReload in lamarzocco (#149119) 2025-07-20 12:31:18 +02:00
G Johansson
5d653d46c3
Remove not used config entry update listener from nut (#149096) 2025-07-20 12:30:22 +02:00
G Johansson
b262a5c9b6
Use OptionsFlowWithReload in lastfm (#149113) 2025-07-20 12:05:24 +02:00
G Johansson
ead99c549f
Use OptionsFlowWithReload in denonavr (#149109) 2025-07-20 11:12:51 +02:00
G Johansson
1a6bfc0310
Use OptionsFlowWithReload in knx (#149097) 2025-07-20 10:17:09 +02:00
hahn-th
507f29a209
Bump homematicip to 2.2.0 (#149038) 2025-07-19 21:12:49 +02:00
G Johansson
d796ab8fe7
Use OptionsFlowWithReload in kitchen_sink (#149091) 2025-07-19 21:12:17 +02:00
G Johansson
d35dca377f
Use OptionsFlowWithReload in purpleair (#149095) 2025-07-19 21:11:15 +02:00
Michael
96766fc62a
Use OptionsFlowWithReload in Synology DSM (#149086) 2025-07-19 21:08:37 +02:00
G Johansson
afbb0ee2f4
Use OptionsFlowWithReload in github (#149089) 2025-07-19 21:07:55 +02:00
G Johansson
e885ae1b15
Use OptionsFlowWithReload in holiday (#149090) 2025-07-19 21:07:23 +02:00
G Johansson
51d38f8f05
Use OptionsFlowWithReload in emoncms (#149094) 2025-07-19 21:06:14 +02:00
peteS-UK
be644ca96e
Add type to coordinator for Squeezebox (#149087) 2025-07-19 20:39:22 +02:00
Michael
d266b6f6ab
Use OptionsFlowWithReload in AVM Fritz!Box Tools (#149085) 2025-07-19 20:08:20 +02:00
G Johansson
dbdc666a92
Use OptionsFlowWithReload in control4 (#149058) 2025-07-19 19:51:01 +02:00
Allen Porter
2577d9f108
Fix a bug in rainbird device migration that results in additional devices (#149078) 2025-07-19 19:49:14 +02:00
peteS-UK
7dfb54c8e8
Paramaterize test for on/off for Squeezebox (#149048) 2025-07-19 19:30:40 +02:00
peteS-UK
a50d926e2a
Check for error in test_squeezebox_play_media_with_announce_volume_invalid for Squeezebox (#149044) 2025-07-19 19:30:15 +02:00
peteS-UK
0cfb395ab5
Remove unnecessary getattr from init for Squeezebox (#149077) 2025-07-19 19:20:11 +02:00
peteS-UK
b3f049676d
Move Squeezebox registry tests to test_init (#149050) 2025-07-19 19:17:34 +02:00
G Johansson
7e04a7ec19
Use OptionsFlowWithReload in unifiprotect (#149064) 2025-07-19 17:40:16 +02:00
G Johansson
c15bf097f0
Use OptionsFlowWithReload in airnow (#149049) 2025-07-19 16:50:41 +02:00
G Johansson
dba3d98a2b
Use OptionsFlowWithReload in xiaomi_miio (#149051) 2025-07-19 16:50:13 +02:00
G Johansson
4a5e193ebb
Use OptionsFlowWithReload in ws66i (#149052) 2025-07-19 16:49:19 +02:00
G Johansson
1bbd07fe48
Use OptionsFlowWithReload in wiffi (#149053) 2025-07-19 16:48:53 +02:00
G Johansson
b9d19ffb29
Use OptionsFlowWithReload in vera (#149055) 2025-07-19 16:48:23 +02:00
G Johansson
22b35030a9
Use OptionsFlowWithReload in analytics_insight (#149056) 2025-07-19 16:47:09 +02:00
G Johansson
69c26e5f1f
Use OptionsFlowWithReload in dnsip (#149059) 2025-07-19 16:46:30 +02:00
G Johansson
cb4d17b24f
Use OptionsFlowWithReload in Ping (#149061) 2025-07-19 16:45:39 +02:00
G Johansson
ff14f6b823
Use OptionsFlowWithReload in somfy_mylink (#149062) 2025-07-19 16:44:51 +02:00
G Johansson
ab964c8bca
Use OptionsFlowWithReload in tankerkoenig (#149063) 2025-07-19 16:43:49 +02:00
peteS-UK
05f686cb86
Update comments in 3 Squeezebox platforms (#149065) 2025-07-19 16:42:21 +02:00
G Johansson
440a20340e
Use OptionsFlowWithReload in nobo_hub (#149066) 2025-07-19 16:41:38 +02:00
G Johansson
676a931c48
Use OptionsFlowWithReload in nmap_tracker (#149067) 2025-07-19 16:40:57 +02:00
G Johansson
360da43868
Use OptionsFlowWithReload in nina (#149068) 2025-07-19 16:40:32 +02:00
Marc Mueller
12193587c9
Use OptionsFlowWithReload in fritzbox_callmonitor (#149071) 2025-07-19 16:39:38 +02:00
G Johansson
290f19dbd9
Use OptionsFlowWithReload in motion_blinds (#149070) 2025-07-19 16:38:28 +02:00
G Johansson
13434012e7
Use OptionsFlowWithReload in netgear (#149069) 2025-07-19 16:37:37 +02:00
peteS-UK
7202203f35
Update bool test in coordinator platform for Squeezebox (#149073) 2025-07-19 16:33:34 +02:00
G Johansson
31167f5da7
Use OptionsFlowWithReload in webostv (#149054) 2025-07-19 16:16:56 +03:00
G Johansson
665991a3c1
Use OptionsFlowWithReload in wled (#149046) 2025-07-19 13:27:46 +01:00
G Johansson
8a2493e9d2
Use OptionsFlowWithReload in Workday (#149043) 2025-07-19 13:26:54 +01:00
G Johansson
be6743d4fd
Use OptionsFlowWithReload in yale_smart_alarm (#149040) 2025-07-19 13:14:38 +01:00
G Johansson
284b90d502
Use OptionsFlowWithReload in yeelight (#149045) 2025-07-19 13:14:13 +01:00
G Johansson
d7d2013ec8
Use OptionsFlowWithReload in sql (#149047) 2025-07-19 13:12:25 +01:00
G Johansson
b3bd882a80
Use OptionsFlowWithReload in Trafikverket Train (#149042) 2025-07-19 13:09:54 +01:00
J. Nick Koston
3a6f23b95f
Bump aioesphomeapi to 37.0.1 (#149035) 2025-07-19 12:53:51 +01:00
G Johansson
6f59aaebdd
Add extended class for OptionsFlow that automatically reloads (#146910)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-19 13:14:20 +02:00
Allen Porter
f90e06fde1
Add attachment support in ollama ai task (#148981) 2025-07-19 07:27:48 +02:00
Paul Bottein
380c737901
Add reorder option to entity selector (#149002) 2025-07-18 19:41:59 +01:00
Petro31
33cc257e75
Consolidate template integration's config schemas (#149018) 2025-07-18 19:38:53 +01:00
Franck Nijhof
3877a6211a
Ensure Lokalise download runs as the same user as GitHub Actions (#149026) 2025-07-18 19:56:19 +02:00
J. Nick Koston
916b4368dd
Bump aioesphomeapi to 36.0.1 (#148991) 2025-07-18 07:30:34 -10:00
Franck Nijhof
0675e34c62
Bump version to 2025.7.3 2025-07-18 17:05:52 +00:00
Simone Chemelli
190c98f5a8
Bump aioamazondevices to 3.5.0 (#149011) 2025-07-18 17:04:01 +00:00
Jan Bouwhuis
c6bb26be89
Ignore MQTT sensor unit of measurement if it is an empty string (#149006) 2025-07-18 17:02:02 +00:00
J. Nick Koston
d57c5ffa8f
Bump PySwitchbot to 0.68.2 (#148996) 2025-07-18 17:02:01 +00:00
Bram Kragten
68889e1790
Update frontend to 20250702.3 (#148994) 2025-07-18 17:02:00 +00:00
Joost Lekkerkerker
8fdc50a29f
Pass Syncthru entry to coordinator (#148974) 2025-07-18 17:01:58 +00:00
Steven Looman
5656b4c20d
Bump async-upnp-client to 0.45.0 (#148961) 2025-07-18 17:01:57 +00:00
Maciej Bieniek
b6edcc9422
Bump gios to version 6.1.2 (#148884) 2025-07-18 17:01:56 +00:00
Maciej Bieniek
7a3eb53453
Bump gios to version 6.1.1 (#148414) 2025-07-18 17:01:54 +00:00
Arie Catsman
11a2c73e8a
Bump pyenphase to 2.2.2 (#148870) 2025-07-18 17:00:32 +00:00
Brett Adams
1644484c92
Fix button platform parent class in Teslemetry (#148863) 2025-07-18 17:00:30 +00:00
Pete Sage
8e0a89dc2f
Add guard to prevent exception in Sonos Favorites (#148854) 2025-07-18 17:00:29 +00:00
Robert Resch
9e4b8df344
Use ffmpeg for generic cameras in go2rtc (#148818) 2025-07-18 17:00:28 +00:00
Brett Adams
69fdc1d269
Bump Tesla Fleet API to 1.2.2 (#148776) 2025-07-18 17:00:26 +00:00
Joost Lekkerkerker
56e0aa103d
Bump pySmartThings to 3.2.8 (#148761) 2025-07-18 17:00:25 +00:00
Maciej Bieniek
caf0492009
Fix Shelly n_current sensor removal condition (#148740) 2025-07-18 17:00:24 +00:00
hahn-th
c6d0aad3d3
Handle connection issues after websocket reconnected in homematicip_cloud (#147731) 2025-07-18 17:00:22 +00:00
Jan Bouwhuis
4c99fe9ae5
Ignore MQTT sensor unit of measurement if it is an empty string (#149006) 2025-07-18 18:57:03 +02:00
Marc Mueller
353b573707
Update bluecurrent-api to 1.2.4 (#149005) 2025-07-18 15:43:43 +02:00
Maciej Bieniek
109663f177
Bump imgw_pib to version 1.4.2 (#149009) 2025-07-18 15:36:17 +02:00
Simone Chemelli
3b89b2cbbe
Bump aioamazondevices to 3.5.0 (#149011) 2025-07-18 15:35:38 +02:00
Abílio Costa
29d0d6cd43
Add top-level target support to trigger schema (#148894) 2025-07-18 14:32:16 +01:00
Erik Montnemery
1743766d17
Add last_reported to state reported event data (#148932) 2025-07-18 13:53:30 +02:00
G Johansson
277241c4d3
Adjust ManualTriggerSensorEntity to handle timestamp device classes (#145909) 2025-07-18 13:49:12 +02:00
Bram Kragten
17034f4d6a
Update frontend to 20250702.3 (#148994) 2025-07-18 13:15:55 +02:00
Thomas55555
ec544b0430
Mark entities as unavailable when they don't have a value in Husqvarna Automower (#148563) 2025-07-18 12:49:50 +02:00
Marc Mueller
75c803e376
Update pysmarlaapi to 0.9.1 (#149001) 2025-07-18 12:48:39 +02:00
J. Nick Koston
a96e31f1d8
Bump PySwitchbot to 0.68.2 (#148996) 2025-07-18 12:48:09 +02:00
c0ffeeca7
43a30fad96
Home Assistant Cloud: fix capitalization (#148992) 2025-07-18 12:19:33 +02:00
Petar Petrov
39d323186f
Disable "last seen" Z-Wave entity by default (#148987) 2025-07-18 09:53:47 +02:00
karwosts
57c024449c
Fix broken invalid_config tests (#148965) 2025-07-18 09:02:44 +02:00
Manu
414057d455
Add image platform to PlayStation Network (#148928) 2025-07-18 08:33:30 +02:00
Joost Lekkerkerker
50688bbd69
Add support for calling tools in Open Router (#148881) 2025-07-18 05:49:27 +02:00
Álvaro Fernández Rojas
073ea813f0
Update aioairzone-cloud to v0.6.15 (#148947) 2025-07-17 23:08:45 +01:00
Vincent Wolsink
6b959f42f6
Introduce base entity for supporting multiple platforms in Huum (#148957) 2025-07-17 23:06:51 +01:00
Joost Lekkerkerker
0ff0902ccf
Add icons to WAQI (#148976) 2025-07-17 22:36:18 +01:00
Joost Lekkerkerker
37a154b1df
Migrate WAQI to runtime data (#148977) 2025-07-17 23:22:30 +02:00
Petro31
3c87a3e892
Add a preview to template config flow for alarm control panel, image, and select platforms (#148441) 2025-07-17 22:19:45 +01:00
Joost Lekkerkerker
aacaa9a20f
Pass Syncthru entry to coordinator (#148974) 2025-07-18 00:14:19 +03:00
Joost Lekkerkerker
c074453763
Remove obsolete variables in WAQI (#148975) 2025-07-18 00:13:46 +03:00
Jan Bouwhuis
29afa891ec
Add YAML and discovery info export feature for MQTT device subentries (#141896)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-17 23:06:47 +02:00
Steven Looman
3b6eb045c6
Bump async-upnp-client to 0.45.0 (#148961) 2025-07-17 21:19:47 +02:00
Joost Lekkerkerker
0d819f2389
Refactor WAQI tests (#148968) 2025-07-17 20:30:40 +02:00
Joakim Sørensen
9802441fea
Bump hass-nabucasa from 0.106.0 to 0.107.1 (#148949) 2025-07-17 18:47:00 +01:00
Joakim Plate
fb13c8f4f2
Update arcam to 1.8.2 (#148956) 2025-07-17 18:34:58 +01:00
AlCalzone
a96e38871f
Z-Wave JS: Simplify strings for RSSI sensors (#148936) 2025-07-17 18:49:34 +03:00
Vincent Wolsink
17920b6ec3
Use climate min/max temp from sauna configuration in Huum (#148955) 2025-07-17 15:34:15 +01:00
karwosts
40cabc8d70
Validate min/max for input_text config (#148909) 2025-07-17 16:27:41 +02:00
AlCalzone
b33a556ca5
Bump zwave-js-server-python to 0.66.0 (#148939)
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
2025-07-17 16:20:03 +03:00
Marc Mueller
9df97fb2e2
Add correct labels for dependabot PRs (#148944) 2025-07-17 12:31:55 +02:00
Erik Montnemery
ee35fc495d
Improve derivative sensor tests (#148941) 2025-07-17 11:44:37 +02:00
Vincent Wolsink
9373bb287c
Huum - Introduce coordinator to support multiple platforms (#148889)
Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-07-17 11:43:26 +02:00
Erik Montnemery
d72fb021c1
Improve statistics tests (#148937) 2025-07-17 11:42:25 +02:00
Erik Montnemery
0e6a1e3242
Improve integration sensor tests (#148938)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2025-07-17 11:41:39 +02:00
asafhas
79b8e74d87
Add numbers configuration to Tuya alarm (#148907) 2025-07-17 11:26:33 +02:00
Aidan Timson
72d1c3cfc8
Fix Tuya support for climate fan modes which use "windspeed" function (#148646)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2025-07-17 09:47:54 +02:00
AlCalzone
3d278b626a
Z-Wave JS: Add statistics sensors for channel 3 background RSSI (#148899) 2025-07-17 09:19:44 +02:00
Joakim Plate
5383ff96ef
Make sure gardena bluetooth mock unload if it mocks load (#148920) 2025-07-17 09:00:44 +02:00
epenet
a0991134c4
Rename tuya fixture file to match category (#148892) 2025-07-17 08:59:34 +02:00
Jan-Philipp Benecke
9def44dca4
Bump inexogy quality scale to platinum (#148908) 2025-07-17 08:58:53 +02:00
Joris Pelgröm
656822b39c
Bump letpot to 0.5.0 (#148922) 2025-07-17 08:57:11 +02:00
epenet
ae03fc2295
Fix missing unit of measurement in tuya numbers (#148924) 2025-07-17 08:55:47 +02:00
Abílio Costa
e32e06d7a0
Fix Husqvarna Automower coordinator listener list mutating (#148926) 2025-07-17 08:52:59 +02:00
Artur Pragacz
6dc2340c5a
Fix docstring for WaitIntegrationOnboardingView (#148904) 2025-07-16 23:15:45 +01:00
Thomas55555
83cd2dfef3
Bump aioautomower to 2.0.0 (#148846) 2025-07-16 22:12:35 +02:00
Franck Nijhof
a5c301db1b
Add code review guidelines to exclude imports and formatting feedback (#148912) 2025-07-16 21:55:37 +02:00
Norbert Rittel
5b41d5a795
Fix typo "barametric" in rainmachine (#148917) 2025-07-16 21:50:29 +02:00
Michael
9d178ad5f1
Deprecate the usage of ContextVar for config_entry in coordinator (#138161) 2025-07-16 21:45:22 +02:00
Franck Nijhof
e8fca19335
Fix flaky husqvarna_automower test with comprehensive race condition fix (#148911)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-16 21:40:44 +02:00
Joost Lekkerkerker
58bb2fa327
Bump python-open-router to 0.3.0 (#148900) 2025-07-16 18:51:52 +02:00
epenet
fca05f6bcf
Add snapshot tests for tuya dj category (#148897) 2025-07-16 18:34:28 +02:00
Joost Lekkerkerker
a5f0f6c8b9
Add prompt as constant and common translation key (#148896) 2025-07-16 18:23:38 +02:00
Artur Pragacz
e2340314c6
Do not allow filters for services with no target in hassfest (#148869) 2025-07-16 17:40:35 +02:00
Erik Montnemery
aab6cd665f
Fix flaky notify group test (#148895) 2025-07-16 17:06:35 +02:00
Paulus Schoutsen
1734b316d5
Return intent response from LLM chat log if available (#148522) 2025-07-16 16:16:01 +02:00
Maciej Bieniek
3449863eee
Bump gios to version 6.1.2 (#148884) 2025-07-16 15:49:02 +02:00
Manu
b68de0af88
Change deprecated media_player state standby to off in PlayStation Network (#148885) 2025-07-16 15:48:39 +02:00
Artur Pragacz
840e0d1388
Clean up ModuleWrapper from loader (#148488) 2025-07-16 15:19:22 +02:00
Joost Lekkerkerker
412035b970
Add devices to OpenRouter (#148888) 2025-07-16 15:07:53 +02:00
Denis Shulyaka
3e465da892
Add Code Interpreter tool for OpenAI Conversation (#148383) 2025-07-16 14:52:53 +02:00
Marc Mueller
0d79f7db51
Update mypy-dev to 1.18.0a2 (#148880) 2025-07-16 14:43:55 +02:00
Erik Montnemery
62e3802ff2
Deprecate MediaPlayerState.STANDBY (#148151)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-16 14:22:42 +02:00
tronikos
02a11638b3
Add Google AI STT (#147563) 2025-07-16 14:11:29 +02:00
Josef Zweck
26a9af7371
Add search functionality to jellyfin (#148822) 2025-07-16 13:26:46 +02:00
epenet
e28f02d163
Add initial support for tuya qccdz (#148874) 2025-07-16 12:28:18 +02:00
G Johansson
a6828898d1
Add sensor platform to SMHI (#139295) 2025-07-16 12:25:10 +02:00
Paulus Schoutsen
29e105b0ef
Set default mode for number selector to box (#148773) 2025-07-16 11:19:31 +01:00
Maciej Bieniek
ce4a811b96
Add hydrological alert sensor to IMGW-PIB integration (#148848) 2025-07-16 10:55:50 +01:00
Arie Catsman
fe8384719d
Bump pyenphase to 2.2.2 (#148870) 2025-07-15 23:18:14 -10:00
Joost Lekkerkerker
a57d48fd31
Add OpenRouter integration (#143098) 2025-07-16 10:55:28 +02:00
Thomas55555
8a73511b02
Add inactive reason sensor to Husqvarna Automower (#147684) 2025-07-16 10:44:04 +02:00
epenet
033d8b3dfb
Add snapshot tests for tuya co2bj and gyd categories (#148872) 2025-07-16 10:38:43 +02:00
epenet
6833bf1900
Add battery status and configuration entities to Tuya thermostat (wk) (#148821) 2025-07-16 10:15:44 +02:00
Brett Adams
84e3dac406
Update vehicle type handling in Teslemetry (#148862) 2025-07-16 10:05:17 +02:00
epenet
bafd342d5d
Add initial support for tuya cwjwq (#148420) 2025-07-16 09:54:44 +02:00
epenet
fae6b375cd
Fix incorrectly rejected device classes in tuya (#148596) 2025-07-16 09:39:22 +02:00
epenet
d8de6e34dd
Add support for Tuya ks category (tower fan) (#148811) 2025-07-16 09:24:20 +02:00
Artur Pragacz
9db5b0b3b7
Validate selectors in the service helper (#148857) 2025-07-16 08:51:16 +02:00
Brett Adams
bcec29763f
Fix button platform parent class in Teslemetry (#148863) 2025-07-16 08:16:36 +02:00
epenet
27ad459ae0
Add tuya snapshots for more humidifiers (cs category) (#148797) 2025-07-16 08:11:55 +02:00
hahn-th
9c933ef01f
Add support for HmIPW-DRBL4 in homematicip_cloud (#148844) 2025-07-16 08:10:56 +02:00
Norbert Rittel
2011e64390
Different fixes in user-facing strings of nasweb (#148830) 2025-07-16 08:10:29 +02:00
Brett Adams
ffc2b0a8cf
Add mock for listen in Teslemetry tests (#148853) 2025-07-16 08:09:54 +02:00
Pete Sage
549069e22c
Add guard to prevent exception in Sonos Favorites (#148854) 2025-07-16 08:09:24 +02:00
Jan-Philipp Benecke
57e4270b7b
Make exceptions translatable in inexogy integration (#148865) 2025-07-16 08:06:49 +02:00
Maciej Bieniek
38e4e18f60
Bump IMGW-PIB to version 1.4.1 (#148849) 2025-07-16 00:41:56 +01:00
Robert Resch
7f2a32d4eb
Remove not needed go2rtc stream config (#148836) 2025-07-15 22:11:55 +01:00
Manu
d46e0e132b
Add reconfigure flow to Uptime Kuma (#148833) 2025-07-15 22:46:37 +02:00
Álvaro Fernández Rojas
828f0f8b26
Update aioairzone-cloud to v0.6.14 (#148820) 2025-07-15 22:43:40 +02:00
Erik Montnemery
849a25e3cc
Handle changes to source entities in mold_indicator helper (#148823)
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2025-07-15 22:19:32 +02:00
Erik Montnemery
3cb579d585
Do not add statistics config entry to source device (#148731) 2025-07-15 22:13:26 +02:00
Erik Montnemery
381bd489d8
Do not add template config entry to source device (#148756) 2025-07-15 22:13:03 +02:00
Marc Mueller
f5b785acd5
Update youtubeaio to 2.0.0 (#148814) 2025-07-15 20:44:32 +02:00
Manu
648dce2fa3
Add diagnostics platform to Uptime Kuma (#148835) 2025-07-15 20:19:14 +02:00
Manu
d14a0e0191
Bump pythonkuma to v0.3.1 (#148834) 2025-07-15 20:18:47 +02:00
Maciej Bieniek
9caf46c68b
Bump imgw_pib library to version 1.4.0 (#148831) 2025-07-15 20:17:54 +02:00
Artur Pragacz
e89ae021d8
Clean up validate_supported_features in selector helper (#148843) 2025-07-15 20:10:16 +02:00
Marc Mueller
36156d9c54
Update orjson to 3.11.0 (#148840) 2025-07-15 19:43:44 +02:00
Artur Pragacz
3e0628cec2
Fix entity and device selectors (#148580) 2025-07-15 18:58:42 +02:00
Robert Resch
8bd51a7fd1
Use ffmpeg for generic cameras in go2rtc (#148818) 2025-07-15 16:38:19 +01:00
Paul Bottein
5b29d6bbdf
Set icon for off state for light domain (#148749) 2025-07-15 16:25:22 +01:00
karwosts
2c2ac4b669
Throw an error from reload_themes if themes are invalid (#148827)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-15 17:08:19 +02:00
Petro31
35097602d7
Remove unnecessary hass if check in AbstractTemplateEntity (#148828) 2025-07-15 17:04:31 +02:00
Petro31
e5fe243a86
Remove device id references from button and image (#148826) 2025-07-15 17:03:47 +02:00
Manu
fd10fa1fba
Add reauthentication flow to Uptime Kuma (#148772) 2025-07-15 16:49:08 +02:00
Myles Eftos
087a938a7d
Add forecast service to amberelectric (#144848)
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2025-07-15 16:32:59 +02:00
Petro31
c058561162
Add initalize for abstract template entities (#147504) 2025-07-15 15:53:01 +02:00
epenet
b89b248b4c
Add tuya snapshots for qxj category (#148802) 2025-07-15 14:18:14 +02:00
Samuel Xiao
cd94685b7d
Add Fan platform to Switchbot cloud (#148304)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-15 13:55:13 +02:00
Matrix
0acfb81d50
Clean up YoLink entities on startup (#148718) 2025-07-15 13:53:29 +02:00
Andrea Turri
7d06aec8da
Discovery of Miele temperature sensors (#144585)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-15 12:50:28 +02:00
Åke Strandberg
ee4325a927
Replace deprecated battery property on Miele vacuum with sensor (#148765) 2025-07-15 11:40:48 +01:00
Alex Leversen
c7aadcdd20
Add file name/size sensors to OctoPrint integration (#148636) 2025-07-15 12:35:20 +02:00
wuede
8256401f7f
expose schedule id as an extra state attribute in Netatmo (#147076) 2025-07-15 12:16:59 +02:00
hahn-th
ab187f39c2
Add support for HmIP-RGBW and HmIP-LSC in homematicip_cloud integration (#148639) 2025-07-15 12:16:07 +02:00
hahn-th
1cb278966c
Handle connection issues after websocket reconnected in homematicip_cloud (#147731) 2025-07-15 12:15:19 +02:00
Josef Zweck
b522bd5ef2
Get media player features elsewhere for jellyfin (#148805) 2025-07-15 12:07:57 +02:00
Álvaro Fernández Rojas
a6e1d96852
Update aioairzone-cloud to v0.6.13 (#148798)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2025-07-15 11:21:54 +02:00
Marc Mueller
3d74d02704
Update pytouchlinesl to 0.4.0 (#148801) 2025-07-15 11:15:06 +02:00
Artur Pragacz
db45f46c8a
Fan support in WiZ (#146440) 2025-07-15 11:14:47 +02:00
ehendrix23
4f938d032d
Bump elevenlabs to 2.3.0 (#147224) 2025-07-15 10:45:55 +02:00
nasWebio
e1f15dac39
Add Sensor platform to NASweb integration (#133063)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-15 10:39:53 +02:00
epenet
41e261096a
Use suggested unit of measurement in Tuya (#148599) 2025-07-15 10:34:16 +02:00
Max Velitchko
f6aa4aa788
Bump amcrest to 1.9.9 (#148769) 2025-07-15 10:14:26 +02:00
Brett Adams
7d7767c93a
Bump Tesla Fleet API to 1.2.2 (#148776) 2025-07-15 09:21:00 +02:00
J. Nick Koston
5e883cfb12
Fix flaky nuki tests by preventing teardown race condition (#148795) 2025-07-14 21:03:49 -10:00
Paulus Schoutsen
e2cc51f21d
Allow AI Task to handle camera attachments (#148753) 2025-07-15 08:51:08 +02:00
Petro31
816977dd75
Refactor async_setup_platform for template platforms (#147379) 2025-07-15 08:26:34 +02:00
kingy444
a81e83cb28
Manually register powerview hub (#146709)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-14 22:38:01 +01:00
Maciej Bieniek
c476500c49
Fix Shelly n_current sensor removal condition (#148740) 2025-07-14 23:40:46 +03:00
Matthias Alphart
f65fa38429
Add reconfigure flow for KNX (#145067)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-14 21:49:52 +02:00
Manu
66641356cc
Add Uptime Kuma integration (#146393) 2025-07-14 21:35:57 +02:00
Willem-Jan van Rootselaar
37ae476c67
Add Zeroconf support for bsblan integration (#146137)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-14 21:26:03 +02:00
Manu
5ec9c4e6e3
Add PS Vita support to PlayStation Network integration (#148186) 2025-07-14 21:24:50 +02:00
Marc Mueller
80eb4fb2f6
Replace asyncio.iscoroutinefunction (#148738) 2025-07-14 20:24:32 +01:00
Joost Lekkerkerker
9e3a78b7ef
Bump pySmartThings to 3.2.8 (#148761) 2025-07-14 20:18:12 +01:00
hahn-th
c08c402409
Add switches for HmIPW-DRI16, HmIPW-DRI32, HmIPW-DRS4, HmIPW-DRS8 (#148571) 2025-07-14 21:16:29 +02:00
Vincent Wolsink
d42d270fb2
Bump Huum to version 0.8.0 (#148763) 2025-07-14 20:16:26 +01:00
fwestenberg
9068a09620
Add Stookwijzer forecast service (#138392)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-14 21:08:16 +02:00
Stephan Traub
1ef07544d5
Fix for ignored devices issue #137114 (#146562) 2025-07-14 21:07:47 +02:00
Erik Montnemery
ed4a23d104
Override connect method in RecorderPool (#148490) 2025-07-14 20:57:00 +02:00
peteS-UK
0729b3a2f1
Change hass.data storage to runtime.data for Squeezebox (#146482) 2025-07-14 20:53:53 +02:00
Manu
c9356868f7
Add add-on discovery flow to pyLoad integration (#148494) 2025-07-14 19:29:57 +01:00
Abílio Costa
1753baf186
Add method to track entity state changes from target selectors (#148086)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-14 19:28:53 +01:00
Petro31
8421ca7802
Add assumed optimistic state to template select (#148513) 2025-07-14 19:28:27 +01:00
Paulus Schoutsen
124931b2ee
TTS to always stream when available (#148695)
Co-authored-by: Michael Hansen <mike@rhasspy.org>
2025-07-14 20:23:43 +02:00
Erik Montnemery
c27a67db82
Do not add integration config entry to source device (#148730) 2025-07-14 20:18:41 +02:00
Erik Montnemery
3ae9ea3f19
Do not add generic_thermostat config entry to source device (#148728) 2025-07-14 20:18:21 +02:00
Erik Montnemery
e35f7b12f1
Do not add generic_hygrostat config entry to source device (#148727) 2025-07-14 20:18:11 +02:00
Erik Montnemery
1a1e9e9f57
Add test for combining state change and state report listeners (#148721) 2025-07-14 20:15:39 +02:00
Erik Montnemery
254f766357
Do not add history_stats config entry to source device (#148729) 2025-07-14 20:05:34 +02:00
Erik Montnemery
7df0016fab
Do not add threshold config entry to source device (#148732) 2025-07-14 20:05:20 +02:00
Erik Montnemery
57f89dd606
Do not add trend config entry to source device (#148733) 2025-07-14 20:00:49 +02:00
Erik Montnemery
92bb1f2551
Do not add utility_meter config entry to source device (#148735) 2025-07-14 20:00:21 +02:00
kanshurichard
f680e992ff
Add support for Broadlink A2 air quality sensor (#142203)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-14 19:07:50 +02:00
Thomas55555
f08d1e547f
Fix adding a work area in Husqvarna Automower (#148358) 2025-07-14 19:04:00 +02:00
Tsvi Mostovicz
9e022ad75e
Quality fixes for Jewish Calendar (#148689) 2025-07-14 17:44:11 +02:00
Paulus Schoutsen
14ff04200e
Make AI Task instructions multiline (#148606) 2025-07-14 15:24:44 +01:00
Michael
5e4ce46dae
Use absolute humidity device class in Airq (#148568) 2025-07-14 14:38:33 +02:00
Erik Montnemery
155fc134b6
Do not add derivative config entry to source device (#148674)
Co-authored-by: Artur Pragacz <49985303+arturpragacz@users.noreply.github.com>
2025-07-14 13:33:00 +02:00
Franck Nijhof
1f59b735c6
2025.7.2 (#148725) 2025-07-14 13:12:29 +02:00
Franck Nijhof
87af9fc8ba
Bump version to 2025.7.2 2025-07-14 10:30:35 +00:00
Simone Chemelli
691a0ca065
Bump aioamazondevices to 3.2.10 (#148709) 2025-07-14 10:27:45 +00:00
Shay Levy
80384b89a5
Bump aioshelly to 13.7.2 (#148706) 2025-07-14 10:25:24 +00:00
Jan Bouwhuis
f7672985ed
Fix hide empty sections in mqtt subentry flows (#148692) 2025-07-14 10:25:23 +00:00
Christopher Fenner
d4374dbcc7
Bump PyViCare to 2.50.0 (#148679) 2025-07-14 10:25:22 +00:00
Brett Adams
c4ddcd64c8
Fix Charge Cable binary sensor in Teslemetry (#148675) 2025-07-14 10:25:21 +00:00
0xEF
c802430066
Bump nyt_games to 0.5.0 (#148654) 2025-07-14 10:25:20 +00:00
falconindy
649fbfc729
snoo: use correct value for right safety clip binary sensor (#148647) 2025-07-14 10:25:18 +00:00
Jan Bouwhuis
80c52ad8ea
Fix - only enable AlexaModeController if at least one mode is offered (#148614) 2025-07-14 10:25:17 +00:00
Lưu Quang Vũ
150d4716fa
Fix Google Cloud 504 Deadline Exceeded (#148589) 2025-07-14 10:25:16 +00:00
Bram Kragten
dc2736580f
Update frontend to 20250702.2 (#148573) 2025-07-14 10:25:15 +00:00
J. Nick Koston
f1272ef513
Bump aiohttp to 3.12.14 (#148565) 2025-07-14 10:25:14 +00:00
Åke Strandberg
3c2fa023b4
Remove vg argument from miele auth flow (#148541) 2025-07-14 10:25:12 +00:00
Kristof Mariën
5cf5be8c9c
Fix for Renson set Breeze fan speed (#148537) 2025-07-14 10:25:11 +00:00
Jan-Philipp Benecke
63b21fda1a
Ensure response is fully read to prevent premature connection closure in rest command (#148532) 2025-07-14 10:25:10 +00:00
J. Diego Rodríguez Royo
d87379d083
Use the link to the issue instead of creating new issues at Home Connect (#148523) 2025-07-14 10:25:09 +00:00
J. Diego Rodríguez Royo
0990cef917
Add Home Connect resume command button when an appliance is paused (#148512) 2025-07-14 10:25:08 +00:00
Michael
962ad99c20
Add workaround for sub units without main device in AVM Fritz!SmartHome (#148507) 2025-07-14 10:25:07 +00:00
Michael
9c9836defd
Bump aioimmich to 0.10.2 (#148503) 2025-07-14 10:25:06 +00:00
Jan Bouwhuis
e951fc401c
Fix entity_id should be based on object_id the first time an entity is added (#148484) 2025-07-14 10:25:05 +00:00
Robert Resch
00e2a177a5
Revert "Deprecate hddtemp" (#148482) 2025-07-14 10:25:04 +00:00
Joakim Sørensen
b6d316c8f2
Bump hass-nabucasa from 0.105.0 to 0.106.0 (#148473) 2025-07-14 10:25:02 +00:00
Raphael Hehl
b8425de0d0
Bump uiprotect to version 7.14.2 (#148453) 2025-07-14 10:25:01 +00:00
Joost Lekkerkerker
d51a44acbc
Bump pySmartThings to 3.2.7 (#148394) 2025-07-14 10:25:00 +00:00
Josef Zweck
435465e569
Bump pylamarzocco to 2.0.11 (#148386) 2025-07-14 10:24:59 +00:00
Josef Zweck
3b047859f9
Create own clientsession for lamarzocco (#148385) 2025-07-14 10:24:58 +00:00
Simone Chemelli
91cdf1a367
Bump aioamazondevices to 3.2.8 (#148365)
Co-authored-by: Joakim Plate <elupus@ecce.se>
2025-07-14 10:24:57 +00:00
Joakim Plate
2377b136f3
Handle binary coils with non default mappings in nibe heatpump (#148354) 2025-07-14 10:24:56 +00:00
Retha Runolfsson
186c4e7038
Bump pyswitchbot to 0.68.1 (#148335) 2025-07-14 10:24:55 +00:00
Samuel Xiao
d303a7d17e
Fix Switchbot cloud plug mini current unit Issue (#148314) 2025-07-14 10:24:54 +00:00
jvits227
14f059c766
Add lamp states to smartthings selector (#148302)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-14 10:23:55 +00:00
Arie Catsman
4a10370932
Bump pyenphase to 2.2.1 (#148292) 2025-07-14 10:13:43 +00:00
J. Nick Koston
672ffa5984
Restore httpx compatibility for non-primitive REST query parameters (#148286) 2025-07-14 10:13:42 +00:00
Maciej Bieniek
3d3f2527cb
Bump gios to version 6.1.0 (#148274) 2025-07-14 10:13:41 +00:00
Shay Levy
5c3b279f95
Bump aiowebostv to 0.7.4 (#148273) 2025-07-14 10:13:40 +00:00
starkillerOG
59bcf1167a
bump motionblinds to 0.6.29 (#148265) 2025-07-14 10:13:39 +00:00
Mark Adkins
b4d789f8e2
Bump sharkiq to 1.1.1 (#148244) 2025-07-14 10:12:00 +00:00
Josef Zweck
f4ca56052b
Bump pylamarzocco to 2.0.10 (#148233) 2025-07-14 10:11:59 +00:00
J. Nick Koston
74f9549431
Fix UTF-8 encoding for REST basic authentication (#148225) 2025-07-14 10:11:58 +00:00
J. Nick Koston
9650727515
Fix REST sensor charset handling to respect Content-Type header (#148223) 2025-07-14 10:11:57 +00:00
ekutner
25f64a2f36
Do not specify the code_format when a code is not required (#148698) 2025-07-14 12:11:36 +02:00
TimL
c965da6559
Bump pysmlight to v0.2.7 (#148101)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-14 10:09:19 +00:00
Sören Beye
9077965214
Squeezebox: Fix tracks not having thumbnails (#147187) 2025-07-14 10:09:18 +00:00
Sören Beye
2b7992e849
Squeezebox: Fix track selection in media browser (#147185) 2025-07-14 10:09:16 +00:00
Erik Montnemery
dcbdce4b2b
Improve docstrings of event helpers related to state changes (#148722) 2025-07-14 11:57:27 +02:00
Michael
50047f0a4e
Add new device class for absolute humidity (#148567) 2025-07-14 11:46:17 +02:00
Fredrik Mårtensson
21b1122f83
Add test fixture for Tuya cover (#148660) 2025-07-14 11:43:02 +02:00
Jan Bouwhuis
09104fca4d
Fix hide empty sections in mqtt subentry flows (#148692) 2025-07-14 11:26:37 +02:00
Jan Bouwhuis
ad4e5459b1
Fix - only enable AlexaModeController if at least one mode is offered (#148614) 2025-07-14 11:25:22 +02:00
Joost Lekkerkerker
334d5f09fb
Create Google Generative AI sub entries for an enabled entry (#148161)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-07-14 11:24:00 +02:00
Niccolò Maggioni
9f3d890e91
Bump pysnmp to v7 and brother to v5 (#129761)
Co-authored-by: Maciej Bieniek <bieniu@users.noreply.github.com>
2025-07-14 10:46:13 +02:00
Hessel
eae9f4f925
Wallbox Integration - Add repair action for insufficient rights (#148610)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-14 10:30:48 +02:00
Brett Adams
5e50c723a7
Fix Charge Cable binary sensor in Teslemetry (#148675) 2025-07-14 10:29:29 +02:00
MattMorgan
f761f7628a
Minor update to keymitt_ble manifest. (#148708) 2025-07-14 08:50:25 +02:00
karwosts
26d71fcdba
Fix derivative migration from 'none' unit_prefix (#147820) 2025-07-14 08:17:20 +02:00
Christopher Fenner
e4359e74c6
Bump PyViCare to 2.50.0 (#148679) 2025-07-14 08:08:54 +02:00
Marc Mueller
5e30e6cb91
Update python-mystrom to 2.4.0 (#148682) 2025-07-14 08:02:43 +02:00
Simone Chemelli
bc07030304
Bump aioamazondevices to 3.2.10 (#148709) 2025-07-14 01:18:35 +03:00
Shay Levy
25ba2437dd
Bump aioshelly to 13.7.2 (#148706) 2025-07-14 01:15:50 +03:00
Kevin Worrel
cfc7cfcf37
Bump screenlogicpy to 0.10.2 (#148703) 2025-07-13 11:44:55 -10:00
J. Diego Rodríguez Royo
74288a3bc8
Re-enable Home Connect updates automatically (#148657)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-07-13 22:46:42 +02:00
Marc Mueller
b2fe17c6d4
Update PyMicroBot to 0.0.23 (#148700) 2025-07-13 22:12:00 +02:00
Paulus Schoutsen
611f86cf8c
OpenAI: Add attachment support to AI task (#148676) 2025-07-13 21:51:46 +02:00
Paulus Schoutsen
23a8442abe
Make attachments native to chat log (#148693)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-13 19:35:11 +02:00
Paulus Schoutsen
f3ad6bd9b6
Report correctly when no funds for OpenAI (#148677) 2025-07-13 17:55:24 +02:00
Robert Meijers
023dd9d523
Discover Heos players using Zeroconf (#144763) 2025-07-13 09:56:31 -05:00
Steven Tegreeny
f7d132b043
Add Z-WAVE discovery entry for the GE/JASCO in-wall smart fan control (#148246) 2025-07-13 13:46:37 +02:00
Brett Adams
bb17f34bae
Remove history first refresh from Teslemetry (#148531) 2025-07-13 13:01:38 +02:00
Erik Montnemery
d22dd68119
Fix exception in EntityRegistry.async_device_modified (#148645) 2025-07-13 10:37:48 +02:00
Alex Leversen
4122af1d33
Bump pyoctoprintapi version to 0.1.14 (#148651) 2025-07-13 09:04:01 +02:00
J. Nick Koston
87fd45d4ab
Add device_id parameter to ESPHome command calls for sub-device support (#148667) 2025-07-12 20:12:14 -10:00
asafhas
1c35aff510
Add configuration entities to Tuya multifunction alarm (#148556) 2025-07-13 07:55:37 +02:00
J. Nick Koston
ab6ac94af9
Bump aioesphomeapi to 35.0.0 (#148666) 2025-07-12 18:49:59 -10:00
Marc Mueller
d33f73fce2
Cleanup bleak warnings (#148665) 2025-07-12 16:26:31 -10:00
Marc Mueller
fca6dc264f
Update bleak to 1.0.1 (#147742)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-07-12 13:11:37 -10:00
Amit Finkelstein
5287f4de81
Bump pyatv to 0.16.1 (#148659) 2025-07-12 21:52:26 +01:00
jvits227
ccc1f01ff6
Add lamp states to smartthings selector (#148302)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-12 20:51:09 +02:00
falconindy
531f1f1964
snoo: use correct value for right safety clip binary sensor (#148647) 2025-07-12 20:46:03 +02:00
Hessel
72dc2b15d5
Wallbox Add translation to exception config entry auth failed (#148649) 2025-07-12 20:40:39 +02:00
0xEF
cf2ef4cec1
Bump nyt_games to 0.5.0 (#148654) 2025-07-12 20:30:26 +02:00
Hessel
28994152ae
Wallbox - Add translation to exception (#148644) 2025-07-12 12:24:59 +02:00
AlCalzone
ad881d892b
Keep entities of dead Z-Wave devices available (#148611) 2025-07-11 23:45:57 +02:00
Paulus Schoutsen
87e641bf59
Update recommended model for Ollama to Qwen3 (#148627) 2025-07-11 16:15:13 -05:00
Paulus Schoutsen
6ecaca753d
Update Anthropic max tokens to 3000 and recommended model to claude-3-5-haiku-latest (#148624)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-11 23:00:04 +02:00
Paulus Schoutsen
017cd0bf45
Update OpenAI conversation max tokens to 3000 (#148623)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-11 22:59:51 +02:00
Paulus Schoutsen
1920edd712
Update Google Generative AI Conversation max tokens to 3000 (#148625)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-11 13:10:12 -07:00
Erik Montnemery
2dca78efbb
Improve entity registry handling of device changes (#148425) 2025-07-11 20:56:50 +02:00
Lưu Quang Vũ
e0179a7d45
Fix Google Cloud 504 Deadline Exceeded (#148589) 2025-07-11 11:53:38 -07:00
Abílio Costa
d393d5fdbb
Use non-autospec mock for Reolink's util and view tests (#148579) 2025-07-11 16:27:06 +02:00
Joost Lekkerkerker
a34264f345
Add SmartThings RVC fixture (#148552) 2025-07-11 14:01:11 +02:00
epenet
73c9d99abf
Add tuya snapshot tests for wxkg category (#148609) 2025-07-11 13:55:01 +02:00
Avi Miller
ec5991bc68
Add support for LIFX 26"x13" Ceiling (#148459)
Signed-off-by: Avi Miller <me@dje.li>
2025-07-11 13:42:50 +02:00
Arjan
87aecf0ed9
Linkplay: add select entity to set Audio Output hardware (#143329) 2025-07-11 12:45:21 +02:00
Norbert Rittel
0b2ce73eac
Fix description of html5.dismiss action (#148591) 2025-07-11 11:43:29 +02:00
Hessel
22828568e2
Wallbox Integration - Type Config Entry (#148594) 2025-07-11 11:37:24 +02:00
Jan Bouwhuis
5a4c837328
Fix entity_id should be based on object_id the first time an entity is added (#148484) 2025-07-11 11:19:54 +02:00
Jan-Philipp Benecke
cd73824e3e
Ensure response is fully read to prevent premature connection closure in rest command (#148532) 2025-07-11 09:06:18 +02:00
Robin Thoni
32121a073c
Add release URL for Tessie updates (#148548)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-11 07:56:23 +02:00
Matrix
c6c622797d
Add YoLink YS7A12 support (#148588) 2025-07-11 07:55:13 +02:00
jlestel
193b32218f
Fix domain validation in Tesla Fleet (#148555) 2025-07-11 00:41:03 +01:00
Paulus Schoutsen
e6702d2392
Serialize Object Selector correctly if a field is required (#148577) 2025-07-10 22:45:56 +01:00
Paulus Schoutsen
19b3b6cb28
Add attachment support to Google Gemini (#148208) 2025-07-10 23:45:11 +02:00
Harry Heymann
a2220cc2e6
Add LED intensity custom attributes for Matter Inovelli Dimmers (#148074)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-10 23:36:51 +02:00
J. Nick Koston
18a89d5815
Bump aiohttp to 3.12.14 (#148565) 2025-07-10 23:10:48 +02:00
Bram Kragten
6eeec948a8
Update frontend to 20250702.2 (#148573) 2025-07-10 23:09:47 +02:00
Paulus Schoutsen
0e09a47476
Add OpenAI AI Task entity (#148295) 2025-07-10 23:08:56 +02:00
karwosts
f0a636949a
Support all Energy units in Energy integration (#148566) 2025-07-10 19:29:48 +01:00
Allen Porter
d15baf9f9f
Drop homeassistant agent and assist_pipeline migration code (#147968)
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2025-07-10 17:30:54 +02:00
epenet
4f27058a68
Add fault binary sensors to tuya dehumidifer (#148485) 2025-07-10 16:15:07 +02:00
epenet
058e1ede10
Add tuya snapshot tests for wsdcg and zndb category (#148554) 2025-07-10 15:55:22 +02:00
epenet
d23321cf54
Add tuya snapshot tests for dlq category (#148549) 2025-07-10 15:55:03 +02:00
epenet
eb20292683
Move tuya models to separate module (#148550) 2025-07-10 15:54:05 +02:00
Norbert Rittel
12f913e737
Improve names and descriptions of rainmachine.push_weather_data (#148534) 2025-07-10 13:38:42 +02:00
tronikos
7e405d4ddb
100% test coverage in Google Assistant SDK (#148536) 2025-07-10 13:21:19 +02:00
Nathan Spencer
2829cc1248
Add visits today sensor for pets (#147459) 2025-07-10 11:24:54 +01:00
Matrix
8881919efd
Add YS8009 support to Yolink (#148538) 2025-07-10 12:10:15 +02:00
Åke Strandberg
a00f61f7be
Remove vg argument from miele auth flow (#148541) 2025-07-10 12:09:24 +02:00
Josh Barnard
c37b0a8f1d
Adding precision for voltage and wind speed sensors in Ecowitt (#148462) 2025-07-10 11:21:44 +02:00
Kristof Mariën
c75b34a911
Fix for Renson set Breeze fan speed (#148537) 2025-07-10 10:52:03 +02:00
Denis Shulyaka
cbe2fbdc34
Encrypted reasoning items support for OpenAI Conversation (#148279) 2025-07-10 10:46:10 +02:00
J. Diego Rodríguez Royo
c2bc4a990e
Use the link to the issue instead of creating new issues at Home Connect (#148523) 2025-07-10 09:35:30 +02:00
J. Diego Rodríguez Royo
49baa65f61
Add Home Connect resume command button when an appliance is paused (#148512) 2025-07-10 00:26:13 +02:00
Matthias Alphart
24a7ebd2bb
Move KNXModule class to separate module (#146100) 2025-07-09 23:51:40 +02:00
Noah Husby
a4b9efa1b1
Support AM/FM channel name in Russound RIO (#148421) 2025-07-09 23:23:04 +02:00
Manu
15544769b6
Add action for activity reactions to Bring! (#138175) 2025-07-09 23:08:24 +02:00
Tsvi Mostovicz
3307132441
Jewish calendar: appropriate polling for sensors (2/3) (#144906)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-09 22:50:09 +02:00
Thomas55555
da255af8de
Bump aioautomower to 1.2.2 (#148497) 2025-07-09 22:02:31 +02:00
Maciej Bieniek
a7e879714b
Add water flow sensor to IMGW PIB integration (#148517) 2025-07-09 21:59:08 +02:00
Michael
8aaf5756e0
Add workaround for sub units without main device in AVM Fritz!SmartHome (#148507) 2025-07-09 21:44:50 +02:00
Maciej Bieniek
ce5f06b1e5
Add new sensors to GIOS integration (#148510) 2025-07-09 21:43:02 +02:00
Denis Shulyaka
e42ca06173
Bump openai to 1.93.3 (#148501) 2025-07-09 21:41:50 +02:00
Thomas55555
2807f057de
Fix flaky test in Husqvarna Automower (#148515) 2025-07-09 22:34:37 +03:00
Mickael Goubin
283d0d16c0
Linkplay - when grouped, the first media player returned is the coordinator (#146295)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-09 21:33:15 +02:00
Michael
84959a0077
Add platinum quality scale to Pegel Online (#131382) 2025-07-09 21:33:07 +02:00
Michael
e012196af8
Bump aioimmich to 0.10.2 (#148503) 2025-07-09 21:22:31 +02:00
Maciej Bieniek
5d43938f0d
Bump imgw_pib to version 1.2.0 (#148511) 2025-07-09 21:20:38 +02:00
Nathan Spencer
cbdc8e3800
Bump pylitterbot to 2024.2.2 (#148505) 2025-07-09 20:45:45 +02:00
Jan-Philipp Benecke
1b5bbda6b0
Add response headers to action response of rest command (#148480) 2025-07-09 20:37:00 +02:00
G Johansson
57083d877e
Add repairs from issue registry to integration diagnostics (#148498) 2025-07-09 18:52:16 +01:00
Petro31
3045f67ae5
Modernize binary sensor template tests (#148367) 2025-07-09 17:49:28 +02:00
Joost Lekkerkerker
6f31057d30
Rework Snapcast config flow tests (#148434) 2025-07-09 16:01:17 +01:00
epenet
511ffdc03c
Add tuya snapshot tests for kg category (#148492) 2025-07-09 16:20:29 +02:00
epenet
59fe6da47c
Adjust tuya test docstrings (#148493) 2025-07-09 15:59:43 +02:00
epenet
e1cdc1af1c
Add diagnostics tests to tuya (#148489) 2025-07-09 15:47:48 +02:00
epenet
f6e2b962fd
Use SnapshotAssertion in lifx diagnostics tests (#148491) 2025-07-09 15:30:17 +02:00
epenet
fe0ce9bc6d
Use real product_id in tuya fixture (#148415) 2025-07-09 14:44:18 +02:00
Robert Resch
b083919031
Revert "Deprecate hddtemp" (#148482) 2025-07-09 13:53:15 +02:00
epenet
ef2e699d2c
Add tuya snapshot tests for curtain switch (#148465)
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-09 13:05:53 +02:00
Raphael Hehl
71df8ffe6e
Bump uiprotect to version 7.14.2 (#148453) 2025-07-09 12:37:45 +02:00
Joakim Sørensen
98604f09fc
Bump hass-nabucasa from 0.105.0 to 0.106.0 (#148473) 2025-07-09 12:30:43 +02:00
Artur Pragacz
b97b04661e
Improve logging in bootstrap (#148469) 2025-07-09 11:29:56 +01:00
Andrew Jackson
828037de1f
Set quality scale on Mealie to silver (#148467) 2025-07-09 11:25:56 +01:00
Norbert Rittel
659504c91f
Fix friendly name of increased_non_neutral_output in zha (#148468) 2025-07-09 12:24:44 +02:00
Franck Nijhof
434ac421d1
Tiny tweaks to task form (#148475) 2025-07-09 12:04:00 +02:00
Denis Shulyaka
de849b920a
Enable web search for OpenAI reasoning models (#148393) 2025-07-09 10:54:49 +02:00
Artur Pragacz
e387d4834f
Fix unloading update listener in Unifi (#148471) 2025-07-09 10:44:21 +02:00
Artur Pragacz
39ed877a17
Fix unloading update listener in Axis (#148470) 2025-07-09 10:43:55 +02:00
epenet
13d05a338b
Sort tuya definitions by category (#148472) 2025-07-09 10:42:55 +02:00
Avi Miller
cb2095bcbe
Bump aiolifx to 1.2.1 (#148464)
Signed-off-by: Avi Miller <me@dje.li>
2025-07-09 09:43:29 +02:00
Norbert Rittel
6de630ef3e
Fix sentence-casing of trigger subtypes in xiaomi_ble (#148463) 2025-07-09 10:43:22 +03:00
Rico Hageman
a02359b25d
Add dew point to Awair integration (#148403) 2025-07-09 09:28:55 +02:00
Oliver Heesakkers
afcd991262
Handle processing errors when writing to Zabbix (#148449) 2025-07-09 08:01:54 +02:00
J. Nick Koston
6b5b35fece
Bump aioesphomeapi to 34.2.0 (#148456) 2025-07-08 22:34:35 -06:00
Norbert Rittel
ed8effa162
Fix spelling of "non-existent", "non-blocking" and "currently used" (#148440) 2025-07-08 22:58:39 +01:00
Simone Chemelli
70c01efe57
Update Alexa Devices quality scale to silver (#148435) 2025-07-08 17:58:35 +01:00
Norbert Rittel
ebffaed0bd
Fix spelling of "non-resettable" in iskra (#148417) 2025-07-08 19:45:39 +03:00
Norbert Rittel
ab1e323d49
Fix spelling of "non-volatile memory" in z-wave_js (#148422) 2025-07-08 19:44:11 +03:00
Simone Chemelli
6e63c17b39
Improve exceptions in Alexa Devices (#148260) 2025-07-08 17:58:48 +02:00
Petro31
a35299d94c
Add preview tests for number and sensor (#148426) 2025-07-08 16:04:06 +01:00
Tucker Kern
c97ad9657f
Add metadata support to Snapcast media players (#132283)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-08 16:58:32 +02:00
Erik Montnemery
aab8908af8
Improve entity registry tests related to config entries in devices (#148399)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-08 16:24:06 +02:00
Maciej Bieniek
ae7bc14059
Make the update interval a property of the NextDNS coordinator class (#148410) 2025-07-08 16:14:02 +02:00
Maciej Bieniek
546f6afac2
Bump gios to version 6.1.1 (#148414) 2025-07-08 16:11:15 +02:00
epenet
8ccd097e98
Add tuya snapshot tests for bladeless tower fan (#148401) 2025-07-08 14:50:49 +02:00
epenet
77ae6048ef
Add tuya snapshot tests for gas leak sensor (#148400) 2025-07-08 14:49:52 +02:00
Abílio Costa
420d1e169d
Fix hassfest command in copilot-instructions (#148405) 2025-07-08 14:49:09 +02:00
hanwg
91b8262128
Update strings for Telegram bot (#148409) 2025-07-08 14:48:44 +02:00
Ludovic BOUÉ
e393929014
Matter EVSE StateOfCharge (#148213) 2025-07-08 14:28:13 +02:00
Samuel Xiao
11938762eb
Fix Switchbot cloud plug mini current unit Issue (#148314) 2025-07-08 13:57:30 +02:00
Simone Chemelli
94862e6a50
Update Alexa Devices quality scale (#147259) 2025-07-08 13:49:00 +02:00
epenet
1a8d4c5041
Add tuya snapshot tests for Avatto WT598 thermostat (#148398) 2025-07-08 13:40:16 +02:00
Erik Montnemery
b775ba2955
Do not add switch_as_x config entry to source device (#148346) 2025-07-08 13:23:28 +02:00
Josef Zweck
d2bf27195a
Bump pylamarzocco to 2.0.11 (#148386) 2025-07-08 13:06:43 +02:00
Josef Zweck
824006729b
Create own clientsession for lamarzocco (#148385) 2025-07-08 13:06:05 +02:00
Joakim Plate
a7cba2b9bb
Handle binary coils with non default mappings in nibe heatpump (#148354) 2025-07-08 13:05:16 +02:00
Joost Lekkerkerker
bd1917c9b6
Bump pySmartThings to 3.2.7 (#148394) 2025-07-08 12:34:51 +02:00
Josef Zweck
7541e266da
Make api_version runtime_data in pi_hole (#148238) 2025-07-08 11:46:13 +02:00
Manu
f58c76c883
Fix error when personalDetail is missing in PlayStation Network integration (#148389) 2025-07-08 10:16:10 +02:00
Simone Chemelli
a77a071954
Bump aioamazondevices to 3.2.8 (#148365)
Co-authored-by: Joakim Plate <elupus@ecce.se>
2025-07-08 10:14:41 +02:00
Jiacheng Ma
0dc145aee3
Fix tuya vacuum return_to_base function (#144362)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-08 10:03:35 +02:00
Joakim Plate
ac5d4f4a81
Fix CI issues due to nibe heatpump (#148388) 2025-07-08 09:17:27 +02:00
Noah Husby
d44b822295
Add play media support to Russound RIO (#148240) 2025-07-08 08:51:18 +02:00
Paulus Schoutsen
6d0891e970
OpenAI: Extract file attachment logic (#148288) 2025-07-08 08:01:49 +02:00
Avi Miller
73730e3eb3
Bump aiolifx to 1.2.0 (#148382) 2025-07-08 07:57:41 +02:00
Alexandre CUER
87b00fdc7b
Emoncms add reconfigure flow (#145108)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-08 07:28:16 +02:00
hahn-th
f780b9763d
Add support for ELV-SH-CTV Sensor to homematicip_cloud (#143737) 2025-07-08 07:24:55 +02:00
Joakim Sørensen
7a7e16bbb6
Change how subscription information is fetched (#148337)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-08 06:52:41 +02:00
J. Nick Koston
dcf8d7f74d
Track ESPHome entities by (device_id, key) to support sub-devices with overlaping names (#148297) 2025-07-08 06:41:20 +02:00
Ville Skyttä
ccc80c78a0
Add huawei_lte device registry upnp udn connection (#148370) 2025-07-08 06:32:29 +02:00
epenet
b0f7c985e4
Add snapshots tests for new platforms in tuya (#148334) 2025-07-08 06:25:53 +02:00
Joakim Sørensen
7875290256
Adds claude-code feature to the devcontainer (#148338) 2025-07-08 06:24:31 +02:00
Ruben van Dijk
f478812568
Allow multiple set-cookie headers with hassio ingress (#148148) 2025-07-08 06:13:08 +02:00
Joakim Plate
9ce03c79f0
Switch to box default for numbers in nibe_heatpump integration (#148364) 2025-07-08 06:09:22 +02:00
Joakim Plate
19951d9403
Handle when heat pump rejects same value writes in nibe_heatpump (#148366) 2025-07-08 06:07:41 +02:00
G Johansson
4b8dcc39b4
Bump holidays to 0.76 (#148363) 2025-07-08 06:05:18 +02:00
Joakim Plate
b151a9bf75
Add missing connection for gardena ble device (#148376) 2025-07-08 06:02:56 +02:00
Manu
e3cc4acdc6
Remove deprecated max_health, habits and rewards sensors from Habitica integration (#148377) 2025-07-08 05:57:46 +02:00
Ville Skyttä
fc53ddb3b4
Remove huawei_lte notify related timeout suppression (#148373) 2025-07-08 00:08:43 +02:00
hanwg
0409c05265
Add basic authentication option for Telegram bot (#148247) 2025-07-07 22:08:49 +02:00
jlanchares
9d2ffa6372
Goodwe TCP support (port 502) (#147900) 2025-07-07 19:37:20 +02:00
Joakim Plate
5c4f166f6f
Add translation for write failures in nibe_heatpump (#148352) 2025-07-07 18:48:34 +02:00
Erik Montnemery
6396f54e0d
Move zone conditions to the zone integration (#148157) 2025-07-07 18:27:44 +02:00
Denis Shulyaka
090b8f0659
Bump openai to 1.93.0 (#148350) 2025-07-07 18:07:28 +02:00
G Johansson
a46cc82916
Don't log deprecation warning in vacuum until after entity added to hass (#147959)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-07 16:52:29 +02:00
J. Nick Koston
8007bf1c31
Fix REST sensor charset handling to respect Content-Type header (#148223) 2025-07-07 14:32:58 +01:00
Manu
c296e1f818
Remove deprecated register_static_path method (#148303)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-07 14:27:19 +01:00
Retha Runolfsson
799dc97d4a
Bump pyswitchbot to 0.68.1 (#148335) 2025-07-07 14:26:23 +01:00
Mark Adkins
e4c9df6d98
Bump sharkiq to 1.1.1 (#148244) 2025-07-07 15:18:15 +02:00
J. Nick Koston
03e295ace0
Restore httpx compatibility for non-primitive REST query parameters (#148286) 2025-07-07 08:01:48 -05:00
Abílio Costa
b71bcb002b
Move target selector extractor method to common module (#148087) 2025-07-07 13:48:48 +01:00
Norbert Rittel
c60e06d32f
Fix missing sentence-casing and spelling of "REST" in iskra (#148330) 2025-07-07 14:06:27 +02:00
Norbert Rittel
448d6041e5
Fix missing sentence-casing in wallbox (#148332) 2025-07-07 14:06:13 +02:00
tronikos
15c9ddea78
Bump gassist-text to 0.0.14 (#148312) 2025-07-07 04:10:50 -07:00
Erik Montnemery
0c783e87d1
Fix homee test (#148322) 2025-07-07 11:59:35 +02:00
Franck Nijhof
42b50c71ec
Revert "Add tests for Sonos Alarms" (#148319) 2025-07-07 11:54:36 +02:00
Maciej Bieniek
991864a8af
Bump gios to version 6.1.0 (#148274) 2025-07-07 11:43:39 +02:00
Arie Catsman
b79e770bcf
Bump pyenphase to 2.2.1 (#148292) 2025-07-07 11:40:48 +02:00
Shay Levy
f02c1b0d4e
Bump aiowebostv to 0.7.4 (#148273) 2025-07-07 11:37:39 +02:00
Norbert Rittel
a5d6bfd1b3
Reword option for 'Main' control in wled (#148309) 2025-07-07 10:30:39 +02:00
Norbert Rittel
21f6bf3914
Improve translation_key of EnergyEvseSupplyStateSensor in matter (#148280) 2025-07-07 10:26:20 +02:00
Hessel
0bce01da0b
Address some Wallbox quality scale issues (#148200) 2025-07-07 10:09:07 +02:00
Ludovic BOUÉ
6351c3302e
Matter OperationalState CountdownTime (#147705)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-07-06 23:40:05 +02:00
J. Nick Koston
2ea20ee2ab
Fix UTF-8 encoding for REST basic authentication (#148225) 2025-07-06 12:40:19 -05:00
Paulus Schoutsen
008e2a3d10
Add attachment support to AI task (#148120) 2025-07-06 19:33:41 +02:00
Joakim Sørensen
699c60f293
Add the current version to the starting log to aid troubleshooting (#148271) 2025-07-06 19:06:27 +02:00
karwosts
404d17efca
Translate number selector unit for utility_meter (#148276) 2025-07-06 18:36:38 +02:00
Allen Porter
4b5c04b2f0
Add AI Task support in Ollama (#148226)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2025-07-06 16:56:37 +02:00
Paulus Schoutsen
8cb9cadce9
Extract files_to_prompt from Gemini action (#148203)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Allen Porter <allen.porter@gmail.com>
2025-07-06 15:15:38 +02:00
Robin Thoni
075efb469a
Bump sfrbox-api to 0.0.12 (#148259)
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2025-07-06 13:08:27 +02:00
starkillerOG
0e7a4c91bf
bump motionblinds to 0.6.29 (#148265) 2025-07-06 12:38:57 +02:00
Norbert Rittel
4ee930507d
Fix typo in wrong_hub abort message of homee (#148261) 2025-07-06 12:11:44 +02:00
Markus Adrario
1b11ac9123
Add Homee general tests (#137128) 2025-07-06 12:05:43 +02:00
Norbert Rittel
8d7e387b46
Deduplicate strings in nordpool actions (#148258) 2025-07-06 11:23:57 +02:00
Joakim Sørensen
70e9c4e2d0
Add reauth flow to the Traccar Server integration (#148236)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-07-06 08:09:59 +02:00
Josef Zweck
26de1ea37b
Update strings in pihole (#148234)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-05 23:14:59 +01:00
Josef Zweck
3ffcfa42ba
Bump pylamarzocco to 2.0.10 (#148233) 2025-07-05 23:34:23 +02:00
G Johansson
e304022560
Add service in Nord Pool for fetching normalized price indices (#147979) 2025-07-05 21:39:48 +02:00
G Johansson
160e4e4d05
Block options flow for default hostname in dnsip (#148221) 2025-07-05 21:36:15 +02:00
Noah Husby
eb0f11a859
Bump aiorussound to 4.8.0 (#148235) 2025-07-05 21:13:48 +02:00
TheJulianJES
295b15ace9
Change ZHA string "autoshutdown" to "auto-shutdown" (#148230) 2025-07-05 20:23:03 +02:00
Pete Sage
d997efc500
Add tests for Sonos Alarms (#146308) 2025-07-05 17:39:52 +02:00
Jack Powell
736865c130
Add binary sensor platform to PlayStation Network Integration (#147639) 2025-07-05 17:27:23 +02:00
Paulus Schoutsen
4f4ec6f41a
Add Google Gen AI structured data support (#148143) 2025-07-05 08:22:17 -07:00
Luka Matijević
33d05d99eb
Fix Miele hob plate power step typo (#148214) 2025-07-05 16:44:41 +02:00
Guido Schmitz
8d82e34ba5
Make connected stations coordinator a dict in devolo Home Network (#147042) 2025-07-05 11:42:15 +02:00
Sören Beye
2ea09ff37a
Squeezebox: Fix track selection in media browser (#147185) 2025-07-05 11:36:45 +02:00
Sören Beye
676567f471
Squeezebox: Fix tracks not having thumbnails (#147187) 2025-07-05 11:31:30 +02:00
Denis Shulyaka
3151713a34
Replace dot with underscores for NamespacedTool and ActionTool (#147764) 2025-07-05 11:27:27 +02:00
David Rapan
23773759ea
Starlink's last boot time occasional, back and forth changes by 1 s fix (#147969) 2025-07-05 11:18:54 +02:00
Norbert Rittel
ef255788d2
Make lat/long attribute names localizable in dwd_weather_warnings (#147988) 2025-07-05 11:01:27 +02:00
Norbert Rittel
b72536acfa
Make "autorelock" consistent across integrations in matter (#148023) 2025-07-05 10:59:57 +02:00
tronikos
fea7dc7eba
Remember Opower utility and username on config flow errors (#148097) 2025-07-05 10:26:15 +02:00
Markus Adrario
f1698cdb75
Add reauth flow to homee (#147258) 2025-07-05 10:26:04 +02:00
HarvsG
1b21c986e8
Enable Pihole API v6 (#145890)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Josef Zweck <josef@zweck.dev>
2025-07-05 10:21:32 +02:00
Paulus Schoutsen
1e164c94b1
Include path when media source file can be accessed on disk (#148180) 2025-07-05 10:14:52 +02:00
epenet
7898e3f0fb
Add initial tuya snapshot tests (#148034)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-05 09:54:54 +02:00
Norbert Rittel
0d54e75940
Fix spelling of "auto" prefixes in zha (#148022) 2025-07-05 09:34:24 +02:00
karwosts
3cfff4de3a
Add a preview to history_stats options flow (#145721) 2025-07-05 09:09:02 +02:00
Andrey Kupreychik
275d390a6c
Add reconfiguration support for keenetic_ndms2 integration (#142191)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-05 08:52:43 +02:00
Matt Zimmerman
e63e6a6072
Bump python-smarttub to 0.0.43 (#147317) 2025-07-05 08:08:52 +02:00
Josef Zweck
e592e565c0
Make ready time sensors unavailable instead in lamarzocco (#147985) 2025-07-05 07:20:42 +02:00
Arie Catsman
12b90f3c8e
Add debug logs to trace enphase auth process at load. (#148117) 2025-07-04 23:14:51 +01:00
epenet
76be2fdba1
Improve (and align) deprecation messages (#147948) 2025-07-05 00:02:36 +02:00
Thomas55555
528daad854
Constant polling for Husqvarna Automower (#147957) 2025-07-04 23:42:17 +02:00
Ville Skyttä
dcad5bbe04
Simplify unnecessary re.findall calls (#147907)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-04 23:26:36 +02:00
Michael Podhorodecki
ca85ffc068
Add Deadlock (SecureMode) support to the Yale Access Bluetooth integration (#144107)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-07-04 23:07:13 +02:00
Kevin Stillhammer
9a5cbe483b
Remove obsolete string unit_system in here_travel_time (#146656) 2025-07-04 23:06:47 +02:00
Pete Sage
be7735964b
Sonos remove unneeded mocking from test (#147064) 2025-07-04 23:02:38 +02:00
Guido Schmitz
79683c8267
Log availability of devices in devolo Home Control (#147091) 2025-07-04 22:59:38 +02:00
Andre Lengwenus
8f24ebe967
Remove deprecated support for lock sensors and corresponding actions in lcn (#147143) 2025-07-04 22:55:20 +02:00
Andre Lengwenus
520d92b902
Use brightness stored in hardware device when switching LCN lights (#147375) 2025-07-04 22:53:11 +02:00
karwosts
22e46d9977
Make derivative sensor unavailable when source sensor is unavailable (#147468) 2025-07-04 22:48:48 +02:00
TimL
57c04f3a56
Bump pysmlight to v0.2.7 (#148101)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-04 22:35:44 +02:00
Franck Nijhof
c0368f2448
Add weekdays to time trigger (#147505)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-04 22:31:11 +02:00
Paulus Schoutsen
6a7f4953cd
Fix media selector validation (#147855)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-04 22:30:35 +02:00
Joakim Plate
470baa782e
Add zeroconf discovery to philips_js (#147913)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-07-04 22:24:40 +02:00
Sid
6e607ffa01
Add reconfigure flow to eheimdigital (#147930) 2025-07-04 22:18:13 +02:00
Wesley Vos
f5b51c6cf0
Add serial_numbers to device_info of inverters, encharge and enpower (#147964) 2025-07-04 22:04:48 +02:00
Franck Nijhof
5d6b02f470
2025.7.1 (#148171) 2025-07-04 22:00:18 +02:00
Hessel
bfccee17ef
Wallbox, Improve test setup (#148036) 2025-07-04 21:56:44 +02:00
Erik Montnemery
b6b6de24ac
Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in cambridge_audio (#148133) 2025-07-04 21:54:11 +02:00
Thomas55555
70624f72b6
Additional icon translation for Husqvarna Automower (#148167) 2025-07-04 21:51:47 +02:00
Franck Nijhof
a274961593
Bump version to 2025.7.1 2025-07-04 19:22:41 +00:00
Michael Freeman
4e163c4591
Bump venstarcolortouch to 0.21 (#148152) 2025-07-04 19:21:33 +00:00
Marc Mueller
3ffec2a655
[ci] Fix typing issue with aiohttp and aiosignal (#148141) 2025-07-04 19:21:31 +00:00
Bram Kragten
c646658643
Update frontend to 20250702.1 (#148131) 2025-07-04 19:21:30 +00:00
Simone Chemelli
342b4c3442
Bump aioamazondevices to 3.2.3 (#148082) 2025-07-04 19:21:28 +00:00
Arie Catsman
eb58c10e5e
Cancel enphase mac verification on unload. (#148072) 2025-07-04 19:21:27 +00:00
Arie Catsman
f42e7d982f
Bump pyenphase to 2.2.0 (#148070) 2025-07-04 19:21:25 +00:00
hanwg
898ef43750
Fix Telegram bots using plain text parser failing to load on restart (#148050) 2025-07-04 19:21:24 +00:00
Joakim Sørensen
f806e6ba49
Bump hass-nabucasa from 0.104.0 to 0.105.0 (#148040) 2025-07-04 19:21:23 +00:00
Marcel van der Veldt
c23bfb1b39
Fix state being incorrectly reported in some situations on Music Assistant players (#147997) 2025-07-04 19:21:22 +00:00
Robert Svensson
a2ffe32b02
Bump aiounifi to v84 (#147987) 2025-07-04 19:21:21 +00:00
puddly
0f32b6331d
Bump ZHA to 0.0.62 (#147966) 2025-07-04 19:21:19 +00:00
epenet
9a4959560e
Fix missing port in samsungtv (#147962)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-04 19:21:18 +00:00
Thomas55555
41ab7b346c
Set timeout for remote calendar (#147024) 2025-07-04 19:21:17 +00:00
Thomas55555
c61cd422d1
Delete stale icon translation in Husqvarna Automower (#148168) 2025-07-04 20:47:32 +02:00
karwosts
0b2db2510f
Support translating number selector UoM (#148162) 2025-07-04 21:06:33 +03:00
Erik Montnemery
bb1e263149
Remove cv.SUN_CONDITION_SCHEMA (#148158) 2025-07-04 18:34:55 +02:00
Michael Freeman
8e6b9c04f6
Bump venstarcolortouch to 0.21 (#148152) 2025-07-04 17:46:59 +02:00
Greg Dowling
cf931a75a7
Remove incorrect use of via_device in roon component (#146572) 2025-07-04 17:04:16 +02:00
Thomas55555
3250a2fb46
Bump aioautomower to 1.2.0 (#148078) 2025-07-04 16:43:36 +02:00
Franck Nijhof
6235adc69a
Fix flaky emulated_roku/test_binding.py::test_events_fired_properly test (#148069) 2025-07-04 16:42:24 +02:00
Simone Chemelli
5d258c2f82
Bump aioamazondevices to 3.2.3 (#148082) 2025-07-04 16:33:16 +02:00
hanwg
cc2aca2c2c
Fix Telegram bots using plain text parser failing to load on restart (#148050) 2025-07-04 16:32:46 +02:00
Erik Montnemery
04bd1967a7
Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in apple_tv (#148132) 2025-07-04 16:31:44 +02:00
Erik Montnemery
a046530eaf
Replace MediaPlayerState.STANDBY with MediaPlayerState.IDLE in mediaroom (#148135) 2025-07-04 16:30:03 +02:00
Erik Montnemery
631523dfaf
Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in lookin (#148134) 2025-07-04 16:27:54 +02:00
Erik Montnemery
dc20375506
Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in snapcast (#148138) 2025-07-04 16:27:33 +02:00
Erik Montnemery
811f085556
Replace MediaPlayerState.STANDBY with MediaPlayerState.IDLE in androidtv (#148130) 2025-07-04 16:27:01 +02:00
Erik Montnemery
fd86a43b28
Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in ps4 (#148136) 2025-07-04 16:25:59 +02:00
Bram Kragten
b7f830523e
Update frontend to 20250702.1 (#148131) 2025-07-04 16:25:28 +02:00
Erik Montnemery
3f752e13ff
Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in roku (#148137) 2025-07-04 16:23:18 +02:00
Marc Mueller
783102f2f6
[ci] Fix typing issue with aiohttp and aiosignal (#148141) 2025-07-04 16:22:38 +02:00
Erik Montnemery
8ce30d9559
Add tests of legacy entity without platform writing state (#148109) 2025-07-04 16:21:48 +02:00
Paulus Schoutsen
cde17fc0ca
add extra tests for media source URI parsing (#148114) 2025-07-04 16:21:11 +02:00
David Knowles
83ae5f52da
Bump pydrawise to 2025.7.0 (#148088) 2025-07-04 16:20:24 +02:00
tronikos
1cb9767bb8
Enable strict typing for Opower (#148096) 2025-07-04 16:19:04 +02:00
tronikos
e98fe7dc9c
Add data_description to Opower forms (#148099) 2025-07-04 16:17:41 +02:00
tronikos
40ec51c0a3
Add redirect URL in Google Assistant SDK setup (#148076) 2025-07-04 16:17:10 +02:00
Harry Heymann
40fcc3b75b
Rename Matter device conversion methods (#148090) 2025-07-04 16:13:40 +02:00
Erik Montnemery
510fd09163
Allow core integrations to describe their conditions (#147529)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-04 16:03:42 +02:00
epenet
e47bdc06a0
Set docstyle convention to google in ruff (#148142) 2025-07-04 16:00:37 +02:00
Allen Porter
b3d9908cd9
Add AI task structured output (#148083)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2025-07-04 15:03:34 +02:00
Erik Montnemery
99d63c49bb
Add comment about error assigning in frame.report_usage (#148105) 2025-07-04 14:47:01 +02:00
Robin Thoni
4be2e84ce6
Add backward compatibility with older versions of Traccar server (#146639)
Co-authored-by: Joakim Sørensen <joasoe@proton.me>
2025-07-04 14:36:25 +02:00
Allen Porter
1fc624c7a7
Update LLM selector serializer to support ObjectSelector fields and arrays (#148094) 2025-07-04 13:05:16 +02:00
tronikos
8641a2141c
Fix has-entity-name and entity-translations in Opower (#148098) 2025-07-04 10:10:21 +02:00
Paulus Schoutsen
04cc451c76
Add AI Task platform to Google Gen AI (#146766) 2025-07-03 23:36:34 -07:00
Erik Montnemery
a3b03caead
Deduce integration from module in loader.async_get_issue_tracker (#148017) 2025-07-04 07:55:20 +02:00
Franck Nijhof
49d1d781b8
Fix ezviz test timeout (#148066) 2025-07-03 23:11:54 +02:00
HeroOfCanton16
11c75d7ef2
Add sensor attributes restore to modem_callerid integration (#147753) 2025-07-03 22:10:26 +01:00
Arie Catsman
8ef6b62d9a
Cancel enphase mac verification on unload. (#148072) 2025-07-03 22:06:38 +02:00
tronikos
b410b414ec
Add reconfigure flow in Android TV Remote (#148044) 2025-07-03 22:00:07 +02:00
Arie Catsman
e5f7421703
Bump pyenphase to 2.2.0 (#148070) 2025-07-03 21:04:13 +02:00
Marc Mueller
8330ae2d3a
Update license-expression to 30.4.3 (#147941) 2025-07-03 20:22:10 +02:00
tronikos
4b162f09bd
Bump androidtvremote2 to 0.2.3 (#148042) 2025-07-03 20:15:47 +02:00
tronikos
9c558fabcd
Use AndroidTVRemoteConfigEntry (#148046) 2025-07-03 20:15:36 +02:00
tronikos
5f9cc0a5f6
Add data_description to forms in Android TV Remote (#148045)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
Co-authored-by: Artem Draft <Drafteed@users.noreply.github.com>
2025-07-03 20:13:44 +02:00
Erik Montnemery
bc4a322e81
Improve helpers.frame.report_usage when called from outside the event loop (#148021) 2025-07-03 20:12:52 +02:00
Jeef
b999c5906e
Bump weatherflow4py to 1.4.1 (#148054) 2025-07-03 20:11:33 +02:00
Erik Montnemery
d2825e1c80
Don't gather TRIGGER_PLATFORM_SUBSCRIPTIONS (#147954)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-03 19:33:28 +02:00
epenet
419e4f3b1d
Remove unused module in tuya tests (#148058) 2025-07-03 19:14:27 +02:00
Thomas55555
4a937d2452
Set timeout for remote calendar (#147024) 2025-07-03 10:08:58 -07:00
Noah Husby
01b4a5ceed
Bump aiorussound to 4.7.0 (#148057) 2025-07-03 19:04:18 +02:00
Abílio Costa
4e71745c62
Set assist_satellite preannounce default to True (#148060) 2025-07-03 18:41:08 +02:00
Franck Nijhof
6a88ee7a8f
Add Task issue form (#148038) 2025-07-03 18:27:51 +02:00
J. Nick Koston
3c4ecffa1b
Bump aioesphomeapi to 34.1.0 (#148048) 2025-07-03 17:33:44 +02:00
Joakim Sørensen
244e0f5ea8
Bump hass-nabucasa from 0.104.0 to 0.105.0 (#148040) 2025-07-03 14:24:51 +02:00
epenet
a656b6e26a
Use HassKey in media_source (#148011) 2025-07-03 09:56:46 +02:00
epenet
691681a78a
Move medcom_ble coordinator to separate module (#148009) 2025-07-03 09:32:57 +02:00
epenet
3bc00824e2
Use runtime_data in mystrom (#148020) 2025-07-03 09:27:38 +02:00
epenet
7d36a2e3a7
Move meteoclimatic coordinator to separate module (#148018) 2025-07-03 09:26:24 +02:00
Norbert Rittel
b1e3561ead
Clarify description of autorelock setting in zwave_js (#148019) 2025-07-03 09:23:45 +02:00
epenet
bfc814c839
Use entry.async_on_unload in meteo_france (#148015) 2025-07-03 09:22:27 +02:00
epenet
5008151688
Use entry.async_on_unload in monoprice (#148016) 2025-07-03 09:20:50 +02:00
Franck Nijhof
d738c0d6b1
Merge branch 'master' into dev 2025-07-03 07:04:46 +00:00
epenet
e42235285d
Use runtime_data in melcloud (#148012)
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-03 08:57:22 +02:00
epenet
04e69479f4
Fix hass.data reference in lookin (#148008) 2025-07-03 08:54:20 +02:00
epenet
b973916032
Move met_eireann coordinator to separate module (#148014) 2025-07-03 08:53:22 +02:00
epenet
6f4757ef42
Use runtime_data in melnor (#148013) 2025-07-03 08:52:40 +02:00
epenet
a6962e9e1e
Fix missing port in samsungtv (#147962)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-03 08:51:38 +02:00
Marcel van der Veldt
142c10cccc
Fix state being incorrectly reported in some situations on Music Assistant players (#147997) 2025-07-03 08:50:41 +02:00
Matthias Alphart
c137c96cfd
KNX: use async_load_json_object_fixture in tests (#147991) 2025-07-03 08:00:34 +02:00
Robert Svensson
f0e0c954e7
Bump aiounifi to v84 (#147987) 2025-07-02 23:10:21 +02:00
Norbert Rittel
681961d3a5
Use common config_flow strings in vegehub (#147984) 2025-07-02 22:14:55 +02:00
Matthias Alphart
53d2f6b0c6
KNX: Use a ConfigExtractor helper class for value retrieval (#147983) 2025-07-02 21:49:24 +02:00
G Johansson
78c39f8a06
Remove deprecated battery properties from demo vacuum (#147980) 2025-07-02 21:49:12 +02:00
Ludovic BOUÉ
a748525e03
Allow LevelControl Cluster for Matter Pump devices (#145004)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-07-02 21:48:15 +02:00
Manuel Rüger
8ca1fe83b7
Bump switchbot-api to v2.7.0 (#147978) 2025-07-02 21:36:06 +02:00
Matthias Alphart
8968cf704b
Use send_json_auto_id in KNX tests (#147982) 2025-07-02 21:34:30 +02:00
puddly
ebe04466f4
Bump ZHA to 0.0.62 (#147966) 2025-07-02 21:19:32 +02:00
G Johansson
e31470ba5b
Change breaking version for battery props in vacuum (#147956) 2025-07-02 19:06:56 +02:00
Franck Nijhof
4bc2951f44
2025.7.0 (#147533) 2025-07-02 18:01:06 +02:00
Franck Nijhof
8334a0398c
Bump version to 2025.7.0 2025-07-02 15:12:16 +00:00
Ville Skyttä
80a1e0e4cd
Improve huawei_lte config flow class naming (#147910) 2025-07-02 17:02:39 +02:00
Thomas55555
3778f537d5
Remove noisy debug logs in Husgvarna Automower (#147958) 2025-07-02 15:28:42 +01:00
Petro31
adec157d43
Allow trigger based numeric sensors to be set to unknown (#137047)
* Allow trigger based numeric sensors to be set to unknown

* resolve comments

* Do case insensitive check

* use _parse_result

---------

Co-authored-by: abmantis <amfcalt@gmail.com>
2025-07-02 15:35:47 +02:00
Franck Nijhof
8fc3fa51a8
Bump version to 2025.7.0b9 2025-07-02 13:30:51 +00:00
c0ffeeca7
4eb688b560
Z-Wave JS: rename controller to adapter according to term decision (#147955)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-02 13:30:31 +00:00
Simone Chemelli
9472ff5d36
Bump aioamazondevices to 3.2.2 (#147953) 2025-07-02 13:30:29 +00:00
Bram Kragten
12e8b81ec7
Update frontend to 20250702.0 (#147952) 2025-07-02 13:30:28 +00:00
Paulus Schoutsen
ec5e543c09
Ollama: Migrate pick model to subentry (#147944) 2025-07-02 13:30:27 +00:00
Paulus Schoutsen
116c745872
Split Ollama entity (#147769) 2025-07-02 13:30:26 +00:00
Robert Resch
1fdf152292
Bump deebot-client to 13.5.0 (#147938) 2025-07-02 13:27:47 +00:00
G Johansson
b816f1a408
Handle additional errors in Nord Pool (#147937) 2025-07-02 13:27:46 +00:00
John Hess
eb351e6505
Bump thermopro-ble to 0.13.1 (#147924) 2025-07-02 13:27:45 +00:00
Maciej Bieniek
2f27d55495
Open repair issue when outbound WebSocket is enabled for Shelly non-sleeping RPC device (#147901) 2025-07-02 13:26:03 +00:00
Space
fa1bed1849
Skip processing request body for HTTP HEAD requests (#147899)
* Skip processing request body for HTTP HEAD requests

* Use aiohttp's must_be_empty_body() to check whether ingress requests should be streamed

* Only call must_be_empty_body() once per request

* Fix incorrect use of walrus operator
2025-07-02 13:26:01 +00:00
Raphael Hehl
b8c19f23f3
UnifiProtect Change log level from debug to error for connection exceptions in ProtectFlowHandler (#147730) 2025-07-02 13:26:00 +00:00
Erwin Douna
b677ce6c90
SMA add DHCP strictness (#145753)
* Add DHCP strictness (needs beta check)

* Update to check on CONF_MAC

* Update to check on CONF_HOST

* Update hostname

* Polish it a bit

* Update to CONF_HOST, again

* Add split

* Add CONF_MAC add upon detection

* epenet feedback

* epenet round II
2025-07-02 13:25:59 +00:00
c0ffeeca7
d6da686ffe
Z-Wave JS: rename controller to adapter according to term decision (#147955)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-02 15:23:08 +02:00
Paulus Schoutsen
f50ef79c72
Ollama: Migrate pick model to subentry (#147944) 2025-07-02 15:20:42 +02:00
Erik Montnemery
943fb9948b
Adjust logic related to entity platform state (#147882)
* Adjust logic related to entity platform state

* Break up hard to read if-statement

* Add and improve tests
2025-07-02 14:57:53 +02:00
Raphael Hehl
7447cf329b
UnifiProtect Change log level from debug to error for connection exceptions in ProtectFlowHandler (#147730) 2025-07-02 14:57:46 +02:00
Erwin Douna
3d27c0ce52
SMA add DHCP strictness (#145753)
* Add DHCP strictness (needs beta check)

* Update to check on CONF_MAC

* Update to check on CONF_HOST

* Update hostname

* Polish it a bit

* Update to CONF_HOST, again

* Add split

* Add CONF_MAC add upon detection

* epenet feedback

* epenet round II
2025-07-02 14:48:21 +02:00
Simone Chemelli
b7496be61f
Bump aioamazondevices to 3.2.2 (#147953) 2025-07-02 14:27:51 +02:00
Bram Kragten
57a98240bd
Update frontend to 20250702.0 (#147952) 2025-07-02 14:26:19 +02:00
Ville Skyttä
ff76017ba6
Simplify unnecessary re match.groups()[0] calls (#147909) 2025-07-02 14:12:26 +02:00
Maikel Punie
f10fcde6d8
Remove the deprecated interface paramater for velbus (#147868) 2025-07-02 14:07:47 +02:00
Marc Mueller
a7002e3a24
Update pytest to 8.4.1 (#147951) 2025-07-02 13:02:18 +01:00
tronikos
bbe03dcab7
Add missing Opower tests (#147934) 2025-07-02 13:46:40 +02:00
Andre Lengwenus
f77e6cc8fc
Add missing exception translations to LCN (#147723) 2025-07-02 13:41:06 +02:00
Petro31
cb8e076703
Fix missing device_class and state_class on compensation entities (#146115)
Co-authored-by: Robert Resch <robert@resch.dev>
2025-07-02 13:39:19 +02:00
G Johansson
73251fbb1c
Handle additional errors in Nord Pool (#147937) 2025-07-02 13:26:47 +02:00
Maciej Bieniek
7ff90ca49d
Open repair issue when outbound WebSocket is enabled for Shelly non-sleeping RPC device (#147901) 2025-07-02 13:06:27 +02:00
Manu
bab9ec9976
Add sensor for online status to PlayStation Network (#147842) 2025-07-02 11:47:41 +01:00
Marc Mueller
1051f85ac0
Update coverage to 7.9.1 (#147940) 2025-07-02 12:20:50 +02:00
Marc Mueller
6c7da57af2
Update pytest-cov to 6.2.1 (#147942) 2025-07-02 12:14:27 +02:00
Marc Mueller
73e505d48d
Update pytest-xdist to 3.8.0 (#147943) 2025-07-02 12:11:09 +02:00
Marc Mueller
ec65066f5e
Update mypy-dev to 1.17.0a4 (#147939) 2025-07-02 12:09:39 +02:00
Robert Resch
9c4951261c
Bump deebot-client to 13.5.0 (#147938) 2025-07-02 12:00:48 +02:00
Space
00dfc04b86
Skip processing request body for HTTP HEAD requests (#147899)
* Skip processing request body for HTTP HEAD requests

* Use aiohttp's must_be_empty_body() to check whether ingress requests should be streamed

* Only call must_be_empty_body() once per request

* Fix incorrect use of walrus operator
2025-07-02 11:45:45 +02:00
Manu
bee07ad284
Fix Online ID string in PlayStation Network integration (#147915) 2025-07-02 10:45:07 +02:00
Paulus Schoutsen
b2108fdd40
Update Dockerfile.dev to only use uv for Python (#147926) 2025-07-02 10:40:16 +02:00
John Hess
3730a1a379
Bump thermopro-ble to 0.13.1 (#147924) 2025-07-02 10:11:49 +02:00
Sid
088c02d38a
Complete tests for eheimdigital (#143337)
* Complete tests for eheimdigital

* Review

* Review

* Review

* Review

* Fix tests
2025-07-02 10:09:30 +02:00
Harry Heymann
afb247c907
Bump Python Matter server to 8.0.0 (#147783) 2025-07-02 08:12:47 +02:00
Simone Chemelli
77dcba0984
Manager wrong country selection in Alexa Devices (#147914)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-02 08:02:53 +02:00
Simone Chemelli
48f9a12cca
Bump aioamazondevices to 3.2.1 (#147912) 2025-07-02 07:36:41 +02:00
J. Nick Koston
bdd2ac9ae4
Bump bluetooth-data-tools to 1.28.2 (#147920) 2025-07-02 07:34:40 +02:00
Ivan Lopez Hernandez
2e7113d881
Swap the Models label for the model name not it's display name, (#147918)
Swap display name for name.
2025-07-01 21:12:58 -07:00
Sid
6842bfae4c
Bump eheimdigital to 1.3.0 (#147908) 2025-07-01 23:00:25 +01:00
nadimz
392cde20d9
Add support for opening state in template lock (#147813)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-01 22:03:20 +01:00
cristianburrini
a6146fb5a9
Increase the number of irrigation zones up to 8 for Tuya enabled controllers. (#147793) 2025-07-01 22:40:36 +02:00
Jesse Hills
6104731d53
Remove codeowner from ESPHome (#147850) 2025-07-01 22:09:23 +02:00
Erik Montnemery
66308a848a
Set Entity._platform_state in google_assistant tests (#147892) 2025-07-01 21:46:36 +02:00
Erik Montnemery
c71dbd9d4d
Set Entity._platform_state in universal tests (#147894) 2025-07-01 21:46:01 +02:00
Erik Montnemery
1195c2ec10
Set Entity._platform_state in core customize test (#147895) 2025-07-01 21:45:08 +02:00
Norbert Rittel
78a9cd9201
Use (new) common state "Empty" for water level in switchbot (#147836) 2025-07-01 21:43:21 +02:00
Erik Montnemery
639a749a0f
Mock recorder in ista_ecotrend tests (#147893) 2025-07-01 20:09:48 +01:00
Simone Chemelli
058f3b8b6e
Add reauth to Alexa Devices config flow (#147773) 2025-07-01 20:57:24 +02:00
Manu
926e9261ab
Add switch to enable/disable boost in IronOS integration (#147831) 2025-07-01 20:53:13 +02:00
Erik Montnemery
d6fb860889
Use entity_registry_enabled_by_default fixture in dsmr_reader tests (#147891) 2025-07-01 20:50:38 +02:00
Marcel van der Veldt
5e03900e0a
Bump Music Assistant Client to 1.2.3 (#147885) 2025-07-01 20:26:26 +02:00
Erik Montnemery
1e6e5ca1b6
Fix broadlink tests (#147890) 2025-07-01 18:32:58 +01:00
Erik Montnemery
60e3b38de1
Set Entity._platform_state in arcam_fmj tests (#147889) 2025-07-01 17:58:15 +02:00
epenet
852522219c
Use correctly formatted MAC in bond tests (#147887) 2025-07-01 17:56:10 +02:00
epenet
23f1e8d1a3
Use correctly formatted MAC in elkm1 tests (#147888) 2025-07-01 17:55:46 +02:00
avee87
655f009f07
Fix station name sensor for metoffice (#145500) 2025-07-01 16:18:13 +02:00
Jamin
59bf39f4ed
Bump VoIP utils to 0.3.3 (#147880) 2025-07-01 16:09:51 +02:00
Fredrik Mårtensson
510e3977df
Add water_level sensor to Tuya pet fountain cwysj (#146602)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-01 14:57:17 +01:00
micha91
922720576a
fix: Create new aiohttp session with DummyCookieJar (#147827) 2025-07-01 15:50:04 +02:00
Paul Bottein
e10b581d4b
Fix Meteo france Ciel clair condition mapping (#146965)
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2025-07-01 15:43:34 +02:00
hanwg
e38eac9415
Include chat ID in Telegram bot subentry title (#147643) 2025-07-01 15:42:32 +02:00
Maciej Bieniek
11c9aa9280
Bump Nettigo Air Monitor backend library to version 5.0.0 (#147812) 2025-07-01 15:39:29 +02:00
Paul Bottein
52c86f8a6a
Update frontend to 20250701.0 (#147879) 2025-07-01 15:38:04 +02:00
Marc Mueller
6364a9ad98
Update pillow to 11.3.0 (#147869) 2025-07-01 14:31:06 +01:00
Manu
651162b8e7
Fix error in last online sensor of PlayStation integration (#147844)
* Fix Last online sensor

* set unavailable

* available_fn
2025-07-01 15:17:10 +02:00
Denis Shulyaka
7deca35172
Add multiple LLM API support for MCP Server (#147785)
* Add multiple LLM API support for MCP Server

* Update homeassistant/components/mcp_server/config_flow.py

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

* ruff

* Update tests/components/mcp_server/conftest.py

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Allen Porter <allen.porter@gmail.com>
2025-07-01 06:14:03 -07:00
epenet
073a467fb2
Use correctly formatted MAC in bond tests (#147870) 2025-07-01 14:41:31 +02:00
epenet
3f9590b03b
Use correctly formatted MAC in gogogate2 tests (#147872) 2025-07-01 14:41:20 +02:00
epenet
b47f989c77
Use correctly formatted MAC in wmspro tests (#147876) 2025-07-01 14:40:41 +02:00
epenet
4ebffa8d23
Use correctly formatted MAC in palazzetti tests (#147875) 2025-07-01 14:40:27 +02:00
epenet
c5873c6dd0
Use correctly formatted MAC in dlink tests (#147871) 2025-07-01 14:40:12 +02:00
Erik Montnemery
2cb80e083e
Initialize EsphomeEntity._has_state (#147877) 2025-07-01 07:33:33 -05:00
epenet
871296dff6
Use correctly formatted MAC in lamarzocco tests (#147874) 2025-07-01 14:13:21 +02:00
Claudio Ruggeri - CR-Tech
c92873bbff
Change default slave id from 0 to 1 in modbus actions (#142865)
* set default slave id in service calls

* add test

* revert out of scope change
2025-07-01 13:15:32 +02:00
Norbert Rittel
5fea4915ef
Use (new) common state "Empty" in litterrobot (#147835) 2025-07-01 13:13:12 +02:00
dependabot[bot]
8fa016059d
Bump github/codeql-action from 3.29.1 to 3.29.2 (#147867)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 12:30:01 +02:00
Bob Laz
61a29db72c
fix state_class for water used today sensor (#147787) 2025-07-01 12:28:13 +02:00
epenet
5a3aa7874d
Use correctly formatted MAC in airthings tests (#147817) 2025-07-01 12:26:10 +02:00
Parker Brown
12e2493c42
Capitalize "version" in Tesla fleet strings (#146501) 2025-07-01 12:18:55 +02:00
Paulus Schoutsen
659cd42739
Move async_reload on updates in async_setup_entry in Anthropic (#147862)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-01 12:16:00 +02:00
Paulus Schoutsen
7fcea17e83
Move async_reload on updates in async_setup_entry in OpenAI Conversation (#147863)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-01 12:15:28 +02:00
Paulus Schoutsen
30a85c40da
Move async_reload on updates in async_setup_entry in Ollama (#147861)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-01 12:14:46 +02:00
epenet
57a8f1e0cc
Use correctly formatted MAC in rehlko tests (#147864) 2025-07-01 12:09:00 +02:00
epenet
78aeae577d
Use correctly formatted MAC in roomba tests (#147865) 2025-07-01 11:24:08 +02:00
epenet
3f95cb37e6
Use correctly formatted MAC in sma tests (#147866) 2025-07-01 11:23:31 +02:00
epenet
12aef4aae5
Use correctly formatted MAC in knocki tests (#147821) 2025-07-01 11:22:48 +02:00
Thomas55555
2e12db001d
Fix wrong state in Husqvarna Automower (#146075) 2025-07-01 10:53:55 +02:00
epenet
573325be97
Use correctly formatted MAC in home_connect tests (#147818) 2025-07-01 10:51:49 +02:00
Erik Montnemery
7021fe7495
Correct openai conversation config entry migration (#147859) 2025-07-01 10:49:07 +02:00
Erik Montnemery
b7999755bd
Correct anthropic config entry migration (#147857) 2025-07-01 10:47:06 +02:00
Erik Montnemery
99f7a031d6
Correct Google generative AI config entry migration (#147856) 2025-07-01 10:46:13 +02:00
Erik Montnemery
8fc31283b7
Correct ollama config entry migration (#147858) 2025-07-01 10:45:17 +02:00
Jan-Philipp Benecke
5ff698c78d
Catch access denied errors in webdav and display proper message (#147093) 2025-07-01 10:15:45 +02:00
Jesse Hills
9469c6ad1c
Implement suggested_display_precision for ESPHome (#147849) 2025-07-01 09:16:23 +02:00
Norbert Rittel
35f0505c7b
Use (new) common state "Empty" in whirlpool (#147847)
Use (new) common state "Empty"
2025-07-01 08:59:55 +02:00
Norbert Rittel
a180cabea9
Use (new) common state "Full" in overkiz (#147848)
Use (new) common state "Full"
2025-07-01 08:58:31 +02:00
Jan Bouwhuis
4f7348b8bc
Fix invalid configuration of MQTT device QoS option in subentry flow (#147837) 2025-07-01 08:46:58 +02:00
On Freund
ddf56f053b
Support device removal in CoolMasterNet integration (#147851) 2025-07-01 08:26:04 +02:00
G Johansson
9719d2ef2b
Start deprecation of battery properties in vacuum (#146401)
* Start deprecation of battery properties in vacuum

* Small fixes

* Fixes

* Deprecate battery supported feature
2025-07-01 08:23:47 +02:00
Manu
2afe475234
Add more mac address prefixes for discovery to PlayStation Network (#147739) 2025-07-01 07:12:00 +02:00
Norbert Rittel
23c304fc75
Use (new) common state "Full" in enphase_envoy (#147834)
Use (new) common state "Full"
2025-06-30 20:13:05 -04:00
Norbert Rittel
84645d0ca6
Use (new) common states for "Full" and "Empty" in lg_thinq (#147833)
Use (new) common states for "Full" and "Empty"
2025-07-01 01:59:33 +02:00
Norbert Rittel
2bdfc8cf5e
Add common states "Empty" and "Full" (#146646) 2025-06-30 22:08:55 +02:00
epenet
603e277a5b
Add docstring to DhcpServiceInfo MAC address (#147823)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-06-30 21:54:05 +02:00
Paulus Schoutsen
38a7b21052
Split Anthropic entity (#147770) 2025-06-30 21:47:44 +02:00
Paulus Schoutsen
bf74ba990a
Split Ollama entity (#147769) 2025-06-30 21:31:54 +02:00
Paulus Schoutsen
70856bd92a
Split OpenAI entity (#147771) 2025-06-30 21:11:51 +02:00
Paulus Schoutsen
be6b624081
Improve validation for media selector (#147768) 2025-06-30 20:26:52 +02:00
mvn23
217fbb2849
Populate hvac_modes list in opentherm_gw (#142074) 2025-06-30 20:24:13 +02:00
epenet
22a14da19c
Rename service registration method (#146615) 2025-06-30 20:21:38 +02:00
puddly
20f5d85800
Await firmware installation task when flashing ZBT-1/Yellow firmware (#147824) 2025-06-30 20:18:22 +02:00
hanwg
88feb5139b
Fix Telegram bot proxy URL not initialized when creating a new bot (#147707) 2025-06-30 20:16:45 +02:00
Hessel
90cbe272a0
Wallbox Integration, Reduce API impact by limiting the amount of API calls made (#147618) 2025-06-30 20:15:48 +02:00
Paulus Schoutsen
511b739bf6
Use media selector for Assist Satellite actions (#147767)
Co-authored-by: Michael Hansen <mike@rhasspy.org>
2025-06-30 20:12:03 +02:00
Manu
9961a499ee
Fix sensor displaying unknown when getting readings from heat meters in ista EcoTrend (#147741) 2025-06-30 20:11:46 +02:00
rubenbe
d8c7ed473b
Bump xiaomi-ble to 1.1.0 (#147828)
Bump xiaomi-ble to 1.1.0
2025-06-30 20:11:03 +02:00
Manu
2c30a5a14c
Improve exception handling of PlayStation Network (#147792) 2025-06-30 19:53:46 +02:00
Manu
5e3fc858d8
Add sensor last online to PlayStation Network integration (#147796) 2025-06-30 19:52:11 +02:00
epenet
f03af213d4
Use correctly formatted MAC in lg_thinq tests (#147822) 2025-06-30 19:50:50 +02:00
epenet
1e3ebd5650
Use correctly formatted MAC in incomfort tests (#147819) 2025-06-30 18:02:42 +02:00
epenet
53936ab062
Use async_load_fixture in weatherflow_cloud (#147816) 2025-06-30 18:01:14 +02:00
Bouwe Westerdijk
b52a248def
Bump plugwise to v1.7.7 and adapt (#147809) 2025-06-30 14:40:10 +01:00
Jeef
ea70229426
Add Weatherflow Cloud wind support via websocket (#125611)
* rebase off of dev

* update tests

* update tests

* addressing PR finally

* API to back

* adding a return type

* need to test

* removed teh extra check on available

* some changes

* ready for re-review

* change assertions

* remove icon function

* update ambr

* ruff

* update snapshot and push

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* enhnaced tests

* better coverage

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* Update homeassistant/components/weatherflow_cloud/coordinator.py

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

* remove comments

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-06-30 15:26:17 +02:00
Erik Montnemery
741a3d5009
Remove backup helper (#143558)
* Remove backup helper

* Update aws_s3 tests
2025-06-30 14:11:10 +02:00
Pete Sage
ee8830cc77
Person ble_trackers for non-home zones not processed correctly (#138475)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-06-30 13:35:19 +02:00
Bouwe Westerdijk
7fbf25e862
Plugwise: remove outdated fixtures (#147806) 2025-06-30 12:15:52 +02:00
epenet
e642cd45ae
Enforce async_load_fixture in async test functions (#145709) 2025-06-30 11:56:26 +02:00
dependabot[bot]
179e1c2b00
Bump github/codeql-action from 3.29.0 to 3.29.1 (#147799)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 11:53:30 +02:00
Phill (pssc)
52a99aea0c
Squeezebox: Fix Allow server device details to merge with players with the same MAC (#133517)
* Disambiguate bewtween servers and player to stop them being merged

* ruff format

* make SqueezeLite players not a service

* ruff

* Tidy redunant code

* config url

* revert config url

* change to domain server

* use default to see how they are mereged with server device

* refactor to use defaults so where a player is part of a bigger ie server service device in the same intergration it doesnt replace its information

* ruff

* make test match the new data

* Fix merge

* Fix tests

* Fix meregd test data

* Fix all tests add new test for merged device in reg

* Remove info from device_info so its only a lookup

* manual merge of server player shared devices

* Fix format of merged entires

* fixes for testing

* Fix test with input from @peteS-UK device knowlonger exits for this test

* Fix test now device doesnt exits for tests

* Update homeassistant/components/squeezebox/media_player.py

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

* Fix Copilots formatting

* Apply suggestions from code review

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-06-30 11:41:22 +02:00
Paulus Schoutsen
c7b2f236be
Type Z-Wave JS config entry (#147456)
* Type Z-Wave JS config entry

* Migrate to data class
2025-06-30 11:15:12 +02:00
Evan Severson
a6e3da43ca
Fixed pushbullet handling of fields longer than 255 characters (#146993) 2025-06-30 11:08:50 +02:00
Steffen Rusitschka
4d58024d5d
Add publish_string_states config to zabbix (#134773)
* Add include_strings config to zabbix

* Remove commented code

* Fix ruff formatting

* Update homeassistant/components/zabbix/__init__.py

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

* Update homeassistant/components/zabbix/__init__.py

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

* Don't use dict.get, CONF_INCLUDE_STRINGS has a default value and will always be set.

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

* Convert to string only when include_strings is true

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

* change to guard

* Fix review comments

* ruff, mypy, pylint fixes

* more ruff, mypy fixes

* and another ruff format fix

---------

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-06-30 10:52:33 +02:00
Manu
c7603b39ec
Fix inputs to correctly handle Fahrenheit in IronOS (#135421)
* Fix inputs to correctly handle Fahrenheit in IronOS

* some refactoring

* add boost switch entity

* Revert switch entity

* refactor

* remove commented code

* some changes
2025-06-30 10:44:39 +02:00
epenet
c17ee0d123
Allow binary sensor template to return state unknown (#128861)
* Allow binary sensor template to return state unknown

* Add tests

* Adjust TriggerBinarySensorEntity

* Add restore tests for BinarySensorTemplate

* Add tests for TriggerBinarySensorEntity

* Tweak

* Tweak

* Adjust tests

* Adjust
2025-06-30 10:06:05 +02:00
Alexandre CUER
97c1e21a69
Add possibility to synchronize automatically all available feeds in emoncms (#128122)
* Add checkbox in options to sync all feeds once

* Add sync mode selector in async_step_user
Remove checkbox in options

* Correct use of SYNC_MODE & SYNC_MODE_AUTO in tests

* Use dropdown for mode selection

* rmv_unused_const

* Add separate tests + use SelectSelector
2025-06-30 10:05:07 +02:00
starkillerOG
c9a6b1fd45
Bump reolink_aio to 0.14.2 (#147797) 2025-06-30 09:39:02 +02:00
mkmer
05ceee568e
Honeywell: Don't use shared session (#147772) 2025-06-29 21:22:59 +02:00
Shay Levy
08a6b38699
Bump aioshelly to 13.7.1 (#146221)
* Bump aioshelly to 13.8.0

* Change version to 13.7.1
2025-06-29 21:41:50 +03:00
Norbert Rittel
4add346272
Deduplicate strings and fix sentence-casing in proximity (#147777)
* Deduplicate strings and fix sentence-casing in `proximity`

* Update test_init.py
2025-06-29 21:00:16 +03:00
Andre Lengwenus
369c8d1e0d
Bump pypck to 0.8.10 (#147774) 2025-06-29 20:58:41 +03:00
tronikos
25ab47a587
Move the async_reload on updates in async_setup_entry in Google Generative AI (#147748)
Move the async_reload on updates in async_setup_entry
2025-06-29 07:56:37 +02:00
Marc Hörsken
617ea1925c
Update pywmspro to 0.3.0 to wait for short-lived actions (#147679)
Replace action delays with detailed action responses.
2025-06-29 07:33:44 +02:00
cdnninja
8bacab4f9c
Fix Vesync set_percentage error (#147751) 2025-06-29 07:22:04 +02:00
J. Nick Koston
6d28b99344
Preserve httpx boolean behavior in REST integration after aiohttp conversion (#147738) 2025-06-28 17:24:09 -05:00
cnico
bbd1cbf5c9
Correct Chlorine unit definition in flipr integration (#147537)
* Correction of bug 145683

* constant for chlorine unit correction

* constant name correction

* Review correction
2025-06-28 22:29:24 +01:00
starkillerOG
43450d4489
Reduce idle timeout of HLS stream to conserve camera battery life (#147728)
* Reduce IDLE timeout of HLS stream to conserve camera battery life

* adjust tests
2025-06-28 22:20:47 +02:00
J. Nick Koston
f8c052e0ce
Improve rest error logging (#147736)
* Improve rest error logging

* Improve rest error logging

* Improve rest error logging

* Improve rest error logging

* Improve rest error logging

* top level
2025-06-28 22:18:46 +02:00
Florian von Garrel
1f3bdfc7b7
bump pypaperless to 4.1.1 (#147735) 2025-06-28 22:13:51 +02:00
Antoni Czaplicki
0652bffd68
Bump vulcan-api to 2.4.2 (#146857) 2025-06-28 22:11:59 +02:00
Manu
8322611099
Use test parametrization in ista EcoTrend integration (#147729) 2025-06-28 21:57:51 +02:00
Marc Hörsken
134967b817
Fix error if cover position is not available or unknown (#147732) 2025-06-28 21:57:26 +02:00
Shay Levy
39abae36f0
Fix Shelly Block entity removal (#147694) 2025-06-28 22:40:58 +03:00
Marc Mueller
227760f203
Fix RuntimeWarnings in homeassistant_yellow tests (#147724) 2025-06-28 20:31:01 +02:00
Jan Bouwhuis
969809456e
Move MQTT device sw and hw version to collapsed section in subentry flow (#147685)
Move MQTT device sw and hw version to collapsed section
2025-06-28 11:25:59 +02:00
Daniel Hjelseth Høyer
d2e8a48b2c
Bump pytibber to 0.31.6 (#147703) 2025-06-28 10:11:17 +02:00
epenet
ea6332ee42
Move backup services to separate module (#146427) 2025-06-27 20:54:56 +02:00
Erik Montnemery
91c3b43d7f
Improve comment for helpers.entity.entity_sources (#146529) 2025-06-27 20:54:19 +02:00
Thomas55555
1d82d44794
Add device prefix to summary in Husqvarna Automower (#147405) 2025-06-27 20:34:50 +02:00
Thomas55555
571376badc
Bump aioautomower to 1.0.1 (#147683) 2025-06-27 20:28:45 +02:00
Manu
32236b2f4d
Add reconfiguration flow to PlayStation Network (#147552) 2025-06-27 20:17:06 +02:00
Samuel Xiao
18c1953bc5
Add lock models to switchbot cloud (#147569) 2025-06-27 20:16:21 +02:00
Bernardus Jansen
d874c28dc9
Add previously missing state classes to dsmr sensors (#147633) 2025-06-27 19:45:36 +02:00
Brett Adams
19d89c8952
Fix energy history in Teslemetry (#147646) 2025-06-27 19:43:03 +02:00
Ludovic BOUÉ
e3ba1f34ca
Matter TemperatureControl (#145706)
* TemperatureControl

* Add tests

* Commands.SetTemperature

* Update homeassistant/components/matter/number.py

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

* Apply suggestions from code review

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

* Update number.py

* Update number.py

* Update number.py

* Update homeassistant/components/matter/number.py

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

* Refactor MatterRangeNumber to streamline command handling in async_set_native_value

* testing requested changes

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2025-06-27 19:41:39 +02:00
Thomas55555
b630fb0520
Respect availability of parent class in Husqvarna Automower (#147649) 2025-06-27 19:38:42 +02:00
Ville Skyttä
5129f89086
Finish config flow in huawei_lte SSDP test (#147542) 2025-06-27 19:00:01 +02:00
Ville Skyttä
0be0e22e76
Simplify rflink dimmable set_level parsing (#147636) 2025-06-27 18:59:10 +02:00
epenet
b8500b338a
Improve tests for binary sensor template (#147657) 2025-06-27 18:58:16 +02:00
Simone Chemelli
4cab3a0465
Bump aioamazondevices to 3.1.22 (#147681) 2025-06-27 18:44:01 +02:00
hanwg
ff711324d5
Add codeowner for Telegram bot (#147680) 2025-06-27 18:18:01 +02:00
Michael
113e7dc003
Add data descriptions to PEGELONLINE integration (#147594) 2025-06-27 18:16:38 +02:00
Shay Levy
2120ff6a0a
Fix Shelly entity removal (#147665) 2025-06-27 18:50:35 +03:00
Marc Mueller
8ee5c30754
Update ruff to 0.12.1 (#147677) 2025-06-27 17:40:08 +02:00
Paul Bottein
a1518b96c4
Update frontend to 20250627.0 (#147668) 2025-06-27 17:28:14 +02:00
Petar Petrov
bba7f5c3f0
Z-WaveJS config flow: Change keys question (#147518)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-06-27 17:27:43 +02:00
Manu
8a5671af76
Remove dweet.io integration (#147645) 2025-06-27 17:23:42 +02:00
Raphael Hehl
8a18dea8c7
UniFi Protect removing early access checks and issue creation (#147432)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-27 17:15:34 +02:00
Thomas55555
4b02f22724
Bump aioautomower to 1.0.0 (#147676) 2025-06-27 17:02:52 +02:00
mkmer
7229c2ca2c
Bump aiosomecomfort to 0.0.33 (#147673) 2025-06-27 16:32:25 +02:00
Norbert Rittel
d83eddf13b
Fix sentence-casing and spacing of button in thermopro (#147671) 2025-06-27 15:53:18 +02:00
Josef Zweck
4a192a7b09
Bump jellyfin-apiclient-python to 1.11.0 (#147658) 2025-06-27 11:07:14 +02:00
Josef Zweck
58c434887e
Fix: Unhandled NoneType sessions in jellyfin (#147659) 2025-06-27 11:00:23 +02:00
Abílio Costa
78c2405e61
Bump whirlpool to 0.21.1 (#147611) 2025-06-27 10:33:49 +02:00
Josef Zweck
8cc4105984
Make jellyfin not single config entry (#147656) 2025-06-27 10:31:13 +02:00
Josef Zweck
917f1e4c6f
Make entities unavailable when machine is physically off in lamarzocco (#147426) 2025-06-27 10:03:14 +02:00
hanwg
3879f6d2ef
Fix Telegram bot yaml import for webhooks containing None value for URL (#147586) 2025-06-27 10:03:03 +02:00
Norbert Rittel
78060e4833
Clarify descriptions of subaru.unlock_specific_door action (#147655) 2025-06-27 10:01:44 +02:00
Guido Schmitz
fda66c4be4
Handle deleted devices dynamically in devolo Home Control (#147585) 2025-06-27 09:52:00 +02:00
Michael
21131d00b3
Fix config schema to make credentials optional in NUT flows (#147593) 2025-06-27 09:51:28 +02:00
puddly
a84313de33
Allow setup of Zigbee/Thread for ZBT-1 and Yellow without internet access (#147549)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-06-27 09:50:45 +02:00
Manu
c73346e6b3
Bump pynecil to v4.1.1 (#147648) 2025-06-27 09:31:35 +02:00
Franck Nijhof
55a37a2936
Extend GitHub Copilot instructions with new learnings from reviews (#147652) 2025-06-27 09:01:09 +02:00
Abílio Costa
e481f14335
Simplify reolink light tests (#147637) 2025-06-27 08:58:09 +02:00
Petar Petrov
1ca03c8ae9
Do not factory reset old Z-Wave controller during migration (#147576)
* Do not factory reset old Z-Wave controller during migration

* PR comments

* remove obsolete test
2025-06-27 08:02:12 +02:00
Ville Skyttä
61b43ca1fc
Remove unnecessary wilight trigger regex use (#147638) 2025-06-26 23:16:21 +01:00
Joost Lekkerkerker
1b2be083c2
Make sure Google Generative AI integration migration is clean (#147625) 2025-06-26 23:03:36 +02:00
Joost Lekkerkerker
4bdf3d6f30
Make sure OpenAI integration migration is clean (#147627) 2025-06-26 23:03:11 +02:00
Joost Lekkerkerker
43535ede8b
Make sure Anthropic integration migration is clean (#147629) 2025-06-26 23:02:59 +02:00
Joost Lekkerkerker
9bd0762799
Make sure Ollama integration migration is clean (#147630) 2025-06-26 23:02:35 +02:00
Ville Skyttä
1bb653b4f7
Remove unused config regexps (#147631) 2025-06-26 23:02:14 +02:00
Franck Nijhof
2655edcfc8
Extend GitHub Copilot instructions and make it suitable for Claude Code (#147632) 2025-06-26 23:00:02 +02:00
Franck Nijhof
7a08edc3dd
Add Claude to gitignore (#147622) 2025-06-26 21:06:34 +02:00
Abílio Costa
b3131355b0
Use non-autospec mock for Reolink's light tests (#147621) 2025-06-26 21:05:23 +02:00
Abílio Costa
06d04c001d
Use non-autospec mock for Reolink's host tests (#147619) 2025-06-26 20:55:46 +02:00
Jack Powell
babecdf32c
Add Diagnostics to PlayStation Network (#147607)
* Add Diagnostics support to PlayStation_Network

* Remove unused constant

* minor cleanup

* Redact additional data

* Redact additional data
2025-06-26 20:52:07 +02:00
Renat Sibgatulin
17cd39748b
Create a new client session for air-Q to fix cookie polution (#147027) 2025-06-26 19:59:49 +02:00
Simone Chemelli
c2f1e86a4e
Add action exceptions to Alexa Devices (#147546) 2025-06-26 19:59:02 +02:00
Joost Lekkerkerker
61a32466b6
Hide Telegram bot proxy URL behind section (#147613)
Co-authored-by: Manu <4445816+tr4nt0r@users.noreply.github.com>
2025-06-26 19:55:38 +02:00
Manu
aef08091f8
Fix asset url in Habitica integration (#147612) 2025-06-26 19:52:58 +02:00
Joost Lekkerkerker
1416f0f1e0
Fix meaters not being added after a reload (#147614) 2025-06-26 19:52:29 +02:00
HarvsG
af7b1a76bc
Add description placeholders to SchemaFlowFormStep (#147544)
* test description placeholders

* Update test_schema_config_entry_flow.py

* fix copy and paste indentation

* Apply suggestions from code review

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-06-26 19:51:31 +02:00
Maximilian Arzberger
bf88fcd5bf
Add Manual Charge Switch for Installers for Kostal Plenticore (#146932)
* Add Manual Charge Switch for Installers

* Update stale docstring

* Installer config fixture

* fix ruff
2025-06-26 19:50:27 +02:00
Joost Lekkerkerker
35478e3162
Set Google AI model as device model (#147582)
* Set Google AI model as device model

* fix
2025-06-26 19:44:15 +02:00
Joost Lekkerkerker
69af74a593
Improve explanation on how to get API token in Telegram (#147605) 2025-06-26 18:21:56 +02:00
tronikos
b4dd912bee
Refactor in Google AI TTS in preparation for STT (#147562) 2025-06-26 11:53:16 -04:00
Bram Kragten
b5821ef499
Update frontend to 20250626.0 (#147601) 2025-06-26 17:46:45 +02:00
Fabio Natanael Kepler
1a92d4530e
Fix playing TTS and local media source over DLNA (#134903)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-06-26 17:12:15 +02:00
Joost Lekkerkerker
7b80c1c693
Add default conversation name for OpenAI integration (#147597) 2025-06-26 17:11:48 +02:00
Joost Lekkerkerker
e7cc03c1d9
Add default title to migrated Claude entry (#147598) 2025-06-26 17:11:13 +02:00
Luca Angemi
69f0b6244a
Remove default icon for wind direction sensor for Buienradar (#147603)
* Fix wind direction state class sensor

* Remove default icon for wind direction sensor
2025-06-26 17:05:59 +02:00
Joost Lekkerkerker
01205f8a14
Add default title to migrated Ollama entry (#147599) 2025-06-26 17:05:26 +02:00
hanwg
68924d23ab
Fix Telegram bot default target when sending messages (#147470)
* handle targets

* updated error message

* validate chat id for single target

* add validation for chat id

* handle empty target

* handle empty target
2025-06-26 16:43:09 +02:00
Artur Pragacz
40f553a007
Migrate device connections to a normalized form (#140383)
* Normalize device connections migration

* Update version

* Slightly improve tests

* Update homeassistant/helpers/device_registry.py

* Add validators

* Fix validator

* Move format mac function too

* Add validator test

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2025-06-26 15:33:34 +02:00
Robin Lintermann
bc46894b74
Fixed issue when tests (should) fail in Smarla (#146102)
* Fixed issue when tests (should) fail

* Use usefixture decorator

* Throw ConfigEntryError instead of AuthFailed
2025-06-26 15:30:03 +02:00
Anders Peter Fugmann
6f4615f012
Bump dependency on pyW215 for DLink integration to 0.8.0 (#147534) 2025-06-26 12:56:46 +02:00
Joost Lekkerkerker
4244d2f66f
Set right model in OpenAI conversation (#147575) 2025-06-26 12:49:33 +02:00
Petar Petrov
a73dafe097
Hide unnamed paths when selecting a USB Z-Wave adapter (#147571)
* Hide unnamed paths when selecting a USB Z-Wave adapter

* remove pointless sorting
2025-06-26 12:15:02 +02:00
Stefan Agner
be49296547
Deduplicate shared logic in Matter vacuum commands (#147578)
Get the run mode by tag in a single place to avoid code duplication.
Also raise an error if the run mode (unexpectedly) is not found.
2025-06-26 11:54:52 +02:00
Marcel van der Veldt
d55ecd885e
Do not make the favorite button unavailable when no content playing on a Music Assistant player (#147579) 2025-06-26 11:49:06 +02:00
Luca Angemi
076248c455
Fix wind direction state class sensor for AEMET (#147535) 2025-06-26 11:07:07 +02:00
Petar Petrov
13ce27c94c
Remove obsolete routing info when migrating a Z-Wave network (#147568) 2025-06-26 11:06:36 +02:00
Joost Lekkerkerker
4b9b08ece5
Show current Lametric version if there is no newer version (#147538) 2025-06-26 10:55:31 +02:00
Simone Chemelli
79df38eff2
Improve config flow strings for Alexa Devices (#147523) 2025-06-26 10:52:14 +02:00
tronikos
fb133664e4
Include subentries in Google Generative AI diagnostics (#147558) 2025-06-26 10:50:47 +02:00
Marcel van der Veldt
38669ce96c
Fix sending commands to Matter vacuum (#147567) 2025-06-26 10:47:24 +02:00
Petar Petrov
651b33d49b
Bump zwave-js-server-python to 0.65.0 (#147561)
* Bump zwave-js-server-python to 0.65.0

* update tests
2025-06-26 10:11:25 +03:00
Erik Montnemery
3b64db5f76
Set end date for when allowing unique id collisions in config entries (#147516)
* Set end date for when allowing unique id collisions in config entries

* Update test
2025-06-26 08:20:26 +02:00
tronikos
0f95fe566c
Use default title for migrated Google Generative AI entries (#147551) 2025-06-25 22:30:41 -04:00
Simone Chemelli
6290facffb
Fix unload for Alexa Devices (#147548) 2025-06-26 01:55:58 +02:00
tronikos
f0a78aadbe
Fixes in Google AI TTS (#147501)
* Fix Google AI not using correct config options after subentries migration

* Fixes in Google AI TTS

* Fix tests by @IvanLH

* Change type name.

---------

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2025-06-25 18:12:23 -04:00
Pete Sage
345ec97dd5
Add enum sensor for Sonos Power Source (#147449)
* feat: add power source sensor

* fix: translations

* fix:cleanup

* fix: simpify

* fix: improve coverage

* fix: improve coverage

* fix: add missing test

* fix: call it charging_base

* fix: disable entity by default

* update snapshots

* Update homeassistant/components/sonos/strings.json

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

* fix: update test

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-06-25 23:49:06 +02:00
Franck Nijhof
1286b5d9d8
Bump version to 2025.8.0dev0 (#147531) 2025-06-25 21:38:35 +02:00
2166 changed files with 105270 additions and 28819 deletions

View File

@ -8,6 +8,7 @@
"PYTHONASYNCIODEBUG": "1"
},
"features": {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
// Port 5683 udp is used by Shelly integration

53
.github/ISSUE_TEMPLATE/task.yml vendored Normal file
View File

@ -0,0 +1,53 @@
name: Task
description: For staff only - Create a task
type: Task
body:
- type: markdown
attributes:
value: |
## ⚠️ RESTRICTED ACCESS
**This form is restricted to Open Home Foundation staff, authorized contributors, and integration code owners only.**
If you are a community member wanting to contribute, please:
- For bug reports: Use the [bug report form](https://github.com/home-assistant/core/issues/new?template=bug_report.yml)
- For feature requests: Submit to [Feature Requests](https://github.com/orgs/home-assistant/discussions)
---
### For authorized contributors
Use this form to create tasks for development work, improvements, or other actionable items that need to be tracked.
- type: textarea
id: description
attributes:
label: Description
description: |
Provide a clear and detailed description of the task that needs to be accomplished.
Be specific about what needs to be done, why it's important, and any constraints or requirements.
placeholder: |
Describe the task, including:
- What needs to be done
- Why this task is needed
- Expected outcome
- Any constraints or requirements
validations:
required: true
- type: textarea
id: additional_context
attributes:
label: Additional context
description: |
Any additional information, links, research, or context that would be helpful.
Include links to related issues, research, prototypes, roadmap opportunities etc.
placeholder: |
- Roadmap opportunity: [link]
- Epic: [link]
- Feature request: [link]
- Technical design documents: [link]
- Prototype/mockup: [link]
- Dependencies: [links]
validations:
required: false

File diff suppressed because it is too large Load Diff

View File

@ -6,3 +6,6 @@ updates:
interval: daily
time: "06:00"
open-pull-requests-limit: 10
labels:
- dependency
- github_actions

View File

@ -324,7 +324,7 @@ jobs:
uses: actions/checkout@v4.2.2
- name: Install Cosign
uses: sigstore/cosign-installer@v3.9.1
uses: sigstore/cosign-installer@v3.9.2
with:
cosign-release: "v2.2.3"

View File

@ -37,10 +37,10 @@ on:
type: boolean
env:
CACHE_VERSION: 3
CACHE_VERSION: 4
UV_CACHE_VERSION: 1
MYPY_CACHE_VERSION: 1
HA_SHORT_VERSION: "2025.7"
HA_SHORT_VERSION: "2025.8"
DEFAULT_PYTHON: "3.13"
ALL_PYTHON_VERSIONS: "['3.13']"
# 10.3 is the oldest supported version

View File

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

View File

@ -231,7 +231,7 @@ jobs:
- 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
uses: actions/ai-inference@v1.2.3
with:
model: openai/gpt-4o
system-prompt: |

View File

@ -57,7 +57,7 @@ jobs:
- name: Detect language using AI
id: ai_language_detection
if: steps.detect_language.outputs.should_continue == 'true'
uses: actions/ai-inference@v1.1.0
uses: actions/ai-inference@v1.2.3
with:
model: openai/gpt-4o-mini
system-prompt: |

View File

@ -0,0 +1,84 @@
name: Restrict task creation
# yamllint disable-line rule:truthy
on:
issues:
types: [opened]
jobs:
check-authorization:
runs-on: ubuntu-latest
# Only run if this is a Task issue type (from the issue form)
if: github.event.issue.issue_type == 'Task'
steps:
- name: Check if user is authorized
uses: actions/github-script@v7
with:
script: |
const issueAuthor = context.payload.issue.user.login;
// First check if user is an organization member
try {
await github.rest.orgs.checkMembershipForUser({
org: 'home-assistant',
username: issueAuthor
});
console.log(`✅ ${issueAuthor} is an organization member`);
return; // Authorized, no need to check further
} catch (error) {
console.log(` ${issueAuthor} is not an organization member, checking codeowners...`);
}
// If not an org member, check if they're a codeowner
try {
// Fetch CODEOWNERS file from the repository
const { data: codeownersFile } = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: 'CODEOWNERS',
ref: 'dev'
});
// Decode the content (it's base64 encoded)
const codeownersContent = Buffer.from(codeownersFile.content, 'base64').toString('utf-8');
// Check if the issue author is mentioned in CODEOWNERS
// GitHub usernames in CODEOWNERS are prefixed with @
if (codeownersContent.includes(`@${issueAuthor}`)) {
console.log(`✅ ${issueAuthor} is a integration code owner`);
return; // Authorized
}
} catch (error) {
console.error('Error checking CODEOWNERS:', error);
}
// If we reach here, user is not authorized
console.log(`❌ ${issueAuthor} is not authorized to create Task issues`);
// Close the issue with a comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Hi @${issueAuthor}, thank you for your contribution!\n\n` +
`Task issues are restricted to Open Home Foundation staff, authorized contributors, and integration code owners.\n\n` +
`If you would like to:\n` +
`- Report a bug: Please use the [bug report form](https://github.com/home-assistant/core/issues/new?template=bug_report.yml)\n` +
`- Request a feature: Please submit to [Feature Requests](https://github.com/orgs/home-assistant/discussions)\n\n` +
`If you believe you should have access to create Task issues, please contact the maintainers.`
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: 'closed'
});
// Add a label to indicate this was auto-closed
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['auto-closed']
});

6
.gitignore vendored
View File

@ -137,4 +137,8 @@ tmp_cache
.ropeproject
# Will be created from script/split_tests.py
pytest_buckets.txt
pytest_buckets.txt
# AI tooling
.claude

View File

@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.0
rev: v0.12.1
hooks:
- id: ruff-check
args:

View File

@ -53,6 +53,7 @@ homeassistant.components.air_quality.*
homeassistant.components.airgradient.*
homeassistant.components.airly.*
homeassistant.components.airnow.*
homeassistant.components.airos.*
homeassistant.components.airq.*
homeassistant.components.airthings.*
homeassistant.components.airthings_ble.*
@ -377,10 +378,12 @@ homeassistant.components.onedrive.*
homeassistant.components.onewire.*
homeassistant.components.onkyo.*
homeassistant.components.open_meteo.*
homeassistant.components.open_router.*
homeassistant.components.openai_conversation.*
homeassistant.components.openexchangerates.*
homeassistant.components.opensky.*
homeassistant.components.openuv.*
homeassistant.components.opower.*
homeassistant.components.oralb.*
homeassistant.components.otbr.*
homeassistant.components.overkiz.*
@ -499,6 +502,7 @@ homeassistant.components.tag.*
homeassistant.components.tailscale.*
homeassistant.components.tailwind.*
homeassistant.components.tami4.*
homeassistant.components.tankerkoenig.*
homeassistant.components.tautulli.*
homeassistant.components.tcp.*
homeassistant.components.technove.*
@ -534,6 +538,7 @@ homeassistant.components.unifiprotect.*
homeassistant.components.upcloud.*
homeassistant.components.update.*
homeassistant.components.uptime.*
homeassistant.components.uptime_kuma.*
homeassistant.components.uptimerobot.*
homeassistant.components.usb.*
homeassistant.components.uvc.*
@ -543,6 +548,7 @@ homeassistant.components.valve.*
homeassistant.components.velbus.*
homeassistant.components.vlc_telnet.*
homeassistant.components.vodafone_station.*
homeassistant.components.volvo.*
homeassistant.components.wake_on_lan.*
homeassistant.components.wake_word.*
homeassistant.components.wallbox.*

1
CLAUDE.md Symbolic link
View File

@ -0,0 +1 @@
.github/copilot-instructions.md

20
CODEOWNERS generated
View File

@ -67,6 +67,8 @@ build.json @home-assistant/supervisor
/tests/components/airly/ @bieniu
/homeassistant/components/airnow/ @asymworks
/tests/components/airnow/ @asymworks
/homeassistant/components/airos/ @CoMPaTech
/tests/components/airos/ @CoMPaTech
/homeassistant/components/airq/ @Sibgatulin @dl2080
/tests/components/airq/ @Sibgatulin @dl2080
/homeassistant/components/airthings/ @danielhiversen @LaStrada
@ -452,8 +454,8 @@ build.json @home-assistant/supervisor
/tests/components/eq3btsmart/ @eulemitkeule @dbuezas
/homeassistant/components/escea/ @lazdavila
/tests/components/escea/ @lazdavila
/homeassistant/components/esphome/ @OttoWinter @jesserockz @kbx81 @bdraco
/tests/components/esphome/ @OttoWinter @jesserockz @kbx81 @bdraco
/homeassistant/components/esphome/ @jesserockz @kbx81 @bdraco
/tests/components/esphome/ @jesserockz @kbx81 @bdraco
/homeassistant/components/eufylife_ble/ @bdr99
/tests/components/eufylife_ble/ @bdr99
/homeassistant/components/event/ @home-assistant/core
@ -684,8 +686,8 @@ build.json @home-assistant/supervisor
/tests/components/husqvarna_automower/ @Thomas55555
/homeassistant/components/husqvarna_automower_ble/ @alistair23
/tests/components/husqvarna_automower_ble/ @alistair23
/homeassistant/components/huum/ @frwickst
/tests/components/huum/ @frwickst
/homeassistant/components/huum/ @frwickst @vincentwolsink
/tests/components/huum/ @frwickst @vincentwolsink
/homeassistant/components/hvv_departures/ @vigonotion
/tests/components/hvv_departures/ @vigonotion
/homeassistant/components/hydrawise/ @dknowles2 @thomaskistler @ptcryan
@ -1102,6 +1104,8 @@ build.json @home-assistant/supervisor
/tests/components/onvif/ @hunterjm @jterrace
/homeassistant/components/open_meteo/ @frenck
/tests/components/open_meteo/ @frenck
/homeassistant/components/open_router/ @joostlek
/tests/components/open_router/ @joostlek
/homeassistant/components/openai_conversation/ @balloob
/tests/components/openai_conversation/ @balloob
/homeassistant/components/openerz/ @misialq
@ -1658,6 +1662,8 @@ build.json @home-assistant/supervisor
/tests/components/upnp/ @StevenLooman
/homeassistant/components/uptime/ @frenck
/tests/components/uptime/ @frenck
/homeassistant/components/uptime_kuma/ @tr4nt0r
/tests/components/uptime_kuma/ @tr4nt0r
/homeassistant/components/uptimerobot/ @ludeeus @chemelli74
/tests/components/uptimerobot/ @ludeeus @chemelli74
/homeassistant/components/usb/ @bdraco
@ -1702,6 +1708,8 @@ build.json @home-assistant/supervisor
/tests/components/voip/ @balloob @synesthesiam @jaminh
/homeassistant/components/volumio/ @OnFreund
/tests/components/volumio/ @OnFreund
/homeassistant/components/volvo/ @thomasddn
/tests/components/volvo/ @thomasddn
/homeassistant/components/volvooncall/ @molobrakos
/tests/components/volvooncall/ @molobrakos
/homeassistant/components/vulcan/ @Antoni-Czaplicki
@ -1756,8 +1764,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/wirelesstag/ @sergeymaysak
/homeassistant/components/withings/ @joostlek
/tests/components/withings/ @joostlek
/homeassistant/components/wiz/ @sbidy
/tests/components/wiz/ @sbidy
/homeassistant/components/wiz/ @sbidy @arturpragacz
/tests/components/wiz/ @sbidy @arturpragacz
/homeassistant/components/wled/ @frenck
/tests/components/wled/ @frenck
/homeassistant/components/wmspro/ @mback2k

View File

@ -1,15 +1,7 @@
FROM mcr.microsoft.com/devcontainers/python:1-3.13
FROM mcr.microsoft.com/vscode/devcontainers/base:debian
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Uninstall pre-installed formatting and linting tools
# They would conflict with our pinned versions
RUN \
pipx uninstall pydocstyle \
&& pipx uninstall pycodestyle \
&& pipx uninstall mypy \
&& pipx uninstall pylint
RUN \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& apt-get update \
@ -32,21 +24,18 @@ RUN \
libxml2 \
git \
cmake \
autoconf \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Add go2rtc binary
COPY --from=ghcr.io/alexxit/go2rtc:latest /usr/local/bin/go2rtc /bin/go2rtc
# Install uv
RUN pip3 install uv
WORKDIR /usr/src
# Setup hass-release
RUN git clone --depth 1 https://github.com/home-assistant/hass-release \
&& uv pip install --system -e hass-release/ \
&& chown -R vscode /usr/src/hass-release/data
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
RUN uv python install 3.13.2
USER vscode
ENV VIRTUAL_ENV="/home/vscode/.local/ha-venv"
@ -55,6 +44,10 @@ ENV PATH="$VIRTUAL_ENV/bin:$PATH"
WORKDIR /tmp
# Setup hass-release
RUN git clone --depth 1 https://github.com/home-assistant/hass-release ~/hass-release \
&& uv pip install -e ~/hass-release/
# Install Python dependencies from requirements
COPY requirements.txt ./
COPY homeassistant/package_constraints.txt homeassistant/package_constraints.txt
@ -65,4 +58,4 @@ RUN uv pip install -r requirements_test.txt
WORKDIR /workspaces
# Set the default shell to bash instead of sh
ENV SHELL /bin/bash
ENV SHELL=/bin/bash

View File

@ -75,8 +75,8 @@ from .core_config import async_process_ha_core_config
from .exceptions import HomeAssistantError
from .helpers import (
area_registry,
backup,
category_registry,
condition,
config_validation as cv,
device_registry,
entity,
@ -332,6 +332,9 @@ async def async_setup_hass(
if not is_virtual_env():
await async_mount_local_lib_path(runtime_config.config_dir)
if hass.config.safe_mode:
_LOGGER.info("Starting in safe mode")
basic_setup_success = (
await async_from_config_dict(config_dict, hass) is not None
)
@ -384,8 +387,6 @@ async def async_setup_hass(
{"recovery_mode": {}, "http": http_conf},
hass,
)
elif hass.config.safe_mode:
_LOGGER.info("Starting in safe mode")
if runtime_config.open_ui:
hass.add_job(open_hass_ui, hass)
@ -453,6 +454,7 @@ async def async_load_base_functionality(hass: core.HomeAssistant) -> None:
create_eager_task(restore_state.async_load(hass)),
create_eager_task(hass.config_entries.async_initialize()),
create_eager_task(async_get_system_info(hass)),
create_eager_task(condition.async_setup(hass)),
create_eager_task(trigger.async_setup(hass)),
)
@ -607,7 +609,7 @@ async def async_enable_logging(
)
threading.excepthook = lambda args: logging.getLogger().exception(
"Uncaught thread exception",
exc_info=( # type: ignore[arg-type] # noqa: LOG014
exc_info=( # type: ignore[arg-type]
args.exc_type,
args.exc_value,
args.exc_traceback,
@ -693,10 +695,10 @@ async def async_mount_local_lib_path(config_dir: str) -> str:
def _get_domains(hass: core.HomeAssistant, config: dict[str, Any]) -> set[str]:
"""Get domains of components to set up."""
# Filter out the repeating and common config section [homeassistant]
domains = {
domain for key in config if (domain := cv.domain_key(key)) != core.DOMAIN
}
# The common config section [homeassistant] could be filtered here,
# but that is not necessary, since it corresponds to the core integration,
# that is always unconditionally loaded.
domains = {cv.domain_key(key) for key in config}
# Add config entry and default domains
if not hass.config.recovery_mode:
@ -724,34 +726,28 @@ async def _async_resolve_domains_and_preload(
together with all their dependencies.
"""
domains_to_setup = _get_domains(hass, config)
platform_integrations = conf_util.extract_platform_integrations(
config, BASE_PLATFORMS
)
# Ensure base platforms that have platform integrations are added to `domains`,
# so they can be setup first instead of discovering them later when a config
# entry setup task notices that it's needed and there is already a long line
# to use the import executor.
# Also process all base platforms since we do not require the manifest
# to list them as dependencies.
# We want to later avoid lock contention when multiple integrations try to load
# their manifests at once.
#
# Additionally process integrations that are defined under base platforms
# to speed things up.
# For example if we have
# sensor:
# - platform: template
#
# `template` has to be loaded to validate the config for sensor
# so we want to start loading `sensor` as soon as we know
# it will be needed. The more platforms under `sensor:`, the longer
# `template` has to be loaded to validate the config for sensor.
# The more platforms under `sensor:`, the longer
# it will take to finish setup for `sensor` because each of these
# platforms has to be imported before we can validate the config.
#
# Thankfully we are migrating away from the platform pattern
# so this will be less of a problem in the future.
domains_to_setup.update(platform_integrations)
# Additionally process base platforms since we do not require the manifest
# to list them as dependencies.
# We want to later avoid lock contention when multiple integrations try to load
# their manifests at once.
# Also process integrations that are defined under base platforms
# to speed things up.
platform_integrations = conf_util.extract_platform_integrations(
config, BASE_PLATFORMS
)
additional_domains_to_process = {
*BASE_PLATFORMS,
*chain.from_iterable(platform_integrations.values()),
@ -869,9 +865,9 @@ async def _async_set_up_integrations(
domains = set(integrations) & all_domains
_LOGGER.info(
"Domains to be set up: %s | %s",
domains,
all_domains - domains,
"Domains to be set up: %s\nDependencies: %s",
domains or "{}",
(all_domains - domains) or "{}",
)
async_set_domains_to_be_loaded(hass, all_domains)
@ -880,10 +876,6 @@ async def _async_set_up_integrations(
if "recorder" in all_domains:
recorder.async_initialize_recorder(hass)
# Initialize backup
if "backup" in all_domains:
backup.async_initialize_backup(hass)
stages: list[tuple[str, set[str], int | None]] = [
*(
(name, domain_group, timeout)
@ -916,12 +908,13 @@ async def _async_set_up_integrations(
stage_all_domains = stage_domains | stage_dep_domains
_LOGGER.info(
"Setting up stage %s: %s | %s\nDependencies: %s | %s",
"Setting up stage %s: %s; already set up: %s\n"
"Dependencies: %s; already set up: %s",
name,
stage_domains,
stage_domains_unfiltered - stage_domains,
stage_dep_domains,
stage_dep_domains_unfiltered - stage_dep_domains,
(stage_domains_unfiltered - stage_domains) or "{}",
stage_dep_domains or "{}",
(stage_dep_domains_unfiltered - stage_dep_domains) or "{}",
)
if timeout is None:
@ -1061,5 +1054,5 @@ async def _async_setup_multi_components(
_LOGGER.error(
"Error setting up integration %s - received exception",
domain,
exc_info=(type(result), result, result.__traceback__), # noqa: LOG014
exc_info=(type(result), result, result.__traceback__),
)

View File

@ -1,5 +1,5 @@
{
"domain": "ubiquiti",
"name": "Ubiquiti",
"integrations": ["unifi", "unifi_direct", "unifiled", "unifiprotect"]
"integrations": ["airos", "unifi", "unifi_direct", "unifiled", "unifiprotect"]
}

View File

@ -1,11 +1,12 @@
"""Integration to offer AI tasks to Home Assistant."""
import logging
from typing import Any
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.const import ATTR_ENTITY_ID, CONF_DESCRIPTION, CONF_SELECTOR
from homeassistant.core import (
HassJobType,
HomeAssistant,
@ -14,12 +15,15 @@ from homeassistant.core import (
SupportsResponse,
callback,
)
from homeassistant.helpers import config_validation as cv, storage
from homeassistant.helpers import config_validation as cv, selector, storage
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import UNDEFINED, ConfigType, UndefinedType
from .const import (
ATTR_ATTACHMENTS,
ATTR_INSTRUCTIONS,
ATTR_REQUIRED,
ATTR_STRUCTURE,
ATTR_TASK_NAME,
DATA_COMPONENT,
DATA_PREFERENCES,
@ -47,6 +51,27 @@ _LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
STRUCTURE_FIELD_SCHEMA = vol.Schema(
{
vol.Optional(CONF_DESCRIPTION): str,
vol.Optional(ATTR_REQUIRED): bool,
vol.Required(CONF_SELECTOR): selector.validate_selector,
}
)
def _validate_structure_fields(value: dict[str, Any]) -> vol.Schema:
"""Validate the structure fields as a voluptuous Schema."""
if not isinstance(value, dict):
raise vol.Invalid("Structure must be a dictionary")
fields = {}
for k, v in value.items():
field_class = vol.Required if v.get(ATTR_REQUIRED, False) else vol.Optional
fields[field_class(k, description=v.get(CONF_DESCRIPTION))] = selector.selector(
v[CONF_SELECTOR]
)
return vol.Schema(fields, extra=vol.PREVENT_EXTRA)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Register the process service."""
@ -64,6 +89,13 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
vol.Required(ATTR_TASK_NAME): cv.string,
vol.Optional(ATTR_ENTITY_ID): cv.entity_id,
vol.Required(ATTR_INSTRUCTIONS): cv.string,
vol.Optional(ATTR_STRUCTURE): vol.All(
vol.Schema({str: STRUCTURE_FIELD_SCHEMA}),
_validate_structure_fields,
),
vol.Optional(ATTR_ATTACHMENTS): vol.All(
cv.ensure_list, [selector.MediaSelector({"accept": ["*/*"]})]
),
}
),
supports_response=SupportsResponse.ONLY,

View File

@ -21,6 +21,9 @@ SERVICE_GENERATE_DATA = "generate_data"
ATTR_INSTRUCTIONS: Final = "instructions"
ATTR_TASK_NAME: Final = "task_name"
ATTR_STRUCTURE: Final = "structure"
ATTR_REQUIRED: Final = "required"
ATTR_ATTACHMENTS: Final = "attachments"
DEFAULT_SYSTEM_PROMPT = (
"You are a Home Assistant expert and help users with their tasks."
@ -32,3 +35,6 @@ class AITaskEntityFeature(IntFlag):
GENERATE_DATA = 1
"""Generate data based on instructions."""
SUPPORT_ATTACHMENTS = 2
"""Support attachments with generate data."""

View File

@ -13,7 +13,7 @@ from homeassistant.components.conversation import (
)
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.chat_session import ChatSession
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.util import dt as dt_util
@ -56,12 +56,12 @@ class AITaskEntity(RestoreEntity):
@contextlib.asynccontextmanager
async def _async_get_ai_task_chat_log(
self,
session: ChatSession,
task: GenDataTask,
) -> 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,
@ -79,19 +79,22 @@ class AITaskEntity(RestoreEntity):
user_llm_prompt=DEFAULT_SYSTEM_PROMPT,
)
chat_log.async_add_user_content(UserContent(task.instructions))
chat_log.async_add_user_content(
UserContent(task.instructions, attachments=task.attachments)
)
yield chat_log
@final
async def internal_async_generate_data(
self,
session: ChatSession,
task: GenDataTask,
) -> GenDataTaskResult:
"""Run a gen data 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:
async with self._async_get_ai_task_chat_log(session, task) as chat_log:
return await self._async_generate_data(task, chat_log)
async def _async_generate_data(

View File

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

View File

@ -10,10 +10,24 @@ generate_data:
required: true
selector:
text:
multiline: true
entity_id:
required: false
selector:
entity:
domain: ai_task
supported_features:
- ai_task.AITaskEntityFeature.GENERATE_DATA
filter:
domain: ai_task
supported_features:
- ai_task.AITaskEntityFeature.GENERATE_DATA
structure:
advanced: true
required: false
example: '{ "name": { "selector": { "text": }, "description": "Name of the user", "required": "True" } } }, "age": { "selector": { "number": }, "description": "Age of the user" } }'
selector:
object:
attachments:
required: false
selector:
media:
accept:
- "*"

View File

@ -15,6 +15,14 @@
"entity_id": {
"name": "Entity ID",
"description": "Entity ID to run the task on. If not provided, the preferred entity will be used."
},
"structure": {
"name": "Structured output",
"description": "When set, the AI Task will output fields with this in structure. The structure is a dictionary where the keys are the field names and the values contain a 'description', a 'selector', and an optional 'required' field."
},
"attachments": {
"name": "Attachments",
"description": "List of files to attach for multi-modal AI analysis."
}
}
}

View File

@ -3,20 +3,40 @@
from __future__ import annotations
from dataclasses import dataclass
import mimetypes
from pathlib import Path
import tempfile
from typing import Any
from homeassistant.core import HomeAssistant
import voluptuous as vol
from homeassistant.components import camera, conversation, media_source
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.chat_session import async_get_chat_session
from .const import DATA_COMPONENT, DATA_PREFERENCES, AITaskEntityFeature
def _save_camera_snapshot(image: camera.Image) -> Path:
"""Save camera snapshot to temp file."""
with tempfile.NamedTemporaryFile(
mode="wb",
suffix=mimetypes.guess_extension(image.content_type, False),
delete=False,
) as temp_file:
temp_file.write(image.content)
return Path(temp_file.name)
async def async_generate_data(
hass: HomeAssistant,
*,
task_name: str,
entity_id: str | None = None,
instructions: str,
structure: vol.Schema | None = None,
attachments: list[dict] | None = None,
) -> GenDataTaskResult:
"""Run a task in the AI Task integration."""
if entity_id is None:
@ -34,12 +54,80 @@ async def async_generate_data(
f"AI Task entity {entity_id} does not support generating data"
)
return await entity.internal_async_generate_data(
GenDataTask(
name=task_name,
instructions=instructions,
# Resolve attachments
resolved_attachments: list[conversation.Attachment] = []
created_files: list[Path] = []
if (
attachments
and AITaskEntityFeature.SUPPORT_ATTACHMENTS not in entity.supported_features
):
raise HomeAssistantError(
f"AI Task entity {entity_id} does not support attachments"
)
for attachment in attachments or []:
media_content_id = attachment["media_content_id"]
# Special case for camera media sources
if media_content_id.startswith("media-source://camera/"):
# Extract entity_id from the media content ID
entity_id = media_content_id.removeprefix("media-source://camera/")
# Get snapshot from camera
image = await camera.async_get_image(hass, entity_id)
temp_filename = await hass.async_add_executor_job(
_save_camera_snapshot, image
)
created_files.append(temp_filename)
resolved_attachments.append(
conversation.Attachment(
media_content_id=media_content_id,
mime_type=image.content_type,
path=temp_filename,
)
)
else:
# Handle regular media sources
media = await media_source.async_resolve_media(hass, media_content_id, None)
if media.path is None:
raise HomeAssistantError(
"Only local attachments are currently supported"
)
resolved_attachments.append(
conversation.Attachment(
media_content_id=media_content_id,
mime_type=media.mime_type,
path=media.path,
)
)
with async_get_chat_session(hass) as session:
if created_files:
def cleanup_files() -> None:
"""Cleanup temporary files."""
for file in created_files:
file.unlink(missing_ok=True)
@callback
def cleanup_files_callback() -> None:
"""Cleanup temporary files."""
hass.async_add_executor_job(cleanup_files)
session.async_on_cleanup(cleanup_files_callback)
return await entity.internal_async_generate_data(
session,
GenDataTask(
name=task_name,
instructions=instructions,
structure=structure,
attachments=resolved_attachments or None,
),
)
)
@dataclass(slots=True)
@ -52,6 +140,12 @@ class GenDataTask:
instructions: str
"""Instructions on what needs to be done."""
structure: vol.Schema | None = None
"""Optional structure for the data to be generated."""
attachments: list[conversation.Attachment] | None = None
"""List of attachments to go along the instructions."""
def __str__(self) -> str:
"""Return task as a string."""
return f"<GenDataTask {self.name}: {id(self)}>"

View File

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

View File

@ -14,9 +14,9 @@ rules:
status: exempt
comment: |
This integration does not provide additional actions.
docs-high-level-description: todo
docs-installation-instructions: todo
docs-removal-instructions: todo
docs-high-level-description: done
docs-installation-instructions: done
docs-removal-instructions: done
entity-event-setup:
status: exempt
comment: |
@ -34,7 +34,7 @@ rules:
docs-configuration-parameters:
status: exempt
comment: No options to configure
docs-installation-parameters: todo
docs-installation-parameters: done
entity-unavailable: done
integration-owner: done
log-when-unavailable: done
@ -43,23 +43,19 @@ rules:
status: exempt
comment: |
This integration does not require authentication.
test-coverage: todo
test-coverage: done
# Gold
devices: done
diagnostics: done
discovery-update-info:
status: todo
comment: DHCP is still possible
discovery:
status: todo
comment: DHCP is still possible
docs-data-update: todo
docs-examples: todo
docs-known-limitations: todo
docs-supported-devices: todo
docs-supported-functions: todo
docs-troubleshooting: todo
docs-use-cases: todo
discovery-update-info: done
discovery: done
docs-data-update: done
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: done
docs-use-cases: done
dynamic-devices:
status: exempt
comment: |

View File

@ -45,9 +45,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirNowConfigEntry) -> bo
# Store Entity and Initialize Platforms
entry.runtime_data = coordinator
# Listen for option changes
entry.async_on_unload(entry.add_update_listener(update_listener))
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
# Clean up unused device entries with no entities
@ -88,8 +85,3 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: AirNowConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)

View File

@ -13,7 +13,7 @@ from homeassistant.config_entries import (
ConfigEntry,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
OptionsFlowWithReload,
)
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_RADIUS
from homeassistant.core import HomeAssistant, callback
@ -126,7 +126,7 @@ class AirNowConfigFlow(ConfigFlow, domain=DOMAIN):
return AirNowOptionsFlowHandler()
class AirNowOptionsFlowHandler(OptionsFlow):
class AirNowOptionsFlowHandler(OptionsFlowWithReload):
"""Handle an options flow for AirNow."""
async def async_step_init(

View File

@ -0,0 +1,42 @@
"""The Ubiquiti airOS integration."""
from __future__ import annotations
from airos.airos8 import AirOS
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .coordinator import AirOSConfigEntry, AirOSDataUpdateCoordinator
_PLATFORMS: list[Platform] = [Platform.SENSOR]
async def async_setup_entry(hass: HomeAssistant, entry: AirOSConfigEntry) -> bool:
"""Set up Ubiquiti airOS from a config entry."""
# By default airOS 8 comes with self-signed SSL certificates,
# with no option in the web UI to change or upload a custom certificate.
session = async_get_clientsession(hass, verify_ssl=False)
airos_device = AirOS(
host=entry.data[CONF_HOST],
username=entry.data[CONF_USERNAME],
password=entry.data[CONF_PASSWORD],
session=session,
)
coordinator = AirOSDataUpdateCoordinator(hass, entry, airos_device)
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: AirOSConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, _PLATFORMS)

View File

@ -0,0 +1,82 @@
"""Config flow for the Ubiquiti airOS integration."""
from __future__ import annotations
import logging
from typing import Any
from airos.exceptions import (
ConnectionAuthenticationError,
ConnectionSetupError,
DataMissingError,
DeviceConnectionError,
KeyDataMissingError,
)
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
from .coordinator import AirOS
_LOGGER = logging.getLogger(__name__)
STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Required(CONF_USERNAME, default="ubnt"): str,
vol.Required(CONF_PASSWORD): str,
}
)
class AirOSConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Ubiquiti airOS."""
VERSION = 1
async def async_step_user(
self,
user_input: dict[str, Any] | None = None,
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
# By default airOS 8 comes with self-signed SSL certificates,
# with no option in the web UI to change or upload a custom certificate.
session = async_get_clientsession(self.hass, verify_ssl=False)
airos_device = AirOS(
host=user_input[CONF_HOST],
username=user_input[CONF_USERNAME],
password=user_input[CONF_PASSWORD],
session=session,
)
try:
await airos_device.login()
airos_data = await airos_device.status()
except (
ConnectionSetupError,
DeviceConnectionError,
):
errors["base"] = "cannot_connect"
except (ConnectionAuthenticationError, DataMissingError):
errors["base"] = "invalid_auth"
except KeyDataMissingError:
errors["base"] = "key_data_missing"
except Exception:
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
await self.async_set_unique_id(airos_data.derived.mac)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=airos_data.host.hostname, data=user_input
)
return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
)

View File

@ -0,0 +1,9 @@
"""Constants for the Ubiquiti airOS integration."""
from datetime import timedelta
DOMAIN = "airos"
SCAN_INTERVAL = timedelta(minutes=1)
MANUFACTURER = "Ubiquiti"

View File

@ -0,0 +1,66 @@
"""DataUpdateCoordinator for AirOS."""
from __future__ import annotations
import logging
from airos.airos8 import AirOS, AirOSData
from airos.exceptions import (
ConnectionAuthenticationError,
ConnectionSetupError,
DataMissingError,
DeviceConnectionError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN, SCAN_INTERVAL
_LOGGER = logging.getLogger(__name__)
type AirOSConfigEntry = ConfigEntry[AirOSDataUpdateCoordinator]
class AirOSDataUpdateCoordinator(DataUpdateCoordinator[AirOSData]):
"""Class to manage fetching AirOS data from single endpoint."""
config_entry: AirOSConfigEntry
def __init__(
self, hass: HomeAssistant, config_entry: AirOSConfigEntry, airos_device: AirOS
) -> None:
"""Initialize the coordinator."""
self.airos_device = airos_device
super().__init__(
hass,
_LOGGER,
config_entry=config_entry,
name=DOMAIN,
update_interval=SCAN_INTERVAL,
)
async def _async_update_data(self) -> AirOSData:
"""Fetch data from AirOS."""
try:
await self.airos_device.login()
return await self.airos_device.status()
except (ConnectionAuthenticationError,) as err:
_LOGGER.exception("Error authenticating with airOS device")
raise ConfigEntryError(
translation_domain=DOMAIN, translation_key="invalid_auth"
) from err
except (ConnectionSetupError, DeviceConnectionError, TimeoutError) as err:
_LOGGER.error("Error connecting to airOS device: %s", err)
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="cannot_connect",
) from err
except (DataMissingError,) as err:
_LOGGER.error("Expected data not returned by airOS device: %s", err)
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="error_data_missing",
) from err

View File

@ -0,0 +1,36 @@
"""Generic AirOS Entity Class."""
from __future__ import annotations
from homeassistant.const import CONF_HOST
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN, MANUFACTURER
from .coordinator import AirOSDataUpdateCoordinator
class AirOSEntity(CoordinatorEntity[AirOSDataUpdateCoordinator]):
"""Represent a AirOS Entity."""
_attr_has_entity_name = True
def __init__(self, coordinator: AirOSDataUpdateCoordinator) -> None:
"""Initialise the gateway."""
super().__init__(coordinator)
airos_data = self.coordinator.data
configuration_url: str | None = (
f"https://{coordinator.config_entry.data[CONF_HOST]}"
)
self._attr_device_info = DeviceInfo(
connections={(CONNECTION_NETWORK_MAC, airos_data.derived.mac)},
configuration_url=configuration_url,
identifiers={(DOMAIN, str(airos_data.host.device_id))},
manufacturer=MANUFACTURER,
model=airos_data.host.devmodel,
name=airos_data.host.hostname,
sw_version=airos_data.host.fwversion,
)

View File

@ -0,0 +1,10 @@
{
"domain": "airos",
"name": "Ubiquiti airOS",
"codeowners": ["@CoMPaTech"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/airos",
"iot_class": "local_polling",
"quality_scale": "bronze",
"requirements": ["airos==0.2.1"]
}

View File

@ -0,0 +1,72 @@
rules:
# Bronze
action-setup:
status: exempt
comment: airOS does not have 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: airOS does not have actions
docs-high-level-description: done
docs-installation-instructions: done
docs-removal-instructions: done
entity-event-setup:
status: exempt
comment: local_polling without events
entity-unique-id: done
has-entity-name: done
runtime-data: done
test-before-configure: done
test-before-setup: done
unique-config-entry: done
# Silver
action-exceptions:
status: exempt
comment: airOS does not have actions
config-entry-unloading: done
docs-configuration-parameters: done
docs-installation-parameters: done
entity-unavailable: todo
integration-owner: done
log-when-unavailable: todo
parallel-updates: todo
reauthentication-flow: todo
test-coverage: done
# Gold
devices: done
diagnostics: todo
discovery-update-info: todo
discovery: todo
docs-data-update: done
docs-examples: todo
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: todo
docs-troubleshooting: done
docs-use-cases: todo
dynamic-devices: todo
entity-category: done
entity-device-class: done
entity-disabled-by-default:
status: todo
comment: prepared binary_sensors will provide this
entity-translations: done
exception-translations: done
icon-translations:
status: exempt
comment: no (custom) icons used or envisioned
reconfiguration-flow: todo
repair-issues: todo
stale-devices: todo
# Platinum
async-dependency: done
inject-websession: done
strict-typing: done

View File

@ -0,0 +1,152 @@
"""AirOS Sensor component for Home Assistant."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import logging
from airos.data import NetRole, WirelessMode
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS,
UnitOfDataRate,
UnitOfFrequency,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .coordinator import AirOSConfigEntry, AirOSData, AirOSDataUpdateCoordinator
from .entity import AirOSEntity
_LOGGER = logging.getLogger(__name__)
WIRELESS_MODE_OPTIONS = [mode.value.replace("-", "_").lower() for mode in WirelessMode]
NETROLE_OPTIONS = [mode.value for mode in NetRole]
@dataclass(frozen=True, kw_only=True)
class AirOSSensorEntityDescription(SensorEntityDescription):
"""Describe an AirOS sensor."""
value_fn: Callable[[AirOSData], StateType]
SENSORS: tuple[AirOSSensorEntityDescription, ...] = (
AirOSSensorEntityDescription(
key="host_cpuload",
translation_key="host_cpuload",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.host.cpuload,
entity_registry_enabled_default=False,
),
AirOSSensorEntityDescription(
key="host_netrole",
translation_key="host_netrole",
device_class=SensorDeviceClass.ENUM,
value_fn=lambda data: data.host.netrole.value,
options=NETROLE_OPTIONS,
),
AirOSSensorEntityDescription(
key="wireless_frequency",
translation_key="wireless_frequency",
native_unit_of_measurement=UnitOfFrequency.MEGAHERTZ,
device_class=SensorDeviceClass.FREQUENCY,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.wireless.frequency,
),
AirOSSensorEntityDescription(
key="wireless_essid",
translation_key="wireless_essid",
value_fn=lambda data: data.wireless.essid,
),
AirOSSensorEntityDescription(
key="wireless_mode",
translation_key="wireless_mode",
device_class=SensorDeviceClass.ENUM,
value_fn=lambda data: data.wireless.mode.value.replace("-", "_").lower(),
options=WIRELESS_MODE_OPTIONS,
),
AirOSSensorEntityDescription(
key="wireless_antenna_gain",
translation_key="wireless_antenna_gain",
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.wireless.antenna_gain,
),
AirOSSensorEntityDescription(
key="wireless_throughput_tx",
translation_key="wireless_throughput_tx",
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
device_class=SensorDeviceClass.DATA_RATE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.wireless.throughput.tx,
),
AirOSSensorEntityDescription(
key="wireless_throughput_rx",
translation_key="wireless_throughput_rx",
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
device_class=SensorDeviceClass.DATA_RATE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.wireless.throughput.rx,
),
AirOSSensorEntityDescription(
key="wireless_polling_dl_capacity",
translation_key="wireless_polling_dl_capacity",
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
device_class=SensorDeviceClass.DATA_RATE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.wireless.polling.dl_capacity,
),
AirOSSensorEntityDescription(
key="wireless_polling_ul_capacity",
translation_key="wireless_polling_ul_capacity",
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
device_class=SensorDeviceClass.DATA_RATE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.wireless.polling.ul_capacity,
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: AirOSConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the AirOS sensors from a config entry."""
coordinator = config_entry.runtime_data
async_add_entities(AirOSSensor(coordinator, description) for description in SENSORS)
class AirOSSensor(AirOSEntity, SensorEntity):
"""Representation of a Sensor."""
entity_description: AirOSSensorEntityDescription
def __init__(
self,
coordinator: AirOSDataUpdateCoordinator,
description: AirOSSensorEntityDescription,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.data.derived.mac}_{description.key}"
@property
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self.entity_description.value_fn(self.coordinator.data)

View File

@ -0,0 +1,87 @@
{
"config": {
"flow_title": "Ubiquiti airOS device",
"step": {
"user": {
"data": {
"host": "[%key:common::config_flow::data::host%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]"
},
"data_description": {
"host": "IP address or hostname of the airOS device",
"username": "Administrator username for the airOS device, normally 'ubnt'",
"password": "Password configured through the UISP app or web interface"
}
}
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"key_data_missing": "Expected data not returned from the device, check the documentation for supported devices",
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}
},
"entity": {
"sensor": {
"host_cpuload": {
"name": "CPU load"
},
"host_netrole": {
"name": "Network role",
"state": {
"bridge": "Bridge",
"router": "Router"
}
},
"wireless_frequency": {
"name": "Wireless frequency"
},
"wireless_essid": {
"name": "Wireless SSID"
},
"wireless_mode": {
"name": "Wireless mode",
"state": {
"ap_ptp": "Access point",
"sta_ptp": "Station"
}
},
"wireless_antenna_gain": {
"name": "Antenna gain"
},
"wireless_throughput_tx": {
"name": "Throughput transmit (actual)"
},
"wireless_throughput_rx": {
"name": "Throughput receive (actual)"
},
"wireless_polling_dl_capacity": {
"name": "Download capacity"
},
"wireless_polling_ul_capacity": {
"name": "Upload capacity"
},
"wireless_remote_hostname": {
"name": "Remote hostname"
}
}
},
"exceptions": {
"invalid_auth": {
"message": "[%key:common::config_flow::error::invalid_auth%]"
},
"cannot_connect": {
"message": "[%key:common::config_flow::error::cannot_connect%]"
},
"key_data_missing": {
"message": "Key data not returned from device"
},
"error_data_missing": {
"message": "Data incomplete or missing"
}
}
}

View File

@ -6,6 +6,5 @@ CONF_RETURN_AVERAGE: Final = "return_average"
CONF_CLIP_NEGATIVE: Final = "clip_negatives"
DOMAIN: Final = "airq"
MANUFACTURER: Final = "CorantGmbH"
CONCENTRATION_GRAMS_PER_CUBIC_METER: Final = "g/m³"
ACTIVITY_BECQUEREL_PER_CUBIC_METER: Final = "Bq/m³"
UPDATE_INTERVAL: float = 10.0

View File

@ -4,9 +4,6 @@
"health_index": {
"default": "mdi:heart-pulse"
},
"absolute_humidity": {
"default": "mdi:water"
},
"oxygen": {
"default": "mdi:leaf"
},

View File

@ -14,6 +14,7 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_GRAMS_PER_CUBIC_METER,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
@ -28,10 +29,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import AirQConfigEntry, AirQCoordinator
from .const import (
ACTIVITY_BECQUEREL_PER_CUBIC_METER,
CONCENTRATION_GRAMS_PER_CUBIC_METER,
)
from .const import ACTIVITY_BECQUEREL_PER_CUBIC_METER
_LOGGER = logging.getLogger(__name__)
@ -195,7 +193,7 @@ SENSOR_TYPES: list[AirQEntityDescription] = [
),
AirQEntityDescription(
key="humidity_abs",
translation_key="absolute_humidity",
device_class=SensorDeviceClass.ABSOLUTE_HUMIDITY,
native_unit_of_measurement=CONCENTRATION_GRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value=lambda data: data.get("humidity_abs"),

View File

@ -93,9 +93,6 @@
"health_index": {
"name": "Health index"
},
"absolute_humidity": {
"name": "Absolute humidity"
},
"hydrogen": {
"name": "Hydrogen"
},

View File

@ -45,6 +45,8 @@ class AirthingsConfigFlow(ConfigFlow, domain=DOMAIN):
)
errors = {}
await self.async_set_unique_id(user_input[CONF_ID])
self._abort_if_unique_id_configured()
try:
await airthings.get_token(
@ -60,9 +62,6 @@ class AirthingsConfigFlow(ConfigFlow, domain=DOMAIN):
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
await self.async_set_unique_id(user_input[CONF_ID])
self._abort_if_unique_id_configured()
return self.async_create_entry(title="Airthings", data=user_input)
return self.async_show_form(

View File

@ -150,7 +150,7 @@ async def async_setup_entry(
coordinator = entry.runtime_data
entities = [
AirthingsHeaterEnergySensor(
AirthingsDeviceSensor(
coordinator,
airthings_device,
SENSORS[sensor_types],
@ -162,7 +162,7 @@ async def async_setup_entry(
async_add_entities(entities)
class AirthingsHeaterEnergySensor(
class AirthingsDeviceSensor(
CoordinatorEntity[AirthingsDataUpdateCoordinator], SensorEntity
):
"""Representation of a Airthings Sensor device."""

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/airzone_cloud",
"iot_class": "cloud_push",
"loggers": ["aioairzone_cloud"],
"requirements": ["aioairzone-cloud==0.6.12"]
"requirements": ["aioairzone-cloud==0.7.1"]
}

View File

@ -505,8 +505,13 @@ class ClimateCapabilities(AlexaEntity):
):
yield AlexaThermostatController(self.hass, self.entity)
yield AlexaTemperatureSensor(self.hass, self.entity)
if self.entity.domain == water_heater.DOMAIN and (
supported_features & water_heater.WaterHeaterEntityFeature.OPERATION_MODE
if (
self.entity.domain == water_heater.DOMAIN
and (
supported_features
& water_heater.WaterHeaterEntityFeature.OPERATION_MODE
)
and self.entity.attributes.get(water_heater.ATTR_OPERATION_LIST)
):
yield AlexaModeController(
self.entity,
@ -634,7 +639,9 @@ class FanCapabilities(AlexaEntity):
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}"
)
force_range_controller = False
if supported & fan.FanEntityFeature.PRESET_MODE:
if supported & fan.FanEntityFeature.PRESET_MODE and self.entity.attributes.get(
fan.ATTR_PRESET_MODES
):
yield AlexaModeController(
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_PRESET_MODE}"
)
@ -672,7 +679,11 @@ class RemoteCapabilities(AlexaEntity):
yield AlexaPowerController(self.entity)
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
activities = self.entity.attributes.get(remote.ATTR_ACTIVITY_LIST) or []
if activities and supported & remote.RemoteEntityFeature.ACTIVITY:
if (
activities
and (supported & remote.RemoteEntityFeature.ACTIVITY)
and self.entity.attributes.get(remote.ATTR_ACTIVITY_LIST)
):
yield AlexaModeController(
self.entity, instance=f"{remote.DOMAIN}.{remote.ATTR_ACTIVITY}"
)
@ -692,7 +703,9 @@ class HumidifierCapabilities(AlexaEntity):
"""Yield the supported interfaces."""
yield AlexaPowerController(self.entity)
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
if supported & humidifier.HumidifierEntityFeature.MODES:
if (
supported & humidifier.HumidifierEntityFeature.MODES
) and self.entity.attributes.get(humidifier.ATTR_AVAILABLE_MODES):
yield AlexaModeController(
self.entity, instance=f"{humidifier.DOMAIN}.{humidifier.ATTR_MODE}"
)

View File

@ -2,19 +2,50 @@
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from aioamazondevices.api import AmazonEchoApi
from aioamazondevices.exceptions import CannotAuthenticate, CannotConnect, WrongCountry
from aioamazondevices.exceptions import (
CannotAuthenticate,
CannotConnect,
CannotRetrieveData,
WrongCountry,
)
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_CODE, CONF_COUNTRY, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.selector import CountrySelector
from .const import CONF_LOGIN_DATA, DOMAIN
STEP_REAUTH_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_CODE): cv.string,
}
)
async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, Any]:
"""Validate the user input allows us to connect."""
api = AmazonEchoApi(
data[CONF_COUNTRY],
data[CONF_USERNAME],
data[CONF_PASSWORD],
)
try:
data = await api.login_mode_interactive(data[CONF_CODE])
finally:
await api.close()
return data
class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Alexa Devices."""
@ -25,17 +56,14 @@ class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
"""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])
data = await validate_input(self.hass, user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except CannotAuthenticate:
errors["base"] = "invalid_auth"
except CannotRetrieveData:
errors["base"] = "cannot_retrieve_data"
except WrongCountry:
errors["base"] = "wrong_country"
else:
@ -46,8 +74,6 @@ class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
title=user_input[CONF_USERNAME],
data=user_input | {CONF_LOGIN_DATA: data},
)
finally:
await client.close()
return self.async_show_form(
step_id="user",
@ -63,3 +89,45 @@ class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
}
),
)
async def async_step_reauth(
self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle reauth flow."""
self.context["title_placeholders"] = {CONF_USERNAME: entry_data[CONF_USERNAME]}
return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle reauth confirm."""
errors: dict[str, str] = {}
reauth_entry = self._get_reauth_entry()
entry_data = reauth_entry.data
if user_input is not None:
try:
await validate_input(self.hass, {**reauth_entry.data, **user_input})
except CannotConnect:
errors["base"] = "cannot_connect"
except CannotAuthenticate:
errors["base"] = "invalid_auth"
except CannotRetrieveData:
errors["base"] = "cannot_retrieve_data"
else:
return self.async_update_reload_and_abort(
reauth_entry,
data={
CONF_USERNAME: entry_data[CONF_USERNAME],
CONF_PASSWORD: entry_data[CONF_PASSWORD],
CONF_CODE: user_input[CONF_CODE],
},
)
return self.async_show_form(
step_id="reauth_confirm",
description_placeholders={CONF_USERNAME: entry_data[CONF_USERNAME]},
data_schema=STEP_REAUTH_DATA_SCHEMA,
errors=errors,
)

View File

@ -12,10 +12,10 @@ from aioamazondevices.exceptions import (
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.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import _LOGGER, CONF_LOGIN_DATA
from .const import _LOGGER, CONF_LOGIN_DATA, DOMAIN
SCAN_INTERVAL = 30
@ -52,7 +52,21 @@ class AmazonDevicesCoordinator(DataUpdateCoordinator[dict[str, AmazonDevice]]):
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 CannotConnect as err:
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="cannot_connect_with_error",
translation_placeholders={"error": repr(err)},
) from err
except CannotRetrieveData as err:
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="cannot_retrieve_data_with_error",
translation_placeholders={"error": repr(err)},
) from err
except CannotAuthenticate as err:
raise ConfigEntryError("Could not authenticate") from err
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
translation_key="invalid_auth",
translation_placeholders={"error": repr(err)},
) from err

View File

@ -7,6 +7,6 @@
"integration_type": "hub",
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "bronze",
"requirements": ["aioamazondevices==3.2.1"]
"quality_scale": "silver",
"requirements": ["aioamazondevices==3.5.1"]
}

View File

@ -28,39 +28,37 @@ rules:
# Silver
action-exceptions: done
config-entry-unloading: done
docs-configuration-parameters: todo
docs-installation-parameters: todo
docs-configuration-parameters: done
docs-installation-parameters: done
entity-unavailable: done
integration-owner: done
log-when-unavailable: done
parallel-updates: done
reauthentication-flow: todo
test-coverage:
status: todo
comment: all tests missing
reauthentication-flow: done
test-coverage: done
# Gold
devices: done
diagnostics: todo
diagnostics: done
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
docs-data-update: done
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: done
docs-use-cases: done
dynamic-devices: todo
entity-category: done
entity-device-class: done
entity-disabled-by-default: done
entity-translations: done
exception-translations: todo
exception-translations: done
icon-translations: done
reconfiguration-flow: todo
repair-issues:

View File

@ -22,16 +22,28 @@
"password": "[%key:component::alexa_devices::common::data_description_password%]",
"code": "[%key:component::alexa_devices::common::data_description_code%]"
}
},
"reauth_confirm": {
"data": {
"password": "[%key:common::config_flow::data::password%]",
"code": "[%key:component::alexa_devices::common::data_code%]"
},
"data_description": {
"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%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"cannot_retrieve_data": "Unable to retrieve data from Amazon. Please try again later.",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"wrong_country": "Wrong country selected. Please select the country where your Amazon account is registered.",
"unknown": "[%key:common::config_flow::error::unknown%]"
@ -73,10 +85,10 @@
}
},
"exceptions": {
"cannot_connect": {
"cannot_connect_with_error": {
"message": "Error connecting: {error}"
},
"cannot_retrieve_data": {
"cannot_retrieve_data_with_error": {
"message": "Error retrieving data: {error}"
}
}

View File

@ -26,14 +26,14 @@ def alexa_api_call[_T: AmazonEntity, **_P](
self.coordinator.last_update_success = False
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="cannot_connect",
translation_key="cannot_connect_with_error",
translation_placeholders={"error": repr(err)},
) from err
except CannotRetrieveData as err:
self.coordinator.last_update_success = False
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="cannot_retrieve_data",
translation_key="cannot_retrieve_data_with_error",
translation_placeholders={"error": repr(err)},
) from err

View File

@ -2,11 +2,22 @@
import amberelectric
from homeassistant.components.sensor import ConfigType
from homeassistant.const import CONF_API_TOKEN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from .const import CONF_SITE_ID, PLATFORMS
from .const import CONF_SITE_ID, DOMAIN, PLATFORMS
from .coordinator import AmberConfigEntry, AmberUpdateCoordinator
from .services import setup_services
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Amber component."""
setup_services(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: AmberConfigEntry) -> bool:

View File

@ -1,14 +1,24 @@
"""Amber Electric Constants."""
import logging
from typing import Final
from homeassistant.const import Platform
DOMAIN = "amberelectric"
DOMAIN: Final = "amberelectric"
CONF_SITE_NAME = "site_name"
CONF_SITE_ID = "site_id"
ATTR_CONFIG_ENTRY_ID = "config_entry_id"
ATTR_CHANNEL_TYPE = "channel_type"
ATTRIBUTION = "Data provided by Amber Electric"
LOGGER = logging.getLogger(__package__)
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
SERVICE_GET_FORECASTS = "get_forecasts"
GENERAL_CHANNEL = "general"
CONTROLLED_LOAD_CHANNEL = "controlled_load"
FEED_IN_CHANNEL = "feed_in"

View File

@ -10,7 +10,6 @@ from amberelectric.models.actual_interval import ActualInterval
from amberelectric.models.channel import ChannelType
from amberelectric.models.current_interval import CurrentInterval
from amberelectric.models.forecast_interval import ForecastInterval
from amberelectric.models.price_descriptor import PriceDescriptor
from amberelectric.rest import ApiException
from homeassistant.config_entries import ConfigEntry
@ -18,6 +17,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import LOGGER
from .helpers import normalize_descriptor
type AmberConfigEntry = ConfigEntry[AmberUpdateCoordinator]
@ -49,27 +49,6 @@ def is_feed_in(interval: ActualInterval | CurrentInterval | ForecastInterval) ->
return interval.channel_type == ChannelType.FEEDIN
def normalize_descriptor(descriptor: PriceDescriptor | None) -> str | None:
"""Return the snake case versions of descriptor names. Returns None if the name is not recognized."""
if descriptor is None:
return None
if descriptor.value == "spike":
return "spike"
if descriptor.value == "high":
return "high"
if descriptor.value == "neutral":
return "neutral"
if descriptor.value == "low":
return "low"
if descriptor.value == "veryLow":
return "very_low"
if descriptor.value == "extremelyLow":
return "extremely_low"
if descriptor.value == "negative":
return "negative"
return None
class AmberUpdateCoordinator(DataUpdateCoordinator):
"""AmberUpdateCoordinator - In charge of downloading the data for a site, which all the sensors read."""
@ -103,7 +82,7 @@ class AmberUpdateCoordinator(DataUpdateCoordinator):
"grid": {},
}
try:
data = self._api.get_current_prices(self.site_id, next=48)
data = self._api.get_current_prices(self.site_id, next=288)
intervals = [interval.actual_instance for interval in data]
except ApiException as api_exception:
raise UpdateFailed("Missing price data, skipping update") from api_exception

View File

@ -0,0 +1,25 @@
"""Formatting helpers used to convert things."""
from amberelectric.models.price_descriptor import PriceDescriptor
DESCRIPTOR_MAP: dict[str, str] = {
PriceDescriptor.SPIKE: "spike",
PriceDescriptor.HIGH: "high",
PriceDescriptor.NEUTRAL: "neutral",
PriceDescriptor.LOW: "low",
PriceDescriptor.VERYLOW: "very_low",
PriceDescriptor.EXTREMELYLOW: "extremely_low",
PriceDescriptor.NEGATIVE: "negative",
}
def normalize_descriptor(descriptor: PriceDescriptor | None) -> str | None:
"""Return the snake case versions of descriptor names. Returns None if the name is not recognized."""
if descriptor in DESCRIPTOR_MAP:
return DESCRIPTOR_MAP[descriptor]
return None
def format_cents_to_dollars(cents: float) -> float:
"""Return a formatted conversion from cents to dollars."""
return round(cents / 100, 2)

View File

@ -22,5 +22,10 @@
}
}
}
},
"services": {
"get_forecasts": {
"service": "mdi:transmission-tower"
}
}
}

View File

@ -23,16 +23,12 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ATTRIBUTION
from .coordinator import AmberConfigEntry, AmberUpdateCoordinator, normalize_descriptor
from .coordinator import AmberConfigEntry, AmberUpdateCoordinator
from .helpers import format_cents_to_dollars, normalize_descriptor
UNIT = f"{CURRENCY_DOLLAR}/{UnitOfEnergy.KILO_WATT_HOUR}"
def format_cents_to_dollars(cents: float) -> float:
"""Return a formatted conversion from cents to dollars."""
return round(cents / 100, 2)
def friendly_channel_type(channel_type: str) -> str:
"""Return a human readable version of the channel type."""
if channel_type == "controlled_load":

View File

@ -0,0 +1,121 @@
"""Amber Electric Service class."""
from amberelectric.models.channel import ChannelType
import voluptuous as vol
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import (
HomeAssistant,
ServiceCall,
ServiceResponse,
SupportsResponse,
)
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers.selector import ConfigEntrySelector
from homeassistant.util.json import JsonValueType
from .const import (
ATTR_CHANNEL_TYPE,
ATTR_CONFIG_ENTRY_ID,
CONTROLLED_LOAD_CHANNEL,
DOMAIN,
FEED_IN_CHANNEL,
GENERAL_CHANNEL,
SERVICE_GET_FORECASTS,
)
from .coordinator import AmberConfigEntry
from .helpers import format_cents_to_dollars, normalize_descriptor
GET_FORECASTS_SCHEMA = vol.Schema(
{
ATTR_CONFIG_ENTRY_ID: ConfigEntrySelector({"integration": DOMAIN}),
ATTR_CHANNEL_TYPE: vol.In(
[GENERAL_CHANNEL, CONTROLLED_LOAD_CHANNEL, FEED_IN_CHANNEL]
),
}
)
def async_get_entry(hass: HomeAssistant, config_entry_id: str) -> AmberConfigEntry:
"""Get the Amber config entry."""
if not (entry := hass.config_entries.async_get_entry(config_entry_id)):
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="integration_not_found",
translation_placeholders={"target": config_entry_id},
)
if entry.state is not ConfigEntryState.LOADED:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="not_loaded",
translation_placeholders={"target": entry.title},
)
return entry
def get_forecasts(channel_type: str, data: dict) -> list[JsonValueType]:
"""Return an array of forecasts."""
results: list[JsonValueType] = []
if channel_type not in data["forecasts"]:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="channel_not_found",
translation_placeholders={"channel_type": channel_type},
)
intervals = data["forecasts"][channel_type]
for interval in intervals:
datum = {}
datum["duration"] = interval.duration
datum["date"] = interval.var_date.isoformat()
datum["nem_date"] = interval.nem_time.isoformat()
datum["per_kwh"] = format_cents_to_dollars(interval.per_kwh)
if interval.channel_type == ChannelType.FEEDIN:
datum["per_kwh"] = datum["per_kwh"] * -1
datum["spot_per_kwh"] = format_cents_to_dollars(interval.spot_per_kwh)
datum["start_time"] = interval.start_time.isoformat()
datum["end_time"] = interval.end_time.isoformat()
datum["renewables"] = round(interval.renewables)
datum["spike_status"] = interval.spike_status.value
datum["descriptor"] = normalize_descriptor(interval.descriptor)
if interval.range is not None:
datum["range_min"] = format_cents_to_dollars(interval.range.min)
datum["range_max"] = format_cents_to_dollars(interval.range.max)
if interval.advanced_price is not None:
multiplier = -1 if interval.channel_type == ChannelType.FEEDIN else 1
datum["advanced_price_low"] = multiplier * format_cents_to_dollars(
interval.advanced_price.low
)
datum["advanced_price_predicted"] = multiplier * format_cents_to_dollars(
interval.advanced_price.predicted
)
datum["advanced_price_high"] = multiplier * format_cents_to_dollars(
interval.advanced_price.high
)
results.append(datum)
return results
def setup_services(hass: HomeAssistant) -> None:
"""Set up the services for the Amber integration."""
async def handle_get_forecasts(call: ServiceCall) -> ServiceResponse:
channel_type = call.data[ATTR_CHANNEL_TYPE]
entry = async_get_entry(hass, call.data[ATTR_CONFIG_ENTRY_ID])
coordinator = entry.runtime_data
forecasts = get_forecasts(channel_type, coordinator.data)
return {"forecasts": forecasts}
hass.services.async_register(
DOMAIN,
SERVICE_GET_FORECASTS,
handle_get_forecasts,
GET_FORECASTS_SCHEMA,
supports_response=SupportsResponse.ONLY,
)

View File

@ -0,0 +1,16 @@
get_forecasts:
fields:
config_entry_id:
required: true
selector:
config_entry:
integration: amberelectric
channel_type:
required: true
selector:
select:
options:
- general
- controlled_load
- feed_in
translation_key: channel_type

View File

@ -1,25 +1,61 @@
{
"config": {
"error": {
"invalid_api_token": "[%key:common::config_flow::error::invalid_api_key%]",
"no_site": "No site provided",
"unknown_error": "[%key:common::config_flow::error::unknown%]"
},
"step": {
"site": {
"data": {
"site_id": "Site NMI",
"site_name": "Site name"
},
"description": "Select the NMI of the site you would like to add"
},
"user": {
"data": {
"api_token": "[%key:common::config_flow::data::api_token%]",
"site_id": "Site ID"
},
"description": "Go to {api_url} to generate an API key"
},
"site": {
"data": {
"site_id": "Site NMI",
"site_name": "Site Name"
},
"description": "Select the NMI of the site you would like to add"
}
}
},
"services": {
"get_forecasts": {
"name": "Get price forecasts",
"description": "Retrieves price forecasts from Amber Electric for a site.",
"fields": {
"config_entry_id": {
"description": "The config entry of the site to get forecasts for.",
"name": "Config entry"
},
"channel_type": {
"name": "Channel type",
"description": "The channel to get forecasts for."
}
}
}
},
"exceptions": {
"integration_not_found": {
"message": "Config entry \"{target}\" not found in registry."
},
"error": {
"invalid_api_token": "[%key:common::config_flow::error::invalid_api_key%]",
"no_site": "No site provided",
"unknown_error": "[%key:common::config_flow::error::unknown%]"
"not_loaded": {
"message": "{target} is not loaded."
},
"channel_not_found": {
"message": "There is no {channel_type} channel at this site."
}
},
"selector": {
"channel_type": {
"options": {
"general": "General",
"controlled_load": "Controlled load",
"feed_in": "Feed-in"
}
}
}
}

View File

@ -7,5 +7,5 @@
"iot_class": "local_polling",
"loggers": ["amcrest"],
"quality_scale": "legacy",
"requirements": ["amcrest==1.9.8"]
"requirements": ["amcrest==1.9.9"]
}

View File

@ -14,6 +14,7 @@ from homeassistant.util.hass_dict import HassKey
from .analytics import Analytics
from .const import ATTR_ONBOARDED, ATTR_PREFERENCES, DOMAIN, INTERVAL, PREFERENCE_SCHEMA
from .http import AnalyticsDevicesView
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
@ -55,6 +56,8 @@ async def async_setup(hass: HomeAssistant, _: ConfigType) -> bool:
websocket_api.async_register_command(hass, websocket_analytics)
websocket_api.async_register_command(hass, websocket_analytics_preferences)
hass.http.register_view(AnalyticsDevicesView)
hass.data[DATA_COMPONENT] = analytics
return True

View File

@ -27,7 +27,7 @@ from homeassistant.config_entries import SOURCE_IGNORE
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
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.storage import Store
@ -77,6 +77,11 @@ from .const import (
)
def gen_uuid() -> str:
"""Generate a new UUID."""
return uuid.uuid4().hex
@dataclass
class AnalyticsData:
"""Analytics data."""
@ -184,7 +189,7 @@ class Analytics:
return
if self._data.uuid is None:
self._data.uuid = uuid.uuid4().hex
self._data.uuid = gen_uuid()
await self._store.async_save(dataclass_asdict(self._data))
if self.supervisor:
@ -381,3 +386,83 @@ def _domains_from_yaml_config(yaml_configuration: dict[str, Any]) -> set[str]:
).values():
domains.update(platforms)
return domains
async def async_devices_payload(hass: HomeAssistant) -> dict:
"""Return the devices payload."""
integrations_without_model_id: set[str] = set()
devices: list[dict[str, Any]] = []
dev_reg = dr.async_get(hass)
# Devices that need via device info set
new_indexes: dict[str, int] = {}
via_devices: dict[str, str] = {}
seen_integrations = set()
for device in dev_reg.devices.values():
# Ignore services
if device.entry_type:
continue
if not device.primary_config_entry:
continue
config_entry = hass.config_entries.async_get_entry(device.primary_config_entry)
if config_entry is None:
continue
seen_integrations.add(config_entry.domain)
if not device.model_id:
integrations_without_model_id.add(config_entry.domain)
continue
if not device.manufacturer:
continue
new_indexes[device.id] = len(devices)
devices.append(
{
"integration": config_entry.domain,
"manufacturer": device.manufacturer,
"model_id": device.model_id,
"model": device.model,
"sw_version": device.sw_version,
"hw_version": device.hw_version,
"has_suggested_area": device.suggested_area is not None,
"has_configuration_url": device.configuration_url is not None,
"via_device": None,
}
)
if device.via_device_id:
via_devices[device.id] = device.via_device_id
for from_device, via_device in via_devices.items():
if via_device not in new_indexes:
continue
devices[new_indexes[from_device]]["via_device"] = new_indexes[via_device]
integrations = {
domain: integration
for domain, integration in (
await async_get_integrations(hass, seen_integrations)
).items()
if isinstance(integration, Integration)
}
for device_info in devices:
if integration := integrations.get(device_info["integration"]):
device_info["is_custom_integration"] = not integration.is_built_in
return {
"version": "home-assistant:1",
"no_model_id": sorted(
[
domain
for domain in integrations_without_model_id
if domain in integrations and integrations[domain].is_built_in
]
),
"devices": devices,
}

View File

@ -0,0 +1,27 @@
"""HTTP endpoints for analytics integration."""
from aiohttp import web
from homeassistant.components.http import KEY_HASS, HomeAssistantView, require_admin
from homeassistant.core import HomeAssistant
from .analytics import async_devices_payload
class AnalyticsDevicesView(HomeAssistantView):
"""View to handle analytics devices payload download requests."""
url = "/api/analytics/devices"
name = "api:analytics:devices"
@require_admin
async def get(self, request: web.Request) -> web.Response:
"""Return analytics devices payload as JSON."""
hass: HomeAssistant = request.app[KEY_HASS]
payload = await async_devices_payload(hass)
return self.json(
payload,
headers={
"Content-Disposition": "attachment; filename=analytics_devices.json"
},
)

View File

@ -3,7 +3,7 @@
"name": "Analytics",
"after_dependencies": ["energy", "hassio", "recorder"],
"codeowners": ["@home-assistant/core", "@ludeeus"],
"dependencies": ["api", "websocket_api"],
"dependencies": ["api", "websocket_api", "http"],
"documentation": "https://www.home-assistant.io/integrations/analytics",
"integration_type": "system",
"iot_class": "cloud_push",

View File

@ -55,7 +55,6 @@ async def async_setup_entry(
entry.runtime_data = AnalyticsInsightsData(coordinator=coordinator, names=names)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(update_listener))
return True
@ -65,10 +64,3 @@ async def async_unload_entry(
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def update_listener(
hass: HomeAssistant, entry: AnalyticsInsightsConfigEntry
) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)

View File

@ -11,7 +11,11 @@ from python_homeassistant_analytics import (
from python_homeassistant_analytics.models import Environment, IntegrationType
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow
from homeassistant.config_entries import (
ConfigFlow,
ConfigFlowResult,
OptionsFlowWithReload,
)
from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.selector import (
@ -129,7 +133,7 @@ class HomeassistantAnalyticsConfigFlow(ConfigFlow, domain=DOMAIN):
)
class HomeassistantAnalyticsOptionsFlowHandler(OptionsFlow):
class HomeassistantAnalyticsOptionsFlowHandler(OptionsFlowWithReload):
"""Handle Homeassistant Analytics options."""
async def async_step_init(

View File

@ -56,7 +56,7 @@ SERVICE_UPLOAD = "upload"
ANDROIDTV_STATES = {
"off": MediaPlayerState.OFF,
"idle": MediaPlayerState.IDLE,
"standby": MediaPlayerState.STANDBY,
"standby": MediaPlayerState.IDLE,
"playing": MediaPlayerState.PLAYING,
"paused": MediaPlayerState.PAUSED,
}

View File

@ -5,26 +5,18 @@ from __future__ import annotations
from asyncio import timeout
import logging
from androidtvremote2 import (
AndroidTVRemote,
CannotConnect,
ConnectionClosed,
InvalidAuth,
)
from androidtvremote2 import CannotConnect, ConnectionClosed, InvalidAuth
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_NAME, EVENT_HOMEASSISTANT_STOP, Platform
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from .helpers import create_api, get_enable_ime
from .helpers import AndroidTVRemoteConfigEntry, create_api, get_enable_ime
_LOGGER = logging.getLogger(__name__)
PLATFORMS: list[Platform] = [Platform.MEDIA_PLAYER, Platform.REMOTE]
AndroidTVRemoteConfigEntry = ConfigEntry[AndroidTVRemote]
async def async_setup_entry(
hass: HomeAssistant, entry: AndroidTVRemoteConfigEntry
@ -76,21 +68,14 @@ async def async_setup_entry(
entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop)
)
entry.async_on_unload(entry.add_update_listener(async_update_options))
entry.async_on_unload(api.disconnect)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(
hass: HomeAssistant, entry: AndroidTVRemoteConfigEntry
) -> bool:
"""Unload a config entry."""
_LOGGER.debug("async_unload_entry: %s", entry.data)
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle options update."""
_LOGGER.debug(
"async_update_options: data: %s options: %s", entry.data, entry.options
)
await hass.config_entries.async_reload(entry.entry_id)

View File

@ -16,10 +16,10 @@ import voluptuous as vol
from homeassistant.config_entries import (
SOURCE_REAUTH,
ConfigEntry,
SOURCE_RECONFIGURE,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
OptionsFlowWithReload,
)
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME
from homeassistant.core import callback
@ -33,7 +33,7 @@ from homeassistant.helpers.selector import (
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
from .const import CONF_APP_ICON, CONF_APP_NAME, CONF_APPS, CONF_ENABLE_IME, DOMAIN
from .helpers import create_api, get_enable_ime
from .helpers import AndroidTVRemoteConfigEntry, create_api, get_enable_ime
_LOGGER = logging.getLogger(__name__)
@ -41,12 +41,6 @@ APPS_NEW_ID = "NewApp"
CONF_APP_DELETE = "app_delete"
CONF_APP_ID = "app_id"
STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required("host"): str,
}
)
STEP_PAIR_DATA_SCHEMA = vol.Schema(
{
vol.Required("pin"): str,
@ -67,7 +61,7 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
"""Handle the initial and reconfigure step."""
errors: dict[str, str] = {}
if user_input is not None:
self.host = user_input[CONF_HOST]
@ -76,15 +70,32 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
await api.async_generate_cert_if_missing()
self.name, self.mac = await api.async_get_name_and_mac()
await self.async_set_unique_id(format_mac(self.mac))
if self.source == SOURCE_RECONFIGURE:
self._abort_if_unique_id_mismatch()
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data={
CONF_HOST: self.host,
CONF_NAME: self.name,
CONF_MAC: self.mac,
},
)
self._abort_if_unique_id_configured(updates={CONF_HOST: self.host})
return await self._async_start_pair()
except (CannotConnect, ConnectionClosed):
# Likely invalid IP address or device is network unreachable. Stay
# in the user step allowing the user to enter a different host.
errors["base"] = "cannot_connect"
else:
user_input = {}
default_host = user_input.get(CONF_HOST, vol.UNDEFINED)
if self.source == SOURCE_RECONFIGURE:
default_host = self._get_reconfigure_entry().data[CONF_HOST]
return self.async_show_form(
step_id="user",
data_schema=STEP_USER_DATA_SCHEMA,
step_id="reconfigure" if self.source == SOURCE_RECONFIGURE else "user",
data_schema=vol.Schema(
{vol.Required(CONF_HOST, default=default_host): str}
),
errors=errors,
)
@ -105,10 +116,10 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
pin = user_input["pin"]
await self.api.async_finish_pairing(pin)
if self.source == SOURCE_REAUTH:
await self.hass.config_entries.async_reload(
self._get_reauth_entry().entry_id
return self.async_update_reload_and_abort(
self._get_reauth_entry(), reload_even_if_entry_is_unchanged=True
)
return self.async_abort(reason="reauth_successful")
return self.async_create_entry(
title=self.name,
data={
@ -217,19 +228,25 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
errors=errors,
)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle reconfiguration."""
return await self.async_step_user(user_input)
@staticmethod
@callback
def async_get_options_flow(
config_entry: ConfigEntry,
config_entry: AndroidTVRemoteConfigEntry,
) -> AndroidTVRemoteOptionsFlowHandler:
"""Create the options flow."""
return AndroidTVRemoteOptionsFlowHandler(config_entry)
class AndroidTVRemoteOptionsFlowHandler(OptionsFlow):
class AndroidTVRemoteOptionsFlowHandler(OptionsFlowWithReload):
"""Android TV Remote options flow."""
def __init__(self, config_entry: ConfigEntry) -> None:
def __init__(self, config_entry: AndroidTVRemoteConfigEntry) -> None:
"""Initialize options flow."""
self._apps: dict[str, Any] = dict(config_entry.options.get(CONF_APPS, {}))
self._conf_app_id: str | None = None

View File

@ -8,7 +8,7 @@ from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_HOST, CONF_MAC
from homeassistant.core import HomeAssistant
from . import AndroidTVRemoteConfigEntry
from .helpers import AndroidTVRemoteConfigEntry
TO_REDACT = {CONF_HOST, CONF_MAC}

View File

@ -6,7 +6,6 @@ from typing import Any
from androidtvremote2 import AndroidTVRemote, ConnectionClosed
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
@ -14,6 +13,7 @@ from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, Device
from homeassistant.helpers.entity import Entity
from .const import CONF_APPS, DOMAIN
from .helpers import AndroidTVRemoteConfigEntry
class AndroidTVRemoteBaseEntity(Entity):
@ -23,7 +23,9 @@ class AndroidTVRemoteBaseEntity(Entity):
_attr_has_entity_name = True
_attr_should_poll = False
def __init__(self, api: AndroidTVRemote, config_entry: ConfigEntry) -> None:
def __init__(
self, api: AndroidTVRemote, config_entry: AndroidTVRemoteConfigEntry
) -> None:
"""Initialize the entity."""
self._api = api
self._host = config_entry.data[CONF_HOST]

View File

@ -10,6 +10,8 @@ from homeassistant.helpers.storage import STORAGE_DIR
from .const import CONF_ENABLE_IME, CONF_ENABLE_IME_DEFAULT_VALUE
AndroidTVRemoteConfigEntry = ConfigEntry[AndroidTVRemote]
def create_api(hass: HomeAssistant, host: str, enable_ime: bool) -> AndroidTVRemote:
"""Create an AndroidTVRemote instance."""
@ -23,6 +25,6 @@ def create_api(hass: HomeAssistant, host: str, enable_ime: bool) -> AndroidTVRem
)
def get_enable_ime(entry: ConfigEntry) -> bool:
def get_enable_ime(entry: AndroidTVRemoteConfigEntry) -> bool:
"""Get value of enable_ime option or its default value."""
return entry.options.get(CONF_ENABLE_IME, CONF_ENABLE_IME_DEFAULT_VALUE)
return entry.options.get(CONF_ENABLE_IME, CONF_ENABLE_IME_DEFAULT_VALUE) # type: ignore[no-any-return]

View File

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

View File

@ -5,7 +5,7 @@ from __future__ import annotations
import asyncio
from typing import Any
from androidtvremote2 import AndroidTVRemote, ConnectionClosed
from androidtvremote2 import AndroidTVRemote, ConnectionClosed, VolumeInfo
from homeassistant.components.media_player import (
BrowseMedia,
@ -20,9 +20,9 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import AndroidTVRemoteConfigEntry
from .const import CONF_APP_ICON, CONF_APP_NAME, DOMAIN
from .entity import AndroidTVRemoteBaseEntity
from .helpers import AndroidTVRemoteConfigEntry
PARALLEL_UPDATES = 0
@ -75,13 +75,11 @@ class AndroidTVRemoteMediaPlayerEntity(AndroidTVRemoteBaseEntity, MediaPlayerEnt
else current_app
)
def _update_volume_info(self, volume_info: dict[str, str | bool]) -> None:
def _update_volume_info(self, volume_info: VolumeInfo) -> None:
"""Update volume info."""
if volume_info.get("max"):
self._attr_volume_level = int(volume_info["level"]) / int(
volume_info["max"]
)
self._attr_is_volume_muted = bool(volume_info["muted"])
self._attr_volume_level = volume_info["level"] / volume_info["max"]
self._attr_is_volume_muted = volume_info["muted"]
else:
self._attr_volume_level = None
self._attr_is_volume_muted = None
@ -93,7 +91,7 @@ class AndroidTVRemoteMediaPlayerEntity(AndroidTVRemoteBaseEntity, MediaPlayerEnt
self.async_write_ha_state()
@callback
def _volume_info_updated(self, volume_info: dict[str, str | bool]) -> None:
def _volume_info_updated(self, volume_info: VolumeInfo) -> None:
"""Update the state when the volume info changes."""
self._update_volume_info(volume_info)
self.async_write_ha_state()
@ -102,8 +100,10 @@ class AndroidTVRemoteMediaPlayerEntity(AndroidTVRemoteBaseEntity, MediaPlayerEnt
"""Register callbacks."""
await super().async_added_to_hass()
self._update_current_app(self._api.current_app)
self._update_volume_info(self._api.volume_info)
if self._api.current_app is not None:
self._update_current_app(self._api.current_app)
if self._api.volume_info is not None:
self._update_volume_info(self._api.volume_info)
self._api.add_current_app_updated_callback(self._current_app_updated)
self._api.add_volume_info_updated_callback(self._volume_info_updated)

View File

@ -20,9 +20,9 @@ from homeassistant.components.remote import (
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import AndroidTVRemoteConfigEntry
from .const import CONF_APP_NAME
from .entity import AndroidTVRemoteBaseEntity
from .helpers import AndroidTVRemoteConfigEntry
PARALLEL_UPDATES = 0
@ -63,7 +63,8 @@ class AndroidTVRemoteEntity(AndroidTVRemoteBaseEntity, RemoteEntity):
self._attr_activity_list = [
app.get(CONF_APP_NAME, "") for app in self._apps.values()
]
self._update_current_app(self._api.current_app)
if self._api.current_app is not None:
self._update_current_app(self._api.current_app)
self._api.add_current_app_updated_callback(self._current_app_updated)
async def async_will_remove_from_hass(self) -> None:

View File

@ -6,6 +6,18 @@
"description": "Enter the IP address of the Android TV you want to add to Home Assistant. It will turn on and a pairing code will be displayed on it that you will need to enter in the next screen.",
"data": {
"host": "[%key:common::config_flow::data::host%]"
},
"data_description": {
"host": "The hostname or IP address of the Android TV device."
}
},
"reconfigure": {
"description": "Update the IP address of this previously configured Android TV device.",
"data": {
"host": "[%key:common::config_flow::data::host%]"
},
"data_description": {
"host": "The hostname or IP address of the Android TV device."
}
},
"zeroconf_confirm": {
@ -16,6 +28,9 @@
"description": "Enter the pairing code displayed on the Android TV ({name}).",
"data": {
"pin": "[%key:common::config_flow::data::pin%]"
},
"data_description": {
"pin": "Pairing code displayed on the Android TV device."
}
},
"reauth_confirm": {
@ -32,7 +47,9 @@
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
"unique_id_mismatch": "Please ensure you reconfigure against the same device."
}
},
"options": {
@ -40,7 +57,11 @@
"init": {
"data": {
"apps": "Configure applications list",
"enable_ime": "Enable IME. Needed for getting the current app. Disable for devices that show 'Use keyboard on mobile device screen' instead of the on screen keyboard."
"enable_ime": "Enable IME"
},
"data_description": {
"apps": "Here you can define the list of applications, specify names and icons that will be displayed in the UI.",
"enable_ime": "Enable this option to be able to get the current app name and send text as keyboard input. Disable it for devices that show 'Use keyboard on mobile device screen' instead of the on-screen keyboard."
}
},
"apps": {
@ -53,8 +74,10 @@
"app_delete": "Check to delete this application"
},
"data_description": {
"app_name": "Name of the application as you would like it to be displayed in Home Assistant.",
"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"
"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",
"app_delete": "Check this box to delete the application from the list."
}
}
}

View File

@ -10,7 +10,7 @@
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"cannot_receive_deviceinfo": "Failed to retrieve MAC Address. Make sure the device is turned on"
"cannot_receive_deviceinfo": "Failed to retrieve MAC address. Make sure the device is turned on"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"

View File

@ -61,6 +61,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: AnthropicConfigEntry) ->
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(async_update_options))
return True
@ -69,6 +71,13 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_update_options(
hass: HomeAssistant, entry: AnthropicConfigEntry
) -> None:
"""Update options."""
await hass.config_entries.async_reload(entry.entry_id)
async def async_migrate_integration(hass: HomeAssistant) -> None:
"""Migrate integration entry structure."""

View File

@ -10,9 +10,9 @@ DEFAULT_CONVERSATION_NAME = "Claude conversation"
CONF_RECOMMENDED = "recommended"
CONF_PROMPT = "prompt"
CONF_CHAT_MODEL = "chat_model"
RECOMMENDED_CHAT_MODEL = "claude-3-haiku-20240307"
RECOMMENDED_CHAT_MODEL = "claude-3-5-haiku-latest"
CONF_MAX_TOKENS = "max_tokens"
RECOMMENDED_MAX_TOKENS = 1024
RECOMMENDED_MAX_TOKENS = 3000
CONF_TEMPERATURE = "temperature"
RECOMMENDED_TEMPERATURE = 1.0
CONF_THINKING_BUDGET = "thinking_budget"

View File

@ -1,69 +1,16 @@
"""Conversation support for Anthropic."""
from collections.abc import AsyncGenerator, Callable, Iterable
import json
from typing import Any, Literal, cast
import anthropic
from anthropic import AsyncStream
from anthropic._types import NOT_GIVEN
from anthropic.types import (
InputJSONDelta,
MessageDeltaUsage,
MessageParam,
MessageStreamEvent,
RawContentBlockDeltaEvent,
RawContentBlockStartEvent,
RawContentBlockStopEvent,
RawMessageDeltaEvent,
RawMessageStartEvent,
RawMessageStopEvent,
RedactedThinkingBlock,
RedactedThinkingBlockParam,
SignatureDelta,
TextBlock,
TextBlockParam,
TextDelta,
ThinkingBlock,
ThinkingBlockParam,
ThinkingConfigDisabledParam,
ThinkingConfigEnabledParam,
ThinkingDelta,
ToolParam,
ToolResultBlockParam,
ToolUseBlock,
ToolUseBlockParam,
Usage,
)
from voluptuous_openapi import convert
from typing import Literal
from homeassistant.components import conversation
from homeassistant.config_entries import ConfigEntry, ConfigSubentry
from homeassistant.config_entries import ConfigSubentry
from homeassistant.const import CONF_LLM_HASS_API, MATCH_ALL
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, intent, llm
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import AnthropicConfigEntry
from .const import (
CONF_CHAT_MODEL,
CONF_MAX_TOKENS,
CONF_PROMPT,
CONF_TEMPERATURE,
CONF_THINKING_BUDGET,
DOMAIN,
LOGGER,
MIN_THINKING_BUDGET,
RECOMMENDED_CHAT_MODEL,
RECOMMENDED_MAX_TOKENS,
RECOMMENDED_TEMPERATURE,
RECOMMENDED_THINKING_BUDGET,
THINKING_MODELS,
)
# Max number of back and forth with the LLM to generate a response
MAX_TOOL_ITERATIONS = 10
from .const import CONF_PROMPT, DOMAIN
from .entity import AnthropicBaseLLMEntity
async def async_setup_entry(
@ -82,253 +29,10 @@ async def async_setup_entry(
)
def _format_tool(
tool: llm.Tool, custom_serializer: Callable[[Any], Any] | None
) -> ToolParam:
"""Format tool specification."""
return ToolParam(
name=tool.name,
description=tool.description or "",
input_schema=convert(tool.parameters, custom_serializer=custom_serializer),
)
def _convert_content(
chat_content: Iterable[conversation.Content],
) -> list[MessageParam]:
"""Transform HA chat_log content into Anthropic API format."""
messages: list[MessageParam] = []
for content in chat_content:
if isinstance(content, conversation.ToolResultContent):
tool_result_block = ToolResultBlockParam(
type="tool_result",
tool_use_id=content.tool_call_id,
content=json.dumps(content.tool_result),
)
if not messages or messages[-1]["role"] != "user":
messages.append(
MessageParam(
role="user",
content=[tool_result_block],
)
)
elif isinstance(messages[-1]["content"], str):
messages[-1]["content"] = [
TextBlockParam(type="text", text=messages[-1]["content"]),
tool_result_block,
]
else:
messages[-1]["content"].append(tool_result_block) # type: ignore[attr-defined]
elif isinstance(content, conversation.UserContent):
# Combine consequent user messages
if not messages or messages[-1]["role"] != "user":
messages.append(
MessageParam(
role="user",
content=content.content,
)
)
elif isinstance(messages[-1]["content"], str):
messages[-1]["content"] = [
TextBlockParam(type="text", text=messages[-1]["content"]),
TextBlockParam(type="text", text=content.content),
]
else:
messages[-1]["content"].append( # type: ignore[attr-defined]
TextBlockParam(type="text", text=content.content)
)
elif isinstance(content, conversation.AssistantContent):
# Combine consequent assistant messages
if not messages or messages[-1]["role"] != "assistant":
messages.append(
MessageParam(
role="assistant",
content=[],
)
)
if content.content:
messages[-1]["content"].append( # type: ignore[union-attr]
TextBlockParam(type="text", text=content.content)
)
if content.tool_calls:
messages[-1]["content"].extend( # type: ignore[union-attr]
[
ToolUseBlockParam(
type="tool_use",
id=tool_call.id,
name=tool_call.tool_name,
input=tool_call.tool_args,
)
for tool_call in content.tool_calls
]
)
else:
# Note: We don't pass SystemContent here as its passed to the API as the prompt
raise TypeError(f"Unexpected content type: {type(content)}")
return messages
async def _transform_stream( # noqa: C901 - This is complex, but better to have it in one place
chat_log: conversation.ChatLog,
result: AsyncStream[MessageStreamEvent],
messages: list[MessageParam],
) -> AsyncGenerator[conversation.AssistantContentDeltaDict]:
"""Transform the response stream into HA format.
A typical stream of responses might look something like the following:
- RawMessageStartEvent with no content
- RawContentBlockStartEvent with an empty ThinkingBlock (if extended thinking is enabled)
- RawContentBlockDeltaEvent with a ThinkingDelta
- RawContentBlockDeltaEvent with a ThinkingDelta
- RawContentBlockDeltaEvent with a ThinkingDelta
- ...
- RawContentBlockDeltaEvent with a SignatureDelta
- RawContentBlockStopEvent
- RawContentBlockStartEvent with a RedactedThinkingBlock (occasionally)
- RawContentBlockStopEvent (RedactedThinkingBlock does not have a delta)
- RawContentBlockStartEvent with an empty TextBlock
- RawContentBlockDeltaEvent with a TextDelta
- RawContentBlockDeltaEvent with a TextDelta
- RawContentBlockDeltaEvent with a TextDelta
- ...
- RawContentBlockStopEvent
- RawContentBlockStartEvent with ToolUseBlock specifying the function name
- RawContentBlockDeltaEvent with a InputJSONDelta
- RawContentBlockDeltaEvent with a InputJSONDelta
- ...
- RawContentBlockStopEvent
- RawMessageDeltaEvent with a stop_reason='tool_use'
- RawMessageStopEvent(type='message_stop')
Each message could contain multiple blocks of the same type.
"""
if result is None:
raise TypeError("Expected a stream of messages")
current_message: MessageParam | None = None
current_block: (
TextBlockParam
| ToolUseBlockParam
| ThinkingBlockParam
| RedactedThinkingBlockParam
| None
) = None
current_tool_args: str
input_usage: Usage | None = None
async for response in result:
LOGGER.debug("Received response: %s", response)
if isinstance(response, RawMessageStartEvent):
if response.message.role != "assistant":
raise ValueError("Unexpected message role")
current_message = MessageParam(role=response.message.role, content=[])
input_usage = response.message.usage
elif isinstance(response, RawContentBlockStartEvent):
if isinstance(response.content_block, ToolUseBlock):
current_block = ToolUseBlockParam(
type="tool_use",
id=response.content_block.id,
name=response.content_block.name,
input="",
)
current_tool_args = ""
elif isinstance(response.content_block, TextBlock):
current_block = TextBlockParam(
type="text", text=response.content_block.text
)
yield {"role": "assistant"}
if response.content_block.text:
yield {"content": response.content_block.text}
elif isinstance(response.content_block, ThinkingBlock):
current_block = ThinkingBlockParam(
type="thinking",
thinking=response.content_block.thinking,
signature=response.content_block.signature,
)
elif isinstance(response.content_block, RedactedThinkingBlock):
current_block = RedactedThinkingBlockParam(
type="redacted_thinking", data=response.content_block.data
)
LOGGER.debug(
"Some of Claudes internal reasoning has been automatically "
"encrypted for safety reasons. This doesnt affect the quality of "
"responses"
)
elif isinstance(response, RawContentBlockDeltaEvent):
if current_block is None:
raise ValueError("Unexpected delta without a block")
if isinstance(response.delta, InputJSONDelta):
current_tool_args += response.delta.partial_json
elif isinstance(response.delta, TextDelta):
text_block = cast(TextBlockParam, current_block)
text_block["text"] += response.delta.text
yield {"content": response.delta.text}
elif isinstance(response.delta, ThinkingDelta):
thinking_block = cast(ThinkingBlockParam, current_block)
thinking_block["thinking"] += response.delta.thinking
elif isinstance(response.delta, SignatureDelta):
thinking_block = cast(ThinkingBlockParam, current_block)
thinking_block["signature"] += response.delta.signature
elif isinstance(response, RawContentBlockStopEvent):
if current_block is None:
raise ValueError("Unexpected stop event without a current block")
if current_block["type"] == "tool_use":
# tool block
tool_args = json.loads(current_tool_args) if current_tool_args else {}
current_block["input"] = tool_args
yield {
"tool_calls": [
llm.ToolInput(
id=current_block["id"],
tool_name=current_block["name"],
tool_args=tool_args,
)
]
}
elif current_block["type"] == "thinking":
# thinking block
LOGGER.debug("Thinking: %s", current_block["thinking"])
if current_message is None:
raise ValueError("Unexpected stop event without a current message")
current_message["content"].append(current_block) # type: ignore[union-attr]
current_block = None
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)
current_message = None
def _create_token_stats(
input_usage: Usage | None, response_usage: MessageDeltaUsage
) -> dict[str, Any]:
"""Create token stats for conversation agent tracing."""
input_tokens = 0
cached_input_tokens = 0
if input_usage:
input_tokens = input_usage.input_tokens
cached_input_tokens = input_usage.cache_creation_input_tokens or 0
output_tokens = response_usage.output_tokens
return {
"stats": {
"input_tokens": input_tokens,
"cached_input_tokens": cached_input_tokens,
"output_tokens": output_tokens,
}
}
class AnthropicConversationEntity(
conversation.ConversationEntity, conversation.AbstractConversationAgent
conversation.ConversationEntity,
conversation.AbstractConversationAgent,
AnthropicBaseLLMEntity,
):
"""Anthropic conversation agent."""
@ -336,17 +40,7 @@ class AnthropicConversationEntity(
def __init__(self, entry: AnthropicConfigEntry, subentry: ConfigSubentry) -> None:
"""Initialize the agent."""
self.entry = entry
self.subentry = subentry
self._attr_name = subentry.title
self._attr_unique_id = subentry.subentry_id
self._attr_device_info = dr.DeviceInfo(
identifiers={(DOMAIN, subentry.subentry_id)},
name=subentry.title,
manufacturer="Anthropic",
model="Claude",
entry_type=dr.DeviceEntryType.SERVICE,
)
super().__init__(entry, subentry)
if self.subentry.data.get(CONF_LLM_HASS_API):
self._attr_supported_features = (
conversation.ConversationEntityFeature.CONTROL
@ -357,13 +51,6 @@ class AnthropicConversationEntity(
"""Return a list of supported languages."""
return MATCH_ALL
async def async_added_to_hass(self) -> None:
"""When entity is added to Home Assistant."""
await super().async_added_to_hass()
self.entry.async_on_unload(
self.entry.add_update_listener(self._async_entry_update_listener)
)
async def _async_handle_message(
self,
user_input: conversation.ConversationInput,
@ -384,87 +71,4 @@ class AnthropicConversationEntity(
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.subentry.data
tools: list[ToolParam] | None = None
if chat_log.llm_api:
tools = [
_format_tool(tool, chat_log.llm_api.custom_serializer)
for tool in chat_log.llm_api.tools
]
system = chat_log.content[0]
if not isinstance(system, conversation.SystemContent):
raise TypeError("First message must be a system message")
messages = _convert_content(chat_log.content[1:])
client = self.entry.runtime_data
thinking_budget = options.get(CONF_THINKING_BUDGET, RECOMMENDED_THINKING_BUDGET)
model = options.get(CONF_CHAT_MODEL, RECOMMENDED_CHAT_MODEL)
# To prevent infinite loops, we limit the number of iterations
for _iteration in range(MAX_TOOL_ITERATIONS):
model_args = {
"model": model,
"messages": messages,
"tools": tools or NOT_GIVEN,
"max_tokens": options.get(CONF_MAX_TOKENS, RECOMMENDED_MAX_TOKENS),
"system": system.content,
"stream": True,
}
if model in THINKING_MODELS and thinking_budget >= MIN_THINKING_BUDGET:
model_args["thinking"] = ThinkingConfigEnabledParam(
type="enabled", budget_tokens=thinking_budget
)
else:
model_args["thinking"] = ThinkingConfigDisabledParam(type="disabled")
model_args["temperature"] = options.get(
CONF_TEMPERATURE, RECOMMENDED_TEMPERATURE
)
try:
stream = await client.messages.create(**model_args)
except anthropic.AnthropicError as err:
raise HomeAssistantError(
f"Sorry, I had a problem talking to Anthropic: {err}"
) from err
messages.extend(
_convert_content(
[
content
async for content in chat_log.async_add_delta_content_stream(
self.entity_id,
_transform_stream(chat_log, stream, messages),
)
if not isinstance(content, conversation.AssistantContent)
]
)
)
if not chat_log.unresponded_tool_results:
break
async def _async_entry_update_listener(
self, hass: HomeAssistant, entry: ConfigEntry
) -> None:
"""Handle options update."""
# Reload as we update device info + entity name + supported features
await hass.config_entries.async_reload(entry.entry_id)
return conversation.async_get_result_from_chat_log(user_input, chat_log)

View File

@ -0,0 +1,395 @@
"""Base entity for Anthropic."""
from collections.abc import AsyncGenerator, Callable, Iterable
import json
from typing import Any, cast
import anthropic
from anthropic import AsyncStream
from anthropic._types import NOT_GIVEN
from anthropic.types import (
InputJSONDelta,
MessageDeltaUsage,
MessageParam,
MessageStreamEvent,
RawContentBlockDeltaEvent,
RawContentBlockStartEvent,
RawContentBlockStopEvent,
RawMessageDeltaEvent,
RawMessageStartEvent,
RawMessageStopEvent,
RedactedThinkingBlock,
RedactedThinkingBlockParam,
SignatureDelta,
TextBlock,
TextBlockParam,
TextDelta,
ThinkingBlock,
ThinkingBlockParam,
ThinkingConfigDisabledParam,
ThinkingConfigEnabledParam,
ThinkingDelta,
ToolParam,
ToolResultBlockParam,
ToolUseBlock,
ToolUseBlockParam,
Usage,
)
from voluptuous_openapi import convert
from homeassistant.components import conversation
from homeassistant.config_entries import ConfigSubentry
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, llm
from homeassistant.helpers.entity import Entity
from . import AnthropicConfigEntry
from .const import (
CONF_CHAT_MODEL,
CONF_MAX_TOKENS,
CONF_TEMPERATURE,
CONF_THINKING_BUDGET,
DOMAIN,
LOGGER,
MIN_THINKING_BUDGET,
RECOMMENDED_CHAT_MODEL,
RECOMMENDED_MAX_TOKENS,
RECOMMENDED_TEMPERATURE,
RECOMMENDED_THINKING_BUDGET,
THINKING_MODELS,
)
# Max number of back and forth with the LLM to generate a response
MAX_TOOL_ITERATIONS = 10
def _format_tool(
tool: llm.Tool, custom_serializer: Callable[[Any], Any] | None
) -> ToolParam:
"""Format tool specification."""
return ToolParam(
name=tool.name,
description=tool.description or "",
input_schema=convert(tool.parameters, custom_serializer=custom_serializer),
)
def _convert_content(
chat_content: Iterable[conversation.Content],
) -> list[MessageParam]:
"""Transform HA chat_log content into Anthropic API format."""
messages: list[MessageParam] = []
for content in chat_content:
if isinstance(content, conversation.ToolResultContent):
tool_result_block = ToolResultBlockParam(
type="tool_result",
tool_use_id=content.tool_call_id,
content=json.dumps(content.tool_result),
)
if not messages or messages[-1]["role"] != "user":
messages.append(
MessageParam(
role="user",
content=[tool_result_block],
)
)
elif isinstance(messages[-1]["content"], str):
messages[-1]["content"] = [
TextBlockParam(type="text", text=messages[-1]["content"]),
tool_result_block,
]
else:
messages[-1]["content"].append(tool_result_block) # type: ignore[attr-defined]
elif isinstance(content, conversation.UserContent):
# Combine consequent user messages
if not messages or messages[-1]["role"] != "user":
messages.append(
MessageParam(
role="user",
content=content.content,
)
)
elif isinstance(messages[-1]["content"], str):
messages[-1]["content"] = [
TextBlockParam(type="text", text=messages[-1]["content"]),
TextBlockParam(type="text", text=content.content),
]
else:
messages[-1]["content"].append( # type: ignore[attr-defined]
TextBlockParam(type="text", text=content.content)
)
elif isinstance(content, conversation.AssistantContent):
# Combine consequent assistant messages
if not messages or messages[-1]["role"] != "assistant":
messages.append(
MessageParam(
role="assistant",
content=[],
)
)
if content.content:
messages[-1]["content"].append( # type: ignore[union-attr]
TextBlockParam(type="text", text=content.content)
)
if content.tool_calls:
messages[-1]["content"].extend( # type: ignore[union-attr]
[
ToolUseBlockParam(
type="tool_use",
id=tool_call.id,
name=tool_call.tool_name,
input=tool_call.tool_args,
)
for tool_call in content.tool_calls
]
)
else:
# Note: We don't pass SystemContent here as its passed to the API as the prompt
raise TypeError(f"Unexpected content type: {type(content)}")
return messages
async def _transform_stream( # noqa: C901 - This is complex, but better to have it in one place
chat_log: conversation.ChatLog,
result: AsyncStream[MessageStreamEvent],
messages: list[MessageParam],
) -> AsyncGenerator[conversation.AssistantContentDeltaDict]:
"""Transform the response stream into HA format.
A typical stream of responses might look something like the following:
- RawMessageStartEvent with no content
- RawContentBlockStartEvent with an empty ThinkingBlock (if extended thinking is enabled)
- RawContentBlockDeltaEvent with a ThinkingDelta
- RawContentBlockDeltaEvent with a ThinkingDelta
- RawContentBlockDeltaEvent with a ThinkingDelta
- ...
- RawContentBlockDeltaEvent with a SignatureDelta
- RawContentBlockStopEvent
- RawContentBlockStartEvent with a RedactedThinkingBlock (occasionally)
- RawContentBlockStopEvent (RedactedThinkingBlock does not have a delta)
- RawContentBlockStartEvent with an empty TextBlock
- RawContentBlockDeltaEvent with a TextDelta
- RawContentBlockDeltaEvent with a TextDelta
- RawContentBlockDeltaEvent with a TextDelta
- ...
- RawContentBlockStopEvent
- RawContentBlockStartEvent with ToolUseBlock specifying the function name
- RawContentBlockDeltaEvent with a InputJSONDelta
- RawContentBlockDeltaEvent with a InputJSONDelta
- ...
- RawContentBlockStopEvent
- RawMessageDeltaEvent with a stop_reason='tool_use'
- RawMessageStopEvent(type='message_stop')
Each message could contain multiple blocks of the same type.
"""
if result is None:
raise TypeError("Expected a stream of messages")
current_message: MessageParam | None = None
current_block: (
TextBlockParam
| ToolUseBlockParam
| ThinkingBlockParam
| RedactedThinkingBlockParam
| None
) = None
current_tool_args: str
input_usage: Usage | None = None
async for response in result:
LOGGER.debug("Received response: %s", response)
if isinstance(response, RawMessageStartEvent):
if response.message.role != "assistant":
raise ValueError("Unexpected message role")
current_message = MessageParam(role=response.message.role, content=[])
input_usage = response.message.usage
elif isinstance(response, RawContentBlockStartEvent):
if isinstance(response.content_block, ToolUseBlock):
current_block = ToolUseBlockParam(
type="tool_use",
id=response.content_block.id,
name=response.content_block.name,
input="",
)
current_tool_args = ""
elif isinstance(response.content_block, TextBlock):
current_block = TextBlockParam(
type="text", text=response.content_block.text
)
yield {"role": "assistant"}
if response.content_block.text:
yield {"content": response.content_block.text}
elif isinstance(response.content_block, ThinkingBlock):
current_block = ThinkingBlockParam(
type="thinking",
thinking=response.content_block.thinking,
signature=response.content_block.signature,
)
elif isinstance(response.content_block, RedactedThinkingBlock):
current_block = RedactedThinkingBlockParam(
type="redacted_thinking", data=response.content_block.data
)
LOGGER.debug(
"Some of Claudes internal reasoning has been automatically "
"encrypted for safety reasons. This doesnt affect the quality of "
"responses"
)
elif isinstance(response, RawContentBlockDeltaEvent):
if current_block is None:
raise ValueError("Unexpected delta without a block")
if isinstance(response.delta, InputJSONDelta):
current_tool_args += response.delta.partial_json
elif isinstance(response.delta, TextDelta):
text_block = cast(TextBlockParam, current_block)
text_block["text"] += response.delta.text
yield {"content": response.delta.text}
elif isinstance(response.delta, ThinkingDelta):
thinking_block = cast(ThinkingBlockParam, current_block)
thinking_block["thinking"] += response.delta.thinking
elif isinstance(response.delta, SignatureDelta):
thinking_block = cast(ThinkingBlockParam, current_block)
thinking_block["signature"] += response.delta.signature
elif isinstance(response, RawContentBlockStopEvent):
if current_block is None:
raise ValueError("Unexpected stop event without a current block")
if current_block["type"] == "tool_use":
# tool block
tool_args = json.loads(current_tool_args) if current_tool_args else {}
current_block["input"] = tool_args
yield {
"tool_calls": [
llm.ToolInput(
id=current_block["id"],
tool_name=current_block["name"],
tool_args=tool_args,
)
]
}
elif current_block["type"] == "thinking":
# thinking block
LOGGER.debug("Thinking: %s", current_block["thinking"])
if current_message is None:
raise ValueError("Unexpected stop event without a current message")
current_message["content"].append(current_block) # type: ignore[union-attr]
current_block = None
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)
current_message = None
def _create_token_stats(
input_usage: Usage | None, response_usage: MessageDeltaUsage
) -> dict[str, Any]:
"""Create token stats for conversation agent tracing."""
input_tokens = 0
cached_input_tokens = 0
if input_usage:
input_tokens = input_usage.input_tokens
cached_input_tokens = input_usage.cache_creation_input_tokens or 0
output_tokens = response_usage.output_tokens
return {
"stats": {
"input_tokens": input_tokens,
"cached_input_tokens": cached_input_tokens,
"output_tokens": output_tokens,
}
}
class AnthropicBaseLLMEntity(Entity):
"""Anthropic base LLM entity."""
_attr_has_entity_name = True
_attr_name = None
def __init__(self, entry: AnthropicConfigEntry, subentry: ConfigSubentry) -> None:
"""Initialize the entity."""
self.entry = entry
self.subentry = subentry
self._attr_unique_id = subentry.subentry_id
self._attr_device_info = dr.DeviceInfo(
identifiers={(DOMAIN, subentry.subentry_id)},
name=subentry.title,
manufacturer="Anthropic",
model="Claude",
entry_type=dr.DeviceEntryType.SERVICE,
)
async def _async_handle_chat_log(
self,
chat_log: conversation.ChatLog,
) -> None:
"""Generate an answer for the chat log."""
options = self.subentry.data
tools: list[ToolParam] | None = None
if chat_log.llm_api:
tools = [
_format_tool(tool, chat_log.llm_api.custom_serializer)
for tool in chat_log.llm_api.tools
]
system = chat_log.content[0]
if not isinstance(system, conversation.SystemContent):
raise TypeError("First message must be a system message")
messages = _convert_content(chat_log.content[1:])
client = self.entry.runtime_data
thinking_budget = options.get(CONF_THINKING_BUDGET, RECOMMENDED_THINKING_BUDGET)
model = options.get(CONF_CHAT_MODEL, RECOMMENDED_CHAT_MODEL)
# To prevent infinite loops, we limit the number of iterations
for _iteration in range(MAX_TOOL_ITERATIONS):
model_args = {
"model": model,
"messages": messages,
"tools": tools or NOT_GIVEN,
"max_tokens": options.get(CONF_MAX_TOKENS, RECOMMENDED_MAX_TOKENS),
"system": system.content,
"stream": True,
}
if model in THINKING_MODELS and thinking_budget >= MIN_THINKING_BUDGET:
model_args["thinking"] = ThinkingConfigEnabledParam(
type="enabled", budget_tokens=thinking_budget
)
else:
model_args["thinking"] = ThinkingConfigDisabledParam(type="disabled")
model_args["temperature"] = options.get(
CONF_TEMPERATURE, RECOMMENDED_TEMPERATURE
)
try:
stream = await client.messages.create(**model_args)
except anthropic.AnthropicError as err:
raise HomeAssistantError(
f"Sorry, I had a problem talking to Anthropic: {err}"
) from err
messages.extend(
_convert_content(
[
content
async for content in chat_log.async_add_delta_content_stream(
self.entity_id,
_transform_stream(chat_log, stream, messages),
)
if not isinstance(content, conversation.AssistantContent)
]
)
)
if not chat_log.unresponded_tool_results:
break

View File

@ -29,7 +29,7 @@
"set_options": {
"data": {
"name": "[%key:common::config_flow::data::name%]",
"prompt": "Instructions",
"prompt": "[%key:common::config_flow::data::prompt%]",
"chat_model": "[%key:common::generic::model%]",
"max_tokens": "Maximum tokens to return in response",
"temperature": "Temperature",

View File

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

View File

@ -191,7 +191,7 @@ class AppleTvMediaPlayer(
self._is_feature_available(FeatureName.PowerState)
and self.atv.power.power_state == PowerState.Off
):
return MediaPlayerState.STANDBY
return MediaPlayerState.OFF
if self._playing:
state = self._playing.device_state
if state in (DeviceState.Idle, DeviceState.Loading):
@ -200,7 +200,7 @@ class AppleTvMediaPlayer(
return MediaPlayerState.PLAYING
if state in (DeviceState.Paused, DeviceState.Seeking, DeviceState.Stopped):
return MediaPlayerState.PAUSED
return MediaPlayerState.STANDBY # Bad or unknown state?
return MediaPlayerState.IDLE # Bad or unknown state?
return None
@callback

View File

@ -6,7 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/arcam_fmj",
"iot_class": "local_polling",
"loggers": ["arcam"],
"requirements": ["arcam-fmj==1.8.1"],
"requirements": ["arcam-fmj==1.8.2"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaRenderer:1",

View File

@ -38,8 +38,6 @@ from .pipeline import (
async_create_default_pipeline,
async_get_pipeline,
async_get_pipelines,
async_migrate_engine,
async_run_migrations,
async_setup_pipeline_store,
async_update_pipeline,
)
@ -61,7 +59,6 @@ __all__ = (
"WakeWordSettings",
"async_create_default_pipeline",
"async_get_pipelines",
"async_migrate_engine",
"async_pipeline_from_audio_stream",
"async_setup",
"async_update_pipeline",
@ -87,7 +84,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
hass.data[DATA_LAST_WAKE_UP] = {}
await async_setup_pipeline_store(hass)
await async_run_migrations(hass)
async_register_websocket_api(hass)
return True

View File

@ -3,7 +3,6 @@
DOMAIN = "assist_pipeline"
DATA_CONFIG = f"{DOMAIN}.config"
DATA_MIGRATIONS = f"{DOMAIN}_migrations"
DEFAULT_PIPELINE_TIMEOUT = 60 * 5 # seconds

View File

@ -13,7 +13,7 @@ from pathlib import Path
from queue import Empty, Queue
from threading import Thread
import time
from typing import TYPE_CHECKING, Any, Literal, cast
from typing import TYPE_CHECKING, Any, cast
import wave
import hass_nabucasa
@ -49,7 +49,6 @@ from .const import (
CONF_DEBUG_RECORDING_DIR,
DATA_CONFIG,
DATA_LAST_WAKE_UP,
DATA_MIGRATIONS,
DOMAIN,
MS_PER_CHUNK,
SAMPLE_CHANNELS,
@ -2059,50 +2058,6 @@ async def async_setup_pipeline_store(hass: HomeAssistant) -> PipelineData:
return PipelineData(pipeline_store)
@callback
def async_migrate_engine(
hass: HomeAssistant,
engine_type: Literal["conversation", "stt", "tts", "wake_word"],
old_value: str,
new_value: str,
) -> None:
"""Register a migration of an engine used in pipelines."""
hass.data.setdefault(DATA_MIGRATIONS, {})[engine_type] = (old_value, new_value)
# Run migrations when config is already loaded
if DATA_CONFIG in hass.data:
hass.async_create_background_task(
async_run_migrations(hass), "assist_pipeline_migration", eager_start=True
)
async def async_run_migrations(hass: HomeAssistant) -> None:
"""Run pipeline migrations."""
if not (migrations := hass.data.get(DATA_MIGRATIONS)):
return
engine_attr = {
"conversation": "conversation_engine",
"stt": "stt_engine",
"tts": "tts_engine",
"wake_word": "wake_word_entity",
}
updates = []
for pipeline in async_get_pipelines(hass):
attr_updates = {}
for engine_type, (old_value, new_value) in migrations.items():
if getattr(pipeline, engine_attr[engine_type]) == old_value:
attr_updates[engine_attr[engine_type]] = new_value
if attr_updates:
updates.append((pipeline, attr_updates))
for pipeline, attr_updates in updates:
await async_update_pipeline(hass, pipeline, **attr_updates)
@dataclass
class PipelineConversationData:
"""Hold data for the duration of a conversation."""

View File

@ -72,7 +72,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
{
vol.Optional("message"): str,
vol.Optional("media_id"): _media_id_validator,
vol.Optional("preannounce"): bool,
vol.Optional("preannounce", default=True): bool,
vol.Optional("preannounce_media_id"): _media_id_validator,
}
),
@ -89,7 +89,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
{
vol.Optional("start_message"): str,
vol.Optional("start_media_id"): _media_id_validator,
vol.Optional("preannounce"): bool,
vol.Optional("preannounce", default=True): bool,
vol.Optional("preannounce_media_id"): _media_id_validator,
vol.Optional("extra_system_prompt"): str,
}
@ -114,7 +114,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
ask_question_args = {
"question": call.data.get("question"),
"question_media_id": call.data.get("question_media_id"),
"preannounce": call.data.get("preannounce", False),
"preannounce": call.data.get("preannounce", True),
"answers": call.data.get("answers"),
}
@ -137,7 +137,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
vol.Required(ATTR_ENTITY_ID): cv.entity_domain(DOMAIN),
vol.Optional("question"): str,
vol.Optional("question_media_id"): _media_id_validator,
vol.Optional("preannounce"): bool,
vol.Optional("preannounce", default=True): bool,
vol.Optional("preannounce_media_id"): _media_id_validator,
vol.Optional("answers"): [
{

View File

@ -68,9 +68,10 @@ ask_question:
required: true
selector:
entity:
domain: assist_satellite
supported_features:
- assist_satellite.AssistSatelliteEntityFeature.START_CONVERSATION
filter:
domain: assist_satellite
supported_features:
- assist_satellite.AssistSatelliteEntityFeature.START_CONVERSATION
question:
required: false
example: "What kind of music would you like to play?"

View File

@ -28,5 +28,5 @@
"documentation": "https://www.home-assistant.io/integrations/august",
"iot_class": "cloud_push",
"loggers": ["pubnub", "yalexs"],
"requirements": ["yalexs==8.10.0", "yalexs-ble==2.6.0"]
"requirements": ["yalexs==8.10.0", "yalexs-ble==3.1.0"]
}

View File

@ -6,6 +6,7 @@ from datetime import timedelta
import logging
API_CO2 = "carbon_dioxide"
API_DEW_POINT = "dew_point"
API_DUST = "dust"
API_HUMID = "humidity"
API_LUX = "illuminance"

View File

@ -34,6 +34,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import (
API_CO2,
API_DEW_POINT,
API_DUST,
API_HUMID,
API_LUX,
@ -110,6 +111,15 @@ SENSOR_TYPES: tuple[AwairSensorEntityDescription, ...] = (
unique_id_tag="CO2", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
),
AwairSensorEntityDescription(
key=API_DEW_POINT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
translation_key="dew_point",
unique_id_tag="dew_point",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
)
SENSOR_TYPES_DUST: tuple[AwairSensorEntityDescription, ...] = (

View File

@ -57,6 +57,9 @@
},
"sound_level": {
"name": "Sound level"
},
"dew_point": {
"name": "Dew point"
}
}
}

View File

@ -30,7 +30,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: AxisConfigEntry)
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
hub.setup()
config_entry.add_update_listener(hub.async_new_address_callback)
config_entry.async_on_unload(
config_entry.add_update_listener(hub.async_new_address_callback)
)
config_entry.async_on_unload(hub.teardown)
config_entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, hub.shutdown)

View File

@ -2,9 +2,9 @@
from homeassistant.config_entries import SOURCE_SYSTEM
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, discovery_flow
from homeassistant.helpers.backup import DATA_BACKUP
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.typing import ConfigType
@ -37,7 +37,6 @@ from .manager import (
IdleEvent,
IncorrectPasswordError,
ManagerBackup,
ManagerStateEvent,
NewBackup,
RestoreBackupEvent,
RestoreBackupStage,
@ -45,6 +44,7 @@ from .manager import (
WrittenBackup,
)
from .models import AddonInfo, AgentBackup, BackupNotFound, Folder
from .services import async_setup_services
from .util import suggested_filename, suggested_filename_from_name_date
from .websocket import async_register_websocket_handlers
@ -71,12 +71,12 @@ __all__ = [
"IncorrectPasswordError",
"LocalBackupAgent",
"ManagerBackup",
"ManagerStateEvent",
"NewBackup",
"RestoreBackupEvent",
"RestoreBackupStage",
"RestoreBackupState",
"WrittenBackup",
"async_get_manager",
"suggested_filename",
"suggested_filename_from_name_date",
]
@ -103,39 +103,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
backup_manager = BackupManager(hass, reader_writer)
hass.data[DATA_MANAGER] = backup_manager
try:
await backup_manager.async_setup()
except Exception as err:
hass.data[DATA_BACKUP].manager_ready.set_exception(err)
raise
else:
hass.data[DATA_BACKUP].manager_ready.set_result(None)
await backup_manager.async_setup()
async_register_websocket_handlers(hass, with_hassio)
async def async_handle_create_service(call: ServiceCall) -> None:
"""Service handler for creating backups."""
agent_id = list(backup_manager.local_backup_agents)[0]
await backup_manager.async_create_backup(
agent_ids=[agent_id],
include_addons=None,
include_all_addons=False,
include_database=True,
include_folders=None,
include_homeassistant=True,
name=None,
password=None,
)
async def async_handle_create_automatic_service(call: ServiceCall) -> None:
"""Service handler for creating automatic backups."""
await backup_manager.async_create_automatic_backup()
if not with_hassio:
hass.services.async_register(DOMAIN, "create", async_handle_create_service)
hass.services.async_register(
DOMAIN, "create_automatic", async_handle_create_automatic_service
)
async_setup_services(hass)
async_register_http_views(hass)
@ -164,3 +136,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: BackupConfigEntry) -> bo
async def async_unload_entry(hass: HomeAssistant, entry: BackupConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
@callback
def async_get_manager(hass: HomeAssistant) -> BackupManager:
"""Get the backup manager instance.
Raises HomeAssistantError if the backup integration is not available.
"""
if DATA_MANAGER not in hass.data:
raise HomeAssistantError("Backup integration is not available")
return hass.data[DATA_MANAGER]

View File

@ -1,38 +0,0 @@
"""Websocket commands for the Backup integration."""
from typing import Any
import voluptuous as vol
from homeassistant.components import websocket_api
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.backup import async_subscribe_events
from .const import DATA_MANAGER
from .manager import ManagerStateEvent
@callback
def async_register_websocket_handlers(hass: HomeAssistant) -> None:
"""Register websocket commands."""
websocket_api.async_register_command(hass, handle_subscribe_events)
@websocket_api.require_admin
@websocket_api.websocket_command({vol.Required("type"): "backup/subscribe_events"})
@websocket_api.async_response
async def handle_subscribe_events(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Subscribe to backup events."""
def on_event(event: ManagerStateEvent) -> None:
connection.send_message(websocket_api.event_message(msg["id"], event))
if DATA_MANAGER in hass.data:
manager = hass.data[DATA_MANAGER]
on_event(manager.last_event)
connection.subscriptions[msg["id"]] = async_subscribe_events(hass, on_event)
connection.send_result(msg["id"])

View File

@ -8,10 +8,6 @@ from datetime import datetime
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.backup import (
async_subscribe_events,
async_subscribe_platform_events,
)
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import DOMAIN, LOGGER
@ -56,8 +52,8 @@ class BackupDataUpdateCoordinator(DataUpdateCoordinator[BackupCoordinatorData]):
update_interval=None,
)
self.unsubscribe: list[Callable[[], None]] = [
async_subscribe_events(hass, self._on_event),
async_subscribe_platform_events(hass, self._on_event),
backup_manager.async_subscribe_events(self._on_event),
backup_manager.async_subscribe_platform_events(self._on_event),
]
self.backup_manager = backup_manager

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