Compare commits

...
Author SHA1 Message Date
Paulus Schoutsen 099a480e57 Use modern Python for OpenAI 2025-07-25 09:46:35 +00:00
Petro31andGitHub 4cc4bd3b9a Remove redundant async_set_context from platforms (#149403) 2025-07-24 22:28:56 +01:00
Raphael HehlandGitHub dbc2b1354b UnifiProtect refactor sensor retrieval in tests to use get_sensor_by_key function (#149398) 2025-07-24 10:11:47 -10:00
fbe257f997 Add quality scale file to ring integration (#136454)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-24 20:19:30 +01:00
Alex HermannandGitHub 208dde10e6 Make default title configurable in XMPP (#149379) 2025-07-24 20:08:47 +01:00
Norbert RittelandGitHub b7b733efc3 Use common state for "Normal" in switchbot (#149399) 2025-07-24 20:03:45 +01:00
Norbert RittelandGitHub 1d9f779b2a Add missing hyphen to "case-sensitive" in tuya (#149400) 2025-07-24 20:03:36 +01:00
56c53fdb9b Allow Bluetooth proxy for Shelly devices only if Zigbee firmware is not active (#149193)
Co-authored-by: Shay Levy <[email protected]>
Co-authored-by: Norbert Rittel <[email protected]>
2025-07-24 21:14:44 +03:00
5c4862ffe1 Fix Air Conditioner set temperature error in LG ThinQ (#147008)
Co-authored-by: yunseon.park <[email protected]>
2025-07-24 20:12:41 +02:00
Abílio CostaandGitHub 5c7913c3bd Remove door state from Whirlpool machine state sensor (#144078) 2025-07-24 20:07:57 +02:00
Norbert RittelandGitHub 36a98470cc Remove excessive comma from dsmr_reader issue description (#149393) 2025-07-24 19:20:42 +02:00
Norbert RittelandGitHub f2c995cf86 Fix sentence-casing of "DSMR options" string (#149392) 2025-07-24 19:20:28 +02:00
eeca5a8030 Improve Airthings test coverage (#144750)
Co-authored-by: Joostlek <[email protected]>
2025-07-24 19:10:01 +02:00
Norbert RittelandGitHub 56d97f5545 Drop duplicated lower-case "qnap" from setup description (#149384) 2025-07-24 18:49:46 +02:00
Simone ChemelliandGitHub 995a99e256 Bump aioamazondevices to 3.5.1 (#149385) 2025-07-24 16:54:00 +01:00
Abílio CostaandGitHub ef7cd815b2 Add list of targeted entities to target state event (#149203) 2025-07-24 16:52:12 +01:00
Paulus SchoutsenandGitHub 8b8616182d Allow downloading a device analytics dump (#149376) 2025-07-24 17:27:02 +02:00
Frank WickströmandGitHub 760b69d458 Only send integers when setting Huum sauna temperature (#149380) 2025-07-24 17:13:54 +02:00
Norbert RittelandGitHub 6adcd34521 Remove space character from "autodetect" in xiaomi_miio (#149381) 2025-07-24 17:10:46 +02:00
a0992498c6 Improve removal of stale entities/devices in Husqvarna Automower (#148428)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-24 15:52:43 +01:00
Marc MuellerandGitHub d6175fb383 Update mypy-dev to 1.18.0a3 (#149383) 2025-07-24 16:05:24 +02:00
G JohanssonandGitHub dd3c9ab3af Use OptionsFlowWithReload in mqtt (#149092) 2025-07-24 15:34:00 +02:00
Maciej BieniekandGitHub fea2ef1ac1 Bump imgw_pib to version 1.5.1 (#149368) 2025-07-24 15:37:01 +03:00
Álvaro Fernández RojasandGitHub 326bcc3f05 Update aioairzone-cloud to v0.7.0 (#149369)
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2025-07-24 15:32:51 +03:00
Andrew JacksonandGitHub feeef88710 Bump aiomealie to 0.10.0 (#149370) 2025-07-24 13:07:35 +02:00
f481c1b92f Add sensors for ventilator in LG ThinQ (#140846)
Co-authored-by: yunseon.park <[email protected]>
2025-07-24 12:33:34 +02:00
eea22d8079 Add config flow for datadog (#148104)
Co-authored-by: G Johansson <[email protected]>
2025-07-24 12:29:07 +02:00
Maciej BieniekandGitHub 393087cf50 Bump aioshelly to 13.8.0 (#149365) 2025-07-24 11:50:26 +02:00
Norbert RittelandGitHub f5718e1df6 Fix spelling of "autoplay" in music_assistant (#149364) 2025-07-24 11:15:57 +02:00
Artur PragaczandGitHub 15f2ae3002 Mark Onkyo quality scale as bronze (#149362) 2025-07-24 11:03:02 +02:00
Norbert RittelandGitHub f458ede468 Small fixes to user-facing strings of webostv (#149359) 2025-07-24 11:53:33 +03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d85ffee27a Bump github/codeql-action from 3.29.3 to 3.29.4 (#149354)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:29:34 +02:00
Norbert RittelandGitHub 2e12d67f2f Improve id_missing abort message in samsungtv (#149357) 2025-07-24 10:23:30 +02:00
Norbert RittelandGitHub 46a01c2060 Fix config entry name and description in rainbird.set_rain_delay action (#149358) 2025-07-24 10:23:17 +02:00
tronikosandGitHub 53d77c4c10 Fix Chinese in Google Cloud STT (#149155) 2025-07-24 01:08:58 -07:00
Norbert RittelandGitHub fcd514a06b Sentence-case "Still image URL" in mjpeg (#149356) 2025-07-24 09:23:21 +02:00
Norbert RittelandGitHub 049a698815 Add missing hyphen to "right-hand drive" in teslemetry (#149355) 2025-07-24 08:56:49 +02:00
Norbert RittelandGitHub 55f01e3485 Make descriptions of modbus.stop/restart actions consistent (#149341) 2025-07-24 08:23:42 +02:00
Artur PragaczandGitHub c2b1932045 Bump aioonkyo to 0.3.0 (#149336) 2025-07-24 08:23:02 +02:00
Norbert RittelandGitHub 5543587527 Fix spelling of "sea level" in luftdaten (#149347) 2025-07-24 08:22:25 +02:00
J. Nick KostonandGitHub 202d8ac802 Bump yalexs-ble to 3.1.0 (#149352) 2025-07-24 08:18:59 +02:00
Norbert RittelandGitHub 7613880645 Fix spelling of "the setup" in nest (#149345) 2025-07-24 02:50:39 +02:00
Norbert RittelandGitHub 3f77c13aad Fix spelling of "re-authenticate" in devolo_home_control (#149342) 2025-07-24 02:46:20 +02:00
Raphael HehlandGitHub b966b59c09 Unifiprotect public api snapshot (#149213) 2025-07-23 13:37:34 -10:00
40cf47ae5a Bump aioimmich to 0.11.1 (#149335)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-23 20:48:04 +02:00
Norbert RittelandGitHub da8ce52ed7 Fix grammar issues in re-interview description of zwave_js (#149337) 2025-07-23 19:00:55 +01:00
Norbert RittelandGitHub b5190788ac Fix missing sentence-casing of "MAC address" in anthemav (#149333) 2025-07-23 19:29:31 +02:00
Norbert RittelandGitHub bfa7ff3ede Make spelling of "Telldus Live" consistent (#149332) 2025-07-23 19:07:40 +02:00
Norbert RittelandGitHub 1312e04c57 Fix typos in update_failed message of fritz (#149330) 2025-07-23 18:53:19 +02:00
Matthias AlphartandGitHub d3771571cd Bump knx-frontend (#149287) 2025-07-23 17:18:41 +01:00
Norbert RittelandGitHub 5aa629edd0 Fix typo in "re-authentication" in devolo_home_network (#149312) 2025-07-23 17:16:00 +01:00
Norbert RittelandGitHub 3ed297676f Remove third "s" from "Home Assistant" in lametric (#149329) 2025-07-23 18:08:01 +02:00
Norbert RittelandGitHub d735af505e Sentence-case "app" in laundrify (#149328) 2025-07-23 18:04:47 +02:00
Norbert RittelandGitHub e337abb12d Clarify setup description in google_travel_time (#149327) 2025-07-23 17:57:45 +02:00
Maciej BieniekandGitHub 45edd12f13 Bump imgw_pib to version 1.5.0 (#149324) 2025-07-23 16:51:24 +01:00
Ludovic BOUÉandGitHub 5b94f5a99a Add more types in TYPE_MAP for Matter Cover (#149188) 2025-07-23 17:33:24 +02:00
Norbert RittelandGitHub 8b7295cd26 Fix three spelling issues in lg_thinq (#149322) 2025-07-23 17:16:28 +02:00
Marc HörskenandGitHub 15f7dade5e Fix warning about failure to get action during setup phase (#148923) 2025-07-23 17:05:35 +02:00
Norbert RittelandGitHub 61807412c4 Fix typo "optimisic" in mqtt (#149291) 2025-07-23 16:03:12 +01:00
Norbert RittelandGitHub f679f33c56 Fix description of current field of keba.set_current action (#149326) 2025-07-23 17:02:59 +02:00
SidandGitHub 2abd203580 Bump eheimdigital quality scale to platinum (#148263) 2025-07-23 16:58:18 +02:00
Avi MillerandGitHub ccd22ce0d5 Fix brightness_step and brightness_step_pct via lifx.set_state (#149217)
Signed-off-by: Avi Miller <[email protected]>
2025-07-23 16:55:44 +02:00
AlCalzoneandGitHub 391b144033 Update Z-Wave LED entity name for ZWA-2 (#149323) 2025-07-23 16:55:00 +02:00
tronikosandGitHub b6db10340e Update supported languages for Google Generative AI TTS and STT (#149154) 2025-07-23 16:54:06 +02:00
epenetandGitHub 23b2936174 Replace RuntimeError with custom ServiceValidationError in Tuya (#149175) 2025-07-23 16:53:36 +02:00
Petro31andGitHub fad5f7a47b Move optimistic platform logic to AbstractTemplateEntity base class (#149245) 2025-07-23 14:52:25 +01:00
MariusandGitHub 58ddf4ea95 Add note about re-interviewing Z-Wave battery powered devices (#149300) 2025-07-23 15:40:09 +02:00
AlCalzoneandGitHub 22fa863984 Discover ZWA-2 LED as a configuration entity in Z-Wave (#149298) 2025-07-23 15:33:52 +02:00
d9b25770ad Remove sensors from Imeon Inverter (#148542)
Co-authored-by: TheBushBoy <[email protected]>
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-23 15:32:32 +02:00
Nick KuiperandGitHub 1c8ae8a21b Add switches for blue current integration. (#146210) 2025-07-23 15:12:53 +02:00
Norbert RittelandGitHub 6d3872252b Fix one inconsistent spelling of "AppArmor" in hassio (#149310) 2025-07-23 15:09:17 +02:00
4730c5b831 Add logging to Tuya for devices that cannot be supported (#149192)
Co-authored-by: Copilot <[email protected]>
2025-07-23 15:07:37 +02:00
Artur PragaczandGitHub 9a9f65dc36 Improve config flow tests in Onkyo (#149199) 2025-07-23 15:06:25 +02:00
G JohanssonandGitHub 7c83fd0bf9 Add twice_daily forecast to SMHI (#148882) 2025-07-23 15:05:39 +02:00
johanzanderandGitHub 70e03cdd4e Implements coordinator pattern for Growatt component data fetching (#143373) 2025-07-23 15:05:19 +02:00
4d5c1b139b Consolidate REST sensor encoding tests using pytest parametrize (#149279)
Co-authored-by: Copilot <[email protected]>
2025-07-23 14:57:07 +02:00
Antoine ReversatandGitHub 6dc5c9beb7 Add fan off mode to the supported fan modes to fujitsu_fglair (#149277) 2025-07-23 14:52:14 +02:00
Brett AdamsandGitHub 47611619db Update Tesla OAuth Server in Tesla Fleet (#149280) 2025-07-23 14:45:50 +02:00
Norbert RittelandGitHub 2a0a31bff8 Capitalize "HEPA" as an abbreviation in matter (#149306) 2025-07-23 14:27:49 +02:00
Joost LekkerkerkerandGitHub dcf29d12a7 Migrate Ollama to has entity name (#149303) 2025-07-23 14:27:32 +02:00
Norbert RittelandGitHub edf6166a9f Fix spelling of "Domino's Pizza" in dominos (#149308) 2025-07-23 13:58:24 +02:00
Joost LekkerkerkerandGitHub eb8ca53a03 Migrate Anthropic to has entity name (#149302) 2025-07-23 12:58:28 +02:00
Joost LekkerkerkerandGitHub 3dffd74607 Migrate OpenAI to has entity name (#149301) 2025-07-23 12:58:15 +02:00
Thomas55555andGitHub b37273ed33 Makes entites available in Husqvarna Automower when mower is in error state (#149261) 2025-07-23 12:39:17 +02:00
David FergusonandGitHub 232b34609c Avoid hardcoded max core climate timeout in SleepIQ (#149283) 2025-07-23 12:37:47 +02:00
Norbert RittelandGitHub aeeabfcae7 Fix typo "hazlenut" in miele (#149299) 2025-07-23 11:55:35 +02:00
Vincent WolsinkandGitHub 52abab8ae8 Use translation_key for entities in Huum (#149256) 2025-07-23 11:28:28 +02:00
Artur PragaczandGitHub 7aa4810b0a Clean up internal_get_tts_audio in TTS entity (#148946) 2025-07-23 11:26:54 +02:00
Norbert RittelandGitHub c4d742f549 Add missing hyphen to "auto-renew period" in whois (#149296) 2025-07-23 12:01:19 +03:00
51a46a128c Begin migrating unifiprotect to use the public API (#149126)
Co-authored-by: J. Nick Koston <[email protected]>
2025-07-22 22:46:52 -10:00
Norbert RittelandGitHub 9a6ba225e4 Fix typo "paela" in miele (#149295) 2025-07-23 10:33:31 +02:00
Norbert RittelandGitHub a5ab523014 Fix sentence-casing in tomorrowio (#149293) 2025-07-23 10:03:04 +02:00
Norbert RittelandGitHub 40571dff3d Replace typo "effect" with "affect" in insteon (#149292) 2025-07-23 09:33:27 +02:00
J. Nick KostonandGitHub 5f2f038609 Bump dbus-fast to 2.44.2 (#149281) 2025-07-23 08:14:41 +02:00
9fd2ad425c Refactor KNX UI conditional selectors and migrate store data (#146067)
Co-authored-by: Copilot <[email protected]>
2025-07-23 07:22:48 +02:00
MichaelandGitHub 2f6c0a1b7f Bump aioimmich to 0.11.0 (#149272) 2025-07-23 00:30:23 +02:00
Artur PragaczandGitHub dde73c05cb Order selectors alphabetically in helper (#149269) 2025-07-22 23:06:51 +02:00
MichaelandGitHub 993b0bbdd7 Use absolute humidity device class in HomematicIP Cloud (#148905) 2025-07-22 22:51:03 +02:00
Raphael HehlandGitHub 45dbf3ef1a Bump uiprotect to version 7.19.0 (#149266) 2025-07-22 22:50:55 +02:00
Paulus SchoutsenandGitHub 71c1837f39 Update OpenAI title to drop "conversation" (#149263) 2025-07-22 22:43:02 +02:00
34eb99530f Use translation_placeholders in tuya cover descriptions (#149248)
Co-authored-by: Simone Chemelli <[email protected]>
2025-07-22 22:21:59 +02:00
Thomas55555andGitHub 55ac4d8855 Bump aioautomower to 2.0.1 (#149262) 2025-07-22 21:17:59 +02:00
epenetandGitHub ef3fb50018 Use translation_placeholders in tuya light descriptions (#149249) 2025-07-22 19:44:51 +02:00
epenetandGitHub 316ac6253b Use translation_placeholders in tuya number descriptions (#149250) 2025-07-22 19:06:14 +02:00
epenetandGitHub 252a46d141 Use translation_placeholders in tuya select descriptions (#149251) 2025-07-22 19:05:54 +02:00
Álvaro Fernández RojasandGitHub 969ad232aa Update aioairzone-cloud to v0.6.16 (#149254) 2025-07-22 17:23:38 +01:00
Martin HjelmareandGitHub 828a47db06 Add Z-Wave USB migration confirm step (#149243) 2025-07-22 17:09:11 +03:00
G JohanssonandGitHub 3947569132 Bump holidays to 0.77 (#149246) 2025-07-22 15:50:38 +02:00
Joakim SørensenandGitHub e5f9788d24 Refactor cloud backup agent to use updated file handling methods (#149231) 2025-07-22 15:15:56 +02:00
Erik MontnemeryandGitHub dd399ef59f Refactor EntityPlatform (#147927) 2025-07-22 14:35:57 +02:00
5a771b501d Fix ColorMode.WHITE support in Tuya (#126242)
Co-authored-by: epenet <[email protected]>
Co-authored-by: Erik Montnemery <[email protected]>
2025-07-22 14:07:34 +02:00
hahn-thandGitHub 3f67ba4c02 Add support for ELV-SH-WSM to homematicip (#149098) 2025-07-22 14:06:03 +02:00
Joost LekkerkerkerandGitHub c075134845 Use OpenRouterClient to get the models (#148903) 2025-07-22 13:58:33 +02:00
Joost LekkerkerkerandGitHub e5c7e04329 Introduce base entity in Open Router (#148910) 2025-07-22 13:43:41 +02:00
Åke StrandbergandGitHub 49807c9fbe Add set_program service to Miele (#143442) 2025-07-22 13:33:03 +02:00
Norbert RittelandGitHub e79d42ecfc Add missing hyphen to "post-heater" in vallox (#149222) 2025-07-22 13:32:45 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1f07dd7946 Bump github/codeql-action from 3.29.2 to 3.29.3 (#149220)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 13:07:56 +02:00
epenetandGitHub 8d1c789ca2 Replace RuntimeError with TYPE_CHECKING in Tuya (#149227) 2025-07-22 12:10:23 +02:00
Artur PragaczandGitHub f5d68a4ea4 Simplify getting domains to resolve in bootstrap (#145829) 2025-07-22 10:10:59 +02:00
Artur PragaczandGitHub 2315bcbfe3 Set has_entity_name in Onkyo (#149223) 2025-07-22 10:02:15 +02:00
Raphael HehlandGitHub df4e1411cc Bump uiprotect to version 7.18.1 (#149209) 2025-07-22 09:00:25 +02:00
Norbert RittelandGitHub 3e7974a638 Add missing hyphen to "post-processing" in nzbget (#149205) 2025-07-22 08:58:32 +02:00
David FergusonandGitHub 48b8827390 Bump asyncsleepiq to 1.5.3 (#149215) 2025-07-22 08:56:54 +02:00
hanwgandGitHub 42cf4e8db7 Fix multiple webhook secrets for Telegram bot (#149103) 2025-07-22 07:42:40 +02:00
ef2531d28d Add diagnostics support to Huawei LTE (#131085)
Co-authored-by: abmantis <[email protected]>
Co-authored-by: Abílio Costa <[email protected]>
2025-07-21 21:52:48 +01:00
Vincent WolsinkandGitHub 79dd91ebc6 Add sauna light control in Huum (#149169) 2025-07-21 22:52:24 +02:00
ecb6cc50b9 Add Reolink post recording time select entity (#149201)
Co-authored-by: Norbert Rittel <[email protected]>
2025-07-21 21:48:02 +01:00
starkillerOGandGitHub b6014da121 Add Reolink wifi signal sensor for IPC cams (#149200) 2025-07-21 21:35:28 +02:00
Erik MontnemeryandGitHub 941d3c2be4 Improve integration sensor tests (#149180) 2025-07-21 18:23:58 +02:00
starkillerOGandGitHub 7d895653fb Bump reolink-aio to 0.14.3 (#149191) 2025-07-21 18:19:56 +02:00
Erik MontnemeryandGitHub 3bd70a4698 Improve derivative sensor tests (#149179) 2025-07-21 17:51:26 +02:00
b85ec55abb Add availability template to template helper config flow (#147623)
Co-authored-by: Norbert Rittel <[email protected]>
Co-authored-by: Joostlek <[email protected]>
Co-authored-by: Erik Montnemery <[email protected]>
2025-07-21 17:41:56 +02:00
Michael HansenandGitHub 3f42911af4 Add streaming to cloud TTS (#148925) 2025-07-21 10:33:23 -05:00
G JohanssonandGitHub 3c70932357 Use OptionsFlowWithReload in enphase_envoy (#149171) 2025-07-21 16:52:25 +02:00
Artur PragaczandGitHub 40252763d7 Switch to a new library in Onkyo (#148613) 2025-07-21 16:31:28 +02:00
G JohanssonandGitHub 80b96b0007 Use OptionsFlowWithReload in roku (#149172) 2025-07-21 15:40:30 +02:00
David KnowlesandGitHub f3db3ba3c8 Bump pyschlage to 2025.7.3 (#149184) 2025-07-21 14:36:12 +01:00
Joakim SørensenandGitHub 102ef257a0 Bump hass-nabucasa from 0.107.1 to 0.108.0 (#149189) 2025-07-21 14:35:35 +01:00
Joost LekkerkerkerandGitHub 2476e7e47c Revert setting a user to download translations (#149190) 2025-07-21 15:27:29 +02:00
G JohanssonandGitHub 671523feb3 Use OptionsFlowWithReload in hyperion (#149163) 2025-07-21 14:52:14 +02:00
G JohanssonandGitHub 54fa4d635b Use OptionsFlowWithReload in sonarr (#149166) 2025-07-21 14:51:48 +02:00
G JohanssonandGitHub af0480f2a4 Use OptionsFlowWithReload in slide_local (#149168) 2025-07-21 14:51:33 +02:00
Ludovic BOUÉandGitHub 64f190749a Add Demo Vacuum in entity name (#148629) 2025-07-21 14:39:42 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6b489e0ab6 Bump sigstore/cosign-installer from 3.9.1 to 3.9.2 (#148985)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 14:34:12 +02:00
Norbert RittelandGitHub 1315095b4a Make spelling of "devolo Home Network" consistent (#149165) 2025-07-21 14:16:03 +02:00
David FergusonandGitHub 2d86fa079e SleepIQ add core climate for SleepNumber Climate 360 beds (#134718) 2025-07-21 14:14:33 +02:00
Paul BotteinandGitHub 875219ccb5 Adds support for hide_states options in state selector (#148959) 2025-07-21 13:02:04 +01:00
bc0162cf85 Add select for heating circuit to Tado zones (#147902)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Abílio Costa <[email protected]>
2025-07-21 12:45:57 +01:00
Marc MuellerandGitHub d774de79db Update types packages (#149178) 2025-07-21 13:33:04 +02:00
G JohanssonandGitHub be25a7bc70 Use OptionsFlowWithReload in ezviz (#149167) 2025-07-21 13:24:15 +02:00
Marc MuellerandGitHub 05566e1621 Update websockets pin (#149004) 2025-07-21 13:23:42 +02:00
Erik MontnemeryandGitHub b59d8b5730 Improve statistics sensor tests (#149181) 2025-07-21 13:20:04 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
75a90ab568 Bump actions/ai-inference from 1.1.0 to 1.2.3 (#149159)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:11:22 +02:00
Erik MontnemeryandGitHub 67c68dedba Make async_track_state_change/report_event listeners fire in order (#148766) 2025-07-21 13:07:52 +02:00
Marc MuellerandGitHub 1fba61973d Update pytest-asyncio to 1.1.0 (#149177) 2025-07-21 12:03:53 +01:00
Simon LamonandGitHub bf1a660dcb Bump Lokalise docker image to v2.6.14 (#149031) 2025-07-21 13:02:50 +02:00
G JohanssonandGitHub 94d077ea41 Use OptionsFlowWithReload in honeywell (#149162) 2025-07-21 12:47:38 +02:00
G JohanssonandGitHub c22f65bd87 Use OptionsFlowWithReload in isy994 (#149174) 2025-07-21 12:47:24 +02:00
G JohanssonandGitHub 0dba32dbcd Use OptionsFlowWithReload in keenetic_ndms2 (#149173) 2025-07-21 12:47:11 +02:00
Elmo-SandGitHub 8c964e64db Add support for UV index attribute in template weather entity (#149015) 2025-07-21 11:39:46 +01:00
epenetandGitHub c08aa74496 Cleanup Tuya climate/cover tests (#149157) 2025-07-21 12:27:37 +02:00
G JohanssonandGitHub ff9fb6228b Use OptionsFlowWithReload in onewire (#149164) 2025-07-21 11:14:02 +02:00
Joost LekkerkerkerandGitHub 6eab118a2d Bump airgradient to platinum (#149014) 2025-07-21 08:26:20 +02:00
G JohanssonandGitHub c1e35cc9cf Use OptionsFlowWithReload in androidtv_remote (#149133) 2025-07-21 08:18:40 +02:00
G JohanssonandGitHub 11dd2dc374 Use OptionsFlowWithReload in file (#149108) 2025-07-21 08:17:12 +02:00
G JohanssonandGitHub 00c4b09773 Use OptionsFlowWithReload in motioneye (#149130) 2025-07-21 08:15:51 +02:00
Joakim PlateandGitHub bc9ad5eac6 Add device class to gardena (#149144) 2025-07-21 08:15:32 +02:00
MichaelandGitHub eca80a1645 Use OptionsFlowWithReload in Feedreader (#149134) 2025-07-21 07:27:02 +02:00
MichaelandGitHub bd7cef92c7 Use OptionsFlowWithReload in Proximity (#149136) 2025-07-21 07:26:29 +02:00
David KnowlesandGitHub 27787e0679 Bump pyschlage to 2025.7.2 (#149148) 2025-07-21 07:25:45 +02:00
Raphael HehlandGitHub 0a9fbb215d Bump uiprotect to version 7.16.0 (#149146) 2025-07-21 02:22:32 +02:00
G JohanssonandGitHub 77a954df9b Use OptionsFlowWithReload in reolink (#149132) 2025-07-20 23:44:39 +02:00
G JohanssonandGitHub 61ca0b6b86 Use OptionsFlowWithReload in vodafone_station (#149131) 2025-07-20 23:18:00 +02:00
G JohanssonandGitHub e3577de9d8 Use OptionsFlowWithReload in onkyo (#149093) 2025-07-20 23:17:43 +02:00
J. Nick KostonandGitHub b8d45fba24 Bump aioesphomeapi to 37.0.2 (#149143) 2025-07-20 10:53:09 -10:00
Vincent WolsinkandGitHub 44fec53bac Add binary_sensor for door status in Huum (#149135) 2025-07-20 22:50:53 +02:00
Raphael HehlandGitHub ca48b9e375 Bump uiprotect to version 7.15.1 (#149124) 2025-07-20 08:41:49 -10:00
Abílio CostaandGitHub 216e89dc5e Add battery charging state icons to Reolink (#149125) 2025-07-20 14:50:17 +02:00
Norbert RittelandGitHub 72d5578128 Fix typo in #device-discovery-payload anchor link of mqtt (#149116) 2025-07-20 14:29:18 +02:00
ThorstenandGitHub e3bdd12dad Add Bauknecht virtual integration (#146801) 2025-07-20 13:13:24 +01:00
G JohanssonandGitHub 43dc73c2e1 Use OptionsFlowWithReload in forecast_solar (#149112) 2025-07-20 13:09:07 +02:00
G JohanssonandGitHub 302b6f03ba Use OptionsFlowWithReload in speedtest (#149111) 2025-07-20 13:08:42 +02:00
G JohanssonandGitHub b31e17f1f9 Use OptionsFlowWithReload in met (#149115) 2025-07-20 13:07:46 +02:00
G JohanssonandGitHub 1b8f3348b0 Use OptionsFlowWithReload in roborock (#149118) 2025-07-20 13:06:59 +02:00
G JohanssonandGitHub 0d42b24467 Use OptionsFlowWithReload in jewish_calendar (#149121) 2025-07-20 13:05:39 +02:00
G JohanssonandGitHub 0c858de1af Use OptionsFlowWithReload in lamarzocco (#149119) 2025-07-20 12:31:18 +02:00
G JohanssonandGitHub 5d653d46c3 Remove not used config entry update listener from nut (#149096) 2025-07-20 12:30:22 +02:00
G JohanssonandGitHub b262a5c9b6 Use OptionsFlowWithReload in lastfm (#149113) 2025-07-20 12:05:24 +02:00
G JohanssonandGitHub ead99c549f Use OptionsFlowWithReload in denonavr (#149109) 2025-07-20 11:12:51 +02:00
G JohanssonandGitHub 1a6bfc0310 Use OptionsFlowWithReload in knx (#149097) 2025-07-20 10:17:09 +02:00
hahn-thandGitHub 507f29a209 Bump homematicip to 2.2.0 (#149038) 2025-07-19 21:12:49 +02:00
G JohanssonandGitHub d796ab8fe7 Use OptionsFlowWithReload in kitchen_sink (#149091) 2025-07-19 21:12:17 +02:00
G JohanssonandGitHub d35dca377f Use OptionsFlowWithReload in purpleair (#149095) 2025-07-19 21:11:15 +02:00
MichaelandGitHub 96766fc62a Use OptionsFlowWithReload in Synology DSM (#149086) 2025-07-19 21:08:37 +02:00
G JohanssonandGitHub afbb0ee2f4 Use OptionsFlowWithReload in github (#149089) 2025-07-19 21:07:55 +02:00
G JohanssonandGitHub e885ae1b15 Use OptionsFlowWithReload in holiday (#149090) 2025-07-19 21:07:23 +02:00
G JohanssonandGitHub 51d38f8f05 Use OptionsFlowWithReload in emoncms (#149094) 2025-07-19 21:06:14 +02:00
peteS-UKandGitHub be644ca96e Add type to coordinator for Squeezebox (#149087) 2025-07-19 20:39:22 +02:00
MichaelandGitHub d266b6f6ab Use OptionsFlowWithReload in AVM Fritz!Box Tools (#149085) 2025-07-19 20:08:20 +02:00
G JohanssonandGitHub dbdc666a92 Use OptionsFlowWithReload in control4 (#149058) 2025-07-19 19:51:01 +02:00
Allen PorterandGitHub 2577d9f108 Fix a bug in rainbird device migration that results in additional devices (#149078) 2025-07-19 19:49:14 +02:00
peteS-UKandGitHub 7dfb54c8e8 Paramaterize test for on/off for Squeezebox (#149048) 2025-07-19 19:30:40 +02:00
peteS-UKandGitHub 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-UKandGitHub 0cfb395ab5 Remove unnecessary getattr from init for Squeezebox (#149077) 2025-07-19 19:20:11 +02:00
peteS-UKandGitHub b3f049676d Move Squeezebox registry tests to test_init (#149050) 2025-07-19 19:17:34 +02:00
G JohanssonandGitHub 7e04a7ec19 Use OptionsFlowWithReload in unifiprotect (#149064) 2025-07-19 17:40:16 +02:00
G JohanssonandGitHub c15bf097f0 Use OptionsFlowWithReload in airnow (#149049) 2025-07-19 16:50:41 +02:00
G JohanssonandGitHub dba3d98a2b Use OptionsFlowWithReload in xiaomi_miio (#149051) 2025-07-19 16:50:13 +02:00
G JohanssonandGitHub 4a5e193ebb Use OptionsFlowWithReload in ws66i (#149052) 2025-07-19 16:49:19 +02:00
G JohanssonandGitHub 1bbd07fe48 Use OptionsFlowWithReload in wiffi (#149053) 2025-07-19 16:48:53 +02:00
G JohanssonandGitHub b9d19ffb29 Use OptionsFlowWithReload in vera (#149055) 2025-07-19 16:48:23 +02:00
G JohanssonandGitHub 22b35030a9 Use OptionsFlowWithReload in analytics_insight (#149056) 2025-07-19 16:47:09 +02:00
G JohanssonandGitHub 69c26e5f1f Use OptionsFlowWithReload in dnsip (#149059) 2025-07-19 16:46:30 +02:00
G JohanssonandGitHub cb4d17b24f Use OptionsFlowWithReload in Ping (#149061) 2025-07-19 16:45:39 +02:00
G JohanssonandGitHub ff14f6b823 Use OptionsFlowWithReload in somfy_mylink (#149062) 2025-07-19 16:44:51 +02:00
G JohanssonandGitHub ab964c8bca Use OptionsFlowWithReload in tankerkoenig (#149063) 2025-07-19 16:43:49 +02:00
peteS-UKandGitHub 05f686cb86 Update comments in 3 Squeezebox platforms (#149065) 2025-07-19 16:42:21 +02:00
G JohanssonandGitHub 440a20340e Use OptionsFlowWithReload in nobo_hub (#149066) 2025-07-19 16:41:38 +02:00
G JohanssonandGitHub 676a931c48 Use OptionsFlowWithReload in nmap_tracker (#149067) 2025-07-19 16:40:57 +02:00
G JohanssonandGitHub 360da43868 Use OptionsFlowWithReload in nina (#149068) 2025-07-19 16:40:32 +02:00
Marc MuellerandGitHub 12193587c9 Use OptionsFlowWithReload in fritzbox_callmonitor (#149071) 2025-07-19 16:39:38 +02:00
G JohanssonandGitHub 290f19dbd9 Use OptionsFlowWithReload in motion_blinds (#149070) 2025-07-19 16:38:28 +02:00
G JohanssonandGitHub 13434012e7 Use OptionsFlowWithReload in netgear (#149069) 2025-07-19 16:37:37 +02:00
peteS-UKandGitHub 7202203f35 Update bool test in coordinator platform for Squeezebox (#149073) 2025-07-19 16:33:34 +02:00
G JohanssonandGitHub 31167f5da7 Use OptionsFlowWithReload in webostv (#149054) 2025-07-19 16:16:56 +03:00
G JohanssonandGitHub 665991a3c1 Use OptionsFlowWithReload in wled (#149046) 2025-07-19 13:27:46 +01:00
G JohanssonandGitHub 8a2493e9d2 Use OptionsFlowWithReload in Workday (#149043) 2025-07-19 13:26:54 +01:00
G JohanssonandGitHub be6743d4fd Use OptionsFlowWithReload in yale_smart_alarm (#149040) 2025-07-19 13:14:38 +01:00
G JohanssonandGitHub 284b90d502 Use OptionsFlowWithReload in yeelight (#149045) 2025-07-19 13:14:13 +01:00
G JohanssonandGitHub d7d2013ec8 Use OptionsFlowWithReload in sql (#149047) 2025-07-19 13:12:25 +01:00
G JohanssonandGitHub b3bd882a80 Use OptionsFlowWithReload in Trafikverket Train (#149042) 2025-07-19 13:09:54 +01:00
J. Nick KostonandGitHub 3a6f23b95f Bump aioesphomeapi to 37.0.1 (#149035) 2025-07-19 12:53:51 +01:00
6f59aaebdd Add extended class for OptionsFlow that automatically reloads (#146910)
Co-authored-by: Erik Montnemery <[email protected]>
2025-07-19 13:14:20 +02:00
Allen PorterandGitHub f90e06fde1 Add attachment support in ollama ai task (#148981) 2025-07-19 07:27:48 +02:00
Paul BotteinandGitHub 380c737901 Add reorder option to entity selector (#149002) 2025-07-18 19:41:59 +01:00
Petro31andGitHub 33cc257e75 Consolidate template integration's config schemas (#149018) 2025-07-18 19:38:53 +01:00
Franck NijhofandGitHub 3877a6211a Ensure Lokalise download runs as the same user as GitHub Actions (#149026) 2025-07-18 19:56:19 +02:00
J. Nick KostonandGitHub 916b4368dd Bump aioesphomeapi to 36.0.1 (#148991) 2025-07-18 07:30:34 -10:00
Jan BouwhuisandGitHub 4c99fe9ae5 Ignore MQTT sensor unit of measurement if it is an empty string (#149006) 2025-07-18 18:57:03 +02:00
Marc MuellerandGitHub 353b573707 Update bluecurrent-api to 1.2.4 (#149005) 2025-07-18 15:43:43 +02:00
Maciej BieniekandGitHub 109663f177 Bump imgw_pib to version 1.4.2 (#149009) 2025-07-18 15:36:17 +02:00
Simone ChemelliandGitHub 3b89b2cbbe Bump aioamazondevices to 3.5.0 (#149011) 2025-07-18 15:35:38 +02:00
Abílio CostaandGitHub 29d0d6cd43 Add top-level target support to trigger schema (#148894) 2025-07-18 14:32:16 +01:00
Erik MontnemeryandGitHub 1743766d17 Add last_reported to state reported event data (#148932) 2025-07-18 13:53:30 +02:00
G JohanssonandGitHub 277241c4d3 Adjust ManualTriggerSensorEntity to handle timestamp device classes (#145909) 2025-07-18 13:49:12 +02:00
Bram KragtenandGitHub 17034f4d6a Update frontend to 20250702.3 (#148994) 2025-07-18 13:15:55 +02:00
Thomas55555andGitHub 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 MuellerandGitHub 75c803e376 Update pysmarlaapi to 0.9.1 (#149001) 2025-07-18 12:48:39 +02:00
J. Nick KostonandGitHub a96e31f1d8 Bump PySwitchbot to 0.68.2 (#148996) 2025-07-18 12:48:09 +02:00
c0ffeeca7andGitHub 43a30fad96 Home Assistant Cloud: fix capitalization (#148992) 2025-07-18 12:19:33 +02:00
Petar PetrovandGitHub 39d323186f Disable "last seen" Z-Wave entity by default (#148987) 2025-07-18 09:53:47 +02:00
karwostsandGitHub 57c024449c Fix broken invalid_config tests (#148965) 2025-07-18 09:02:44 +02:00
ManuandGitHub 414057d455 Add image platform to PlayStation Network (#148928) 2025-07-18 08:33:30 +02:00
Joost LekkerkerkerandGitHub 50688bbd69 Add support for calling tools in Open Router (#148881) 2025-07-18 05:49:27 +02:00
Álvaro Fernández RojasandGitHub 073ea813f0 Update aioairzone-cloud to v0.6.15 (#148947) 2025-07-17 23:08:45 +01:00
Vincent WolsinkandGitHub 6b959f42f6 Introduce base entity for supporting multiple platforms in Huum (#148957) 2025-07-17 23:06:51 +01:00
Joost LekkerkerkerandGitHub 0ff0902ccf Add icons to WAQI (#148976) 2025-07-17 22:36:18 +01:00
Joost LekkerkerkerandGitHub 37a154b1df Migrate WAQI to runtime data (#148977) 2025-07-17 23:22:30 +02:00
Petro31andGitHub 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 LekkerkerkerandGitHub aacaa9a20f Pass Syncthru entry to coordinator (#148974) 2025-07-18 00:14:19 +03:00
Joost LekkerkerkerandGitHub c074453763 Remove obsolete variables in WAQI (#148975) 2025-07-18 00:13:46 +03:00
29afa891ec Add YAML and discovery info export feature for MQTT device subentries (#141896)
Co-authored-by: Norbert Rittel <[email protected]>
2025-07-17 23:06:47 +02:00
Steven LoomanandGitHub 3b6eb045c6 Bump async-upnp-client to 0.45.0 (#148961) 2025-07-17 21:19:47 +02:00
Joost LekkerkerkerandGitHub 0d819f2389 Refactor WAQI tests (#148968) 2025-07-17 20:30:40 +02:00
Joakim SørensenandGitHub 9802441fea Bump hass-nabucasa from 0.106.0 to 0.107.1 (#148949) 2025-07-17 18:47:00 +01:00
Joakim PlateandGitHub fb13c8f4f2 Update arcam to 1.8.2 (#148956) 2025-07-17 18:34:58 +01:00
AlCalzoneandGitHub a96e38871f Z-Wave JS: Simplify strings for RSSI sensors (#148936) 2025-07-17 18:49:34 +03:00
Vincent WolsinkandGitHub 17920b6ec3 Use climate min/max temp from sauna configuration in Huum (#148955) 2025-07-17 15:34:15 +01:00
karwostsandGitHub 40cabc8d70 Validate min/max for input_text config (#148909) 2025-07-17 16:27:41 +02:00
b33a556ca5 Bump zwave-js-server-python to 0.66.0 (#148939)
Co-authored-by: Marc Mueller <[email protected]>
2025-07-17 16:20:03 +03:00
Marc MuellerandGitHub 9df97fb2e2 Add correct labels for dependabot PRs (#148944) 2025-07-17 12:31:55 +02:00
Erik MontnemeryandGitHub ee35fc495d Improve derivative sensor tests (#148941) 2025-07-17 11:44:37 +02:00
9373bb287c Huum - Introduce coordinator to support multiple platforms (#148889)
Co-authored-by: Josef Zweck <[email protected]>
2025-07-17 11:43:26 +02:00
Erik MontnemeryandGitHub d72fb021c1 Improve statistics tests (#148937) 2025-07-17 11:42:25 +02:00
0e6a1e3242 Improve integration sensor tests (#148938)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: G Johansson <[email protected]>
2025-07-17 11:41:39 +02:00
asafhasandGitHub 79b8e74d87 Add numbers configuration to Tuya alarm (#148907) 2025-07-17 11:26:33 +02:00
72d1c3cfc8 Fix Tuya support for climate fan modes which use "windspeed" function (#148646)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: epenet <[email protected]>
2025-07-17 09:47:54 +02:00
AlCalzoneandGitHub 3d278b626a Z-Wave JS: Add statistics sensors for channel 3 background RSSI (#148899) 2025-07-17 09:19:44 +02:00
Joakim PlateandGitHub 5383ff96ef Make sure gardena bluetooth mock unload if it mocks load (#148920) 2025-07-17 09:00:44 +02:00
epenetandGitHub a0991134c4 Rename tuya fixture file to match category (#148892) 2025-07-17 08:59:34 +02:00
Jan-Philipp BeneckeandGitHub 9def44dca4 Bump inexogy quality scale to platinum (#148908) 2025-07-17 08:58:53 +02:00
Joris PelgrömandGitHub 656822b39c Bump letpot to 0.5.0 (#148922) 2025-07-17 08:57:11 +02:00
epenetandGitHub ae03fc2295 Fix missing unit of measurement in tuya numbers (#148924) 2025-07-17 08:55:47 +02:00
Abílio CostaandGitHub e32e06d7a0 Fix Husqvarna Automower coordinator listener list mutating (#148926) 2025-07-17 08:52:59 +02:00
Artur PragaczandGitHub 6dc2340c5a Fix docstring for WaitIntegrationOnboardingView (#148904) 2025-07-16 23:15:45 +01:00
Thomas55555andGitHub 83cd2dfef3 Bump aioautomower to 2.0.0 (#148846) 2025-07-16 22:12:35 +02:00
Franck NijhofandGitHub a5c301db1b Add code review guidelines to exclude imports and formatting feedback (#148912) 2025-07-16 21:55:37 +02:00
Norbert RittelandGitHub 5b41d5a795 Fix typo "barametric" in rainmachine (#148917) 2025-07-16 21:50:29 +02:00
MichaelandGitHub 9d178ad5f1 Deprecate the usage of ContextVar for config_entry in coordinator (#138161) 2025-07-16 21:45:22 +02:00
e8fca19335 Fix flaky husqvarna_automower test with comprehensive race condition fix (#148911)
Co-authored-by: Claude <[email protected]>
2025-07-16 21:40:44 +02:00
Joost LekkerkerkerandGitHub 58bb2fa327 Bump python-open-router to 0.3.0 (#148900) 2025-07-16 18:51:52 +02:00
epenetandGitHub fca05f6bcf Add snapshot tests for tuya dj category (#148897) 2025-07-16 18:34:28 +02:00
Joost LekkerkerkerandGitHub a5f0f6c8b9 Add prompt as constant and common translation key (#148896) 2025-07-16 18:23:38 +02:00
Artur PragaczandGitHub e2340314c6 Do not allow filters for services with no target in hassfest (#148869) 2025-07-16 17:40:35 +02:00
Erik MontnemeryandGitHub aab6cd665f Fix flaky notify group test (#148895) 2025-07-16 17:06:35 +02:00
Paulus SchoutsenandGitHub 1734b316d5 Return intent response from LLM chat log if available (#148522) 2025-07-16 16:16:01 +02:00
Maciej BieniekandGitHub 3449863eee Bump gios to version 6.1.2 (#148884) 2025-07-16 15:49:02 +02:00
ManuandGitHub b68de0af88 Change deprecated media_player state standby to off in PlayStation Network (#148885) 2025-07-16 15:48:39 +02:00
Artur PragaczandGitHub 840e0d1388 Clean up ModuleWrapper from loader (#148488) 2025-07-16 15:19:22 +02:00
Joost LekkerkerkerandGitHub 412035b970 Add devices to OpenRouter (#148888) 2025-07-16 15:07:53 +02:00
Denis ShulyakaandGitHub 3e465da892 Add Code Interpreter tool for OpenAI Conversation (#148383) 2025-07-16 14:52:53 +02:00
Marc MuellerandGitHub 0d79f7db51 Update mypy-dev to 1.18.0a2 (#148880) 2025-07-16 14:43:55 +02:00
62e3802ff2 Deprecate MediaPlayerState.STANDBY (#148151)
Co-authored-by: Franck Nijhof <[email protected]>
2025-07-16 14:22:42 +02:00
tronikosandGitHub 02a11638b3 Add Google AI STT (#147563) 2025-07-16 14:11:29 +02:00
Josef ZweckandGitHub 26a9af7371 Add search functionality to jellyfin (#148822) 2025-07-16 13:26:46 +02:00
epenetandGitHub e28f02d163 Add initial support for tuya qccdz (#148874) 2025-07-16 12:28:18 +02:00
G JohanssonandGitHub a6828898d1 Add sensor platform to SMHI (#139295) 2025-07-16 12:25:10 +02:00
Paulus SchoutsenandGitHub 29e105b0ef Set default mode for number selector to box (#148773) 2025-07-16 11:19:31 +01:00
Maciej BieniekandGitHub ce4a811b96 Add hydrological alert sensor to IMGW-PIB integration (#148848) 2025-07-16 10:55:50 +01:00
Arie CatsmanandGitHub fe8384719d Bump pyenphase to 2.2.2 (#148870) 2025-07-15 23:18:14 -10:00
Joost LekkerkerkerandGitHub a57d48fd31 Add OpenRouter integration (#143098) 2025-07-16 10:55:28 +02:00
Thomas55555andGitHub 8a73511b02 Add inactive reason sensor to Husqvarna Automower (#147684) 2025-07-16 10:44:04 +02:00
epenetandGitHub 033d8b3dfb Add snapshot tests for tuya co2bj and gyd categories (#148872) 2025-07-16 10:38:43 +02:00
epenetandGitHub 6833bf1900 Add battery status and configuration entities to Tuya thermostat (wk) (#148821) 2025-07-16 10:15:44 +02:00
Brett AdamsandGitHub 84e3dac406 Update vehicle type handling in Teslemetry (#148862) 2025-07-16 10:05:17 +02:00
epenetandGitHub bafd342d5d Add initial support for tuya cwjwq (#148420) 2025-07-16 09:54:44 +02:00
epenetandGitHub fae6b375cd Fix incorrectly rejected device classes in tuya (#148596) 2025-07-16 09:39:22 +02:00
epenetandGitHub d8de6e34dd Add support for Tuya ks category (tower fan) (#148811) 2025-07-16 09:24:20 +02:00
Artur PragaczandGitHub 9db5b0b3b7 Validate selectors in the service helper (#148857) 2025-07-16 08:51:16 +02:00
Brett AdamsandGitHub bcec29763f Fix button platform parent class in Teslemetry (#148863) 2025-07-16 08:16:36 +02:00
epenetandGitHub 27ad459ae0 Add tuya snapshots for more humidifiers (cs category) (#148797) 2025-07-16 08:11:55 +02:00
hahn-thandGitHub 9c933ef01f Add support for HmIPW-DRBL4 in homematicip_cloud (#148844) 2025-07-16 08:10:56 +02:00
Norbert RittelandGitHub 2011e64390 Different fixes in user-facing strings of nasweb (#148830) 2025-07-16 08:10:29 +02:00
Brett AdamsandGitHub ffc2b0a8cf Add mock for listen in Teslemetry tests (#148853) 2025-07-16 08:09:54 +02:00
Pete SageandGitHub 549069e22c Add guard to prevent exception in Sonos Favorites (#148854) 2025-07-16 08:09:24 +02:00
Jan-Philipp BeneckeandGitHub 57e4270b7b Make exceptions translatable in inexogy integration (#148865) 2025-07-16 08:06:49 +02:00
Maciej BieniekandGitHub 38e4e18f60 Bump IMGW-PIB to version 1.4.1 (#148849) 2025-07-16 00:41:56 +01:00
Robert ReschandGitHub 7f2a32d4eb Remove not needed go2rtc stream config (#148836) 2025-07-15 22:11:55 +01:00
ManuandGitHub d46e0e132b Add reconfigure flow to Uptime Kuma (#148833) 2025-07-15 22:46:37 +02:00
Álvaro Fernández RojasandGitHub 828f0f8b26 Update aioairzone-cloud to v0.6.14 (#148820) 2025-07-15 22:43:40 +02:00
849a25e3cc Handle changes to source entities in mold_indicator helper (#148823)
Co-authored-by: G Johansson <[email protected]>
2025-07-15 22:19:32 +02:00
Erik MontnemeryandGitHub 3cb579d585 Do not add statistics config entry to source device (#148731) 2025-07-15 22:13:26 +02:00
Erik MontnemeryandGitHub 381bd489d8 Do not add template config entry to source device (#148756) 2025-07-15 22:13:03 +02:00
Marc MuellerandGitHub f5b785acd5 Update youtubeaio to 2.0.0 (#148814) 2025-07-15 20:44:32 +02:00
ManuandGitHub 648dce2fa3 Add diagnostics platform to Uptime Kuma (#148835) 2025-07-15 20:19:14 +02:00
ManuandGitHub d14a0e0191 Bump pythonkuma to v0.3.1 (#148834) 2025-07-15 20:18:47 +02:00
Maciej BieniekandGitHub 9caf46c68b Bump imgw_pib library to version 1.4.0 (#148831) 2025-07-15 20:17:54 +02:00
Artur PragaczandGitHub e89ae021d8 Clean up validate_supported_features in selector helper (#148843) 2025-07-15 20:10:16 +02:00
Marc MuellerandGitHub 36156d9c54 Update orjson to 3.11.0 (#148840) 2025-07-15 19:43:44 +02:00
Artur PragaczandGitHub 3e0628cec2 Fix entity and device selectors (#148580) 2025-07-15 18:58:42 +02:00
Robert ReschandGitHub 8bd51a7fd1 Use ffmpeg for generic cameras in go2rtc (#148818) 2025-07-15 16:38:19 +01:00
Paul BotteinandGitHub 5b29d6bbdf Set icon for off state for light domain (#148749) 2025-07-15 16:25:22 +01:00
2c2ac4b669 Throw an error from reload_themes if themes are invalid (#148827)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-15 17:08:19 +02:00
Petro31andGitHub 35097602d7 Remove unnecessary hass if check in AbstractTemplateEntity (#148828) 2025-07-15 17:04:31 +02:00
Petro31andGitHub e5fe243a86 Remove device id references from button and image (#148826) 2025-07-15 17:03:47 +02:00
ManuandGitHub fd10fa1fba Add reauthentication flow to Uptime Kuma (#148772) 2025-07-15 16:49:08 +02:00
087a938a7d Add forecast service to amberelectric (#144848)
Co-authored-by: G Johansson <[email protected]>
2025-07-15 16:32:59 +02:00
Petro31andGitHub c058561162 Add initalize for abstract template entities (#147504) 2025-07-15 15:53:01 +02:00
epenetandGitHub b89b248b4c Add tuya snapshots for qxj category (#148802) 2025-07-15 14:18:14 +02:00
cd94685b7d Add Fan platform to Switchbot cloud (#148304)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-15 13:55:13 +02:00
MatrixandGitHub 0acfb81d50 Clean up YoLink entities on startup (#148718) 2025-07-15 13:53:29 +02:00
7d06aec8da Discovery of Miele temperature sensors (#144585)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-15 12:50:28 +02:00
Åke StrandbergandGitHub ee4325a927 Replace deprecated battery property on Miele vacuum with sensor (#148765) 2025-07-15 11:40:48 +01:00
Alex LeversenandGitHub c7aadcdd20 Add file name/size sensors to OctoPrint integration (#148636) 2025-07-15 12:35:20 +02:00
wuedeandGitHub 8256401f7f expose schedule id as an extra state attribute in Netatmo (#147076) 2025-07-15 12:16:59 +02:00
hahn-thandGitHub ab187f39c2 Add support for HmIP-RGBW and HmIP-LSC in homematicip_cloud integration (#148639) 2025-07-15 12:16:07 +02:00
hahn-thandGitHub 1cb278966c Handle connection issues after websocket reconnected in homematicip_cloud (#147731) 2025-07-15 12:15:19 +02:00
Josef ZweckandGitHub b522bd5ef2 Get media player features elsewhere for jellyfin (#148805) 2025-07-15 12:07:57 +02:00
Álvaro Fernández RojasandGitHub a6e1d96852 Update aioairzone-cloud to v0.6.13 (#148798)
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2025-07-15 11:21:54 +02:00
Marc MuellerandGitHub 3d74d02704 Update pytouchlinesl to 0.4.0 (#148801) 2025-07-15 11:15:06 +02:00
Artur PragaczandGitHub db45f46c8a Fan support in WiZ (#146440) 2025-07-15 11:14:47 +02:00
ehendrix23andGitHub 4f938d032d Bump elevenlabs to 2.3.0 (#147224) 2025-07-15 10:45:55 +02:00
e1f15dac39 Add Sensor platform to NASweb integration (#133063)
Co-authored-by: Erik Montnemery <[email protected]>
2025-07-15 10:39:53 +02:00
epenetandGitHub 41e261096a Use suggested unit of measurement in Tuya (#148599) 2025-07-15 10:34:16 +02:00
Max VelitchkoandGitHub f6aa4aa788 Bump amcrest to 1.9.9 (#148769) 2025-07-15 10:14:26 +02:00
Brett AdamsandGitHub 7d7767c93a Bump Tesla Fleet API to 1.2.2 (#148776) 2025-07-15 09:21:00 +02:00
J. Nick KostonandGitHub 5e883cfb12 Fix flaky nuki tests by preventing teardown race condition (#148795) 2025-07-14 21:03:49 -10:00
Paulus SchoutsenandGitHub e2cc51f21d Allow AI Task to handle camera attachments (#148753) 2025-07-15 08:51:08 +02:00
Petro31andGitHub 816977dd75 Refactor async_setup_platform for template platforms (#147379) 2025-07-15 08:26:34 +02:00
a81e83cb28 Manually register powerview hub (#146709)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-14 22:38:01 +01:00
Maciej BieniekandGitHub c476500c49 Fix Shelly n_current sensor removal condition (#148740) 2025-07-14 23:40:46 +03:00
f65fa38429 Add reconfigure flow for KNX (#145067)
Co-authored-by: Copilot <[email protected]>
2025-07-14 21:49:52 +02:00
ManuandGitHub 66641356cc Add Uptime Kuma integration (#146393) 2025-07-14 21:35:57 +02:00
37ae476c67 Add Zeroconf support for bsblan integration (#146137)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-14 21:26:03 +02:00
ManuandGitHub 5ec9c4e6e3 Add PS Vita support to PlayStation Network integration (#148186) 2025-07-14 21:24:50 +02:00
Marc MuellerandGitHub 80eb4fb2f6 Replace asyncio.iscoroutinefunction (#148738) 2025-07-14 20:24:32 +01:00
Joost LekkerkerkerandGitHub 9e3a78b7ef Bump pySmartThings to 3.2.8 (#148761) 2025-07-14 20:18:12 +01:00
hahn-thandGitHub c08c402409 Add switches for HmIPW-DRI16, HmIPW-DRI32, HmIPW-DRS4, HmIPW-DRS8 (#148571) 2025-07-14 21:16:29 +02:00
Vincent WolsinkandGitHub d42d270fb2 Bump Huum to version 0.8.0 (#148763) 2025-07-14 20:16:26 +01:00
9068a09620 Add Stookwijzer forecast service (#138392)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-14 21:08:16 +02:00
Stephan TraubandGitHub 1ef07544d5 Fix for ignored devices issue #137114 (#146562) 2025-07-14 21:07:47 +02:00
Erik MontnemeryandGitHub ed4a23d104 Override connect method in RecorderPool (#148490) 2025-07-14 20:57:00 +02:00
peteS-UKandGitHub 0729b3a2f1 Change hass.data storage to runtime.data for Squeezebox (#146482) 2025-07-14 20:53:53 +02:00
ManuandGitHub c9356868f7 Add add-on discovery flow to pyLoad integration (#148494) 2025-07-14 19:29:57 +01:00
1753baf186 Add method to track entity state changes from target selectors (#148086)
Co-authored-by: Erik Montnemery <[email protected]>
2025-07-14 19:28:53 +01:00
Petro31andGitHub 8421ca7802 Add assumed optimistic state to template select (#148513) 2025-07-14 19:28:27 +01:00
124931b2ee TTS to always stream when available (#148695)
Co-authored-by: Michael Hansen <[email protected]>
2025-07-14 20:23:43 +02:00
Erik MontnemeryandGitHub c27a67db82 Do not add integration config entry to source device (#148730) 2025-07-14 20:18:41 +02:00
Erik MontnemeryandGitHub 3ae9ea3f19 Do not add generic_thermostat config entry to source device (#148728) 2025-07-14 20:18:21 +02:00
Erik MontnemeryandGitHub e35f7b12f1 Do not add generic_hygrostat config entry to source device (#148727) 2025-07-14 20:18:11 +02:00
Erik MontnemeryandGitHub 1a1e9e9f57 Add test for combining state change and state report listeners (#148721) 2025-07-14 20:15:39 +02:00
Erik MontnemeryandGitHub 254f766357 Do not add history_stats config entry to source device (#148729) 2025-07-14 20:05:34 +02:00
Erik MontnemeryandGitHub 7df0016fab Do not add threshold config entry to source device (#148732) 2025-07-14 20:05:20 +02:00
Erik MontnemeryandGitHub 57f89dd606 Do not add trend config entry to source device (#148733) 2025-07-14 20:00:49 +02:00
Erik MontnemeryandGitHub 92bb1f2551 Do not add utility_meter config entry to source device (#148735) 2025-07-14 20:00:21 +02:00
f680e992ff Add support for Broadlink A2 air quality sensor (#142203)
Co-authored-by: Joostlek <[email protected]>
2025-07-14 19:07:50 +02:00
Thomas55555andGitHub f08d1e547f Fix adding a work area in Husqvarna Automower (#148358) 2025-07-14 19:04:00 +02:00
Tsvi MostoviczandGitHub 9e022ad75e Quality fixes for Jewish Calendar (#148689) 2025-07-14 17:44:11 +02:00
Paulus SchoutsenandGitHub 14ff04200e Make AI Task instructions multiline (#148606) 2025-07-14 15:24:44 +01:00
MichaelandGitHub 5e4ce46dae Use absolute humidity device class in Airq (#148568) 2025-07-14 14:38:33 +02:00
155fc134b6 Do not add derivative config entry to source device (#148674)
Co-authored-by: Artur Pragacz <[email protected]>
2025-07-14 13:33:00 +02:00
ekutnerandGitHub 25f64a2f36 Do not specify the code_format when a code is not required (#148698) 2025-07-14 12:11:36 +02:00
Erik MontnemeryandGitHub dcbdce4b2b Improve docstrings of event helpers related to state changes (#148722) 2025-07-14 11:57:27 +02:00
MichaelandGitHub 50047f0a4e Add new device class for absolute humidity (#148567) 2025-07-14 11:46:17 +02:00
Fredrik MårtenssonandGitHub 21b1122f83 Add test fixture for Tuya cover (#148660) 2025-07-14 11:43:02 +02:00
Jan BouwhuisandGitHub 09104fca4d Fix hide empty sections in mqtt subentry flows (#148692) 2025-07-14 11:26:37 +02:00
Jan BouwhuisandGitHub ad4e5459b1 Fix - only enable AlexaModeController if at least one mode is offered (#148614) 2025-07-14 11:25:22 +02:00
334d5f09fb Create Google Generative AI sub entries for an enabled entry (#148161)
Co-authored-by: Erik Montnemery <[email protected]>
2025-07-14 11:24:00 +02:00
9f3d890e91 Bump pysnmp to v7 and brother to v5 (#129761)
Co-authored-by: Maciej Bieniek <[email protected]>
2025-07-14 10:46:13 +02:00
eae9f4f925 Wallbox Integration - Add repair action for insufficient rights (#148610)
Co-authored-by: Norbert Rittel <[email protected]>
2025-07-14 10:30:48 +02:00
Brett AdamsandGitHub 5e50c723a7 Fix Charge Cable binary sensor in Teslemetry (#148675) 2025-07-14 10:29:29 +02:00
MattMorganandGitHub f761f7628a Minor update to keymitt_ble manifest. (#148708) 2025-07-14 08:50:25 +02:00
karwostsandGitHub 26d71fcdba Fix derivative migration from 'none' unit_prefix (#147820) 2025-07-14 08:17:20 +02:00
Christopher FennerandGitHub e4359e74c6 Bump PyViCare to 2.50.0 (#148679) 2025-07-14 08:08:54 +02:00
Marc MuellerandGitHub 5e30e6cb91 Update python-mystrom to 2.4.0 (#148682) 2025-07-14 08:02:43 +02:00
Simone ChemelliandGitHub bc07030304 Bump aioamazondevices to 3.2.10 (#148709) 2025-07-14 01:18:35 +03:00
Shay LevyandGitHub 25ba2437dd Bump aioshelly to 13.7.2 (#148706) 2025-07-14 01:15:50 +03:00
Kevin WorrelandGitHub cfc7cfcf37 Bump screenlogicpy to 0.10.2 (#148703) 2025-07-13 11:44:55 -10:00
74288a3bc8 Re-enable Home Connect updates automatically (#148657)
Co-authored-by: Martin Hjelmare <[email protected]>
2025-07-13 22:46:42 +02:00
Marc MuellerandGitHub b2fe17c6d4 Update PyMicroBot to 0.0.23 (#148700) 2025-07-13 22:12:00 +02:00
Paulus SchoutsenandGitHub 611f86cf8c OpenAI: Add attachment support to AI task (#148676) 2025-07-13 21:51:46 +02:00
23a8442abe Make attachments native to chat log (#148693)
Co-authored-by: Copilot <[email protected]>
2025-07-13 19:35:11 +02:00
Paulus SchoutsenandGitHub f3ad6bd9b6 Report correctly when no funds for OpenAI (#148677) 2025-07-13 17:55:24 +02:00
Robert MeijersandGitHub 023dd9d523 Discover Heos players using Zeroconf (#144763) 2025-07-13 09:56:31 -05:00
Steven TegreenyandGitHub 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 AdamsandGitHub bb17f34bae Remove history first refresh from Teslemetry (#148531) 2025-07-13 13:01:38 +02:00
Erik MontnemeryandGitHub d22dd68119 Fix exception in EntityRegistry.async_device_modified (#148645) 2025-07-13 10:37:48 +02:00
Alex LeversenandGitHub 4122af1d33 Bump pyoctoprintapi version to 0.1.14 (#148651) 2025-07-13 09:04:01 +02:00
J. Nick KostonandGitHub 87fd45d4ab Add device_id parameter to ESPHome command calls for sub-device support (#148667) 2025-07-12 20:12:14 -10:00
asafhasandGitHub 1c35aff510 Add configuration entities to Tuya multifunction alarm (#148556) 2025-07-13 07:55:37 +02:00
J. Nick KostonandGitHub ab6ac94af9 Bump aioesphomeapi to 35.0.0 (#148666) 2025-07-12 18:49:59 -10:00
Marc MuellerandGitHub d33f73fce2 Cleanup bleak warnings (#148665) 2025-07-12 16:26:31 -10:00
fca6dc264f Update bleak to 1.0.1 (#147742)
Co-authored-by: J. Nick Koston <[email protected]>
2025-07-12 13:11:37 -10:00
Amit FinkelsteinandGitHub 5287f4de81 Bump pyatv to 0.16.1 (#148659) 2025-07-12 21:52:26 +01:00
ccc1f01ff6 Add lamp states to smartthings selector (#148302)
Co-authored-by: Joostlek <[email protected]>
2025-07-12 20:51:09 +02:00
falconindyandGitHub 531f1f1964 snoo: use correct value for right safety clip binary sensor (#148647) 2025-07-12 20:46:03 +02:00
HesselandGitHub 72dc2b15d5 Wallbox Add translation to exception config entry auth failed (#148649) 2025-07-12 20:40:39 +02:00
0xEFandGitHub cf2ef4cec1 Bump nyt_games to 0.5.0 (#148654) 2025-07-12 20:30:26 +02:00
HesselandGitHub 28994152ae Wallbox - Add translation to exception (#148644) 2025-07-12 12:24:59 +02:00
AlCalzoneandGitHub ad881d892b Keep entities of dead Z-Wave devices available (#148611) 2025-07-11 23:45:57 +02:00
Paulus SchoutsenandGitHub 87e641bf59 Update recommended model for Ollama to Qwen3 (#148627) 2025-07-11 16:15:13 -05:00
6ecaca753d Update Anthropic max tokens to 3000 and recommended model to claude-3-5-haiku-latest (#148624)
Co-authored-by: Claude <[email protected]>
2025-07-11 23:00:04 +02:00
017cd0bf45 Update OpenAI conversation max tokens to 3000 (#148623)
Co-authored-by: Claude <[email protected]>
2025-07-11 22:59:51 +02:00
1920edd712 Update Google Generative AI Conversation max tokens to 3000 (#148625)
Co-authored-by: Claude <[email protected]>
2025-07-11 13:10:12 -07:00
Erik MontnemeryandGitHub 2dca78efbb Improve entity registry handling of device changes (#148425) 2025-07-11 20:56:50 +02:00
Lưu Quang VũandGitHub e0179a7d45 Fix Google Cloud 504 Deadline Exceeded (#148589) 2025-07-11 11:53:38 -07:00
Abílio CostaandGitHub d393d5fdbb Use non-autospec mock for Reolink's util and view tests (#148579) 2025-07-11 16:27:06 +02:00
Joost LekkerkerkerandGitHub a34264f345 Add SmartThings RVC fixture (#148552) 2025-07-11 14:01:11 +02:00
epenetandGitHub 73c9d99abf Add tuya snapshot tests for wxkg category (#148609) 2025-07-11 13:55:01 +02:00
Avi MillerandGitHub ec5991bc68 Add support for LIFX 26"x13" Ceiling (#148459)
Signed-off-by: Avi Miller <[email protected]>
2025-07-11 13:42:50 +02:00
ArjanandGitHub 87aecf0ed9 Linkplay: add select entity to set Audio Output hardware (#143329) 2025-07-11 12:45:21 +02:00
Norbert RittelandGitHub 0b2ce73eac Fix description of html5.dismiss action (#148591) 2025-07-11 11:43:29 +02:00
HesselandGitHub 22828568e2 Wallbox Integration - Type Config Entry (#148594) 2025-07-11 11:37:24 +02:00
Jan BouwhuisandGitHub 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 BeneckeandGitHub cd73824e3e Ensure response is fully read to prevent premature connection closure in rest command (#148532) 2025-07-11 09:06:18 +02:00
32121a073c Add release URL for Tessie updates (#148548)
Co-authored-by: Copilot <[email protected]>
2025-07-11 07:56:23 +02:00
MatrixandGitHub c6c622797d Add YoLink YS7A12 support (#148588) 2025-07-11 07:55:13 +02:00
jlestelandGitHub 193b32218f Fix domain validation in Tesla Fleet (#148555) 2025-07-11 00:41:03 +01:00
Paulus SchoutsenandGitHub e6702d2392 Serialize Object Selector correctly if a field is required (#148577) 2025-07-10 22:45:56 +01:00
Paulus SchoutsenandGitHub 19b3b6cb28 Add attachment support to Google Gemini (#148208) 2025-07-10 23:45:11 +02:00
a2220cc2e6 Add LED intensity custom attributes for Matter Inovelli Dimmers (#148074)
Co-authored-by: Norbert Rittel <[email protected]>
2025-07-10 23:36:51 +02:00
J. Nick KostonandGitHub 18a89d5815 Bump aiohttp to 3.12.14 (#148565) 2025-07-10 23:10:48 +02:00
Bram KragtenandGitHub 6eeec948a8 Update frontend to 20250702.2 (#148573) 2025-07-10 23:09:47 +02:00
Paulus SchoutsenandGitHub 0e09a47476 Add OpenAI AI Task entity (#148295) 2025-07-10 23:08:56 +02:00
karwostsandGitHub f0a636949a Support all Energy units in Energy integration (#148566) 2025-07-10 19:29:48 +01:00
d15baf9f9f Drop homeassistant agent and assist_pipeline migration code (#147968)
Co-authored-by: Franck Nijhof <[email protected]>
Co-authored-by: Paulus Schoutsen <[email protected]>
2025-07-10 17:30:54 +02:00
epenetandGitHub 4f27058a68 Add fault binary sensors to tuya dehumidifer (#148485) 2025-07-10 16:15:07 +02:00
epenetandGitHub 058e1ede10 Add tuya snapshot tests for wsdcg and zndb category (#148554) 2025-07-10 15:55:22 +02:00
epenetandGitHub d23321cf54 Add tuya snapshot tests for dlq category (#148549) 2025-07-10 15:55:03 +02:00
epenetandGitHub eb20292683 Move tuya models to separate module (#148550) 2025-07-10 15:54:05 +02:00
Norbert RittelandGitHub 12f913e737 Improve names and descriptions of rainmachine.push_weather_data (#148534) 2025-07-10 13:38:42 +02:00
tronikosandGitHub 7e405d4ddb 100% test coverage in Google Assistant SDK (#148536) 2025-07-10 13:21:19 +02:00
Nathan SpencerandGitHub 2829cc1248 Add visits today sensor for pets (#147459) 2025-07-10 11:24:54 +01:00
MatrixandGitHub 8881919efd Add YS8009 support to Yolink (#148538) 2025-07-10 12:10:15 +02:00
Åke StrandbergandGitHub a00f61f7be Remove vg argument from miele auth flow (#148541) 2025-07-10 12:09:24 +02:00
Josh BarnardandGitHub c37b0a8f1d Adding precision for voltage and wind speed sensors in Ecowitt (#148462) 2025-07-10 11:21:44 +02:00
Kristof MariënandGitHub c75b34a911 Fix for Renson set Breeze fan speed (#148537) 2025-07-10 10:52:03 +02:00
Denis ShulyakaandGitHub cbe2fbdc34 Encrypted reasoning items support for OpenAI Conversation (#148279) 2025-07-10 10:46:10 +02:00
J. Diego Rodríguez RoyoandGitHub 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 RoyoandGitHub 49baa65f61 Add Home Connect resume command button when an appliance is paused (#148512) 2025-07-10 00:26:13 +02:00
Matthias AlphartandGitHub 24a7ebd2bb Move KNXModule class to separate module (#146100) 2025-07-09 23:51:40 +02:00
Noah HusbyandGitHub a4b9efa1b1 Support AM/FM channel name in Russound RIO (#148421) 2025-07-09 23:23:04 +02:00
ManuandGitHub 15544769b6 Add action for activity reactions to Bring! (#138175) 2025-07-09 23:08:24 +02:00
3307132441 Jewish calendar: appropriate polling for sensors (2/3) (#144906)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-09 22:50:09 +02:00
Thomas55555andGitHub da255af8de Bump aioautomower to 1.2.2 (#148497) 2025-07-09 22:02:31 +02:00
Maciej BieniekandGitHub a7e879714b Add water flow sensor to IMGW PIB integration (#148517) 2025-07-09 21:59:08 +02:00
MichaelandGitHub 8aaf5756e0 Add workaround for sub units without main device in AVM Fritz!SmartHome (#148507) 2025-07-09 21:44:50 +02:00
Maciej BieniekandGitHub ce5f06b1e5 Add new sensors to GIOS integration (#148510) 2025-07-09 21:43:02 +02:00
Denis ShulyakaandGitHub e42ca06173 Bump openai to 1.93.3 (#148501) 2025-07-09 21:41:50 +02:00
Thomas55555andGitHub 2807f057de Fix flaky test in Husqvarna Automower (#148515) 2025-07-09 22:34:37 +03:00
283d0d16c0 Linkplay - when grouped, the first media player returned is the coordinator (#146295)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-09 21:33:15 +02:00
MichaelandGitHub 84959a0077 Add platinum quality scale to Pegel Online (#131382) 2025-07-09 21:33:07 +02:00
MichaelandGitHub e012196af8 Bump aioimmich to 0.10.2 (#148503) 2025-07-09 21:22:31 +02:00
Maciej BieniekandGitHub 5d43938f0d Bump imgw_pib to version 1.2.0 (#148511) 2025-07-09 21:20:38 +02:00
Nathan SpencerandGitHub cbdc8e3800 Bump pylitterbot to 2024.2.2 (#148505) 2025-07-09 20:45:45 +02:00
Jan-Philipp BeneckeandGitHub 1b5bbda6b0 Add response headers to action response of rest command (#148480) 2025-07-09 20:37:00 +02:00
G JohanssonandGitHub 57083d877e Add repairs from issue registry to integration diagnostics (#148498) 2025-07-09 18:52:16 +01:00
Petro31andGitHub 3045f67ae5 Modernize binary sensor template tests (#148367) 2025-07-09 17:49:28 +02:00
Joost LekkerkerkerandGitHub 6f31057d30 Rework Snapcast config flow tests (#148434) 2025-07-09 16:01:17 +01:00
epenetandGitHub 511ffdc03c Add tuya snapshot tests for kg category (#148492) 2025-07-09 16:20:29 +02:00
epenetandGitHub 59fe6da47c Adjust tuya test docstrings (#148493) 2025-07-09 15:59:43 +02:00
epenetandGitHub e1cdc1af1c Add diagnostics tests to tuya (#148489) 2025-07-09 15:47:48 +02:00
epenetandGitHub f6e2b962fd Use SnapshotAssertion in lifx diagnostics tests (#148491) 2025-07-09 15:30:17 +02:00
epenetandGitHub fe0ce9bc6d Use real product_id in tuya fixture (#148415) 2025-07-09 14:44:18 +02:00
Robert ReschandGitHub b083919031 Revert "Deprecate hddtemp" (#148482) 2025-07-09 13:53:15 +02:00
ef2e699d2c Add tuya snapshot tests for curtain switch (#148465)
Co-authored-by: Franck Nijhof <[email protected]>
Co-authored-by: Abílio Costa <[email protected]>
2025-07-09 13:05:53 +02:00
Raphael HehlandGitHub 71df8ffe6e Bump uiprotect to version 7.14.2 (#148453) 2025-07-09 12:37:45 +02:00
Joakim SørensenandGitHub 98604f09fc Bump hass-nabucasa from 0.105.0 to 0.106.0 (#148473) 2025-07-09 12:30:43 +02:00
Artur PragaczandGitHub b97b04661e Improve logging in bootstrap (#148469) 2025-07-09 11:29:56 +01:00
Andrew JacksonandGitHub 828037de1f Set quality scale on Mealie to silver (#148467) 2025-07-09 11:25:56 +01:00
Norbert RittelandGitHub 659504c91f Fix friendly name of increased_non_neutral_output in zha (#148468) 2025-07-09 12:24:44 +02:00
Franck NijhofandGitHub 434ac421d1 Tiny tweaks to task form (#148475) 2025-07-09 12:04:00 +02:00
Denis ShulyakaandGitHub de849b920a Enable web search for OpenAI reasoning models (#148393) 2025-07-09 10:54:49 +02:00
Artur PragaczandGitHub e387d4834f Fix unloading update listener in Unifi (#148471) 2025-07-09 10:44:21 +02:00
Artur PragaczandGitHub 39ed877a17 Fix unloading update listener in Axis (#148470) 2025-07-09 10:43:55 +02:00
epenetandGitHub 13d05a338b Sort tuya definitions by category (#148472) 2025-07-09 10:42:55 +02:00
Avi MillerandGitHub cb2095bcbe Bump aiolifx to 1.2.1 (#148464)
Signed-off-by: Avi Miller <[email protected]>
2025-07-09 09:43:29 +02:00
Norbert RittelandGitHub 6de630ef3e Fix sentence-casing of trigger subtypes in xiaomi_ble (#148463) 2025-07-09 10:43:22 +03:00
Rico HagemanandGitHub a02359b25d Add dew point to Awair integration (#148403) 2025-07-09 09:28:55 +02:00
Oliver HeesakkersandGitHub afcd991262 Handle processing errors when writing to Zabbix (#148449) 2025-07-09 08:01:54 +02:00
J. Nick KostonandGitHub 6b5b35fece Bump aioesphomeapi to 34.2.0 (#148456) 2025-07-08 22:34:35 -06:00
Norbert RittelandGitHub ed8effa162 Fix spelling of "non-existent", "non-blocking" and "currently used" (#148440) 2025-07-08 22:58:39 +01:00
Simone ChemelliandGitHub 70c01efe57 Update Alexa Devices quality scale to silver (#148435) 2025-07-08 17:58:35 +01:00
Norbert RittelandGitHub ebffaed0bd Fix spelling of "non-resettable" in iskra (#148417) 2025-07-08 19:45:39 +03:00
Norbert RittelandGitHub ab1e323d49 Fix spelling of "non-volatile memory" in z-wave_js (#148422) 2025-07-08 19:44:11 +03:00
Simone ChemelliandGitHub 6e63c17b39 Improve exceptions in Alexa Devices (#148260) 2025-07-08 17:58:48 +02:00
Petro31andGitHub a35299d94c Add preview tests for number and sensor (#148426) 2025-07-08 16:04:06 +01:00
c97ad9657f Add metadata support to Snapcast media players (#132283)
Co-authored-by: Joostlek <[email protected]>
2025-07-08 16:58:32 +02:00
aab8908af8 Improve entity registry tests related to config entries in devices (#148399)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-08 16:24:06 +02:00
Maciej BieniekandGitHub ae7bc14059 Make the update interval a property of the NextDNS coordinator class (#148410) 2025-07-08 16:14:02 +02:00
Maciej BieniekandGitHub 546f6afac2 Bump gios to version 6.1.1 (#148414) 2025-07-08 16:11:15 +02:00
epenetandGitHub 8ccd097e98 Add tuya snapshot tests for bladeless tower fan (#148401) 2025-07-08 14:50:49 +02:00
epenetandGitHub 77ae6048ef Add tuya snapshot tests for gas leak sensor (#148400) 2025-07-08 14:49:52 +02:00
Abílio CostaandGitHub 420d1e169d Fix hassfest command in copilot-instructions (#148405) 2025-07-08 14:49:09 +02:00
hanwgandGitHub 91b8262128 Update strings for Telegram bot (#148409) 2025-07-08 14:48:44 +02:00
Ludovic BOUÉandGitHub e393929014 Matter EVSE StateOfCharge (#148213) 2025-07-08 14:28:13 +02:00
Samuel XiaoandGitHub 11938762eb Fix Switchbot cloud plug mini current unit Issue (#148314) 2025-07-08 13:57:30 +02:00
Simone ChemelliandGitHub 94862e6a50 Update Alexa Devices quality scale (#147259) 2025-07-08 13:49:00 +02:00
epenetandGitHub 1a8d4c5041 Add tuya snapshot tests for Avatto WT598 thermostat (#148398) 2025-07-08 13:40:16 +02:00
Erik MontnemeryandGitHub b775ba2955 Do not add switch_as_x config entry to source device (#148346) 2025-07-08 13:23:28 +02:00
Josef ZweckandGitHub d2bf27195a Bump pylamarzocco to 2.0.11 (#148386) 2025-07-08 13:06:43 +02:00
Josef ZweckandGitHub 824006729b Create own clientsession for lamarzocco (#148385) 2025-07-08 13:06:05 +02:00
Joakim PlateandGitHub a7cba2b9bb Handle binary coils with non default mappings in nibe heatpump (#148354) 2025-07-08 13:05:16 +02:00
Joost LekkerkerkerandGitHub bd1917c9b6 Bump pySmartThings to 3.2.7 (#148394) 2025-07-08 12:34:51 +02:00
Josef ZweckandGitHub 7541e266da Make api_version runtime_data in pi_hole (#148238) 2025-07-08 11:46:13 +02:00
ManuandGitHub f58c76c883 Fix error when personalDetail is missing in PlayStation Network integration (#148389) 2025-07-08 10:16:10 +02:00
a77a071954 Bump aioamazondevices to 3.2.8 (#148365)
Co-authored-by: Joakim Plate <[email protected]>
2025-07-08 10:14:41 +02:00
0dc145aee3 Fix tuya vacuum return_to_base function (#144362)
Co-authored-by: Franck Nijhof <[email protected]>
2025-07-08 10:03:35 +02:00
Joakim PlateandGitHub ac5d4f4a81 Fix CI issues due to nibe heatpump (#148388) 2025-07-08 09:17:27 +02:00
Noah HusbyandGitHub d44b822295 Add play media support to Russound RIO (#148240) 2025-07-08 08:51:18 +02:00
Paulus SchoutsenandGitHub 6d0891e970 OpenAI: Extract file attachment logic (#148288) 2025-07-08 08:01:49 +02:00
Avi MillerandGitHub 73730e3eb3 Bump aiolifx to 1.2.0 (#148382) 2025-07-08 07:57:41 +02:00
87b00fdc7b Emoncms add reconfigure flow (#145108)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-08 07:28:16 +02:00
hahn-thandGitHub f780b9763d Add support for ELV-SH-CTV Sensor to homematicip_cloud (#143737) 2025-07-08 07:24:55 +02:00
7a7e16bbb6 Change how subscription information is fetched (#148337)
Co-authored-by: Franck Nijhof <[email protected]>
2025-07-08 06:52:41 +02:00
J. Nick KostonandGitHub 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äandGitHub ccc80c78a0 Add huawei_lte device registry upnp udn connection (#148370) 2025-07-08 06:32:29 +02:00
epenetandGitHub b0f7c985e4 Add snapshots tests for new platforms in tuya (#148334) 2025-07-08 06:25:53 +02:00
Joakim SørensenandGitHub 7875290256 Adds claude-code feature to the devcontainer (#148338) 2025-07-08 06:24:31 +02:00
Ruben van DijkandGitHub f478812568 Allow multiple set-cookie headers with hassio ingress (#148148) 2025-07-08 06:13:08 +02:00
Joakim PlateandGitHub 9ce03c79f0 Switch to box default for numbers in nibe_heatpump integration (#148364) 2025-07-08 06:09:22 +02:00
Joakim PlateandGitHub 19951d9403 Handle when heat pump rejects same value writes in nibe_heatpump (#148366) 2025-07-08 06:07:41 +02:00
G JohanssonandGitHub 4b8dcc39b4 Bump holidays to 0.76 (#148363) 2025-07-08 06:05:18 +02:00
Joakim PlateandGitHub b151a9bf75 Add missing connection for gardena ble device (#148376) 2025-07-08 06:02:56 +02:00
ManuandGitHub e3cc4acdc6 Remove deprecated max_health, habits and rewards sensors from Habitica integration (#148377) 2025-07-08 05:57:46 +02:00
Ville SkyttäandGitHub fc53ddb3b4 Remove huawei_lte notify related timeout suppression (#148373) 2025-07-08 00:08:43 +02:00
hanwgandGitHub 0409c05265 Add basic authentication option for Telegram bot (#148247) 2025-07-07 22:08:49 +02:00
jlancharesandGitHub 9d2ffa6372 Goodwe TCP support (port 502) (#147900) 2025-07-07 19:37:20 +02:00
Joakim PlateandGitHub 5c4f166f6f Add translation for write failures in nibe_heatpump (#148352) 2025-07-07 18:48:34 +02:00
Erik MontnemeryandGitHub 6396f54e0d Move zone conditions to the zone integration (#148157) 2025-07-07 18:27:44 +02:00
Denis ShulyakaandGitHub 090b8f0659 Bump openai to 1.93.0 (#148350) 2025-07-07 18:07:28 +02:00
a46cc82916 Don't log deprecation warning in vacuum until after entity added to hass (#147959)
Co-authored-by: Martin Hjelmare <[email protected]>
Co-authored-by: Abílio Costa <[email protected]>
2025-07-07 16:52:29 +02:00
J. Nick KostonandGitHub 8007bf1c31 Fix REST sensor charset handling to respect Content-Type header (#148223) 2025-07-07 14:32:58 +01:00
c296e1f818 Remove deprecated register_static_path method (#148303)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-07 14:27:19 +01:00
Retha RunolfssonandGitHub 799dc97d4a Bump pyswitchbot to 0.68.1 (#148335) 2025-07-07 14:26:23 +01:00
Mark AdkinsandGitHub e4c9df6d98 Bump sharkiq to 1.1.1 (#148244) 2025-07-07 15:18:15 +02:00
J. Nick KostonandGitHub 03e295ace0 Restore httpx compatibility for non-primitive REST query parameters (#148286) 2025-07-07 08:01:48 -05:00
Abílio CostaandGitHub b71bcb002b Move target selector extractor method to common module (#148087) 2025-07-07 13:48:48 +01:00
Norbert RittelandGitHub c60e06d32f Fix missing sentence-casing and spelling of "REST" in iskra (#148330) 2025-07-07 14:06:27 +02:00
Norbert RittelandGitHub 448d6041e5 Fix missing sentence-casing in wallbox (#148332) 2025-07-07 14:06:13 +02:00
tronikosandGitHub 15c9ddea78 Bump gassist-text to 0.0.14 (#148312) 2025-07-07 04:10:50 -07:00
Erik MontnemeryandGitHub 0c783e87d1 Fix homee test (#148322) 2025-07-07 11:59:35 +02:00
Franck NijhofandGitHub 42b50c71ec Revert "Add tests for Sonos Alarms" (#148319) 2025-07-07 11:54:36 +02:00
Maciej BieniekandGitHub 991864a8af Bump gios to version 6.1.0 (#148274) 2025-07-07 11:43:39 +02:00
Arie CatsmanandGitHub b79e770bcf Bump pyenphase to 2.2.1 (#148292) 2025-07-07 11:40:48 +02:00
Shay LevyandGitHub f02c1b0d4e Bump aiowebostv to 0.7.4 (#148273) 2025-07-07 11:37:39 +02:00
Norbert RittelandGitHub a5d6bfd1b3 Reword option for 'Main' control in wled (#148309) 2025-07-07 10:30:39 +02:00
Norbert RittelandGitHub 21f6bf3914 Improve translation_key of EnergyEvseSupplyStateSensor in matter (#148280) 2025-07-07 10:26:20 +02:00
HesselandGitHub 0bce01da0b Address some Wallbox quality scale issues (#148200) 2025-07-07 10:09:07 +02:00
6351c3302e Matter OperationalState CountdownTime (#147705)
Co-authored-by: Martin Hjelmare <[email protected]>
2025-07-06 23:40:05 +02:00
J. Nick KostonandGitHub 2ea20ee2ab Fix UTF-8 encoding for REST basic authentication (#148225) 2025-07-06 12:40:19 -05:00
Paulus SchoutsenandGitHub 008e2a3d10 Add attachment support to AI task (#148120) 2025-07-06 19:33:41 +02:00
Joakim SørensenandGitHub 699c60f293 Add the current version to the starting log to aid troubleshooting (#148271) 2025-07-06 19:06:27 +02:00
karwostsandGitHub 404d17efca Translate number selector unit for utility_meter (#148276) 2025-07-06 18:36:38 +02:00
4b5c04b2f0 Add AI Task support in Ollama (#148226)
Co-authored-by: Paulus Schoutsen <[email protected]>
2025-07-06 16:56:37 +02:00
8cb9cadce9 Extract files_to_prompt from Gemini action (#148203)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Allen Porter <[email protected]>
2025-07-06 15:15:38 +02:00
075efb469a Bump sfrbox-api to 0.0.12 (#148259)
Co-authored-by: epenet <[email protected]>
2025-07-06 13:08:27 +02:00
starkillerOGandGitHub 0e7a4c91bf bump motionblinds to 0.6.29 (#148265) 2025-07-06 12:38:57 +02:00
Norbert RittelandGitHub 4ee930507d Fix typo in wrong_hub abort message of homee (#148261) 2025-07-06 12:11:44 +02:00
Markus AdrarioandGitHub 1b11ac9123 Add Homee general tests (#137128) 2025-07-06 12:05:43 +02:00
Norbert RittelandGitHub 8d7e387b46 Deduplicate strings in nordpool actions (#148258) 2025-07-06 11:23:57 +02:00
70e9c4e2d0 Add reauth flow to the Traccar Server integration (#148236)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Josef Zweck <[email protected]>
2025-07-06 08:09:59 +02:00
26de1ea37b Update strings in pihole (#148234)
Co-authored-by: Copilot <[email protected]>
2025-07-05 23:14:59 +01:00
Josef ZweckandGitHub 3ffcfa42ba Bump pylamarzocco to 2.0.10 (#148233) 2025-07-05 23:34:23 +02:00
G JohanssonandGitHub e304022560 Add service in Nord Pool for fetching normalized price indices (#147979) 2025-07-05 21:39:48 +02:00
G JohanssonandGitHub 160e4e4d05 Block options flow for default hostname in dnsip (#148221) 2025-07-05 21:36:15 +02:00
Noah HusbyandGitHub eb0f11a859 Bump aiorussound to 4.8.0 (#148235) 2025-07-05 21:13:48 +02:00
TheJulianJESandGitHub 295b15ace9 Change ZHA string "autoshutdown" to "auto-shutdown" (#148230) 2025-07-05 20:23:03 +02:00
Pete SageandGitHub d997efc500 Add tests for Sonos Alarms (#146308) 2025-07-05 17:39:52 +02:00
Jack PowellandGitHub 736865c130 Add binary sensor platform to PlayStation Network Integration (#147639) 2025-07-05 17:27:23 +02:00
Paulus SchoutsenandGitHub 4f4ec6f41a Add Google Gen AI structured data support (#148143) 2025-07-05 08:22:17 -07:00
Luka MatijevićandGitHub 33d05d99eb Fix Miele hob plate power step typo (#148214) 2025-07-05 16:44:41 +02:00
Guido SchmitzandGitHub 8d82e34ba5 Make connected stations coordinator a dict in devolo Home Network (#147042) 2025-07-05 11:42:15 +02:00
Sören BeyeandGitHub 2ea09ff37a Squeezebox: Fix track selection in media browser (#147185) 2025-07-05 11:36:45 +02:00
Sören BeyeandGitHub 676567f471 Squeezebox: Fix tracks not having thumbnails (#147187) 2025-07-05 11:31:30 +02:00
Denis ShulyakaandGitHub 3151713a34 Replace dot with underscores for NamespacedTool and ActionTool (#147764) 2025-07-05 11:27:27 +02:00
David RapanandGitHub 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 RittelandGitHub ef255788d2 Make lat/long attribute names localizable in dwd_weather_warnings (#147988) 2025-07-05 11:01:27 +02:00
Norbert RittelandGitHub b72536acfa Make "autorelock" consistent across integrations in matter (#148023) 2025-07-05 10:59:57 +02:00
tronikosandGitHub fea7dc7eba Remember Opower utility and username on config flow errors (#148097) 2025-07-05 10:26:15 +02:00
Markus AdrarioandGitHub f1698cdb75 Add reauth flow to homee (#147258) 2025-07-05 10:26:04 +02:00
1b21c986e8 Enable Pihole API v6 (#145890)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Josef Zweck <[email protected]>
2025-07-05 10:21:32 +02:00
Paulus SchoutsenandGitHub 1e164c94b1 Include path when media source file can be accessed on disk (#148180) 2025-07-05 10:14:52 +02:00
7898e3f0fb Add initial tuya snapshot tests (#148034)
Co-authored-by: Franck Nijhof <[email protected]>
2025-07-05 09:54:54 +02:00
Norbert RittelandGitHub 0d54e75940 Fix spelling of "auto" prefixes in zha (#148022) 2025-07-05 09:34:24 +02:00
karwostsandGitHub 3cfff4de3a Add a preview to history_stats options flow (#145721) 2025-07-05 09:09:02 +02:00
275d390a6c Add reconfiguration support for keenetic_ndms2 integration (#142191)
Co-authored-by: Franck Nijhof <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Franck Nijhof <[email protected]>
2025-07-05 08:52:43 +02:00
Matt ZimmermanandGitHub e63e6a6072 Bump python-smarttub to 0.0.43 (#147317) 2025-07-05 08:08:52 +02:00
Josef ZweckandGitHub e592e565c0 Make ready time sensors unavailable instead in lamarzocco (#147985) 2025-07-05 07:20:42 +02:00
Arie CatsmanandGitHub 12b90f3c8e Add debug logs to trace enphase auth process at load. (#148117) 2025-07-04 23:14:51 +01:00
epenetandGitHub 76be2fdba1 Improve (and align) deprecation messages (#147948) 2025-07-05 00:02:36 +02:00
Thomas55555andGitHub 528daad854 Constant polling for Husqvarna Automower (#147957) 2025-07-04 23:42:17 +02:00
dcad5bbe04 Simplify unnecessary re.findall calls (#147907)
Co-authored-by: Copilot <[email protected]>
2025-07-04 23:26:36 +02:00
ca85ffc068 Add Deadlock (SecureMode) support to the Yale Access Bluetooth integration (#144107)
Co-authored-by: J. Nick Koston <[email protected]>
Co-authored-by: J. Nick Koston <[email protected]>
2025-07-04 23:07:13 +02:00
Kevin StillhammerandGitHub 9a5cbe483b Remove obsolete string unit_system in here_travel_time (#146656) 2025-07-04 23:06:47 +02:00
Pete SageandGitHub be7735964b Sonos remove unneeded mocking from test (#147064) 2025-07-04 23:02:38 +02:00
Guido SchmitzandGitHub 79683c8267 Log availability of devices in devolo Home Control (#147091) 2025-07-04 22:59:38 +02:00
Andre LengwenusandGitHub 8f24ebe967 Remove deprecated support for lock sensors and corresponding actions in lcn (#147143) 2025-07-04 22:55:20 +02:00
Andre LengwenusandGitHub 520d92b902 Use brightness stored in hardware device when switching LCN lights (#147375) 2025-07-04 22:53:11 +02:00
karwostsandGitHub 22e46d9977 Make derivative sensor unavailable when source sensor is unavailable (#147468) 2025-07-04 22:48:48 +02:00
57c04f3a56 Bump pysmlight to v0.2.7 (#148101)
Co-authored-by: Franck Nijhof <[email protected]>
2025-07-04 22:35:44 +02:00
c0368f2448 Add weekdays to time trigger (#147505)
Co-authored-by: Claude <[email protected]>
2025-07-04 22:31:11 +02:00
6a7f4953cd Fix media selector validation (#147855)
Co-authored-by: Copilot <[email protected]>
2025-07-04 22:30:35 +02:00
470baa782e Add zeroconf discovery to philips_js (#147913)
Co-authored-by: Joost Lekkerkerker <[email protected]>
2025-07-04 22:24:40 +02:00
SidandGitHub 6e607ffa01 Add reconfigure flow to eheimdigital (#147930) 2025-07-04 22:18:13 +02:00
Wesley VosandGitHub f5b51c6cf0 Add serial_numbers to device_info of inverters, encharge and enpower (#147964) 2025-07-04 22:04:48 +02:00
HesselandGitHub bfccee17ef Wallbox, Improve test setup (#148036) 2025-07-04 21:56:44 +02:00
Erik MontnemeryandGitHub b6b6de24ac Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in cambridge_audio (#148133) 2025-07-04 21:54:11 +02:00
Thomas55555andGitHub 70624f72b6 Additional icon translation for Husqvarna Automower (#148167) 2025-07-04 21:51:47 +02:00
Thomas55555andGitHub c61cd422d1 Delete stale icon translation in Husqvarna Automower (#148168) 2025-07-04 20:47:32 +02:00
karwostsandGitHub 0b2db2510f Support translating number selector UoM (#148162) 2025-07-04 21:06:33 +03:00
Erik MontnemeryandGitHub bb1e263149 Remove cv.SUN_CONDITION_SCHEMA (#148158) 2025-07-04 18:34:55 +02:00
Michael FreemanandGitHub 8e6b9c04f6 Bump venstarcolortouch to 0.21 (#148152) 2025-07-04 17:46:59 +02:00
Greg DowlingandGitHub cf931a75a7 Remove incorrect use of via_device in roon component (#146572) 2025-07-04 17:04:16 +02:00
Thomas55555andGitHub 3250a2fb46 Bump aioautomower to 1.2.0 (#148078) 2025-07-04 16:43:36 +02:00
Franck NijhofandGitHub 6235adc69a Fix flaky emulated_roku/test_binding.py::test_events_fired_properly test (#148069) 2025-07-04 16:42:24 +02:00
Simone ChemelliandGitHub 5d258c2f82 Bump aioamazondevices to 3.2.3 (#148082) 2025-07-04 16:33:16 +02:00
hanwgandGitHub cc2aca2c2c Fix Telegram bots using plain text parser failing to load on restart (#148050) 2025-07-04 16:32:46 +02:00
Erik MontnemeryandGitHub 04bd1967a7 Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in apple_tv (#148132) 2025-07-04 16:31:44 +02:00
Erik MontnemeryandGitHub a046530eaf Replace MediaPlayerState.STANDBY with MediaPlayerState.IDLE in mediaroom (#148135) 2025-07-04 16:30:03 +02:00
Erik MontnemeryandGitHub 631523dfaf Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in lookin (#148134) 2025-07-04 16:27:54 +02:00
Erik MontnemeryandGitHub dc20375506 Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in snapcast (#148138) 2025-07-04 16:27:33 +02:00
Erik MontnemeryandGitHub 811f085556 Replace MediaPlayerState.STANDBY with MediaPlayerState.IDLE in androidtv (#148130) 2025-07-04 16:27:01 +02:00
Erik MontnemeryandGitHub fd86a43b28 Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in ps4 (#148136) 2025-07-04 16:25:59 +02:00
Bram KragtenandGitHub b7f830523e Update frontend to 20250702.1 (#148131) 2025-07-04 16:25:28 +02:00
Erik MontnemeryandGitHub 3f752e13ff Replace MediaPlayerState.STANDBY with MediaPlayerState.OFF in roku (#148137) 2025-07-04 16:23:18 +02:00
Marc MuellerandGitHub 783102f2f6 [ci] Fix typing issue with aiohttp and aiosignal (#148141) 2025-07-04 16:22:38 +02:00
Erik MontnemeryandGitHub 8ce30d9559 Add tests of legacy entity without platform writing state (#148109) 2025-07-04 16:21:48 +02:00
Paulus SchoutsenandGitHub cde17fc0ca add extra tests for media source URI parsing (#148114) 2025-07-04 16:21:11 +02:00
David KnowlesandGitHub 83ae5f52da Bump pydrawise to 2025.7.0 (#148088) 2025-07-04 16:20:24 +02:00
tronikosandGitHub 1cb9767bb8 Enable strict typing for Opower (#148096) 2025-07-04 16:19:04 +02:00
tronikosandGitHub e98fe7dc9c Add data_description to Opower forms (#148099) 2025-07-04 16:17:41 +02:00
tronikosandGitHub 40ec51c0a3 Add redirect URL in Google Assistant SDK setup (#148076) 2025-07-04 16:17:10 +02:00
Harry HeymannandGitHub 40fcc3b75b Rename Matter device conversion methods (#148090) 2025-07-04 16:13:40 +02:00
510fd09163 Allow core integrations to describe their conditions (#147529)
Co-authored-by: Abílio Costa <[email protected]>
2025-07-04 16:03:42 +02:00
epenetandGitHub e47bdc06a0 Set docstyle convention to google in ruff (#148142) 2025-07-04 16:00:37 +02:00
b3d9908cd9 Add AI task structured output (#148083)
Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Paulus Schoutsen <[email protected]>
2025-07-04 15:03:34 +02:00
Erik MontnemeryandGitHub 99d63c49bb Add comment about error assigning in frame.report_usage (#148105) 2025-07-04 14:47:01 +02:00
4be2e84ce6 Add backward compatibility with older versions of Traccar server (#146639)
Co-authored-by: Joakim Sørensen <[email protected]>
2025-07-04 14:36:25 +02:00
1603 changed files with 76840 additions and 20925 deletions
+1
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
+4 -2
View File
@@ -21,7 +21,7 @@ body:
- type: textarea
id: description
attributes:
label: Task description
label: Description
description: |
Provide a clear and detailed description of the task that needs to be accomplished.
@@ -43,9 +43,11 @@ body:
Include links to related issues, research, prototypes, roadmap opportunities etc.
placeholder: |
- Roadmap opportunity: [links]
- Roadmap opportunity: [link]
- Epic: [link]
- Feature request: [link]
- Technical design documents: [link]
- Prototype/mockup: [link]
- Dependencies: [links]
validations:
required: false
+7 -1
View File
@@ -45,6 +45,12 @@ rules:
**When Reviewing/Creating Code**: Always check the integration's quality scale level and exemption status before applying rules.
## Code Review Guidelines
**When reviewing code, do NOT comment on:**
- **Missing imports** - We use static analysis tooling to catch that
- **Code formatting** - We have ruff as a formatting tool that will catch those if needed (unless specifically instructed otherwise in these instructions)
## Python Requirements
- **Compatibility**: Python 3.13+
@@ -1149,7 +1155,7 @@ _LOGGER.debug("Processing data: %s", data) # Use lazy logging
### Validation Commands
```bash
# Check specific integration
python -m script.hassfest --integration my_integration
python -m script.hassfest --integration-path homeassistant/components/my_integration
# Validate quality scale
# Check quality_scale.yaml against current rules
+3
View File
@@ -6,3 +6,6 @@ updates:
interval: daily
time: "06:00"
open-pull-requests-limit: 10
labels:
- dependency
- github_actions
+1 -1
View File
@@ -324,7 +324,7 @@ jobs:
uses: actions/[email protected]
- name: Install Cosign
uses: sigstore/[email protected].1
uses: sigstore/[email protected].2
with:
cosign-release: "v2.2.3"
+1 -1
View File
@@ -37,7 +37,7 @@ on:
type: boolean
env:
CACHE_VERSION: 3
CACHE_VERSION: 4
UV_CACHE_VERSION: 1
MYPY_CACHE_VERSION: 1
HA_SHORT_VERSION: "2025.8"
+2 -2
View File
@@ -24,11 +24,11 @@ jobs:
uses: actions/[email protected]
- name: Initialize CodeQL
uses: github/codeql-action/[email protected].2
uses: github/codeql-action/[email protected].4
with:
languages: python
- name: Perform CodeQL Analysis
uses: github/codeql-action/[email protected].2
uses: github/codeql-action/[email protected].4
with:
category: "/language:python"
@@ -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: |
@@ -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: |
+3
View File
@@ -377,10 +377,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.*
@@ -534,6 +536,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.*
Generated
+8 -4
View File
@@ -684,8 +684,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 +1102,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 +1660,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
@@ -1756,8 +1760,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
+29 -31
View File
@@ -76,6 +76,7 @@ from .exceptions import HomeAssistantError
from .helpers import (
area_registry,
category_registry,
condition,
config_validation as cv,
device_registry,
entity,
@@ -331,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
)
@@ -383,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)
@@ -452,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)),
)
@@ -692,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:
@@ -723,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()),
@@ -868,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)
@@ -911,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:
+34 -2
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,
@@ -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."""
+7 -4
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(
@@ -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"
+17 -3
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:
- "*"
@@ -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."
}
}
}
+100 -6
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)}>"
@@ -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."]
}
@@ -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: |
@@ -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)
@@ -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(
-1
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
-3
View File
@@ -4,9 +4,6 @@
"health_index": {
"default": "mdi:heart-pulse"
},
"absolute_humidity": {
"default": "mdi:water"
},
"oxygen": {
"default": "mdi:leaf"
},
+3 -5
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"),
@@ -93,9 +93,6 @@
"health_index": {
"name": "Health index"
},
"absolute_humidity": {
"name": "Absolute humidity"
},
"hydrogen": {
"name": "Hydrogen"
},
@@ -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(
+2 -2
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."""
@@ -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.0"]
}
+18 -5
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}"
)
@@ -6,7 +6,12 @@ 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
@@ -57,6 +62,8 @@ class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
errors["base"] = "cannot_connect"
except CannotAuthenticate:
errors["base"] = "invalid_auth"
except CannotRetrieveData:
errors["base"] = "cannot_retrieve_data"
except WrongCountry:
errors["base"] = "wrong_country"
else:
@@ -106,6 +113,8 @@ class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
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,
@@ -52,8 +52,18 @@ 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 ConfigEntryAuthFailed(
translation_domain=DOMAIN,
@@ -7,6 +7,6 @@
"integration_type": "hub",
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "bronze",
"requirements": ["aioamazondevices==3.2.2"]
"quality_scale": "silver",
"requirements": ["aioamazondevices==3.5.1"]
}
@@ -28,33 +28,31 @@ 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: done
test-coverage:
status: todo
comment: all tests missing
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-data-update: done
docs-examples: done
docs-known-limitations: todo
docs-supported-devices: todo
docs-supported-functions: todo
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: todo
docs-use-cases: todo
docs-use-cases: done
dynamic-devices: todo
entity-category: done
entity-device-class: done
@@ -43,6 +43,7 @@
},
"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%]"
@@ -84,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}"
}
}
@@ -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
@@ -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:
@@ -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"
@@ -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
@@ -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)
@@ -22,5 +22,10 @@
}
}
}
},
"services": {
"get_forecasts": {
"service": "mdi:transmission-tower"
}
}
}
@@ -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":
@@ -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,
)
@@ -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
@@ -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"
}
}
}
}
@@ -7,5 +7,5 @@
"iot_class": "local_polling",
"loggers": ["amcrest"],
"quality_scale": "legacy",
"requirements": ["amcrest==1.9.8"]
"requirements": ["amcrest==1.9.9"]
}
@@ -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
@@ -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,
}
@@ -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"
},
)
@@ -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",
@@ -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)
@@ -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(
@@ -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,
}
@@ -68,7 +68,6 @@ 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
@@ -80,13 +79,3 @@ async def async_unload_entry(
"""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: AndroidTVRemoteConfigEntry
) -> 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)
@@ -19,7 +19,7 @@ from homeassistant.config_entries import (
SOURCE_RECONFIGURE,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
OptionsFlowWithReload,
)
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME
from homeassistant.core import callback
@@ -116,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={
@@ -243,7 +243,7 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
return AndroidTVRemoteOptionsFlowHandler(config_entry)
class AndroidTVRemoteOptionsFlowHandler(OptionsFlow):
class AndroidTVRemoteOptionsFlowHandler(OptionsFlowWithReload):
"""Android TV Remote options flow."""
def __init__(self, config_entry: AndroidTVRemoteConfigEntry) -> None:
@@ -27,4 +27,4 @@ def create_api(hass: HomeAssistant, host: str, enable_ime: bool) -> AndroidTVRem
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]
@@ -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%]"
+2 -2
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"
@@ -6,7 +6,6 @@ from homeassistant.components import conversation
from homeassistant.config_entries import ConfigSubentry
from homeassistant.const import CONF_LLM_HASS_API, MATCH_ALL
from homeassistant.core import HomeAssistant
from homeassistant.helpers import intent
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import AnthropicConfigEntry
@@ -72,13 +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,
)
return conversation.async_get_result_from_chat_log(user_input, chat_log)
+3 -1
View File
@@ -311,11 +311,13 @@ def _create_token_stats(
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_name = subentry.title
self._attr_unique_id = subentry.subentry_id
self._attr_device_info = dr.DeviceInfo(
identifiers={(DOMAIN, subentry.subentry_id)},
@@ -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",
@@ -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.",
@@ -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
@@ -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",
@@ -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
@@ -3,7 +3,6 @@
DOMAIN = "assist_pipeline"
DATA_CONFIG = f"{DOMAIN}.config"
DATA_MIGRATIONS = f"{DOMAIN}_migrations"
DEFAULT_PIPELINE_TIMEOUT = 60 * 5 # seconds
@@ -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."""
@@ -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?"
@@ -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"]
}
+1
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"
+10
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, ...] = (
@@ -57,6 +57,9 @@
},
"sound_level": {
"name": "Sound level"
},
"dew_point": {
"name": "Dew point"
}
}
}
+3 -1
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)
@@ -0,0 +1 @@
"""Bauknecht virtual integration."""
@@ -0,0 +1,6 @@
{
"domain": "bauknecht",
"name": "Bauknecht",
"integration_type": "virtual",
"supported_by": "whirlpool"
}
@@ -15,23 +15,31 @@ from bluecurrent_api.exceptions import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_NAME, CONF_API_TOKEN, Platform
from homeassistant.const import CONF_API_TOKEN, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import DOMAIN, EVSE_ID, LOGGER, MODEL_TYPE
from .const import (
CHARGEPOINT_SETTINGS,
CHARGEPOINT_STATUS,
DOMAIN,
EVSE_ID,
LOGGER,
PLUG_AND_CHARGE,
VALUE,
)
type BlueCurrentConfigEntry = ConfigEntry[Connector]
PLATFORMS = [Platform.BUTTON, Platform.SENSOR]
PLATFORMS = [Platform.BUTTON, Platform.SENSOR, Platform.SWITCH]
CHARGE_POINTS = "CHARGE_POINTS"
DATA = "data"
DELAY = 5
GRID = "GRID"
OBJECT = "object"
VALUE_TYPES = ["CH_STATUS"]
VALUE_TYPES = [CHARGEPOINT_STATUS, CHARGEPOINT_SETTINGS]
async def async_setup_entry(
@@ -94,7 +102,7 @@ class Connector:
elif object_name in VALUE_TYPES:
value_data: dict = message[DATA]
evse_id = value_data.pop(EVSE_ID)
self.update_charge_point(evse_id, value_data)
self.update_charge_point(evse_id, object_name, value_data)
# gets grid key / values
elif GRID in object_name:
@@ -106,26 +114,37 @@ class Connector:
"""Handle incoming chargepoint data."""
await asyncio.gather(
*(
self.handle_charge_point(
entry[EVSE_ID], entry[MODEL_TYPE], entry[ATTR_NAME]
)
self.handle_charge_point(entry[EVSE_ID], entry)
for entry in charge_points_data
),
self.client.get_grid_status(charge_points_data[0][EVSE_ID]),
)
async def handle_charge_point(self, evse_id: str, model: str, name: str) -> None:
async def handle_charge_point(
self, evse_id: str, charge_point: dict[str, Any]
) -> None:
"""Add the chargepoint and request their data."""
self.add_charge_point(evse_id, model, name)
self.add_charge_point(evse_id, charge_point)
await self.client.get_status(evse_id)
def add_charge_point(self, evse_id: str, model: str, name: str) -> None:
def add_charge_point(self, evse_id: str, charge_point: dict[str, Any]) -> None:
"""Add a charge point to charge_points."""
self.charge_points[evse_id] = {MODEL_TYPE: model, ATTR_NAME: name}
self.charge_points[evse_id] = charge_point
def update_charge_point(self, evse_id: str, data: dict) -> None:
def update_charge_point(self, evse_id: str, update_type: str, data: dict) -> None:
"""Update the charge point data."""
self.charge_points[evse_id].update(data)
charge_point = self.charge_points[evse_id]
if update_type == CHARGEPOINT_SETTINGS:
# Update the plug and charge object. The library parses this object to a bool instead of an object.
plug_and_charge = charge_point.get(PLUG_AND_CHARGE)
if plug_and_charge is not None:
plug_and_charge[VALUE] = data[PLUG_AND_CHARGE]
# Remove the plug and charge object from the data list before updating.
del data[PLUG_AND_CHARGE]
charge_point.update(data)
self.dispatch_charge_point_update_signal(evse_id)
def dispatch_charge_point_update_signal(self, evse_id: str) -> None:
@@ -8,3 +8,14 @@ LOGGER = logging.getLogger(__package__)
EVSE_ID = "evse_id"
MODEL_TYPE = "model_type"
PLUG_AND_CHARGE = "plug_and_charge"
VALUE = "value"
PERMISSION = "permission"
CHARGEPOINT_STATUS = "CH_STATUS"
CHARGEPOINT_SETTINGS = "CH_SETTINGS"
BLOCK = "block"
UNAVAILABLE = "unavailable"
AVAILABLE = "available"
LINKED_CHARGE_CARDS = "linked_charge_cards_only"
PUBLIC_CHARGING = "public_charging"
ACTIVITY = "activity"
@@ -30,6 +30,17 @@
"stop_charge_session": {
"default": "mdi:stop"
}
},
"switch": {
"plug_and_charge": {
"default": "mdi:ev-plug-type2"
},
"linked_charge_cards": {
"default": "mdi:account-group"
},
"block": {
"default": "mdi:lock"
}
}
}
}
@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/blue_current",
"iot_class": "cloud_push",
"loggers": ["bluecurrent_api"],
"requirements": ["bluecurrent-api==1.2.3"]
"requirements": ["bluecurrent-api==1.2.4"]
}
@@ -124,6 +124,17 @@
"reset": {
"name": "Reset"
}
},
"switch": {
"plug_and_charge": {
"name": "Plug & Charge"
},
"linked_charge_cards_only": {
"name": "Linked charging cards only"
},
"block": {
"name": "Block charge point"
}
}
}
}
@@ -0,0 +1,169 @@
"""Support for Blue Current switches."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import PLUG_AND_CHARGE, BlueCurrentConfigEntry, Connector
from .const import (
AVAILABLE,
BLOCK,
LINKED_CHARGE_CARDS,
PUBLIC_CHARGING,
UNAVAILABLE,
VALUE,
)
from .entity import ChargepointEntity
@dataclass(kw_only=True, frozen=True)
class BlueCurrentSwitchEntityDescription(SwitchEntityDescription):
"""Describes a Blue Current switch entity."""
function: Callable[[Connector, str, bool], Any]
turn_on_off_fn: Callable[[str, Connector], tuple[bool, bool]]
"""Update the switch based on the latest data received from the websocket. The first returned boolean is _attr_is_on, the second one has_value."""
def update_on_value_and_activity(
key: str, evse_id: str, connector: Connector, reverse_is_on: bool = False
) -> tuple[bool, bool]:
"""Return the updated state of the switch based on received chargepoint data and activity."""
data_object = connector.charge_points[evse_id].get(key)
is_on = data_object[VALUE] if data_object is not None else None
activity = connector.charge_points[evse_id].get("activity")
if is_on is not None and activity == AVAILABLE:
return is_on if not reverse_is_on else not is_on, True
return False, False
def update_block_switch(evse_id: str, connector: Connector) -> tuple[bool, bool]:
"""Return the updated data for a block switch."""
activity = connector.charge_points[evse_id].get("activity")
return activity == UNAVAILABLE, activity in [AVAILABLE, UNAVAILABLE]
def update_charge_point(
key: str, evse_id: str, connector: Connector, new_switch_value: bool
) -> None:
"""Change charge point data when the state of the switch changes."""
data_objects = connector.charge_points[evse_id].get(key)
if data_objects is not None:
data_objects[VALUE] = new_switch_value
async def set_plug_and_charge(connector: Connector, evse_id: str, value: bool) -> None:
"""Toggle the plug and charge setting for a specific charging point."""
await connector.client.set_plug_and_charge(evse_id, value)
update_charge_point(PLUG_AND_CHARGE, evse_id, connector, value)
async def set_linked_charge_cards(
connector: Connector, evse_id: str, value: bool
) -> None:
"""Toggle the plug and charge setting for a specific charging point."""
await connector.client.set_linked_charge_cards_only(evse_id, value)
update_charge_point(PUBLIC_CHARGING, evse_id, connector, not value)
SWITCHES = (
BlueCurrentSwitchEntityDescription(
key=PLUG_AND_CHARGE,
translation_key=PLUG_AND_CHARGE,
function=set_plug_and_charge,
turn_on_off_fn=lambda evse_id, connector: (
update_on_value_and_activity(PLUG_AND_CHARGE, evse_id, connector)
),
),
BlueCurrentSwitchEntityDescription(
key=LINKED_CHARGE_CARDS,
translation_key=LINKED_CHARGE_CARDS,
function=set_linked_charge_cards,
turn_on_off_fn=lambda evse_id, connector: (
update_on_value_and_activity(
PUBLIC_CHARGING, evse_id, connector, reverse_is_on=True
)
),
),
BlueCurrentSwitchEntityDescription(
key=BLOCK,
translation_key=BLOCK,
function=lambda connector, evse_id, value: connector.client.block(
evse_id, value
),
turn_on_off_fn=update_block_switch,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: BlueCurrentConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Blue Current switches."""
connector = entry.runtime_data
async_add_entities(
ChargePointSwitch(
connector,
evse_id,
switch,
)
for evse_id in connector.charge_points
for switch in SWITCHES
)
class ChargePointSwitch(ChargepointEntity, SwitchEntity):
"""Base charge point switch."""
has_value = True
entity_description: BlueCurrentSwitchEntityDescription
def __init__(
self,
connector: Connector,
evse_id: str,
switch: BlueCurrentSwitchEntityDescription,
) -> None:
"""Initialize the switch."""
super().__init__(connector, evse_id)
self.key = switch.key
self.entity_description = switch
self.evse_id = evse_id
self._attr_available = True
self._attr_unique_id = f"{switch.key}_{evse_id}"
async def call_function(self, value: bool) -> None:
"""Call the function to set setting."""
await self.entity_description.function(self.connector, self.evse_id, value)
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
await self.call_function(True)
self._attr_is_on = True
self.async_write_ha_state()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity on."""
await self.call_function(False)
self._attr_is_on = False
self.async_write_ha_state()
@callback
def update_from_latest_data(self) -> None:
"""Fetch new state data for the switch."""
new_state = self.entity_description.turn_on_off_fn(self.evse_id, self.connector)
self._attr_is_on = new_state[0]
self.has_value = new_state[1]
@@ -15,12 +15,12 @@
],
"quality_scale": "internal",
"requirements": [
"bleak==0.22.3",
"bleak-retry-connector==3.9.0",
"bluetooth-adapters==0.21.4",
"bleak==1.0.1",
"bleak-retry-connector==4.0.0",
"bluetooth-adapters==2.0.0",
"bluetooth-auto-recovery==1.5.2",
"bluetooth-data-tools==1.28.2",
"dbus-fast==2.43.0",
"habluetooth==3.49.0"
"dbus-fast==2.44.2",
"habluetooth==4.0.1"
]
}
@@ -8,20 +8,33 @@ from bring_api import Bring
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN
from .coordinator import (
BringActivityCoordinator,
BringConfigEntry,
BringCoordinators,
BringDataUpdateCoordinator,
)
from .services import async_setup_services
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
PLATFORMS: list[Platform] = [Platform.EVENT, Platform.SENSOR, Platform.TODO]
_LOGGER = logging.getLogger(__name__)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Bring! services."""
async_setup_services(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: BringConfigEntry) -> bool:
"""Set up Bring! from a config entry."""
+4 -1
View File
@@ -7,5 +7,8 @@ DOMAIN = "bring"
ATTR_SENDER: Final = "sender"
ATTR_ITEM_NAME: Final = "item"
ATTR_NOTIFICATION_TYPE: Final = "message"
ATTR_REACTION: Final = "reaction"
ATTR_ACTIVITY: Final = "uuid"
ATTR_RECEIVER: Final = "publicUserUuid"
SERVICE_PUSH_NOTIFICATION = "send_message"
SERVICE_ACTIVITY_STREAM_REACTION = "send_reaction"
@@ -35,6 +35,9 @@
"services": {
"send_message": {
"service": "mdi:cellphone-message"
},
"send_reaction": {
"service": "mdi:thumb-up"
}
}
}
+110
View File
@@ -0,0 +1,110 @@
"""Actions for Bring! integration."""
import logging
from typing import TYPE_CHECKING
from bring_api import (
ActivityType,
BringAuthException,
BringNotificationType,
BringRequestException,
ReactionType,
)
import voluptuous as vol
from homeassistant.components.event import ATTR_EVENT_TYPE
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv, entity_registry as er
from .const import (
ATTR_ACTIVITY,
ATTR_REACTION,
ATTR_RECEIVER,
DOMAIN,
SERVICE_ACTIVITY_STREAM_REACTION,
)
from .coordinator import BringConfigEntry
_LOGGER = logging.getLogger(__name__)
SERVICE_ACTIVITY_STREAM_REACTION_SCHEMA = vol.Schema(
{
vol.Required(ATTR_ENTITY_ID): cv.entity_id,
vol.Required(ATTR_REACTION): vol.All(
vol.Upper,
vol.Coerce(ReactionType),
),
}
)
def get_config_entry(hass: HomeAssistant, entry_id: str) -> BringConfigEntry:
"""Return config entry or raise if not found or not loaded."""
entry = hass.config_entries.async_get_entry(entry_id)
if TYPE_CHECKING:
assert entry
if entry.state is not ConfigEntryState.LOADED:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="entry_not_loaded",
)
return entry
def async_setup_services(hass: HomeAssistant) -> None:
"""Set up services for Bring! integration."""
async def async_send_activity_stream_reaction(call: ServiceCall) -> None:
"""Send a reaction in response to recent activity of a list member."""
if (
not (state := hass.states.get(call.data[ATTR_ENTITY_ID]))
or not (entity := er.async_get(hass).async_get(call.data[ATTR_ENTITY_ID]))
or not entity.config_entry_id
):
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="entity_not_found",
translation_placeholders={
ATTR_ENTITY_ID: call.data[ATTR_ENTITY_ID],
},
)
config_entry = get_config_entry(hass, entity.config_entry_id)
coordinator = config_entry.runtime_data.data
list_uuid = entity.unique_id.split("_")[1]
activity = state.attributes[ATTR_EVENT_TYPE]
reaction: ReactionType = call.data[ATTR_REACTION]
if not activity:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="activity_not_found",
)
try:
await coordinator.bring.notify(
list_uuid,
BringNotificationType.LIST_ACTIVITY_STREAM_REACTION,
receiver=state.attributes[ATTR_RECEIVER],
activity=state.attributes[ATTR_ACTIVITY],
activity_type=ActivityType(activity.upper()),
reaction=reaction,
)
except (BringRequestException, BringAuthException) as e:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="reaction_request_failed",
) from e
hass.services.async_register(
DOMAIN,
SERVICE_ACTIVITY_STREAM_REACTION,
async_send_activity_stream_reaction,
SERVICE_ACTIVITY_STREAM_REACTION_SCHEMA,
)
@@ -21,3 +21,28 @@ send_message:
required: false
selector:
text:
send_reaction:
fields:
entity_id:
required: true
selector:
entity:
filter:
- integration: bring
domain: event
example: event.shopping_list
reaction:
required: true
selector:
select:
options:
- label: 👍🏼
value: thumbs_up
- label: 🧐
value: monocle
- label: 🤤
value: drooling
- label: ❤️
value: heart
mode: dropdown
example: thumbs_up
@@ -144,6 +144,19 @@
},
"notify_request_failed": {
"message": "Failed to send push notification for Bring! due to a connection error, try again later"
},
"reaction_request_failed": {
"message": "Failed to send reaction for Bring! due to a connection error, try again later"
},
"activity_not_found": {
"message": "Failed to send reaction for Bring! — No recent activity found"
},
"entity_not_found": {
"message": "Failed to send reaction for Bring! — Unknown entity {entity_id}"
},
"entry_not_loaded": {
"message": "The account associated with this Bring! list is either not loaded or disabled in Home Assistant."
}
},
"services": {
@@ -164,6 +177,20 @@
"description": "Item name(s) to include in an urgent message e.g. 'Attention! Attention! - We still urgently need: [Items]'"
}
}
},
"send_reaction": {
"name": "Send reaction",
"description": "Sends a reaction to a recent activity on a Bring! list by a member of the shared list.",
"fields": {
"entity_id": {
"name": "Activities",
"description": "Select the Bring! activities event entity for reacting to its most recent event"
},
"reaction": {
"name": "Reaction",
"description": "Type of reaction to send in response."
}
}
}
},
"selector": {
@@ -11,6 +11,7 @@ DOMAINS_AND_TYPES = {
Platform.SELECT: {"HYS"},
Platform.SENSOR: {
"A1",
"A2",
"MP1S",
"RM4MINI",
"RM4PRO",
@@ -10,6 +10,7 @@ from homeassistant.components.sensor import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
PERCENTAGE,
UnitOfElectricCurrent,
UnitOfElectricPotential,
@@ -34,6 +35,24 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
key="air_quality",
device_class=SensorDeviceClass.AQI,
),
SensorEntityDescription(
key="pm10",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="pm2_5",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="pm1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="humidity",
native_unit_of_measurement=PERCENTAGE,
@@ -25,6 +25,7 @@ def get_update_manager(device: BroadlinkDevice[_ApiT]) -> BroadlinkUpdateManager
"""Return an update manager for a given Broadlink device."""
update_managers: dict[str, type[BroadlinkUpdateManager]] = {
"A1": BroadlinkA1UpdateManager,
"A2": BroadlinkA2UpdateManager,
"BG1": BroadlinkBG1UpdateManager,
"HYS": BroadlinkThermostatUpdateManager,
"LB1": BroadlinkLB1UpdateManager,
@@ -118,6 +119,16 @@ class BroadlinkA1UpdateManager(BroadlinkUpdateManager[blk.a1]):
return await self.device.async_request(self.device.api.check_sensors_raw)
class BroadlinkA2UpdateManager(BroadlinkUpdateManager[blk.a2]):
"""Manages updates for Broadlink A2 devices."""
SCAN_INTERVAL = timedelta(seconds=10)
async def async_fetch_data(self) -> dict[str, Any]:
"""Fetch data from the device."""
return await self.device.async_request(self.device.api.check_sensors_raw)
class BroadlinkMP1UpdateManager(BroadlinkUpdateManager[blk.mp1]):
"""Manages updates for Broadlink MP1 devices."""
@@ -8,7 +8,7 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["brother", "pyasn1", "pysmi", "pysnmp"],
"requirements": ["brother==4.3.1"],
"requirements": ["brother==5.0.0"],
"zeroconf": [
{
"type": "_printer._tcp.local.",
+129 -13
View File
@@ -12,6 +12,7 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNA
from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
from .const import CONF_PASSKEY, DEFAULT_PORT, DOMAIN
@@ -21,12 +22,15 @@ class BSBLANFlowHandler(ConfigFlow, domain=DOMAIN):
VERSION = 1
host: str
port: int
mac: str
passkey: str | None = None
username: str | None = None
password: str | None = None
def __init__(self) -> None:
"""Initialize BSBLan flow."""
self.host: str | None = None
self.port: int = DEFAULT_PORT
self.mac: str | None = None
self.passkey: str | None = None
self.username: str | None = None
self.password: str | None = None
self._auth_required = True
async def async_step_user(
self, user_input: dict[str, Any] | None = None
@@ -41,9 +45,111 @@ class BSBLANFlowHandler(ConfigFlow, domain=DOMAIN):
self.username = user_input.get(CONF_USERNAME)
self.password = user_input.get(CONF_PASSWORD)
return await self._validate_and_create()
async def async_step_zeroconf(
self, discovery_info: ZeroconfServiceInfo
) -> ConfigFlowResult:
"""Handle Zeroconf discovery."""
self.host = str(discovery_info.ip_address)
self.port = discovery_info.port or DEFAULT_PORT
# Get MAC from properties
self.mac = discovery_info.properties.get("mac")
# If MAC was found in zeroconf, use it immediately
if self.mac:
await self.async_set_unique_id(format_mac(self.mac))
self._abort_if_unique_id_configured(
updates={
CONF_HOST: self.host,
CONF_PORT: self.port,
}
)
else:
# MAC not available from zeroconf - check for existing host/port first
self._async_abort_entries_match(
{CONF_HOST: self.host, CONF_PORT: self.port}
)
# Try to get device info without authentication to minimize discovery popup
config = BSBLANConfig(host=self.host, port=self.port)
session = async_get_clientsession(self.hass)
bsblan = BSBLAN(config, session)
try:
device = await bsblan.device()
except BSBLANError:
# Device requires authentication - proceed to discovery confirm
self.mac = None
else:
self.mac = device.MAC
# Got MAC without auth - set unique ID and check for existing device
await self.async_set_unique_id(format_mac(self.mac))
self._abort_if_unique_id_configured(
updates={
CONF_HOST: self.host,
CONF_PORT: self.port,
}
)
# No auth needed, so we can proceed to a confirmation step without fields
self._auth_required = False
# Proceed to get credentials
self.context["title_placeholders"] = {"name": f"BSBLAN {self.host}"}
return await self.async_step_discovery_confirm()
async def async_step_discovery_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle getting credentials for discovered device."""
if user_input is None:
data_schema = vol.Schema(
{
vol.Optional(CONF_PASSKEY): str,
vol.Optional(CONF_USERNAME): str,
vol.Optional(CONF_PASSWORD): str,
}
)
if not self._auth_required:
data_schema = vol.Schema({})
return self.async_show_form(
step_id="discovery_confirm",
data_schema=data_schema,
description_placeholders={"host": str(self.host)},
)
if not self._auth_required:
return self._async_create_entry()
self.passkey = user_input.get(CONF_PASSKEY)
self.username = user_input.get(CONF_USERNAME)
self.password = user_input.get(CONF_PASSWORD)
return await self._validate_and_create(is_discovery=True)
async def _validate_and_create(
self, is_discovery: bool = False
) -> ConfigFlowResult:
"""Validate device connection and create entry."""
try:
await self._get_bsblan_info()
await self._get_bsblan_info(is_discovery=is_discovery)
except BSBLANError:
if is_discovery:
return self.async_show_form(
step_id="discovery_confirm",
data_schema=vol.Schema(
{
vol.Optional(CONF_PASSKEY): str,
vol.Optional(CONF_USERNAME): str,
vol.Optional(CONF_PASSWORD): str,
}
),
errors={"base": "cannot_connect"},
description_placeholders={"host": str(self.host)},
)
return self._show_setup_form({"base": "cannot_connect"})
return self._async_create_entry()
@@ -67,6 +173,7 @@ class BSBLANFlowHandler(ConfigFlow, domain=DOMAIN):
@callback
def _async_create_entry(self) -> ConfigFlowResult:
"""Create the config entry."""
return self.async_create_entry(
title=format_mac(self.mac),
data={
@@ -78,8 +185,10 @@ class BSBLANFlowHandler(ConfigFlow, domain=DOMAIN):
},
)
async def _get_bsblan_info(self, raise_on_progress: bool = True) -> None:
"""Get device information from an BSBLAN device."""
async def _get_bsblan_info(
self, raise_on_progress: bool = True, is_discovery: bool = False
) -> None:
"""Get device information from a BSBLAN device."""
config = BSBLANConfig(
host=self.host,
passkey=self.passkey,
@@ -90,11 +199,18 @@ class BSBLANFlowHandler(ConfigFlow, domain=DOMAIN):
session = async_get_clientsession(self.hass)
bsblan = BSBLAN(config, session)
device = await bsblan.device()
self.mac = device.MAC
retrieved_mac = device.MAC
await self.async_set_unique_id(
format_mac(self.mac), raise_on_progress=raise_on_progress
)
# Handle unique ID assignment based on whether MAC was available from zeroconf
if not self.mac:
# MAC wasn't available from zeroconf, now we have it from API
self.mac = retrieved_mac
await self.async_set_unique_id(
format_mac(self.mac), raise_on_progress=raise_on_progress
)
# Always allow updating host/port for both user and discovery flows
# This ensures connectivity is maintained when devices change IP addresses
self._abort_if_unique_id_configured(
updates={
CONF_HOST: self.host,
@@ -7,5 +7,11 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["bsblan"],
"requirements": ["python-bsblan==2.1.0"]
"requirements": ["python-bsblan==2.1.0"],
"zeroconf": [
{
"type": "_http._tcp.local.",
"name": "bsb-lan*"
}
]
}
@@ -20,6 +20,8 @@ from . import BSBLanConfigEntry, BSBLanData
from .coordinator import BSBLanCoordinatorData
from .entity import BSBLanEntity
PARALLEL_UPDATES = 1
@dataclass(frozen=True, kw_only=True)
class BSBLanSensorEntityDescription(SensorEntityDescription):
+19 -1
View File
@@ -13,7 +13,25 @@
"password": "[%key:common::config_flow::data::password%]"
},
"data_description": {
"host": "The hostname or IP address of your BSB-Lan device."
"host": "The hostname or IP address of your BSB-Lan device.",
"port": "The port number of your BSB-Lan device.",
"passkey": "The passkey for your BSB-Lan device.",
"username": "The username for your BSB-Lan device.",
"password": "The password for your BSB-Lan device."
}
},
"discovery_confirm": {
"title": "BSB-Lan device discovered",
"description": "A BSB-Lan device was discovered at {host}. Please provide credentials if required.",
"data": {
"passkey": "[%key:component::bsblan::config::step::user::data::passkey%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]"
},
"data_description": {
"passkey": "[%key:component::bsblan::config::step::user::data_description::passkey%]",
"username": "[%key:component::bsblan::config::step::user::data_description::username%]",
"password": "[%key:component::bsblan::config::step::user::data_description::password%]"
}
}
},
@@ -45,7 +45,7 @@ class BTHomePassiveBluetoothProcessorCoordinator(
@property
def sleepy_device(self) -> bool:
"""Return True if the device is a sleepy device."""
return self.entry.data.get(CONF_SLEEPY_DEVICE, self.device_data.sleepy_device)
return self.entry.data.get(CONF_SLEEPY_DEVICE, self.device_data.sleepy_device) # type: ignore[no-any-return]
class BTHomePassiveBluetoothDataProcessor[_T](
@@ -70,7 +70,7 @@ def get_event_classes_by_device_id(hass: HomeAssistant, device_id: str) -> list[
bthome_config_entry = next(
entry for entry in config_entries if entry and entry.domain == DOMAIN
)
return bthome_config_entry.data.get(CONF_DISCOVERED_EVENT_CLASSES, [])
return bthome_config_entry.data.get(CONF_DISCOVERED_EVENT_CLASSES, []) # type: ignore[no-any-return]
def get_event_types_by_event_class(event_class: str) -> set[str]:
@@ -107,7 +107,7 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
"""Return the state of the device."""
media_state = self.client.play_state.state
if media_state == "NETWORK":
return MediaPlayerState.STANDBY
return MediaPlayerState.OFF
if self.client.state.power:
if media_state == "play":
return MediaPlayerState.PLAYING

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