Compare commits

...

711 Commits

Author SHA1 Message Date
Franck Nijhof
fe82e7f24d Bump version to 2024.8.0b1 2024-08-02 17:46:01 +02:00
Bram Kragten
433c1a57e7 Update frontend to 20240802.0 (#123072) 2024-08-02 17:45:50 +02:00
Joost Lekkerkerker
b36059fc64 Do not raise repair issue about missing integration in safe mode (#123066) 2024-08-02 17:45:47 +02:00
Philip Vanloo
13c9d69440 Add additional items to REPEAT_MAP in LinkPlay (#123063)
* Upgrade python-linkplay, add items to REPEAT_MAP

* Undo dependency bump
2024-08-02 17:45:43 +02:00
Philip Vanloo
9c7134a865 LinkPlay: Bump python-linkplay to 0.0.6 (#123062)
Bump python-linkplay to 0.0.6
2024-08-02 17:45:39 +02:00
Erik Montnemery
d7cc2a7e9a Correct squeezebox service (#123060) 2024-08-02 17:45:36 +02:00
Fabian
f9276e28b0 Add device class (#123059) 2024-08-02 17:45:32 +02:00
H. Árkosi Róbert
15ad6db1a7 Add LinkPlay models (#123056)
* Add some LinkPlay models

* Update utils.py

* Update utils.py

* Update utils.py

* Update homeassistant/components/linkplay/utils.py

* Update homeassistant/components/linkplay/utils.py

* Update utils.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-08-02 17:45:29 +02:00
Erik Montnemery
c1043ada22 Correct type annotation for EntityPlatform.async_register_entity_service (#123054)
Correct type annotation for EntityPlatform.async_register_entity_service

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
2024-08-02 17:45:26 +02:00
Paulus Schoutsen
d141122008 Ollama implement CONTROL supported feature (#123049) 2024-08-02 17:45:23 +02:00
Paulus Schoutsen
abeba39842 OpenAI make supported features reflect the config entry options (#123047) 2024-08-02 17:45:19 +02:00
Matthias Alphart
bb597a908d Use freezer in KNX tests (#123044)
use freezer in tests
2024-08-02 17:45:16 +02:00
Matthias Alphart
dcae2f35ce Mitigate breaking change for KNX climate schema (#123043) 2024-08-02 17:45:12 +02:00
Matthias Alphart
b06a5af069 Address post-merge reviews for KNX integration (#123038) 2024-08-02 17:45:09 +02:00
J. Nick Koston
a624ada8d6 Fix doorbird models are missing the schedule API (#123033)
* Fix doorbird models are missing the schedule API

fixes #122997

* cover
2024-08-02 17:45:06 +02:00
David F. Mulcahey
d87366b1e7 Make ZHA load quirks earlier (#123027) 2024-08-02 17:45:03 +02:00
Michael Hansen
5ce8a2d974 Standardize assist pipelines on 10ms chunk size (#123024)
* Make chunk size always 10ms

* Fix voip
2024-08-02 17:44:59 +02:00
Robert Resch
a42615add0 Fix and improve tedee lock states (#123022)
Improve tedee lock states
2024-08-02 17:44:56 +02:00
Matrix
ecbff61332 Bump yolink api to 0.4.6 (#123012) 2024-08-02 17:44:53 +02:00
Paulus Schoutsen
e9bfe82582 Make the Android timer notification high priority (#123006) 2024-08-02 17:44:50 +02:00
Ivan Belokobylskiy
55abe68a5f Bump aioymaps to 1.2.5 (#123005)
Bump aiomaps, fix sessionId parsing
2024-08-02 17:44:46 +02:00
amccook
acf523b5fb Fix handling of directory type playlists in Plex (#122990)
Ignore type directory
2024-08-02 17:44:43 +02:00
Matrix
0216455137 Fix yolink protocol changed (#122989) 2024-08-02 17:44:40 +02:00
J. Nick Koston
cb37ae6608 Update doorbird error notification to be a repair flow (#122987) 2024-08-02 17:44:37 +02:00
karwosts
3b462906d9 Restrict nws.get_forecasts_extra selector to nws weather entities (#122986) 2024-08-02 17:44:34 +02:00
Matrix
dfb4e9c159 Yolink device model adaptation (#122824) 2024-08-02 17:44:31 +02:00
karwosts
6a6814af61 Use text/multiple selector for input_select.set_options (#122539) 2024-08-02 17:44:27 +02:00
Denis Shulyaka
1a7085b068 Add aliases to script llm tool description (#122380)
* Add aliases to script llm tool description

* Also add name
2024-08-02 17:44:24 +02:00
Christopher Fenner
804d7aa4c0 Fix translation key for power exchange sensor in ViCare (#122339) 2024-08-02 17:44:21 +02:00
DeerMaximum
1b1d86409c Velux use node id as fallback for unique id (#117508)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-08-02 17:44:18 +02:00
Ryan Mattson
2520fcd284 Lyric: Properly tie room accessories to the data coordinator (#115902)
* properly tie lyric accessories to the data coordinator so sensors recieve updates

* only check for accessories for LCC devices

* revert: meant to give it its own branch and PR
2024-08-02 17:44:13 +02:00
Franck Nijhof
18afe07c16 Bump version to 2024.8.0b0 2024-07-31 22:38:50 +02:00
Michael Hansen
6baee603a5 Bump pymicro-vad to 1.0.1 (#122973) 2024-07-31 22:10:50 +02:00
Simon
5fefa606b6 Add ElevenLabs text-to-speech integration (#115645)
* Add ElevenLabs text-to-speech integration

* Remove commented out code

* Use model_id instead of model_name for elevenlabs api

* Apply suggestions from code review

Co-authored-by: Sid <27780930+autinerd@users.noreply.github.com>

* Use async client instead of sync

* Add ElevenLabs code owner

* Apply suggestions from code review

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

* Set entity title to voice

* Rename to elevenlabs

* Apply suggestions from code review

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

* Allow multiple voices and options flow

* Sort default voice at beginning

* Rework config flow to include default model and reloading on options flow

* Add error to strings

* Add ElevenLabsData and suggestions from code review

* Shorten options and config flow

* Fix comments

* Fix comments

* Add wip

* Fix

* Cleanup

* Bump elevenlabs version

* Add data description

* Fix

---------

Co-authored-by: Sid <27780930+autinerd@users.noreply.github.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
Co-authored-by: Michael Hansen <mike@rhasspy.org>
Co-authored-by: Joostlek <joostlek@outlook.com>
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
2024-07-31 21:31:09 +02:00
Mr. Bubbles
7bc2381a45 Add Pinecil virtual integration supported by IronOS (#122803) 2024-07-31 21:24:15 +02:00
Jack Gaino
2910369647 Optionally return response data when calling services through the API (#115046)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2024-07-31 21:00:04 +02:00
alexfp14
17f34b452e Add HVAC mode support for AtlanticPassAPCHeatPumpMainComponent (heati… (#122175)
Co-authored-by: Mick Vleeshouwer <mick@imick.nl>
2024-07-31 20:52:32 +02:00
epenet
220f686078 Remove invalid type hint and assignment in number (#122906) 2024-07-31 20:51:24 +02:00
epenet
d878d744e7 Fix implicit-return in irish_rail_transport (#122916) 2024-07-31 20:50:31 +02:00
epenet
b31263b747 Fix implicit-return in itunes (#122917) 2024-07-31 20:50:11 +02:00
epenet
4a4209647e Fix implicit-return in humidifier (#122921) 2024-07-31 20:49:40 +02:00
epenet
9860109db9 Fix implicit-return in satel_integra (#122925) 2024-07-31 20:49:19 +02:00
epenet
b8ac86939b Fix implicit-return in smartthings (#122927) 2024-07-31 20:49:06 +02:00
epenet
9023d80d1b Fix implicit-return in twitter (#122931) 2024-07-31 20:48:51 +02:00
epenet
c702ffa7dd Fix implicit-return in uk_transport (#122932) 2024-07-31 20:48:30 +02:00
epenet
be8186126e Fix implicit-return in valve (#122933) 2024-07-31 20:47:48 +02:00
epenet
4fda025106 Fix implicit-return in wsdot (#122935) 2024-07-31 20:47:33 +02:00
J. Nick Koston
c7f863a141 Drop some unnecessary lambdas in powerwall (#122936) 2024-07-31 20:47:19 +02:00
epenet
4aacec2de7 Fix implicit-return in xiaomi (#122938) 2024-07-31 20:46:30 +02:00
epenet
a6aae4e857 Fix implicit-return in xiaomi_miio (#122939) 2024-07-31 20:45:48 +02:00
epenet
dde97a02f0 Fix implicit-return in xiaomi_aqara (#122940) 2024-07-31 20:45:29 +02:00
epenet
d393317eb2 Fix implicit-return in yamaha (#122942) 2024-07-31 20:45:10 +02:00
J. Nick Koston
2f3f124aa1 Drop unnecessary lambdas in the entity filter (#122941) 2024-07-31 20:44:47 +02:00
epenet
79a741486c Fix implicit-return in wyoming (#122946) 2024-07-31 20:42:57 +02:00
epenet
c0fe65fa60 Fix unnecessary-return-none in homematic (#122948) 2024-07-31 20:42:42 +02:00
J. Nick Koston
8de0e4ca7c Remove aiohappyeyeballs license exception (#122969) 2024-07-31 13:42:33 -05:00
epenet
7c179c33b5 Fix unnecessary-return-none in tradfri (#122950) 2024-07-31 20:42:19 +02:00
epenet
177690bcb3 Rename variable in sensor tests (#122954) 2024-07-31 20:42:05 +02:00
epenet
a23b3f84f0 Fix implicit-return in garadget (#122923) 2024-07-31 20:41:44 +02:00
Michael Hansen
d5388452d4 Use finished speaking detection in ESPHome/Wyoming (#122962) 2024-07-31 20:39:03 +02:00
Marcel van der Veldt
8a4206da99 Matter handle FeatureMap update (#122544) 2024-07-31 20:37:57 +02:00
Pete Sage
f1084a57df Fix Sonos media_player control may fail when grouping speakers (#121853) 2024-07-31 20:36:59 +02:00
Marcel van der Veldt
0189a05297 Extend Matter select entity (#122513) 2024-07-31 20:36:43 +02:00
Steven B.
7276b4b3ad Bump python-kasa to 0.7.1 (#122967) 2024-07-31 13:31:53 -05:00
epenet
93bcd413a7 Fix unnecessary-return-none in iotty (#122947) 2024-07-31 20:21:26 +02:00
epenet
bc25657f0a Fix unnecessary-return-none in telnet (#122949) 2024-07-31 20:21:04 +02:00
Steven B.
9db42beade Fix handling of tplink light effects for scenes (#122965)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-31 12:57:12 -05:00
Thomas55555
cc1a6d60c0 Add override for work areas in Husqvarna Automower (#120427)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-07-31 19:28:46 +02:00
G Johansson
a913587eb6 Climate validate temperature(s) out of range (#118649)
* Climate temperature out of range

* Fix test sensibo

* use temp converting for min/max

* Fix

* Fix mqtt tests

* Fix honeywell tests

* Fix Balboa tests

* Fix whirlpool test

* Fix teslemetry test

* Fix plugwise test

* Fix tplink test

* Fix generic thermostat test

* Fix modbus test

* Fix fritzbox tests

* Honewell
2024-07-31 19:17:53 +02:00
Louis Christ
ae9e8ca419 Simplify async_setup_entry in bluesound integration (#122874)
* Use async_added_to_hass and async_will_remove_from_hass

* Remove self._hass
2024-07-31 19:04:17 +02:00
epenet
69a8c5dc9f Fix implicit-return in hddtemp (#122919) 2024-07-31 18:44:36 +02:00
epenet
3f091470fd Use pytest.mark.usefixtures in risco tests (#122955) 2024-07-31 18:28:35 +02:00
Marcel van der Veldt
c888908cc8 Add default warning for installing matter device updates (#122597) 2024-07-31 18:23:40 +02:00
J. Nick Koston
172e2125f6 Switch to using update for headers middleware (#122952) 2024-07-31 18:17:45 +02:00
Michael
69f54656c4 Fix cleanup of orphan device entries in AVM Fritz!Box Tools (#122937)
* fix cleanup of orphan device entries

* add test for cleanup button
2024-07-31 17:58:11 +02:00
Bram Kragten
c359d4a419 Update frontend to 20240731.0 (#122956) 2024-07-31 17:53:52 +02:00
epenet
a1b8545568 Fix unnecessary-return-none in nest (#122951) 2024-07-31 17:13:53 +02:00
starkillerOG
8c0d9a1320 Add Reolink chime support (#122752) 2024-07-31 17:04:09 +02:00
Christopher Fenner
f764705629 Add support for ventilation device to ViCare (#114175)
* add ventilation program & mode

* add ventilation device

* Update climate.py

* Update climate.py

* Update climate.py

* Update climate.py

* Update climate.py

* Update const.py

* Create fan.py

* Update fan.py

* Update types.py

* add test case

* add translation key

* use translation key

* update snapshot

* fix ruff findings

* fix ruff findings

* add log messages to setter

* adjust test case

* reset climate entity

* do not display speed if not in permanent mode

* update snapshot

* update test cases

* add comment

* mark fan as always on

* prevent turning off device

* allow to set permanent mode

* make speed_count static

* add debug outputs

* add preset state translations

* allow permanent mode

* update snapshot

* add test case

* load programs only on init

* comment on ventilation modes

* adjust test cases

* add exception message

* ignore test coverage on fan.py

* Update test_fan.py

* simplify

* Apply suggestions from code review

* remove tests

* remove extra state attributes

* fix leftover

* add missing labels

* adjust label

* change state keys

* use _attr_preset_modes

* fix ruff findings

* fix attribute access

* fix from_ha_mode

* fix ruff findings

* fix mypy findings

* simplify

* format

* fix typo

* fix ruff finding

* Apply suggestions from code review

* change fan mode handling

* add test cases

* remove turn_off

* Apply suggestions from code review

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

* Apply suggestions from code review

* Update fan.py

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2024-07-31 16:23:27 +02:00
karwosts
3df78043c0 Add enable_millisecond to duration selector (#122821)
* Add enable_milliseconds to duration selector.

* One more test
2024-07-31 16:13:05 +02:00
epenet
97de1c2b66 Fix implicit-return in recorder (#122924) 2024-07-31 15:46:13 +02:00
Michael
f7f0f49015 Move lifespan attributes into own sensors for legacy Ecovacs bots (#122740)
* move available property to base entity class

* add lifespan sensors

* apply suggestion, simplify the method

* don't touch internals in tests

* apply suggestion

* apply suggestions
2024-07-31 15:36:57 +02:00
J. Nick Koston
a35fa0e95a Warn that the minimum SQLite version will change to 3.40.1 as of 2025.2 (#104298)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-07-31 08:13:04 -05:00
Kevin Stillhammer
cddb3bb668 Add reconfigure step for here_travel_time (#114667)
* Add reconfigure step for here_travel_time

* Add comments, reuse step_user, TYPE_CHECKING, remove defaults
2024-07-31 15:08:25 +02:00
epenet
e64e3c2778 Fix implicit-return in time_date (#122929) 2024-07-31 15:00:53 +02:00
epenet
5e1cca1c58 Fix implicit-return in shelly (#122926) 2024-07-31 14:54:52 +02:00
epenet
2f181cbe41 Fix implicit-return in vera (#122934) 2024-07-31 14:53:05 +02:00
epenet
e706ff0564 Fix implicit-return in transport_nsw (#122930) 2024-07-31 14:44:14 +02:00
Allen Porter
8d0e998e54 Improve conversation agent tracing to help with eval and data collection (#122542) 2024-07-31 14:38:44 +02:00
Allen Porter
4f5eab4646 Improve quality of ollama tool calling by repairing arguments (#122749)
* Improve quality of ollama function calling by repairing function call arguments

* Fix formatting of the tests

* Run ruff format on ollama conversation

* Add test for non-string arguments
2024-07-31 14:37:39 +02:00
Franck Nijhof
8b96c7873f Rename 'service' to 'action' in automations and scripts (#122845) 2024-07-31 14:36:53 +02:00
Allen Porter
f14471112d Improve LLM tool quality by more clearly specifying device_class slots (#122723)
* Limit intent / llm API device_class slots to only necessary services and limited set of values

* Fix ruff errors

* Run ruff format

* Fix typing and improve output schema

* Fix schema and improve flattening

* Revert conftest

* Revert recorder

* Fix ruff format errors

* Update using latest version of voluptuous
2024-07-31 14:36:02 +02:00
epenet
7c7b408df1 Fix implicit-return in homekit_controller (#122920) 2024-07-31 14:21:58 +02:00
epenet
3bf00822b0 Fix implicit-return in kodi (#122914) 2024-07-31 13:42:07 +02:00
Yuxin Wang
bf3a2cf393 Add graceful handling for LASTSTEST sensor in APCUPSD (#113125)
* Add handling for LASTSTEST sensor

* Set the state to unknown instead of unavailable

* Use LASTSTEST constant and revise the logic to add it to the entity list

* Use LASTSTEST constant
2024-07-31 13:01:48 +02:00
Maikel Punie
c8dccec956 Bump velbusaio to 2024.07.06 (#122905)
bumpo velbusaio to 2024.07.06
2024-07-31 12:48:08 +02:00
epenet
ed9c4e0c0d Fix implicit-return in landisgyr_heat_meter (#122912) 2024-07-31 12:41:10 +02:00
epenet
cd552ceb2b Fix implicit-return in mystrom (#122911) 2024-07-31 12:40:48 +02:00
epenet
c4398efbbb Fix implicit-return in meteo_france (#122910) 2024-07-31 12:40:30 +02:00
epenet
8b1a527602 Fix implicit-return in meraki (#122909) 2024-07-31 12:39:59 +02:00
epenet
01f41a597e Fix implicit-return in melissa (#122908) 2024-07-31 12:39:39 +02:00
epenet
c32f1efad0 Fix implicit-return in maxcube (#122907) 2024-07-31 12:39:21 +02:00
epenet
47c96c52b1 Fix implicit-return in niko_home_control (#122904) 2024-07-31 12:39:01 +02:00
epenet
dbdb148e12 Fix implicit-return in plaato (#122902) 2024-07-31 12:38:36 +02:00
epenet
6a45124878 Fix implicit-return in qnap (#122901) 2024-07-31 12:38:15 +02:00
Diogo Gomes
02d4d1a75b Adds new sensors and configuration entities to V2C Trydan (#122883)
* Adds new controls and sensors

* update snapshot

* Update homeassistant/components/v2c/strings.json

Co-authored-by: Charles Garwood <cgarwood@newdealmultimedia.com>

* Add unit

* move icons to icons.json

* update snapshot

* missing translation fix

---------

Co-authored-by: Charles Garwood <cgarwood@newdealmultimedia.com>
2024-07-31 12:31:35 +02:00
Alex MF
233c04a469 Add number entity for Ecovacs mower cut direction (#122598) 2024-07-31 12:22:07 +02:00
epenet
8b4f607806 Fix implicit-return in plant (#122903) 2024-07-31 11:39:51 +02:00
Diogo Gomes
68f06e63e2 Bump pytrydan to 0.8.0 (#122898)
bump pytrydan to 0.8.0
2024-07-31 10:32:13 +01:00
Matthias Alphart
67ed8b207a KNX: use xknx 3.0.0 eager telegram decoding (#122896)
* Use KNX xknx 3.0.0 eager telegram decoding

* review suggestion
2024-07-31 11:08:05 +02:00
Erik Montnemery
222011fc5c Log tests in test group (#122892)
* Log tests in test group

* Simplify print
2024-07-31 10:36:46 +02:00
Erik Montnemery
f6f7459c36 Add support for login credentials to homeworks (#122877)
* Add support for login credentials to homeworks

* Store credentials in config entry data
2024-07-31 10:35:05 +02:00
Franck Nijhof
718bc61c88 Merge branch 'master' into dev 2024-07-31 10:31:28 +02:00
Paarth Shah
015a1a6ebc Fix blocking event loop call in matrix (#122730)
Wrap load_json_object in async_add_executor_job
2024-07-31 09:45:30 +02:00
Paarth Shah
e0a1aaa1b9 Fix matrix blocking call by running sync_forever in background_task (#122800)
Fix blocking call by running sync_forever in background_task
2024-07-31 09:44:59 +02:00
Michael Hansen
7f4dabf546 Switch from WebRTC to microVAD (#122861)
* Switch WebRTC to microVAD

* Remove webrtc-noise-gain from licenses
2024-07-31 09:42:45 +02:00
Denis Shulyaka
beb2ef121e Update todo intent slot schema (#122335)
* Update todo intent slot schema

* Update intent.py

* ruff
2024-07-31 09:37:55 +02:00
Denis Shulyaka
5a04d982d9 Bump ollama to 0.3.1 (#122866) 2024-07-31 09:35:45 +02:00
David Bonnes
35bfd0b88f Evohome drops use of async_call_later to avoid lingering task (#122879)
initial commit
2024-07-31 09:35:21 +02:00
Matthias Alphart
9351f300b0 Update xknx to 3.0.0 - more DPT definitions (#122891)
* Support DPTComplex objects and validate sensor types

* Gracefully start and stop xknx device objects

* Use non-awaitable XknxDevice callbacks

* Use non-awaitable xknx.TelegramQueue callbacks

* Use non-awaitable xknx.ConnectionManager callbacks

* Remove unnecessary `hass.async_block_till_done()` calls

* Wait for StateUpdater logic to proceed when receiving responses

* Update import module paths for specific DPTs

* Support Enum data types

* New HVAC mode names

* HVAC Enums instead of Enum member value strings

* New date and time devices

* Update xknx to 3.0.0

* Fix expose tests and DPTEnumData check

* ruff and mypy fixes
2024-07-31 09:10:36 +02:00
Thomas55555
0d678120e4 Bump aioautomower to 2024.7.3 (#121983)
* Bump aioautomower to 2024.7.0

* tests

* Bump to 2024.7.1

* bump to 2024.7.2

* use timezone Europe/Berlin

* bump to 2024.7.3

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2024-07-31 08:28:39 +02:00
Lukas Kolletzki
5766ea9541 Add generic URL handler to blueprint importer (#110576)
* Add generic url handler to blueprint importer

* Update tests/components/blueprint/test_importer.py

* Update tests/components/blueprint/test_importer.py

* Update test_importer.py

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2024-07-31 08:26:57 +02:00
Erik Montnemery
6d8bc84db3 Allow [##:##:##:##:##] type device address in homeworks (#122872)
* Allow [##:##:##:##:##] type device address in homeworks

* Simplify regex
2024-07-31 08:02:15 +02:00
J. Nick Koston
823910b69e Bump ulid-transform to 0.13.1 (#122884)
* Bump ulid-transform to 0.13.0

changelog: https://github.com/bdraco/ulid-transform/compare/v0.10.1...v0.13.0

* Bump ulid-transform to 0.13.1
2024-07-31 07:20:09 +02:00
J. Nick Koston
aa801d9cc6 Bump bluetooth-data-tools to 1.19.4 (#122886) 2024-07-30 18:20:55 -05:00
Jeef
067acce4de Add SimpleFin sensor to show age of data (#122550) 2024-07-30 23:42:10 +02:00
J. Nick Koston
6999c6b0cf Bump aiohttp to 3.10.0 (#122880) 2024-07-30 16:40:38 -05:00
Michael Hansen
da18aae2d8 Bump intents to 2024.7.29 (#122811) 2024-07-30 15:27:16 -05:00
Erik Montnemery
6362ca1052 Bump pyhomeworks to 1.1.0 (#122870) 2024-07-30 21:52:25 +02:00
Bill Flood
022e1b0c02 Add other medium types to Mopeka sensor (#122705)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-30 14:07:12 -05:00
Erik Montnemery
94c0b9fc06 Bump pyhomeworks to 1.0.0 (#122867) 2024-07-30 19:39:53 +02:00
Robert Svensson
5eff4f9816 Unifi improve fixture typing (#122864)
* Improve typing of UniFi fixtures

* Improve fixture typing, excluding image, sensor, switch

* Improve fixture typing in image tests

* Improve fixtures typing in sensor tests

* Improve fixture typing in switch tests

* Fix review comment
2024-07-30 19:33:25 +02:00
Erik Montnemery
fb229fcae8 Improve test coverage of the homeworks integration (#122865)
* Improve test coverage of the homeworks integration

* Revert changes from the future

* Revert changes from the future
2024-07-30 18:40:36 +02:00
Mr. Bubbles
50b35ac4bc Add number platform to IronOS integration (#122801)
* Add setpoint temperature number entity to IronOS integration

* Add tests for number platform

* Initialize settings in coordinator

* Remove unused code
2024-07-30 18:14:01 +02:00
Simon Hörrle
ea727546d6 Add apsystems power switch (#122447)
* bring back power switch

* fix pylint issues

* add SWITCH to platform list

* improve run_on and turn_off functions

* ruff formatting

* replace _state with _attr_is_on

* Update homeassistant/components/apsystems/switch.py

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

* remove unused dependencies

* Update homeassistant/components/apsystems/switch.py

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

* use async functions from api

* convert Api IntEnum Status Information to bool

* add translation key

* implement async_update again

* replace finally with else

* better handling of bool value

* Update homeassistant/components/apsystems/switch.py

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

* Update homeassistant/components/apsystems/switch.py

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

* rename power switch to inverter switch

* add test_number and test_switch module

* remove test_number

* Add mock entry for get_device_power_status

* Add mock entry for get_device_power_status

* Update test snapshots

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-30 18:11:08 +02:00
bdowden
18a7d15d14 Add Traffic Rule switches to UniFi Network (#118821)
* Add Traffic Rule switches to UniFi Network

* Retrieve Fix unifi traffic rule switches

Poll for traffic rule updates; have immediate feedback in the UI for modifying traffic rules

* Remove default values for unifi entity; Remove unnecessary code

* Begin updating traffic rule unit tests

* For the mock get request, allow for meta and data properties to not be appended to support v2 api requests

Fix traffic rule unit tests;

* inspect path to determine json response instead of passing an argument

* Remove entity id parameter from tests; remove unused code; rename traffic rule unique ID prefix

* Remove parameter with default.

* More code removal;

* Rename copy/paste variable; remove commented code; remove duplicate default code

---------

Co-authored-by: ViViDboarder <ViViDboarder@gmail.com>
2024-07-30 17:26:08 +02:00
Denis Shulyaka
be24475cee Update selector converters for llm script tools (#122830) 2024-07-30 08:24:03 -07:00
epenet
8066c7dec6 Fix implicit-return in deconz (#122836) 2024-07-30 17:21:45 +02:00
Kim de Vos
896cd27bea Add sensors for Unifi latency (#116737)
* Add sensors for Unifi latency

* Add needed guard and casting

* Use new types

* Add WAN2 support

* Add literals

* Make ids for WAN and WAN2 unique

* Make methods general

* Update sensor.py

* add more typing

* Simplify usage make_wan_latency_sensors

* Simplify further

* Move latency entity creation to method

* Make method internal

* simplify tests

* Apply feedback

* Reduce boiler copied code and add support function

* Add external method for share logic between

* Remove none

* Add more tests

* Apply feedback and change code to improve code coverage
2024-07-30 17:20:56 +02:00
David Bonnes
1ffde403f0 Ensure evohome leaves no lingering timers (#122860) 2024-07-30 17:18:33 +02:00
Guido Schmitz
b69b927795 Set parallel updates in devolo_home_network (#122847) 2024-07-30 17:17:20 +02:00
Erik Montnemery
6840f27bc6 Verify respx mock routes are cleaned up when tests finish (#122852) 2024-07-30 17:12:58 +02:00
epenet
4a34855a92 Fix implicit-return in scripts (#122831) 2024-07-30 16:57:42 +02:00
Joakim Plate
b3f7f379df Upgrade dsmr-parser to 1.4.2 (#121929) 2024-07-30 16:51:02 +02:00
Marius
4994e46ad0 Add mdi:alert-circle-outline to degrade status (#122859) 2024-07-30 16:44:04 +02:00
Erik Montnemery
1382f7a3dc Fix generic IP camera tests affecting other tests (#122858) 2024-07-30 16:29:59 +02:00
Erik Montnemery
b973455037 Fix template image test affecting other tests (#122849) 2024-07-30 16:28:55 +02:00
Thomas55555
a5136a1021 Speed up slow tests in Husqvarna Automower (#122854) 2024-07-30 16:27:58 +02:00
Erik Montnemery
d9e996def5 Fix template binary sensor test (#122855) 2024-07-30 16:18:47 +02:00
Erik Montnemery
224228e448 Fix Axis tests affecting other tests (#122857) 2024-07-30 16:16:33 +02:00
epenet
c8372a3aa5 Fix implicit-return in ecobee (#122832) 2024-07-30 15:33:57 +02:00
epenet
2135691b90 Fix implicit-return in dublin bus transport (#122833) 2024-07-30 15:33:05 +02:00
epenet
ea508b2629 Fix implicit-return in dialogflow (#122834) 2024-07-30 15:32:29 +02:00
epenet
09cd79772f Fix implicit-return in airtouch4 (#122839) 2024-07-30 15:29:53 +02:00
epenet
7b5db6521c Fix implicit-return in advantage_air (#122840) 2024-07-30 15:29:23 +02:00
epenet
27eba3cd46 Fix implicit-return in fixer (#122841) 2024-07-30 15:24:35 +02:00
epenet
41c7414d97 Fix implicit-return in forked_daapd (#122842) 2024-07-30 15:23:53 +02:00
epenet
fd7c92879c Fix implicit-return in foursquare (#122843) 2024-07-30 15:23:04 +02:00
Sébastien Clément
e7971f5a67 Fix qbittorent current_status key in strings.json (#122848) 2024-07-30 15:03:36 +02:00
epenet
72f9d85bbe Fix implicit-return in whirlpool tests (#122775) 2024-07-30 14:57:43 +02:00
Matthias Alphart
956cc6a85c Add UI to create KNX switch and light entities (#122630)
Update KNX frontend to 2024.7.25.204106
2024-07-30 13:54:44 +02:00
epenet
015c50bbdb Fix implicit-return in ddwrt (#122837) 2024-07-30 14:44:11 +03:00
epenet
b6f0893c33 Fix implicit-return in denon (#122835) 2024-07-30 13:05:38 +02:00
Luke Wale
7c92287f97 Add Airtouch5 cover tests (#122769)
add airtouch5 cover tests
2024-07-30 12:34:49 +02:00
Kristof Mariën
53a59412bb Add Foscam sleep switch (#109491)
* Add sleep switch

* Replace awake with sleep switch
2024-07-30 11:34:30 +02:00
Sébastien Clément
d78acd480a Add QBittorent switch to control alternative speed (#107637)
* Fix key in strings.json for current_status in QBittorrent

* Add switch on QBittorent to control alternative speed

* Add switch file to .coveragerc

* Fix some typo

* Use coordinator for switch

* Update to mach new lib

* Import annotation

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

* Remove quoted coordinator

* Revert "Fix key in strings.json for current_status in QBittorrent"

This reverts commit 962fd0474f.

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
2024-07-30 11:23:55 +02:00
Franck Nijhof
17930a6d66 2024.7.4 (#122770) 2024-07-30 11:12:45 +02:00
Bruno Pantaleão Gonçalves
d825ac346e Add 'use_custom_colors' to iOS Action configuration (#122767) 2024-07-30 11:00:08 +02:00
Denis Shulyaka
fa53055485 Bump voluptuous-openapi (#122828) 2024-07-30 10:57:56 +02:00
epenet
b4cba01870 Fix implicit-return in command_line (#122838) 2024-07-30 10:17:01 +02:00
Robert Svensson
70e368a57e Use snapshot in Axis switch tests (#122680) 2024-07-30 07:14:56 +02:00
David F. Mulcahey
004eccec89 Fix supported_features for ZHA fans (#122813) 2024-07-30 02:10:02 +02:00
David F. Mulcahey
36c01042c1 Enhance ZHA device removal (#122815) 2024-07-30 02:08:21 +02:00
David F. Mulcahey
bd3f0da385 Bump ZHA lib to 0.0.24 and universal-silabs-flasher to 0.0.22 (#122812)
* Bump ZHA lib to 0.0.24

* update for node state change for coordinator data

* bump flasher
2024-07-29 18:16:54 -04:00
Louis Christ
9450744b3b Add device _info to bluesound integration (#122795)
* Add device_info

* Use _attr_unique_id instead of custom methode

* Use different DeviceInfo if port is not DEFAULT_PORT

* Remove name method; Add has_entity_name=True

* Remove self._name completely

* move _attr_has_entity_name and _attr_name out of __init__

* log error if status update fails

* use error for remaining info logs
2024-07-29 23:11:51 +02:00
J. Nick Koston
1c03c83c0a Fix blocking stat() via is_file in image_upload (#122808) 2024-07-29 22:38:58 +02:00
epenet
fdab23c3f9 Fix implicit-return in test schema extractions (#122787) 2024-07-29 22:16:00 +02:00
epenet
7b08e625b4 Fix implicit-return in websocket_api tests (#122779) 2024-07-29 22:14:41 +02:00
epenet
2102a104d2 Adjust DOMAIN imports in homeassistant integration (#122774) 2024-07-29 22:14:05 +02:00
J. Nick Koston
3e1aee4cbc Remove unused constant in august (#122804) 2024-07-29 15:13:39 -05:00
Milan Meulemans
b5b01d97f1 Add support for ASIN Pool devices to ASEKO (#122773) 2024-07-29 22:12:34 +02:00
epenet
02581bbf02 Enforce HOMEASSISTANT_DOMAIN alias for core DOMAIN (#122763) 2024-07-29 22:10:44 +02:00
epenet
4ac85829c8 Fix implicit-return in season tests (#122784) 2024-07-29 22:09:40 +02:00
Robert Resch
ad50136dbd Add created_at/modified_at to config entries (#122456) 2024-07-29 22:08:46 +02:00
Markus Jacobsen
20c4f84a4e Fix incorrect Bang & Olufsen MDNS announcements (#122782) 2024-07-29 22:04:54 +02:00
epenet
bf38db0035 Fix implicit-return in surepetcare tests (#122785) 2024-07-29 22:03:44 +02:00
epenet
b8c363a82c Fix implicit-return in tplink_omada tests (#122776) 2024-07-29 22:03:14 +02:00
epenet
9393dcddb7 Fix implicit-return in nx584 tests (#122788) 2024-07-29 21:59:59 +02:00
epenet
5b434ee336 Fix implicit-return in xiaomi tests (#122778) 2024-07-29 21:58:03 +02:00
epenet
6ba6334512 Fix implicit-return in enigma2 tests (#122790) 2024-07-29 21:57:35 +02:00
J. Nick Koston
8de7a2e3c7 Bump aiohttp to 3.10.0rc0 (#122793) 2024-07-29 21:55:22 +02:00
epenet
197ac8b950 Fix implicit-return in netatmo tests (#122789) 2024-07-29 21:53:22 +02:00
epenet
1958a149c3 Fix implicit-return in ipma tests (#122791) 2024-07-29 21:52:47 +02:00
epenet
7bbbda8d2b Fix implicit-return in sonos tests (#122780) 2024-07-29 21:52:15 +02:00
epenet
5d87a74c3c Fix implicit-return in unifiprotect tests (#122781) 2024-07-29 21:50:45 +02:00
puddly
1f488b00f8 Abstract SkyConnect firmware config flow to the hardware platform (#122140)
* Move the SkyConnect config flow to hardware;

* Clean up

* Get SkyConnect unit tests passing

* Split apart `test_util.py`

* Migrate `test_config_flow`

* Remove unnecessary constants

* Re-apply `contextmanager` typing from #122250

* Move the SkyConnect translation strings into hardware
2024-07-29 12:39:25 -04:00
epenet
570725293c Fix implicit-return in arcam_fmj tests (#122792) 2024-07-29 17:13:31 +02:00
Christian Neumeier
732b9e47c8 Add missing variable 'energy_today' to Zeversolar diagnostics. (#122786)
added var 'energy_today' to zeversolar diagnostics.
2024-07-29 16:48:58 +02:00
Erik Montnemery
ea75c8864f Remove support for live schema migration of old recorder databases (#122399)
* Remove support for live schema migration of old recorder databases

* Update test
2024-07-29 15:52:18 +02:00
epenet
9514a38320 Fix implicit-return rule in zha tests (#122772) 2024-07-29 15:22:08 +02:00
Bram Kragten
d94e79d57a Add Macedonian language (#122768) 2024-07-29 14:49:34 +02:00
Franck Nijhof
02c592d6af Bump version to 2024.7.4 2024-07-29 14:40:02 +02:00
J. Nick Koston
d51d584aed Retry later on OSError during apple_tv entry setup (#122747) 2024-07-29 14:39:27 +02:00
G Johansson
e5fd9819da Return unknown when data is missing in Trafikverket Weather (#122652)
Return unknown when data is missing
2024-07-29 14:23:09 +02:00
Marcel van der Veldt
00c3b0d888 Bump aiohue to version 4.7.2 (#122651) 2024-07-29 14:23:06 +02:00
Robert Resch
aa44c54a19 Bump deebot-client to 8.2.0 (#122612) 2024-07-29 14:23:02 +02:00
Avi Miller
9940d0281b Bump aiolifx to 1.0.6 (#122569) 2024-07-29 13:48:19 +02:00
Andrew Jackson
586a0b12ab Fix target service attribute on Mastodon integration (#122546)
* Fix target

* Fix
2024-07-29 13:48:16 +02:00
Marcel van der Veldt
75f0384a15 Fix typo in Matter lock platform (#122536) 2024-07-29 13:48:13 +02:00
Denis Shulyaka
56f51d3e35 Fix gemini api format conversion (#122403)
* Fix gemini api format conversion

* add tests

* fix tests

* fix tests

* fix coverage
2024-07-29 13:48:10 +02:00
starkillerOG
7135a919e3 Bump reolink-aio to 0.9.5 (#122366) 2024-07-29 13:48:06 +02:00
Denis Shulyaka
9d6bd359c4 Ensure script llm tool name does not start with a digit (#122349)
* Ensure script tool name does not start with a digit

* Fix test name
2024-07-29 13:48:03 +02:00
Denis Shulyaka
f739644735 Goofle Generative AI: Fix string format (#122348)
* Ignore format for string tool args

* Add tests
2024-07-29 13:48:00 +02:00
Christopher Fenner
b63bc72450 Fix device class on sensor in ViCare (#122334)
update device class on init
2024-07-29 13:47:57 +02:00
Alexander Schneider
683069cb98 Add Z-Wave discovery schema for ZVIDAR roller shades (#122332)
Add discovery schema for ZVIDAR roller shades
2024-07-29 13:47:53 +02:00
Jan Bouwhuis
cf20e67f1f Ensure mqtt subscriptions are in a set (#122201) 2024-07-29 13:47:50 +02:00
Maciej Bieniek
74d10b9824 Bump aiotractive to 0.6.0 (#121155)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-29 13:47:46 +02:00
Mick Vleeshouwer
61d4bc1430 Fix device class of water consumption sensor in Overkiz (#122766)
Fixes #118959
2024-07-29 13:38:58 +02:00
epenet
07c7bb8b2a Use HOMEASSISTANT_DOMAIN alias for core DOMAIN (#122760) 2024-07-29 13:35:36 +02:00
epenet
9ce7779bde Use correct constant in rest tests (#122765) 2024-07-29 12:59:57 +02:00
epenet
9e10126505 Revert "Small refactor to cleanup unnecessary returns (#121653)" (#122756) 2024-07-29 12:59:25 +02:00
Pete Sage
cfef72ae57 Add Sonos tests for media_player volume (#122283) 2024-07-29 12:56:26 +02:00
Andrew Jackson
86bfc7ada8 Remove UE Smart Radio integration (#122578) 2024-07-29 12:52:37 +02:00
Rami Mosleh
0de75aeee1 Wait for initial scan to finish before setting up platforms (#122360) 2024-07-29 12:52:01 +02:00
epenet
075550b7ba Use HOMEASSISTANT_DOMAIN alias for core DOMAIN in tests (#122762) 2024-07-29 12:51:12 +02:00
Allen Porter
e5bb1b2cc6 Update LLM prompt to improve quality for local LLMs (#122746) 2024-07-29 12:04:23 +02:00
Marcel van der Veldt
85aca4f095 Fix default turn_on without explicit preset or percentage in Matter Fan platform (#122591) 2024-07-29 12:03:40 +02:00
Richard Kroegel
745eea9a29 Bump bimmer_connected to 0.16.1 (#122699)
Co-authored-by: Richard <rikroe@users.noreply.github.com>
2024-07-29 12:02:47 +02:00
J. Nick Koston
d586e7df33 Retry later on OSError during apple_tv entry setup (#122747) 2024-07-29 11:59:31 +02:00
Marcel van der Veldt
6d4711ce43 Bump aiohue to version 4.7.2 (#122651) 2024-07-29 11:59:13 +02:00
Erik Montnemery
8a84addc54 Add test of recorder platform with statistics support (#122754)
* Add test of recorder platform with statistics support

* Remove excessive line breaks
2024-07-29 11:57:53 +02:00
J. Nick Koston
1879db9f8f Revert to using call_soon for event triggers and state changed event trackers (#122735) 2024-07-29 11:45:39 +02:00
Alexey ALERT Rubashёff
869ec3f670 Bump pyOverkiz to 1.13.14 (#122691) 2024-07-29 11:44:28 +02:00
Mr. Bubbles
70df4ca461 Integration for IronOS (Pinecil V2) soldering irons (#120802)
* Add Pinecil integration

* Refactor with new library

* Add tests for config flow, remove unused code

* requested changes

* update requirements

* Move some sensor values to diagnostics, add tests for sensors

* User service uuid in discovery

* fix manufacturer name

* Bump pynecil to version 0.2.0

* Rename integration to IronOS

* Recreate snapshot

* Update strings

* type checking

* Update snapshot

* Add async_setup to coordinator

* Show device id with serial number

* Added missing boost to operation mode states

* remove super call

* Refactor

* tests
2024-07-29 11:44:01 +02:00
Robert Svensson
06ee8fdd47 Do not use get_hub in deCONZ tests (#122706) 2024-07-29 11:43:04 +02:00
Erik Montnemery
5467685bd8 Adjust warning message when recorder is doing offline migration (#122509)
* Adjust warning message when recorder is doing offline migration

* Address review comments
2024-07-29 11:38:36 +02:00
Erik Montnemery
efaf75f2e6 Rename recorder INTEGRATION_PLATFORMS_RUN_IN_RECORDER_THREAD (#122758) 2024-07-29 11:38:21 +02:00
J. Nick Koston
ca430f0e7b Add coverage for fixing missing params in the doorbird schedule (#122745) 2024-07-29 11:36:44 +02:00
danielsmyers
fa61ad072d Add Bryant Evolution Integration (#119788)
* Add an integration for Bryant Evolution HVAC systems.

* Update newly created tests so that they pass.

* Improve compliance with home assistant guidelines.

* Added tests

* remove xxx

* Minor test cleanups

* Add a test for reading HVAC actions.

* Update homeassistant/components/bryant_evolution/__init__.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/config_flow.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Address reviewer comments.

* Address additional reviewer comments.

* Use translation for exception error messages.

* Simplify config flow.

* Continue addressing comments

* Use mocking rather than DI to provide a for-test client in tests.

* Fix a failure in test_config_flow.py

* Track host->filename in strings.json.

* Use config entry ID for climate entity unique id

* Guard against fan mode returning None in async_update.

* Move unavailable-client check from climate.py to init.py.

* Improve test coverage

* Bump evolutionhttp version

* Address comments

* update comment

* only have one _can_reach_device fn

* Auto-detect which systems and zones are attached.

* Add support for reconfiguration

* Fix a few review comments

* Introduce multiple devices

* Track evolutionhttp library change that returns additional per-zone information during enumeration

* Move construction of devices to init

* Avoid triplicate writing

* rework tests to use mocks

* Correct attribute name to unbreak test

* Pull magic tuple of system-zone into a constant

* Address some test comments

* Create test_init.py

* simplify test_reconfigure

* Replace disable_auto_entity_update with mocks.

* Update tests/components/bryant_evolution/test_climate.py

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

* Update tests/components/bryant_evolution/test_climate.py

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

* Update tests/components/bryant_evolution/test_config_flow.py

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

* Update homeassistant/components/bryant_evolution/config_flow.py

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

* Update tests/components/bryant_evolution/test_config_flow.py

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

* Update tests/components/bryant_evolution/test_config_flow.py

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

* fix test errors

* do not access runtime_data in tests

* use snapshot_platform and type fixtures

---------

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-29 11:25:04 +02:00
Michael
686598b6b3 Don't block HA startup while set up legacy Ecovacs bot (#122732)
wait for connection in background
2024-07-29 11:24:14 +02:00
Erik Montnemery
5f5dcec0b9 Revert unneeded type annotation in the api integration (#122757) 2024-07-29 10:57:49 +02:00
Erik Montnemery
2a5cb8da32 Fix copy-paste errors in alarm_control_panel tests (#122755) 2024-07-29 10:57:34 +02:00
Erik Montnemery
9b497aebb4 Fix bug in timeout util related to multiple global freezes (#122466) 2024-07-29 10:12:18 +02:00
dependabot[bot]
5f08883227 Bump github/codeql-action from 3.25.14 to 3.25.15 (#122753)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 09:58:15 +02:00
Denis Shulyaka
4b2073ca59 Add LLM tools support for Ollama (#120454)
* Add LLM tools support for Ollama

* fix tests

* coverage

* Separate call for tool parameters

* Fix example

* hint on parameters schema if LLM forgot to request it

* Switch to native tool call functionality

* Fix tests

* Fix tools list

* update strings and default model

* Ignore mypy error until fixed upstream

* Ignore mypy error until fixed upstream

* Add missing prompt part

* Update default model
2024-07-28 18:19:53 -07:00
Louis Christ
f98487ef18 Add config_flow to bluesound integration (#115207)
* Add config flow to bluesound

* update init

* abort flow if connection is not possible

* add to codeowners

* update unique id

* add async_unload_entry

* add import flow

* add device_info

* add zeroconf

* fix errors

* formatting

* use bluos specific zeroconf service type

* implement requested changes

* implement requested changes

* fix test; add more tests

* use AsyncMock assert functions

* fix potential naming collision

* move setup_services back to media_player.py

* implement requested changes

* add port to zeroconf flow

* Fix comments

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2024-07-28 20:48:20 +02:00
starkillerOG
dff964582b Bump reolink-aio to 0.9.6 (#122738) 2024-07-28 19:47:37 +02:00
Arie Catsman
e5c36c8d56 Refactor asserts in enphase_envoy test_sensor (#122726)
refactor asserts in enphase_envoy test_sensor
2024-07-28 16:36:36 +02:00
Michael
d765b92cca Unsubscribe event listeners on remove of Ecovacs legacy bot entities (#122731)
* unsubscribe on entity remove, create base EcovacsLegacyEntity

* fix name and model in device info

* apply suggestion

* add manufacturer to device info

* fix device info
2024-07-28 15:01:34 +02:00
J. Nick Koston
ba266ab13c Add coverage for calling doorbird webhook with the wrong token (#122700) 2024-07-28 07:11:56 -05:00
Bill Flood
d4aa981fd7 Bump mopeka-iot-ble to version 0.8.0 (#122717) 2024-07-28 07:07:00 -05:00
dependabot[bot]
ac0d0b21e2 Bump github/codeql-action from 3.25.13 to 3.25.14 (#122632) 2024-07-28 11:50:00 +02:00
Michael
092ab823d1 Add device info for legacy Ecovacs bots (#122671)
* add device info

* add tests
2024-07-28 11:06:32 +02:00
Phill (pssc)
3ad2456dd9 Add yamaha platform retry if receiver unavailable at setup (#122679)
* Add platform retry if recieiver unavailable at setup

* Fix Excpetion handling after testing
2024-07-28 10:39:41 +02:00
Avi Miller
146ec4e760 Create theme select entities on matrix devices (#122695)
Signed-off-by: Avi Miller <me@dje.li>
2024-07-28 10:28:42 +02:00
Jafar Atili
f563817b98 Bump pyElectra to 1.2.4 (#122724)
* Bump PyElectra to 1.2.3

* one more thing

* Bump PyElectra to 1.2.4

* fixed pyElectra license
2024-07-28 10:18:21 +02:00
Sid
ec15a66a68 Bump ruff to 0.5.5 (#122722) 2024-07-28 09:37:38 +02:00
Jafar Atili
e708e30c33 Bump pyswitchbee to 1.8.3 (#122713)
* Bump pyswitchbee to 1.8.3

* fix license
2024-07-27 23:11:42 +02:00
J. Nick Koston
383dd80919 Bump aiohomekit to 3.2.1 (#122704) 2024-07-27 12:13:11 -05:00
Robert Svensson
6752bd450b Use snapshot in Axis light tests (#122703) 2024-07-27 17:41:42 +02:00
Arie Catsman
b0780e1db5 Remove conditions from enphase_envoy test_switch (#122693) 2024-07-27 14:32:37 +02:00
Joakim Plate
02a5df0aee Update nibe library to 2.11.0 (#122697)
Update nibe library to 2.11.0 with changes

Addition of BT71 for F1155/F1255
Addition of climate zones for S1155/S1255
Include log information on incomplete reads
Correct fan speeds from being a percentage to a mapping on F series pumps
Corrections for airflow units
Let denied alarm resets writes be considered as a valid connection on setup
2024-07-27 14:01:58 +02:00
Andrew Jackson
cb4a48ca02 Migrate Mastodon integration to config flow (#122376)
* Migrate to config flow

* Fixes & add code owner

* Add codeowners

* Import within notify module

* Fixes from review

* Fixes

* Remove config schema
2024-07-27 13:07:02 +02:00
Luke Wale
64f997718a Add AirTouch5 cover (#122462)
* AirTouch5 - add cover

Each zone has a damper that can be controlled as a cover.

* remove unused assignment

* remove opinionated feature support

* Revert "remove unused assignment"

This reverts commit b4205a60a22ae3869436229b4a45547348496d39.

* ruff formatting changes

* git push translation and refactor
2024-07-27 12:36:48 +02:00
J. Nick Koston
482cf261c0 Small speedups to unifi (#122684)
- Use a set for event_is_on to avoid linear search
- Avoid many duplicate property lookups
2024-07-27 10:19:53 +02:00
J. Nick Koston
1a5706a693 Cache unifi device_tracker properties that never change (#122683) 2024-07-27 10:14:40 +02:00
Phill (pssc)
13c320902e Fix yamaha uid where host in config is defined (#122676)
Fix for uid where host in config is defined
2024-07-27 08:23:41 +02:00
Joost Lekkerkerker
bfbd01a4e5 Add typing to Comfoconnect (#122669) 2024-07-27 08:07:36 +02:00
SplicedNZ
09622e180e Add virtual integraion for "Mercury NZ Limited" (opower) (#122650)
* Add virtual integraion for "Mercury NZ Limited" and bump opower version requirement

* revert opower version bump, fix newlines

* Update name
2024-07-26 20:00:01 -07:00
Phill (pssc)
84486bad78 Yamaha device setup enhancement with unique id based on serial (#120764)
* fix server unavailale at HA startup Fixes #111108

Remove receiver zone confusion for mediaplayer instances
fix uniq id based on serial where avaialble
get serial suppiled by discovery for config entries.

* Fix linter errors

* ruff format

* Enhance debug to find setup code path for tests

* Enhance debug to find setup code path for tests

* Fix formatting

* Revered uid chanages as not needed yet and cuases other issues

* Revert "Fix formatting"

This reverts commit f3324868d2.

* Fix formatting

* Refector tests to cope with changes to plaform init to get serial numbers

* Update test patch

* Update test formatting

* remove all fixes revert code to only make clear we deal with zones and improve debuging
2024-07-26 23:36:34 +02:00
Robert Svensson
c486baccaa Patch import where its used in Axis hub test (#122674) 2024-07-26 23:33:37 +02:00
David Bonnes
57554aba57 Fix broken token caching for evohome (#122664)
* bugfix token caching
2024-07-26 21:28:58 +01:00
Álvaro Fernández Rojas
c9eb1a2e9c Fix Airzone Cloud WebServer memory usage unit (#122670)
airzone_cloud: sensor: fix webserver memory usage unit

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-26 21:59:16 +02:00
Álvaro Fernández Rojas
1a64489121 Add Airzone Cloud low thermostat battery binary sensor (#122665)
airzone_cloud: binary_sensor: add low thermostat battery

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-26 21:36:39 +02:00
Álvaro Fernández Rojas
888ffc002f Add Airzone Cloud WebServer CPU/Memory sensors (#122667)
airzone_cloud: sensor: add WebServer CPU/Memory

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-26 21:36:21 +02:00
Robert Svensson
58419f14e8 Less use of hass.data[DECONZ_DOMAIN] in deCONZ tests (#122657)
* Less use of hass.data[DECONZ_DOMAIN] in deCONZ tests

* Fix review comment

* Change patch path
2024-07-26 20:58:00 +02:00
Álvaro Fernández Rojas
57a5c7c8b6 Update aioairzone-cloud to v0.6.1 (#122661)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-26 20:41:31 +02:00
SplicedNZ
b2b40d9ed6 Bump opower to 6.0.0 (#122658)
* Bump opower to 0.6.0

* Bump opower to 0.6.0
2024-07-26 20:19:58 +02:00
J. Nick Koston
8e578227c3 Add test coverage for doorbird cameras (#122660) 2024-07-26 20:04:23 +02:00
Álvaro Fernández Rojas
d3d522c463 Add Airzone Cloud zone thermostat sensors (#122648)
* airzone_cloud: sensor: add zone thermostat sensors

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

* airzone_cloud: sensor: add missing signal percentage icon

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

* airzone_cloud: sensor: add signal percentage translation

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

* airzone_cloud: sensor: disable thermostat_coverage

Also add to diagnostics category.

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

* Update homeassistant/components/airzone_cloud/strings.json

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

---------

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-26 19:28:39 +02:00
Robert Svensson
53131390ac Use snapshot in UniFi image tests (#122608)
* Use snapshot in UniFi image tests

* Make Image access_token deterministic
2024-07-26 19:22:09 +02:00
David Knowles
7820bcf218 Add entity services to the Hydrawise integration (#120883)
* Add services to the Hydrawise integration

* Add validation of duration ranges

* Remove clamping test

* Fix duration type in test

* Changes requested during review

* Add back the HydrawiseZoneBinarySensor class
2024-07-26 17:25:56 +02:00
Mr. Bubbles
49e2bfae31 Bump bring-api to v0.8.1 (#122653)
* Bump bring-api to v0.8.1

* update imports
2024-07-26 16:59:28 +02:00
G Johansson
55a1082866 Return unknown when data is missing in Trafikverket Weather (#122652)
Return unknown when data is missing
2024-07-26 16:59:12 +02:00
J. Nick Koston
5bb6272dfa Add test coverage for doorbird events (#122617) 2024-07-26 09:55:14 -05:00
Álvaro Fernández Rojas
850703824b Update aioairzone-cloud to v0.6.0 (#122647)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-26 14:15:48 +02:00
Robert Svensson
72fdcd1cb1 Final steps to runtime_data in Axis integration (#122641)
* Rework connection error test to check config entry status

* Remove final dependencies to hass.data[AXIS_DOMAIN]
2024-07-26 12:29:47 +02:00
Robert Svensson
33ea67e1d0 Remove last references to hass.data[UNIFI_DOMAIN] (#122642) 2024-07-26 12:29:21 +02:00
Robert Svensson
047100069b Clean up some fixtures not referenced within deCONZ tests (#122637) 2024-07-26 11:21:48 +02:00
Andrew Jackson
ecadf6a330 Log line wrap in Mealie integration (#122635)
Log line wrap
2024-07-26 10:21:39 +02:00
Robert Svensson
b41b7aeb5b Remove validation of state==UNAVAILABLE on config entry unload in deCONZ test (#122558)
Only test remove entry marks entities unavailable in one place
2024-07-26 10:06:58 +02:00
Robert Svensson
c9b81a5c04 Replace ConfigEntry with MockConfigEntry in Axis tests (#122629)
* Remove unused fixtures in Axis tests

* Replace ConfigEntry with MockConfigEntry
2024-07-26 09:48:37 +02:00
Robert Svensson
51d5e21203 Remove unused fixtures in UniFi tests (#122628) 2024-07-26 09:48:12 +02:00
Brett Adams
621bd5f0c3 Add dynamic coordinator interval to Tesla Fleet (#122234)
* Add dynamic rate limiter

* tweaks

* Revert min polling back to 2min

* Set max 1 hour

* Remove redundant update_interval

* Tuning and fixes

* Reduce double API calls

* Type test

* Remove RateCalculator
2024-07-26 09:40:49 +02:00
Robert Svensson
9b4cf873c1 Replace ConfigEntry with MockConfigEntry in deCONZ tests (#122631) 2024-07-26 09:36:41 +02:00
J. Nick Koston
e262f759af Speed up bluetooth matching (#122626)
- use a defaultdict to avoid lots of setdefault
- move the intersection outside of the genexpr
  to avoid entering the genexpr if there is no
  intersection
2024-07-26 09:22:56 +02:00
Denis Shulyaka
78a98afb8d Remove obsolete string from openai_conversation strings.json (#122623) 2024-07-26 03:48:26 +02:00
Marc Mueller
e5f2046b19 Update mypy-dev to 1.12.0a2 (#122613) 2024-07-25 21:48:10 +02:00
Robert Resch
d77b5cbbbf Bump deebot-client to 8.2.0 (#122612) 2024-07-25 21:23:14 +02:00
Erik Montnemery
5dbd7684ce Fail tests if recorder creates nested sessions (#122579)
* Fail tests if recorder creates nested sessions

* Adjust import order

* Move get_instance
2024-07-25 21:18:55 +02:00
Robert Resch
32a0463f47 Update Ecovacs translations (#122610)
* Update Ecovacs translations

* Update tests
2024-07-25 21:18:42 +02:00
Robert Resch
62a3902de7 Set mode for Ecovacs clean count entity (#122611) 2024-07-25 21:18:28 +02:00
huettner94
eb3686af06 Add shelly overcurrent sensor for switches (#122494)
shelly: add overcurrent sensor for switches

just like overvoltage shelly switches can react to overcurrent and
diable the switch. Unfortunately this is is not mentioned anywhere in
the documentation.
It can be triggered by a device using more amps than set in
"Output protections" under the name "Overcurrent in amperes".
2024-07-25 21:22:18 +03:00
Erik Montnemery
81983d66f4 Avoid nesting sessions in recorder auto repairs tests (#122596) 2024-07-25 12:52:13 -05:00
Robert Svensson
e015c0a6ae Use snapshot in UniFi device tracker tests (#122603) 2024-07-25 18:16:58 +02:00
Robert Svensson
81c8ba87ab Use snapshot in UniFi button tests (#122602) 2024-07-25 18:16:25 +02:00
Erik Montnemery
ec957e4a94 Run statistics on 5-minute intervals in tests (#122592)
* Run statistics on 5-minute intervals in tests

* Fix test failing when mysql does not return rows in insert order
2024-07-25 17:32:49 +02:00
Robert Svensson
08d7beb803 Use snapshots in UniFi update tests (#122599) 2024-07-25 17:32:31 +02:00
Andrew Jackson
131ce09490 Allow nightly Mealie versions to pass (#121761)
* Allow invalid versions to pass

* Add log warning

* Change log message

* Add assert for log
2024-07-25 17:27:08 +02:00
Allen Porter
e8eb1ed35c Bump airgradient to 0.7.1 removing mashumaro direct dependency (#122534) 2024-07-25 07:46:09 -07:00
Erik Montnemery
0c7ab2062f Avoid creating nested sessions in recorder migration (#122580) 2024-07-25 15:44:48 +02:00
Josef Zweck
f1b933ae0c Add uncalibrated sensor for tedee (#122594)
* add uncalibrated sensor

* change off icon
2024-07-25 15:42:10 +02:00
G Johansson
e6d0bc7d5d Add device to Worldclock (#122557)
* Add device to Worldclock

* has_entity_name
2024-07-25 14:16:21 +02:00
J. Nick Koston
e795f81f73 Add support for govee presence sensor h5127 (#122568) 2024-07-25 13:35:00 +02:00
Álvaro Fernández Rojas
3caffa4dad Update aioqsw to v0.4.0 (#122586)
* Update aioqsw to v0.4.0

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

* trigger CI

---------

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-25 13:34:02 +02:00
Erik Montnemery
1f2c54f112 Avoid nesting sessions in recorder purge tests (#122581) 2024-07-25 13:12:10 +02:00
Erik Montnemery
c12a79ecba Deduplicate sensor recorder tests (#122516) 2024-07-25 12:31:11 +02:00
J. Nick Koston
a94e9d472b Add support for govee H5124 vibration sensors (#122562) 2024-07-25 12:29:52 +02:00
Philip Vanloo
cde22a44db Add LinkPlay integration (#113940)
* Intial commit

* Add artsound as virtual integration

* Add config_flow test
Add linkplay to .coveragerc
Add linkplay to .strict-typing

* Remove artsound component

* Bump package version

* Address mypy and coveragerc

* Address comments

* Address more feedback, add zeroconf and user flow

* Catch broken bridge in async_setup_entry

* Raise ConfigEntryNotReady, add __all__

* Implement new tests for the config_flow

* Fix async warning

* Fix test

* Address feedback

* Address comments

* Address comment

---------

Co-authored-by: Philip Vanloo <26272906+pvanloo@users.noreply.github.com>
2024-07-25 12:27:10 +02:00
Erik Montnemery
33d5ed52e6 Avoid nesting sessions in recorder statistics tests (#122582) 2024-07-25 12:26:44 +02:00
J. Nick Koston
78e24be1e7 Convert qingping to use entry.runtime_data (#122528) 2024-07-25 12:19:55 +02:00
J. Nick Koston
a89853da9d Migrate switchbot to use entry.runtime_data (#122530) 2024-07-25 12:18:24 +02:00
J. Nick Koston
3b01a57de3 Bump aioesphomeapi to 24.6.2 (#122566) 2024-07-25 12:16:16 +02:00
J. Nick Koston
256a2276ef Bump govee-ble to 0.40.0 (#122564) 2024-07-25 12:15:40 +02:00
Erik Montnemery
6223fe93c8 Fix typo in conftest.py (#122583) 2024-07-25 12:08:52 +02:00
J. Nick Koston
7348a1fd0c Convert homekit to use entry.runtime_data (#122533) 2024-07-25 11:06:55 +02:00
karwosts
8687b438f1 Use appropriate selector for homeassistant.update_entity (#122497) 2024-07-25 11:05:31 +02:00
Avi Miller
4901ecba7f Bump aiolifx to 1.0.6 (#122569) 2024-07-24 18:44:56 -05:00
G Johansson
59637d2391 Address Wake on Lan post-merge feedback (#122549)
Address Wake on Late post-merge feedback
2024-07-25 00:26:18 +02:00
Alexandre CUER
fcccd85ac4 Add tests to emoncms (#122547)
* Add tests to emoncms

* Reduce snapshot size

* Reduce snapshot size

* run hassfest to update CODEOWNERS file

* Update requirements_test_all.txt

* Update tests/components/emoncms/test_sensor.py

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

* Dont use snapshot when testing state change

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-24 21:40:05 +02:00
Stefano Semeraro
34b32ced25 Add CCT support to WLED (#122488) 2024-07-24 20:37:38 +02:00
Marcel van der Veldt
d7c713d18d Fix typo in Matter lock platform (#122536) 2024-07-24 20:12:51 +02:00
Marcel van der Veldt
4876e35fd8 Matter event follow up (#122553) 2024-07-24 20:12:20 +02:00
Robert Svensson
9198234465 Use snapshot in deCONZ light tests (#122548) 2024-07-24 20:08:42 +02:00
Robert Svensson
be8e432bea Use snapshot in deCONZ alarm control panel tests (#122551)
* Use snapshot in deCONZ alarm control panel tests

* Clean up comments
2024-07-24 20:08:06 +02:00
Andrew Jackson
943b1afb55 Fix target service attribute on Mastodon integration (#122546)
* Fix target

* Fix
2024-07-24 18:19:12 +02:00
Ian
3e8d3083ac Refactor NextBus integration to use new API (#121133)
* Refactor NextBus integration to use new API

This removes the `messages`, `directions`, and `attribution` attributes
from the sensor. Those may be added back in the future with additional
refactoring.

Some existing sensors may be broken today because of deprecated Agency
names. This patch will not migrate them as the migration path is
ambiguous. Setting up again should work though.

* Move result indexing outside of try/except
2024-07-24 18:18:21 +02:00
Robert Svensson
3c4f2c2dcf Use snapshot in deCONZ select tests (#122541) 2024-07-24 18:07:40 +02:00
Robert Svensson
277883e756 Use snapshot in deCONZ sensor tests (#122543) 2024-07-24 18:07:18 +02:00
Robert Svensson
5bda072141 Use snapshot in deCONZ scene tests (#122540) 2024-07-24 17:32:57 +02:00
Robert Svensson
a8e60a6c53 Use snapshot in deCONZ number tests (#122538) 2024-07-24 17:28:47 +02:00
Robert Svensson
50da3c5c5b Use snapshot in deCONZ climate tests (#122535) 2024-07-24 17:15:01 +02:00
Robert Svensson
c5f9ff6ac5 Use snapshot in deCONZ cover tests (#122537) 2024-07-24 17:14:40 +02:00
J. Nick Koston
6393f1f02d Convert rainmachine to use entry.runtime_data (#122532) 2024-07-24 08:52:14 -06:00
J. Nick Koston
c81b9d624b Convert oralb to use entry.runtime_data (#122527) 2024-07-24 16:23:42 +02:00
Noah Husby
cae992f5e6 Add volume step to Russound media player (#122523)
* Add volume step to Russound media player

* Add return types
2024-07-24 14:44:44 +02:00
Joost Lekkerkerker
9ecdee3b78 Extract Evohome base entities to separate module (#122515)
* Extract Evohome base entities to separate module

* Extract Evohome base entities to separate module
2024-07-24 13:22:48 +02:00
Erik Montnemery
c9f0fe3c5d Rename recorder INTEGRATION_PLATFORMS_LOAD_IN_RECORDER_THREAD (#122511) 2024-07-24 11:37:49 +02:00
Robert Svensson
a90d41d9e7 Use snapshot in deCONZ binary sensor tests (#122507)
* Use snapshot in deCONZ binary sensor tests

* Fix typing in button test
2024-07-24 09:01:34 +02:00
Robert Svensson
4c7828fd50 Improve deCONZ fan tests (#122493)
* Improve fan tests

* Use snapshots
2024-07-24 09:01:09 +02:00
Jan Stienstra
99aa68c93f Use runtime_data instead of hass.data for Jellyfin (#122410)
* Use runtime_data instead of hass.data

* Process review
2024-07-24 08:53:01 +02:00
ribbal
6dd43be6ac Fix incorrect enum option in Hive heating sensor (#122496)
* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* Fix defect with Hive heating sensor options
2024-07-24 08:50:44 +02:00
Avi Miller
67f7e97b4c Bump aiolifx-themes to v0.5.0 (#122503)
Signed-off-by: Avi Miller <me@dje.li>
2024-07-24 08:46:29 +02:00
Robert Svensson
902bf4ae86 Use snapshot in deCONZ button tests (#122505)
Use snapshot in button tests
2024-07-24 08:44:10 +02:00
Noah Husby
b7b3094a49 Bump aiorussound to 2.2.0 (#122500) 2024-07-24 08:40:54 +02:00
J. Nick Koston
e1e64be3c9 Remigrate device_registry created_at/modified_at (#122490)
* Remigrate device_registry created_at/modified_at

Nightly current does not boot up because the device registry
will have KeyError: created_at if the previous nightly was
installed.

* reduce

* split migration per discord comments
2024-07-23 15:47:27 -05:00
Christopher Fenner
f135d3d16c Fix device class on sensor in ViCare (#122334)
update device class on init
2024-07-23 22:56:46 +03:00
Álvaro Fernández Rojas
fd6f1cfbdc Update aioairzone-cloud to v0.5.5 (#122482)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-23 22:55:18 +03:00
Marc Mueller
ac86738572 Update pylutron to 0.2.15 (#122455) 2024-07-23 22:41:16 +03:00
Robert Svensson
ad38b9e9e1 Use snapshot validation on Axis binary sensor (#122483)
* Use snapshot validation on binary sensor

* Use snapshot_platform

* Clean up

* Improve typign
2024-07-23 22:30:03 +03:00
Robert Svensson
e6ef8a34a7 Tweak deCONZ init and hub tests (#122484)
* Improve typing of init tests

* Clean up gateway test

* Validate deconz device registry entry

* Rename gateway to hub

* Snake case BRIDGEID to BRIDGE_ID
2024-07-23 22:29:48 +03:00
Álvaro Fernández Rojas
2730713b39 Update aioairzone to v0.8.1 (#122481)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-23 14:22:42 -05:00
Robert Resch
e00f159ebe Fix loading created_at/modified_at from entity registry store (#122486) 2024-07-23 21:15:12 +02:00
Álvaro Fernández Rojas
57c554f516 Update AEMET-OpenData to v0.5.3 (#122480) 2024-07-23 13:48:34 -05:00
Robert Svensson
34f1443a5a Improve Axis hub tests (#122472)
* Improve some of the hub tests

* Replace constant "name" with "home"

* Add snapshot

* Simplify

* Clean up
2024-07-23 19:54:43 +02:00
Robert Svensson
b53800a69d Tweak axis test fixtures (#122469)
* Don't automatically add config entry to hass

* Improve RTSP fixture typing

* Improve typing of config entry factory and remove unnecessary use of it

* Remove redundant fixture in config flow tests

* Parametrize config flow error test
2024-07-23 19:27:38 +02:00
ribbal
1b7fb9ae12 Create additional sensors in Hive integration (#122453)
* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors

* add temperature and mode sensors
2024-07-23 19:21:58 +02:00
J. Nick Koston
6bdc5be433 Bump aiohttp to 3.10.0b1 (#122409) 2024-07-23 12:10:22 -05:00
Noah Husby
d78327a72f Add dynamic media player features to Russound (#122475)
Add dynamic media player features
2024-07-23 18:37:24 +02:00
ilan
0a62a4459f Add 100% test coverage to Madvr (#122350)
* feat: add 100% test coverage

* fix: dont patch logger

* fix: better names

* fix: use consts

* fix: use built in const
2024-07-23 18:06:26 +02:00
Michael Hansen
3ba2a0518e Switch to official ollama library, update models (#122471)
* Switch to mainstream ollama library, update models

* Fix mypy error
2024-07-23 10:57:54 -05:00
Matthias Alphart
d7b0d1a50e Use dispatcher for KNX GroupMonitor instead of custom HassJob (#122384) 2024-07-23 17:47:45 +02:00
David Bonnes
42b9c0448c Add coordinator to evohome and prune async_update code (#119432)
* functional programming tweak

* doctweak

* typing hint

* rename symbol

* Switch to DataUpdateCoordinator

* move from async_setup to EvoBroker

* tweaks - add v1 back in

* tidy up

* tidy up docstring

* lint

* remove redundant logging

* rename symbol

* split back to inject authenticator clas

* rename symbols

* rename symbol

* Update homeassistant/components/evohome/__init__.py

Co-authored-by: Joakim Plate <elupus@ecce.se>

* allow exception to pass through

* allow re-authentication with diff credentials

* lint

* undo unrelated change

* use async_refresh instead of async_config_entry_first_refresh

* assign None instead of empty dict as Falsey value

* use class attrs instead of type hints

* speed up mypy hint

* speed up mypy check

* small tidy up

* small tidy up

---------

Co-authored-by: Joakim Plate <elupus@ecce.se>
Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2024-07-23 16:47:53 +02:00
Marc Mueller
da6a7ebd42 Update clientsession socket family typing (#122464) 2024-07-23 09:04:09 -05:00
Phill (pssc)
f260d63c58 Add squeezebox server device with common init (#122396)
* squeezebox moves common elements into __init__ to allow for server sensors and device, improves player device

* Update with feedback from PR

* squeezebox Formating fixes, Logging Fixes, remove nasty stored callback

* squeezebox Formating fixes, Logging Fixes, remove nasty stored callback

* squeezebox refactor to use own ConfigEntry and Data

* squeezebox remove own data class

* Update homeassistant/components/squeezebox/__init__.py

Correct typo

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

* Update homeassistant/components/squeezebox/media_player.py

Stronger typing on entry setup SqueezeboxConfigEntry

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

* squeezebox add SqueezeboxConfigEntry

* squeezebox fix mypy type errors

* squeezebox use right Callable

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-23 15:53:58 +02:00
Marc Mueller
ff467463f8 Update pytest warnings filter (#122459) 2024-07-23 15:50:14 +02:00
Marc Mueller
5727f30026 Changes for aiohttp 3.10.0 (#122463) 2024-07-23 15:37:26 +02:00
starkillerOG
32cd54b1e3 Fix flaky Reolink tests (#122451) 2024-07-23 08:35:02 -05:00
Robert Resch
51ef5cd3ba Add model_id to Ecovacs integration (#122457) 2024-07-23 15:28:16 +02:00
Stefan Agner
07b2a7537b Add Matter update entities for devices with OTA requestor (#120304)
* Add Matter update entities for devices with OTA requestor

Matter devices which support the OTA requestor cluster can receive
updates from a OTA provider. The Home Assistant Python Matter Server
implements such an OTA provider now.

Add update entities for devices which support the OTA requestor cluster
and check for available updates. Allow the user to update the firmware.
The update progress will be read directly from the devices' OTA
requestor cluster.

* Update homeassistant/components/matter/update.py

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

* Bump python-matter-server to 6.3.0

This includes models and commands required for device firmware updates.

* Fix tests by including the new bluetooth_enabled field

* Add update entity tests

* Fix update entity test

* Update entity picture docstring

* Add note about reasons for progress state change update

* Enable polling for update entities by default

Matter entities don't enable polling any longer. Enable polling for
update entities by default.

* Add comment about why Update entities are polled

---------

Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
2024-07-23 15:25:02 +02:00
starkillerOG
b46b74df90 Check for incompatible special chars in Reolink password (#122461) 2024-07-23 15:22:23 +02:00
Marc Mueller
156a2427ff Use aiohttp.ClientTimeout for timeout (#122458) 2024-07-23 08:20:04 -05:00
Robert Resch
545514c5cd Add created_at/modified_at to category registry (#122454) 2024-07-23 14:39:38 +02:00
Erik Montnemery
92acfc1464 Indicate database migration in /api/core/state response (#122445)
* Indicate database migration in /api/core/state response

* Change API response according to review comment

* Adjust API response

* Update test

* Add test
2024-07-23 14:13:08 +02:00
Stefan Agner
73ea62edd4 Disable polling for Matter entities by default (#122452)
Matter entities don't implement async_update, they get their update
from the Matter subscriptions through the WebSocket from the Matter
Server. This change disables polling for all Matter Entities by
default.
2024-07-23 13:43:12 +02:00
starkillerOG
1fd3c9d6dd Replace Reolink HDR switch by HDR select entity (#122373)
* Add HDR select

* Update strings.json

* Update strings.json

* add icon

* remove HDR switch

* cleanup old HDR switch

* add tests

* Keep HDR switch entity around untill HA 2025.2.0

* Add repair issue

* Update strings.json

* fixes and review comments

* Add tests

* Update homeassistant/components/reolink/strings.json

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

* Update homeassistant/components/reolink/switch.py

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

* fixes and simplify

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-23 13:28:33 +02:00
Robert Resch
0d765a27c9 Add created_at/modified_at to entity registry (#122444) 2024-07-23 13:12:29 +02:00
Brett Adams
8d14095cb9 Improve API calls in Teslemetry (#122449)
* Improve API calls

* Small tweak

* typing fixtures
2024-07-23 12:59:25 +02:00
fustom
77282ed4b0 Use external temp if needed in Broadlink (#118375)
* Use external temp for current temp depends on the sensor state

* Add SensorMode enum

* Add tests for Broadlink climate

* Check is the sensor included in the data

* Use IntEnum as parent of SensorMode

* Use SensorMode enum value for sensor test data

* Parametrizing tests

* Readd accidentally removed assert

* Use local sensor variable

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

* Refactor test_climate. Check call_counts.

* Add parameter types

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

* Update homeassistant/components/broadlink/climate.py

---------

Co-authored-by: Robert Resch <robert@resch.dev>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-23 12:30:06 +02:00
Marcel van der Veldt
632dec614a Fix several issues with the Matter Generic Switch Cluster (#122191) 2024-07-23 10:10:32 +02:00
Franck Nijhof
d3d91a83e5 Update wled to 0.20.0 (#122441) 2024-07-23 09:56:23 +02:00
Erik Montnemery
108dc3795e Remove incorrect use of Mock.assert_has_calls from recorder tests (#122439)
* Remove incorrect use of Mock.assert_has_calls from recorder tests

* Fix test
2024-07-23 09:39:27 +02:00
Joost Lekkerkerker
cd48278671 Extract Geniushub base entities in separate module (#122331) 2024-07-23 09:34:00 +02:00
Allen Porter
be4c7291bd Update google tasks to return completed items (#122437) 2024-07-23 09:31:22 +02:00
dependabot[bot]
4674502b92 Bump docker/login-action from 3.2.0 to 3.3.0 (#122440)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 09:24:52 +02:00
Robert Svensson
4ee256633b Deduplicate light data with deCONZ websocket fixture (#122421) 2024-07-23 08:40:30 +02:00
J. Nick Koston
0039f1bb49 Make frontend url and route a cached_property (#122430) 2024-07-23 08:39:18 +02:00
Denis Shulyaka
975cfa6457 Fix gemini api format conversion (#122403)
* Fix gemini api format conversion

* add tests

* fix tests

* fix tests

* fix coverage
2024-07-22 17:56:13 -07:00
Erik Montnemery
5d3c57ecfe Freeze integration setup timeout for recorder during non-live migration (#122431) 2024-07-22 18:48:55 -05:00
Erik Montnemery
f4125eaf4c Remove loop shutdown indicator when done with test hass (#122432) 2024-07-23 00:56:06 +02:00
Erik Montnemery
96de0a4c94 Correct off-by-one bug in recorder non live schema migration (#122428)
* Correct off-by-one bug in recorder non live schema migration

* Remove change from the future
2024-07-23 00:30:31 +02:00
J. Nick Koston
d0ba5534cd Bump async-upnp-client to 0.40.0 (#122427) 2024-07-22 17:04:29 -05:00
Erik Montnemery
9b2118e556 Remove recorder from websocket_api after dependencies (#122422)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-22 16:50:05 -05:00
Erik Montnemery
42716723e6 Register WS command recorder/info early (#122425) 2024-07-22 16:26:52 -05:00
ribbal
ba276a5cb6 Add missing binary sensors to Hive integration (#122296)
* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors

* add missing sensors
2024-07-22 23:15:36 +02:00
Erik Montnemery
3df6b34a03 Split recorder and frontend bootstrap steps (#122420) 2024-07-22 23:07:49 +02:00
Denis Shulyaka
ee30510b23 Remove deprecated DALL-E image formats (#122388) 2024-07-22 21:57:48 +02:00
Alexandre CUER
489457c47b Add async_update_data to emoncms coordinator (#122416)
* Add async_update_data to coordinator

* Add const module
2024-07-22 21:47:01 +02:00
Joakim Plate
a1cdd91d23 Continue transition from legacy dict to attr in dsmr (#121906) 2024-07-22 21:41:24 +02:00
Mr. Bubbles
fed17a4905 Add DeviceInfo to OTP integration (#122392) 2024-07-22 21:39:22 +02:00
Robert Svensson
c61efe931a Deduplicate more fixture data related to deCONZ websocket sensor (#122412) 2024-07-22 21:37:58 +02:00
Erik Montnemery
d3df903d1e Make device registry migration unconditional (#122414) 2024-07-22 21:37:47 +02:00
Erik Montnemery
db6704271c Avoid repeated calls to utc_from_timestamp(0).isoformat() when migrating (#122413) 2024-07-22 21:36:36 +02:00
Erik Montnemery
3dc36cf068 Improve error handling when creating new SQLite database (#122406)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-22 14:16:11 -05:00
Erik Montnemery
20fc5233a1 Add recorder data migrator class to clean up states table (#122069) 2024-07-22 13:04:01 -05:00
Robert Resch
4c853803f1 Add created_at/modified_at to device registry (#122369) 2024-07-22 19:15:23 +02:00
Noah Husby
19d9a91392 Add device info to Russound RIO (#122395)
* Add device info to Russound RIO

* Set device info name to Russound model

* Add device class to Russound media player

* Move device info to constructor

* Use connections instead of identifiers for russound

* Add via_device attr to Russound

* Reinstate russound identifiers

* Move has entity name attr
2024-07-22 19:06:13 +02:00
Erik Montnemery
76cd53a864 Improve error handling when recorder schema migration fails (#122397) 2024-07-22 18:55:12 +02:00
Noah Husby
02c34ba3f8 Bump aiorussound to 2.0.7 (#122389) 2024-07-22 18:01:54 +02:00
Erik Montnemery
b14e8d1609 Remove SchemaValidationStatus.valid (#122394) 2024-07-22 17:33:13 +02:00
Erik Montnemery
e8b88557ee Refactor recorder schema migration (#122372)
* Refactor recorder schema migration

* Simplify

* Remove unused imports

* Refactor _migrate_schema according to review comments

* Add comment
2024-07-22 16:53:54 +02:00
Erik Montnemery
c73e7ae178 Handle integration with missing dependencies (#122386) 2024-07-22 15:41:55 +02:00
Joost Lekkerkerker
7ec41275d5 Add mealie service to set mealplan (#122317) 2024-07-22 15:34:10 +02:00
Erik Montnemery
debebcfd25 Improve language in loader error messages (#122387) 2024-07-22 15:32:36 +02:00
Pete Sage
186ca49b16 Fix group media player play_media not passing kwargs (#122258) 2024-07-22 14:30:23 +02:00
Robert Resch
243a68fb1f Frontend wants a timestamp for the created_at/modified_at attributes (#122377) 2024-07-22 14:10:16 +02:00
J. Nick Koston
bd97a09cae Complete coverage for doorbird init (#122272) 2024-07-22 13:57:43 +02:00
J. Nick Koston
d421525f1b Fix missing translation key for august doorbells (#122251) 2024-07-22 13:15:43 +02:00
Allen Porter
7ec332f857 Fix platforms on media pause and unpause intents (#122357) 2024-07-22 13:15:05 +02:00
Brett Adams
31d3b3b675 Handle empty energy sites in Tesla integrations (#122355) 2024-07-22 13:14:15 +02:00
cdnninja
ea94cdb668 Bump pyvesync to 2.1.12 (#122318) 2024-07-22 13:09:08 +02:00
Erik Montnemery
cbe94c4706 Fix typo in recorder persistent notification (#122374) 2024-07-22 12:02:17 +02:00
Duco Sebel
5612e3a92b Bumb python-homewizard-energy to 6.1.1 to embed model in upstream library (#122365) 2024-07-22 11:26:38 +02:00
Paul Bottein
33f0840a26 Add translations for xiaomi miio fan preset modes (#122367) 2024-07-22 11:21:54 +02:00
starkillerOG
8d538fcd52 Add Reolink model_id / item number (#122371) 2024-07-22 11:20:02 +02:00
Marc Mueller
9793aa0a5e Update pytest to 8.3.1 (#122368) 2024-07-22 11:16:05 +02:00
Denis Shulyaka
064d7261b4 Ensure script llm tool name does not start with a digit (#122349)
* Ensure script tool name does not start with a digit

* Fix test name
2024-07-22 11:11:09 +02:00
starkillerOG
0c6dc9e43b Bump reolink-aio to 0.9.5 (#122366) 2024-07-22 11:09:03 +02:00
Marc Mueller
c70e611822 Fix homewizard api close not being awaited on unload (#122324) 2024-07-22 10:19:08 +02:00
J. Nick Koston
02c64c7861 Bump cryptography to 43.0.0 and pyOpenSSL to 24.2.1 and chacha20poly1305-reuseable >= 0.13.0 (#122308) 2024-07-22 10:15:02 +02:00
dependabot[bot]
5b32efb6d6 Bump github/codeql-action from 3.25.12 to 3.25.13 (#122362)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:15 +02:00
Matthias Alphart
34e72ea16a Add support for KNX UI to create light entities (#122342)
* Add light to KNX UI-createable entity platforms

* review from switch

* Add a test
2024-07-22 09:35:29 +02:00
Noah Husby
f30c6e01f9 Bump aiorussound to 2.0.6 (#122354)
bump aiorussound to 2.0.6
2024-07-22 08:56:48 +02:00
J. Nick Koston
db9fc27a5c Convert enphase_envoy to use entry.runtime_data (#122345) 2024-07-22 07:44:00 +02:00
Denis Shulyaka
ac1ad9680b Goofle Generative AI: Fix string format (#122348)
* Ignore format for string tool args

* Add tests
2024-07-21 21:54:31 -07:00
Marc Mueller
4eb096cb0a Update pylint to 3.2.6 (#122338) 2024-07-22 01:44:52 +02:00
Maciej Bieniek
bc5849e4ef Bump aiotractive to 0.6.0 (#121155)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-07-21 18:11:05 -05:00
Alexander Schneider
9a3c7111f7 Add Z-Wave discovery schema for ZVIDAR roller shades (#122332)
Add discovery schema for ZVIDAR roller shades
2024-07-21 23:51:10 +02:00
Allen Porter
c98c80ce69 Change OpenAI default recommended model to gpt-4o-mini (#122333) 2024-07-21 13:37:18 -07:00
Lorzware
453848bcdc APSystems - add configuration option 'port' in config flow (#122144)
* Add configuration option 'port' in config flow
2024-07-21 22:03:41 +02:00
Joost Lekkerkerker
7d46890804 Add support for grouping notify entities (#122123)
* Add support for grouping notify entities

* Add support for grouping notify entities

* Add support for grouping notify entities

* Fix test

* Fix feedback

* Update homeassistant/components/group/notify.py

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

* Test config flow changes

* Test config flow changes

---------

Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
2024-07-21 20:57:49 +02:00
Michael
7e1fb88e4e Post merge review for Feedreader (#122327)
* remove unneccessary typing

* assert type list while type checking

* remove summary, since feedparser parse it already into content

* add further tests
2024-07-21 20:55:02 +02:00
epenet
94ce02f406 Bump renault-api to 2.0.5 (#122326)
* Bump renault-api to 2.0.5

* Update requirements_all.txt

* Update requirements_test_all.txt
2024-07-21 13:18:43 -05:00
Matthias Alphart
d418a40856 Create, update and delete KNX entities from UI / WS-commands (#104079)
* knx entity CRUD - initial commit - switch

* platform dependent schema

* coerce empty GA-lists to None

* read entity configuration from WS

* use entity_id instead of unique_id for lookup

* Add device support

* Rename KNXEntityStore to KNXConfigStore

* fix test after rename

* Send schema options for creating / editing entities

* Return entity_id after entity creation

* remove device_class config in favour of more-info-dialog settings

* refactor group address schema for custom selector

* Rename GA keys and remove invalid keys from schema

* fix rebase

* Fix deleting devices and their entities

* Validate entity schema in extra step - return validation infos

* Use exception to signal validation error; return validated data

* Forward validation result when editing entities

* Get proper validation error message for optional GAs

* Add entity validation only WS command

* use ulid instead of uuid

* Fix error handling for edit unknown entity

* Remove unused optional group address sets from validated schema

* Add optional dpt field for ga_schema

* Move knx config things to sub-key

* Add light platform

* async_forward_entry_setups only once

* Test crate and remove devices

* Test removing entities of a removed device

* Test entity creation and storage

* Test deleting entities

* Test unsuccessful entity creation

* Test updating entity data

* Test get entity config

* Test validate entity

* Update entity data by entity_id instead of unique_id

* Remove unnecessary uid unique check

* remove schema_options

* test fixture for entity creation

* clean up group address schema

class can be used to add custom serializer later

* Revert: Add light platfrom

* remove unused optional_ga_schema

* Test GASelector

* lint tests

* Review

* group entities before adding

* fix / ignore mypy

* always has_entity_name

* Entity name: check for empty string when no device

* use constants instead of strings in schema

* Fix mypy errors for voluptuous schemas

---------

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
2024-07-21 20:01:48 +02:00
GeoffAtHome
890b54e36f Add config flow to Genius hub (#116173)
* Adding config flow

* Fix setup issues.

* Added test for config_flow

* Refactor schemas.

* Fixed ruff-format on const.py

* Added geniushub-cleint to requirements_test_all.txt

* Updates from review.

* Correct multiple logger comment errors.

* User menu rather than check box.

* Correct logger messages.

* Correct test_config_flow

* Import config entry from YAML

* Config flow integration

* Refactor genius hub test_config_flow.

* Improvements and simplification from code review.

* Correct tests

* Stop device being added twice.

* Correct validate_input.

* Changes to meet code review three week ago.

* Fix Ruff undefined error

* Update homeassistant/components/geniushub/config_flow.py

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

* Update homeassistant/components/geniushub/config_flow.py

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

* Change case Cloud and Local to CLOUD and LOCAL.

* More from code review

* Fix

* Fix

* Update homeassistant/components/geniushub/strings.json

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-21 19:57:41 +02:00
Marc Mueller
6de824e875 Fix test RuntimeWarning for upb (#122325) 2024-07-21 18:50:00 +02:00
Joost Lekkerkerker
273dc0998f Clean up Mealie service tests (#122316) 2024-07-21 10:15:28 -05:00
J. Nick Koston
5f4dedb4a8 Add binary sensor platform to govee-ble (#122111) 2024-07-21 09:47:59 -05:00
Joost Lekkerkerker
6f4a8a4a14 Add Mealie service to set a random mealplan (#122313)
* Add Mealie service to set a random mealplan

* Fix coverage

* Fix coverage
2024-07-21 16:43:46 +02:00
J. Nick Koston
39068bb786 Add sleepy device support to govee-ble (#122085) 2024-07-21 09:38:00 -05:00
J. Nick Koston
7e82b3ecdb Add event platform to govee-ble (#122031)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-21 09:32:58 -05:00
Joost Lekkerkerker
8d01ad98eb Clean up Mealie coordinator (#122310)
* Clean up Mealie coordinator

* Clean up Mealie coordinator

* Clean up Mealie coordinator

* Fix

* Fix
2024-07-21 16:24:46 +02:00
Joost Lekkerkerker
a78d6b8c36 Set polling interval for airgradient to 1 minute (#122266) 2024-07-21 16:22:45 +02:00
Joost Lekkerkerker
e8796cd725 Improve Hive typing (#122314) 2024-07-21 16:21:45 +02:00
J. Nick Koston
b0a4140b4d Convert sensorpush to use entry.runtime_data (#122315) 2024-07-21 09:11:18 -05:00
J. Nick Koston
30373a668c Migrate harmony to use entry.runtime_data (#122312) 2024-07-21 09:06:51 -05:00
J. Nick Koston
272f0bc21c Migrate oncue to use entry.runtime_data (#122307) 2024-07-21 08:19:58 -05:00
J. Nick Koston
7f852d0f73 Update bthome to use entry.runtime_data (#122304) 2024-07-21 08:19:46 -05:00
J. Nick Koston
8994c18f73 Update xiaomi-ble to use entry.runtime_data (#122306) 2024-07-21 08:19:33 -05:00
Joost Lekkerkerker
874b1ae873 Add sensor platform to Mealie (#122280)
* Bump aiomealie to 0.7.0

* Add sensor platform to Mealie

* Fix
2024-07-21 14:59:22 +02:00
Joost Lekkerkerker
7f82fb8cb8 Bump aiomealie to 0.8.0 (#122295)
* Bump aiomealie to 0.8.0

* Bump aiomealie to 0.8.0
2024-07-21 14:52:18 +02:00
J. Nick Koston
a8cbfe5159 Make TemplateStateBase.entity_id a cached_property (#122279) 2024-07-21 07:49:59 -05:00
Marcel Vriend
0ab1ccc5ae Fix to prevent Azure Data Explorer JSON serialization from failing (#122300) 2024-07-21 14:08:58 +02:00
Robert Svensson
48661054d9 Improve fixture usage for sensor based deCONZ tests (#122297) 2024-07-21 13:56:16 +02:00
Jan Bouwhuis
87e377cf84 Ensure mqtt subscriptions are in a set (#122201) 2024-07-21 12:36:06 +02:00
Arie Catsman
8da630f8c6 Improve sensor test coverage for enphase_envoy (#122229)
* Improve sensor platform test COV for enphase_envoy

* Use async_fire_time_changed to trigger next data update in enphase_envoy test
2024-07-21 12:26:32 +02:00
Louis Christ
f629364dc4 Use pyblu library in bluesound (#117257)
* Integrate pypi libraray: pyblu

* Raise PlatformNotReady if _sync_status is not available yet

* Revert "Raise PlatformNotReady if _sync_status is not available yet"

This reverts commit a649a6bccd00cf16f80e40dc169ca8797ed3b6b2.

* Replace 'async with timeout' with parameter in library

* Set timeout back to 10 seconds

* ruff fixes

* Update homeassistant/components/bluesound/media_player.py

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

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-21 12:24:54 +02:00
ilan
fcca475e36 Add sensor platform to MadVR (#121617)
* feat: add sensors

* feat: add tests for sensors

* feat: add options flow

* feat: add tests for options flow

* fix: remove options flow

* fix: remove names and mac sensor, add incoming signal type

* feat: add enum types to supported sensors

* fix: consolidate tests into snapshot

* fix: use consts

* fix: update names and use snapshot platform

* fix: fix test name for new translations

* fix: comment

* fix: improve sensor names

* fix: address comments

* feat: disable uncommon sensors by default

* fix: update sensors

* fix: revert config_flow change
2024-07-21 08:43:52 +02:00
Sid
5075f0aac8 Bump ruff to 0.5.4 (#122289) 2024-07-21 08:42:06 +02:00
Joost Lekkerkerker
537a76d049 Add model id to airgradient (#122271) 2024-07-21 08:41:42 +02:00
J. Nick Koston
b3698a59e1 Bump uiprotect to 5.4.0 (#122282) 2024-07-20 17:24:16 -05:00
Joost Lekkerkerker
9b9db86f1c Bump aiomealie to 0.7.0 (#122278) 2024-07-21 00:00:31 +02:00
ilan
1e28ae49f9 Bump py-madvr to 1.6.29 (#122275)
chore: bump version
2024-07-20 22:44:14 +02:00
Joost Lekkerkerker
24b6f71f94 Bump twitchAPI to 4.2.1 (#122269) 2024-07-20 21:29:51 +02:00
Joost Lekkerkerker
ae4360b0e5 Bump airgradient to 0.7.0 (#122268) 2024-07-20 21:26:00 +02:00
Marc Mueller
769d7214a3 Improve tests.common typing (#122257) 2024-07-20 17:34:43 +02:00
Marc Mueller
90e7d82049 Use correct enum in UnitSystem tests (#122256) 2024-07-20 17:33:48 +02:00
Marc Mueller
5e8b022246 Improve shopping_list test typing (#122255) 2024-07-20 16:46:39 +02:00
J. Nick Koston
43aeaf7a9b Upgrade CI to use ubuntu 24.04 (#122254) 2024-07-20 09:43:10 -05:00
Brian Rogers
63b0feeae7 Add calendar for Rachio smart hose timer (#120030) 2024-07-20 09:38:51 -05:00
Brett Adams
0f079454bb Add device tracker to Tesla Fleet (#122222) 2024-07-20 14:37:57 +02:00
Marc Mueller
6be4ef8a1f Improve contextmanager typing (#122250) 2024-07-20 14:09:37 +02:00
Marc Mueller
5fd3b929f4 Update types packages (#122245) 2024-07-20 14:09:10 +02:00
Marc Mueller
55abbc51a4 Update pip-licenses to 4.5.1 (#122240) 2024-07-20 13:52:55 +02:00
Marc Mueller
651fb95010 Update uv to 0.2.27 (#122246) 2024-07-20 13:24:21 +02:00
Marc Mueller
c6713edc8b Update pytest-unordered to 0.6.1 (#122243) 2024-07-20 13:24:01 +02:00
Marc Mueller
ee49c57e95 Update pytest to 8.2.2 (#122244) 2024-07-20 13:16:36 +02:00
Erik Montnemery
2f47312eeb Fix recorder setup hanging if non live schema migration fails (#122242) 2024-07-20 13:10:23 +02:00
Marc Mueller
293ad99dae Update pytest-asyncio to 0.23.8 (#122241) 2024-07-20 13:10:09 +02:00
Marc Mueller
0fe7aa1a43 Update bcrypt to 4.1.3 (#122236) 2024-07-20 13:06:22 +02:00
Marc Mueller
b54b08479d Update pipdeptree to 2.23.1 (#122239) 2024-07-20 12:59:44 +02:00
Marc Mueller
ab2f38216d Update coverage to 7.6.0 (#122238) 2024-07-20 12:59:08 +02:00
Marc Mueller
13da20ddf4 Update Pillow to 10.4.0 (#122237) 2024-07-20 12:58:49 +02:00
Erik Montnemery
436a38c1d2 Revert "Fix recorder setup hanging if non live schema migration fails" (#122232) 2024-07-20 12:29:08 +02:00
Brett Adams
2b93de1348 Add binary sensor to Tesla Fleet (#122225) 2024-07-20 11:28:30 +02:00
Robert Svensson
ecffae0b4f Improve fixture usage for light based deCONZ tests (#122209) 2024-07-20 11:25:00 +02:00
Brett Adams
6f9e39cd3f Add diagnostics to Tesla Fleet (#122223) 2024-07-20 11:22:15 +02:00
Arie Catsman
221480add1 Improve switch platform test COV for enphase_envoy (#122227) 2024-07-20 11:20:46 +02:00
Erik Montnemery
153b69c971 Fix recorder setup hanging if non live schema migration fails (#122207) 2024-07-20 11:17:40 +02:00
Pete Sage
d1d2ce1270 Sonos tests snapshot and restore services (#122198) 2024-07-20 11:16:48 +02:00
Marc Mueller
a6068dcdf2 Update import locations in tests (#122216) 2024-07-20 11:16:04 +02:00
Marc Mueller
0637e342f6 Fix ConfigFlowResult annotations in tests (#122215) 2024-07-20 11:13:13 +02:00
Marc Mueller
e9f5c4188e Fix incompatible signature overwrite async_turn_on + off (#122208) 2024-07-20 11:12:41 +02:00
Marc Mueller
24b12bc509 Improve HA snapshot serializer typing (#122218) 2024-07-20 11:12:02 +02:00
Marc Mueller
f0b9a806d1 Fix missing type[..] annotation in tests (#122217) 2024-07-20 11:11:16 +02:00
Marc Mueller
f8c4ffc060 Update freezegun to 1.5.1 (#122219) 2024-07-20 11:10:46 +02:00
Marc Mueller
768d20c645 Fix recorder datetime annotations (#122214) 2024-07-20 11:10:25 +02:00
Erik Montnemery
a0332d049b Fix flaky recorder test (#122205) 2024-07-20 11:09:52 +02:00
Álvaro Fernández Rojas
4ee2c445d1 Update home_connect to v0.8.0 (#121788)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-07-20 05:28:04 +02:00
Marc Mueller
458c81cdae Improve vizio tests typing (#122213) 2024-07-20 02:50:12 +02:00
Marc Mueller
8e024ad20f Fix invalid Any annotations (#122212) 2024-07-20 02:46:27 +02:00
Mr. Bubbles
a46fffd550 Fix wrong deprecation date in Habitica integration (#122206)
Fix wrong deprecation date
2024-07-20 00:40:29 +02:00
G Johansson
288faf48e7 Add config flow to Wake on LAN (#121605) 2024-07-19 21:20:43 +02:00
HarvsG
7e0970e917 Log timeouts for assist_pipeline end of speech detection (#122182)
* log timeouts

* import logger the right way
2024-07-19 13:43:38 -05:00
Sean Chen
e6e748ae0a Add timestamp sensor for observation (#121752) 2024-07-19 19:50:38 +02:00
dougiteixeira
75b1700ed3 Move constants to const.py in generic Thermostat (#120789) 2024-07-19 19:49:11 +02:00
Franck Nijhof
267dfac737 2024.7.3 (#122194) 2024-07-19 19:38:08 +02:00
Steven B.
099110767a Add tests for ring camera platform for 100% coverage (#122197) 2024-07-19 19:35:44 +02:00
Pierre Mavro
cafff3eddf Add PrusaLink nozzle and mmu support (#120436)
Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-07-19 19:15:42 +02:00
Steven Looman
c0732fbb1d Add options flow for force_poll setting in upnp (#120843) 2024-07-19 19:02:28 +02:00
Stefan Agner
7b5b6c7b85 Tolerate integration removed device (#120722) 2024-07-19 19:00:31 +02:00
Franck Nijhof
a08ffdc8d3 Bump version to 2024.7.3 2024-07-19 18:50:21 +02:00
Mr. Bubbles
1ef4332af6 Fix KeyError in config flow of Bring integration (#122136) 2024-07-19 18:49:45 +02:00
Marc Mueller
d0d2fd7918 Update yt-dlp to 2024.07.16 (#122124) 2024-07-19 18:49:41 +02:00
Steven B.
c518c4756b Bump tplink dependency python-kasa to 0.7.0.5 (#122119) 2024-07-19 18:49:38 +02:00
Shay Levy
a3a99cc631 Prevent connecting to a Shelly device that is already connected (#122105) 2024-07-19 18:49:35 +02:00
Steven B.
977a55e3b8 Update tplink device config during reauth flow (#122089) 2024-07-19 18:49:31 +02:00
Harry Martland
002db3c3e9 Fix hive not updating when boosting (#122042)
* fixes issue where hive does not update when boosting

* formats files
2024-07-19 18:49:28 +02:00
Robert Svensson
d9e44bab69 Mark UniFi power cycle button as unavailable if PoE is not enabled on port (#122035) 2024-07-19 18:49:25 +02:00
G Johansson
4b93fc61b5 Bump python-holidays to 0.53 (#122021) 2024-07-19 18:49:21 +02:00
J. Nick Koston
214b5efd72 Narrow sqlite database corruption check to ensure disk image is malformed (#121947)
* Narrow sqlite database corruption check to ensure disk image is malformed

The database corruption check would also replace the database when it
locked externally instead of only when its malformed.

This was discovered in https://github.com/home-assistant/core/issues/121909#issuecomment-2227409124
when a user did a manual index creation while HA was online

* tweak

* tweak

* fix

* fix
2024-07-19 18:49:16 +02:00
Maciej Bieniek
9bd822d693 Fix configuration_url for Shelly device using IPv6 (#121939)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-07-19 18:48:32 +02:00
Tomasz Gorochowik
bf89eaae25 Fix enigma2 mute (#121928) 2024-07-19 18:42:44 +02:00
Scott K Logan
f9b359ae30 Fix rainforest_raven closing device due to timeout (#121905) 2024-07-19 18:42:41 +02:00
mvn23
24ed003471 Fix opentherm_gw availability (#121892) 2024-07-19 18:42:38 +02:00
J. Nick Koston
a835750252 Log add/remove index complete at the same level as when it starts (#121852) 2024-07-19 18:42:35 +02:00
Avi Miller
ad07bdb62b Bump aiolifx to 1.0.5 (#121824) 2024-07-19 18:42:32 +02:00
Avi Miller
41104324ec Bump aiolifx to 1.0.4 (#121267) 2024-07-19 18:42:28 +02:00
ollo69
e9344ae101 Bump PySwitchbot to 0.48.1 (#121804) 2024-07-19 18:40:25 +02:00
starkillerOG
56a9167ed2 Reolink media second lens (#121800)
DUO lens camera distinguish between lenses for media playback
2024-07-19 18:40:22 +02:00
Jan Bouwhuis
e0b90c4b36 Fix alexa does to check current_position correctly when handling cover range changes (#121798) 2024-07-19 18:40:19 +02:00
Jan-Philipp Benecke
976902f22c Add missing translations to Roborock (#121796) 2024-07-19 18:40:16 +02:00
Steven B
0f69c58ba9 Bump python-kasa to 0.7.0.4 (#121791) 2024-07-19 18:40:13 +02:00
Glenn Waters
1e6c96c6eb Use async_connect in newly bumped 0.5.8 UPB library (#121789) 2024-07-19 18:40:09 +02:00
J. Nick Koston
63b14d14c1 Add some missing tplink ouis (#121785) 2024-07-19 18:40:06 +02:00
Josef Zweck
6aaaba6419 Bump pytedee_async to 0.2.20 (#121783) 2024-07-19 18:40:03 +02:00
Allen Porter
3b8e736fe3 Pin mashumaro version >= 3.13.1 for python 3.12.4 compatibility. (#121782)
Pin mashumaro version for python 3.12.4 compatibility.
2024-07-19 18:40:00 +02:00
tronikos
68841b3d8a Bump opower to 0.5.2 to fix 403 forbidden errors for users with multiple accounts (#121762) 2024-07-19 18:39:56 +02:00
Abílio Costa
3d8afe7cb8 Update Idasen Desk library to 2.6.2 (#121729) 2024-07-19 18:29:45 +02:00
Robert Svensson
8595242142 Fix bad access to UniFi runtime_data when not assigned (#121725)
* Fix bad access to runtime_data when not assigned

* Fix review comment

* Clean up if statements
2024-07-19 18:29:42 +02:00
Joost Lekkerkerker
ebe7bc0686 Bump knocki to 0.3.1 (#121717) 2024-07-19 18:29:39 +02:00
J. Nick Koston
4ab180f016 Fix update happening too early in unifiprotect (#121714) 2024-07-19 18:29:36 +02:00
Mr. Bubbles
372649069e Bump pyloadapi to v1.3.2 (#121709) 2024-07-19 18:29:33 +02:00
Joost Lekkerkerker
98df46f3ea Bump knocki to 0.3.0 (#121704) 2024-07-19 18:29:30 +02:00
Steven B
269fb23527 Fix tplink bug changing color temp on bulbs with light effects (#121696) 2024-07-19 18:29:27 +02:00
Sid
ad5cbf0da6 Allow enigma2 devices to use different source bouquets (#121686) 2024-07-19 18:29:24 +02:00
Lucas Mindêllo de Andrade
10cdf64f90 Bump sunweg 3.0.2 (#121684) 2024-07-19 18:29:21 +02:00
Tomek Porozynski
ec8e639804 Update Supla async_set_cover_position to use "REVEAL_PARTIALLY" (#121663) 2024-07-19 18:29:17 +02:00
Jan Stienstra
37f37f7287 Retain Jellyfin config flow input on connection issue (#121618) 2024-07-19 18:29:13 +02:00
Mr. Bubbles
ef7d68bfd6 Fix reauth error and exception in ista EcoTrend integration (#121482) 2024-07-19 18:29:08 +02:00
Jan Rieger
12ec66c2c2 Avoid blocking I/O in gpsd (#122176) 2024-07-19 18:25:07 +02:00
Mr. Bubbles
72d37036b9 Remove filtering of user data in Habitica integration (#121759)
Remove context-based userFields filtering
2024-07-19 17:56:52 +02:00
Sid
e029dad0eb Add data update coordinator to enigma2 (#122046)
* Add data update coordinator to enigma2

* Apply suggestions from code review

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

---------

Co-authored-by: Robert Resch <robert@resch.dev>
2024-07-19 17:51:34 +02:00
G Johansson
0cde518a89 Allow to add optional holiday categories in workday (#121396)
* Allow to add optional holiday categories in workday

* Add tests

* Fix coverage
2024-07-19 17:49:27 +02:00
Christopher Fenner
dab66990c0 Ignore E3_TCU41_x04 gateway device in ViCare (#122179)
skip gateway device
2024-07-19 11:40:17 -04:00
Steven Looman
d3029af888 Address post merge review changes in upnp (#122189)
Post merge review change
2024-07-19 11:38:38 -04:00
Marcel Vriend
419bf0165a Bump azure-kusto dependencies to 4.5.1 (#121805) 2024-07-19 17:33:02 +02:00
Shai Ungar
978ee918cb Use new 17track api library (#121910) 2024-07-19 17:09:50 +02:00
Marc Mueller
8bca9a3449 Fix return type annotations in tests (#122184) 2024-07-19 16:44:03 +02:00
Malte Franken
87ecf5d85e Bump georss-qld-bushfire-alert-client to 0.8 (#122185) 2024-07-19 16:12:26 +02:00
Marc Mueller
2f8dfb424b Use Generator as return type for fixtures (#122183) 2024-07-19 14:55:23 +02:00
Marc Mueller
53c85a5c9b Fix test fixture annotations (#122180) 2024-07-19 14:46:30 +02:00
Marc Mueller
281c66b6c2 Fix invalid dict annotations in tests (#122178) 2024-07-19 14:45:42 +02:00
Bram Kragten
6788c43775 Add static routes for frontend modern and legacy service workers (#120488) (#122174)
* Bump frontend to 20240719.0

* restore #120488
2024-07-19 14:40:50 +02:00
Josef Zweck
f006716173 Add async_setup method to DataUpdateCoordinator (#116677)
* init

* Update homeassistant/helpers/update_coordinator.py

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

* fix typo, ruff

* consistency with rest, test

* pylint suppression

* ruff

* ruff

* switch to one test

* add last exc

* add tests for auth & Entry Errors

* move exceptions to correct test

* Update update_coordinator.py

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

* test setup call

* simplify

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-07-19 14:24:25 +02:00
dougiteixeira
de5b5f6d36 Add string for value template description in switch Template (#121865)
Add string for value template descrition in switch Template
2024-07-19 13:58:22 +02:00
Harry Martland
e9ea90dc82 Fix hive not updating when boosting (#122042)
* fixes issue where hive does not update when boosting

* formats files
2024-07-19 13:47:28 +02:00
Marc Mueller
0be68dcd7f Fix deconz conftest typing (#122173) 2024-07-19 13:10:38 +02:00
Marc Mueller
c92d9dcb74 Use TypeVar defaults for Generator (#122170) 2024-07-19 13:06:45 +02:00
Marc Mueller
2b486c3bd5 Replace unnecessary typing_extensions imports for Generator (#122169) 2024-07-19 12:56:27 +02:00
Bram Kragten
c28a138dfe Revert "Add static routes for frontend modern and legacy service workers" (#122172) 2024-07-19 12:55:40 +02:00
Mr. Bubbles
3ddcffb7b7 Fix reauth error and exception in ista EcoTrend integration (#121482) 2024-07-19 12:26:40 +02:00
Matrix
8cb7e9785f Add YoLink YS8017 support (#122064) 2024-07-19 12:20:30 +02:00
Jan Bouwhuis
16434b5306 Add command_template option to mqtt switch schema (#122103) 2024-07-19 12:10:49 +02:00
Paolo Burgio
c1c5cff993 Add integration for iotty Smart Home (#103073)
* Initial import 0.0.2

* Fixes to URL, and removed commits

* Initial import 0.0.2

* Fixes to URL, and removed commits

* Added first test for iotty

* First release

* Reviewers request #1
- Removed clutter
- Added support for new naming convention for IottySmartSwitch entity

* Removed commmented code

* Some modifications

* Modified REST EP for iotty CloudApi

* Initial import 0.0.2

* Fixes to URL, and removed commits

* Added first test for iotty

* First release

* Rebased and resolved conflicts

* Reviewers request #1
- Removed clutter
- Added support for new naming convention for IottySmartSwitch entity

* Removed commmented code

* Some modifications

* Modified REST EP for iotty CloudApi

* Removed empty entries in manifest.json

* Added test_config_flow

* Fix as requested by @edenhaus

* Added test_init

* Removed comments, added one assert

* Added TEST_CONFIG_FLOW

* Added test for STORE_ENTITY

* Increased code coverage

* Full coverage for api.py

* Added tests for switch component

* Converted INFO logs onto DEBUG logs

* Removed .gitignore from commits

* Modifications to SWITCH.PY

* Initial import 0.0.2

* Fixes to URL, and removed commits

* Added first test for iotty

* First release

* Rebased and resolved conflicts

* Fixed conflicts

* Reviewers request #1
- Removed clutter
- Added support for new naming convention for IottySmartSwitch entity

* Removed commmented code

* Some modifications

* Modified REST EP for iotty CloudApi

* Removed empty entries in manifest.json

* Added test_config_flow

* Some modifications

* Fix as requested by @edenhaus

* Added test_init

* Removed comments, added one assert

* Added TEST_CONFIG_FLOW

* Added test for STORE_ENTITY

* Increased code coverage

* Full coverage for api.py

* Added tests for switch component

* Converted INFO logs onto DEBUG logs

* Removed .gitignore from commits

* Modifications to SWITCH.PY

* Fixed tests for SWITCH

* First working implementation of Coordinator

* Increased code coverage

* Full code coverage

* Missing a line in testing

* Update homeassistant/components/iotty/__init__.py

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

* Update homeassistant/components/iotty/__init__.py

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

* Modified coordinator as per request by edenhaus

* use coordinator entities for switches

* move platforms to constants

* fix whitespace with ruff-format

* correct iotty entry in application_credentials list

* minor style improvements

* refactor function name

* handle new and deleted devices

* improve code for adding devices after first initialization

* use typed config entry instead of adding known devices to hass.data

* improve iotty entity removal

* test listeners update cycle

* handle iotty as devices and not only as entities

* fix test typing for mock config entry

* test with fewer mocks for an integration test style opposed to the previous unit test style

* remove useless tests and add more integration style tests

* check if device_to_remove is None

* integration style tests for turning switches on and off

* remove redundant coordinator tests

* check device status after issuing command in tests

* remove unused fixtures

* add strict typing for iotty

* additional asserts and named snapshots in tests

* fix mypy issues after enabling strict typing

* upgrade iottycloud version to 0.1.3

* move coordinator to runtime_data

* remove entity name

* fix typing issues

* coding style fixes

* improve tests coding style and assertion targets

* test edge cases when apis are not working

* improve tests comments and assertions

---------

Co-authored-by: Robert Resch <robert@resch.dev>
Co-authored-by: Shapour Nemati <shapour.nemati@iotty.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: shapournemati-iotty <130070037+shapournemati-iotty@users.noreply.github.com>
2024-07-19 12:10:39 +02:00
Sid
4620a54582 Bump Ruff to 0.5.3 (#122167) 2024-07-19 12:06:53 +02:00
Arie Catsman
0b691f9393 Improve number platform test COV for enphase_envoy (#122163)
* Improve number platform COV for enphase_envoy

* remove use of rand in pytest_number of enphase_envoy
2024-07-19 11:47:40 +02:00
Franck Nijhof
bcf4c73f32 Migrate Wiz to config entry runtime data (#122091) 2024-07-19 11:36:59 +02:00
G Johansson
ca4c617d4b Add TURN_OFF/TURN_ON feature flags for fan (#121447) 2024-07-19 11:35:24 +02:00
Åke Strandberg
172778053c Add select platform to myuplink (#118661) 2024-07-19 11:29:58 +02:00
G Johansson
f5f9480b5a Deprecate simulated integration (#122166) 2024-07-19 11:26:05 +02:00
Steve Repsher
e50802aca3 Add static routes for frontend modern and legacy service workers (#120488) 2024-07-19 10:53:37 +02:00
Jeef
de18be235d Add Sensors to Weatherflow Cloud (#111651)
* continue

* Rebase dev

* signle function to generate attr_entity info

* rewrite icon determination as an if block

* handling PR

* Removing wind sensors for now - separate future PR

* ruff

* Update coordinator.py

Thought i already did this

* Update sensor.py

* Update icons.json

* Update sensor.py

* Update homeassistant/components/weatherflow_cloud/entity.py

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

* working on a unified entity

* working on a unified entity

* sensor refactor

* addressing entity comment

* Update homeassistant/components/weatherflow_cloud/entity.py

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

* Update homeassistant/components/weatherflow_cloud/sensor.py

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

* doc

* pr comments again

* fixing PR

* fixing PR

* applying entity class in sensor

* Update homeassistant/components/weatherflow_cloud/sensor.py

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

* Cleaning up weather.py

* station id cleanup for weather class

* rewrite adding sensors the correct way

* Adding snapshot testing

* snapshot update

* added total class

* updated snapshots

* minor tweak

* snapshot away

* adding more coverage

* switch back to total

* Apply suggestions from code review

* Apply suggestions from code review

* Apply suggestions from code review

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-19 10:30:01 +02:00
Kristof Mariën
7810dc213a Load correct Renson fan speed when breeze level is set (#121960)
Renson: Load correct fan speed when breeze level is set
2024-07-19 10:17:45 +02:00
Brent Petit
ba5e3ca44b Remove use of deprecated set_aux_heat call from climate _async_reproduce_states (#121873) 2024-07-19 10:14:12 +02:00
rrooggiieerr
e2c6b7915e Buienradar textual improvements (#122095) 2024-07-19 10:12:58 +02:00
Jan Bouwhuis
5b4dd07189 Deprecate topic_template and payload_template for mqtt publish action (#122098)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-07-19 10:10:38 +02:00
G Johansson
362c772d67 Add config flow to worldclock (#121775) 2024-07-19 10:08:14 +02:00
Matrix
339b5117c5 Add default value for YoLink thermostat (#122114) 2024-07-19 10:05:24 +02:00
Sid
c8a6c6a5c1 Add fallback for webmin systems without MAC address (#113261) 2024-07-19 10:01:46 +02:00
Austin Mroczek
53870617e8 Add binary sensors to TotalConnect (#121888)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-07-19 09:35:54 +02:00
Mr. Bubbles
24144c5855 Fix KeyError in config flow of Bring integration (#122136) 2024-07-19 09:11:29 +02:00
ashalita
978de5b8b0 Upgrade pycoolmasternet-async to 0.2.0 (#122139) 2024-07-19 09:10:47 +02:00
Dave T
1e59ce2909 Update deprecation warning for data_entry_flow (#122154) 2024-07-19 09:08:45 +02:00
J. Nick Koston
fb5443fe2f Add missing coverage for doorbird config_flow (#122146) 2024-07-19 09:08:43 +02:00
J. Nick Koston
dae23a8153 Add coverage for doorbird button platform (#122145) 2024-07-19 09:07:58 +02:00
Brett Adams
a2c2488c8b Add Tesla Fleet integration (#122019)
* Add Tesla Fleet

* Remove debug

* Improvements

* Fix refresh and stage tests

* Working oauth flow test

* Config Flow tests

* Fixes

* fixes

* Remove comment

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

* Remove TYPE_CHECKING

* Add more tests

* More tests

* More tests

* revert teslemetry change

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-07-19 09:05:27 +02:00
Duco Sebel
474e8b7a43 Implement model_id in HomeWizard (#122130)
* Add model_id and use hardcoded model names for HomeWizard

* Update names
2024-07-19 08:22:06 +02:00
b3nj1
243c16d194 Opower: add date sensors (#122138)
opower: Add diagnostic date sensors
2024-07-18 23:07:09 -07:00
J. Nick Koston
a0a5f640dc Add some basic tests for doorbird (#122135)
* basic tests

* basic tests

* basic tests

* basic tests

* cover

* cover

* Update tests/components/doorbird/test_init.py
2024-07-18 22:36:54 +02:00
Shay Levy
d2cc25cee6 Prevent connecting to a Shelly device that is already connected (#122105) 2024-07-18 15:27:03 -05:00
Steven B.
cf0aef079b Bump tplink dependency python-kasa to 0.7.0.5 (#122119) 2024-07-18 15:20:10 -05:00
Arie Catsman
6d725b5e34 Extend sensor platform tests for enphase_envoy (#122132)
* EnphaseTestSensor

* refactor chain use in sensor test of enphase_envoy
2024-07-18 21:50:50 +02:00
Marcel van der Veldt
3d3bc1cab1 Revert "Add mac address as connection for matter device (#121257)" (#122133) 2024-07-18 17:38:30 +02:00
Maciej Bieniek
bf0e5baa76 Add support for Shelly enum virtual component (#121997)
* Support enum virtual component

* Add tests

* Cleaning

* Improve test for select

* Use values

* Update tests

* Use the option title for sensor

---------

Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-07-18 17:55:14 +03:00
MatthewFlamm
f479b64ff9 Add forecast service call for extra attributes for nws (#117254)
* add service call

* fix snapshots in test

* add tests

* fix no data service;add test

* remove unreachable code

* use only extra attributes+context attributes

* detailed descr. only in twice daily; add dewpoint

* fix import from merge

* Remove dewpoint from twice daily.

nws recently removed it

* cleanup unused snapshots

* remove dewpoint; use short_forecast

* return [] for forecasts instead of None

* Use str for short_description

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

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-07-18 16:26:07 +02:00
Marc Mueller
ec937781ca Update pylint to 3.2.5 (#122126)
* Update pylint to 3.2.5

* Remove unused pylint disable comment
2024-07-18 15:54:54 +02:00
Arie Catsman
37426f7366 Add number platform test to enphase_envoy (#122117)
* Add number platform test to enphase_envoy

* Use ATTR_VALUE in enphase_envoy number test
2024-07-18 15:42:57 +02:00
Arie Catsman
d983e3b25d Add select platform test to enphase_envoy (#122127) 2024-07-18 14:20:05 +02:00
Marc Mueller
58d4e72996 Update yt-dlp to 2024.07.16 (#122124) 2024-07-18 14:07:31 +02:00
Josef Zweck
02bb1ec8e7 Add reconfigure step to tedee (#122008)
* Add reconfigure to tedee

* assert data update

* add rconfigure_confirm to strings

* Update integration name

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-07-18 13:00:35 +02:00
Arie Catsman
f551130d65 Add binary_sensor platform test to enphase_envoy (#122120) 2024-07-18 12:45:03 +02:00
Joakim Plate
42610f4e09 Add diagnostic information to DSMR (#122041)
* Add diagnostic information to DSMR

Switches to runtime_data to get access
to the last telegram received.

* Correct import of domain

* Apply suggestions from code review

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

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-07-18 11:57:11 +02:00
Franck Nijhof
41d75e159b Update wled to 0.19.2 (#122101)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-18 10:09:12 +02:00
Brett Adams
b06d3fe3b7 Platinum quality for Tessie (#121962) 2024-07-18 09:38:26 +02:00
J. Nick Koston
e4ef4b81ba Skip poll of HKC accessory if reachable and chars are watchable (#116200) 2024-07-18 08:36:45 +02:00
Erik Montnemery
0927dd9090 Raise repair issues when scripts can't be set up (#122087) 2024-07-18 08:34:41 +02:00
J. Nick Koston
e2276458ed Fix homekit_controller tests to avoid global aid generation (#119852) 2024-07-17 19:10:02 -05:00
Paulus Schoutsen
454ca0ce95 Add timer support to mobile app (#121469)
* Add timer support to mobile app

* Fix tests

* Make it time-sensitive
2024-07-17 18:40:05 -05:00
J. Nick Koston
4ae6e38800 Bump govee-ble to 0.38.0 (#122099) 2024-07-17 22:05:27 +02:00
Steven B.
55cee89392 Update tplink device config during reauth flow (#122089) 2024-07-17 14:07:53 -05:00
Michael Hansen
fa0a5451b9 Split up tests to avoid CI timeouts (#122096) 2024-07-17 20:32:26 +02:00
Aidan Timson
52b90621c7 System Bridge coordinator and connector refactor (#114896)
* Update systembridgeconnector to 5.0.0.dev2

* Refactor

* Move out of single use method

* Update systembridgeconnector to 4.1.0.dev0 and systembridgemodels to 4.1.0

* Refactor WebSocket connection handling in SystemBridgeDataUpdateCoordinator

* Remove unnessasary fluff

* Update system_bridge requirements to version 4.1.0.dev1

* Set systembridgeconnector to 4.1.0

* Fix config flow tests

We'll make this better later

* Add missing tests for media source

* Update config flow tests

* Add missing check

* Refactor WebSocket connection handling in SystemBridgeDataUpdateCoordinator

* Move inside try

* Move log

* Cleanup log

* Fix disconnection update

* Set unregistered on disconnect

* Remove bool, use listener task

* Fix eager start

* == -> is

* Reduce errors

* Update test
2024-07-17 18:39:24 +02:00
Jan Bouwhuis
843fae825f Revert "Remove stale template_topic code for mqtt publish service" (#121758)
Revert "Remove stale `template_topic` code for mqtt publish service (#121604)"

This reverts commit 5b25c24539.
2024-07-17 17:56:34 +02:00
Franck Nijhof
e6dec7c856 Migrate HomeWizard to config entry runtime data (#122088) 2024-07-17 10:20:31 -05:00
Franck Nijhof
7a4e40ade0 Remove Markdown from service action descriptions (#122077) 2024-07-17 10:20:19 -05:00
Robert Resch
10c084c6e0 Add created_at/modified_at to label registry (#122078) 2024-07-17 16:36:14 +02:00
Franck Nijhof
8ae4c4445d Clean up old migration in HomeWizard (#122086) 2024-07-17 16:18:21 +02:00
Franck Nijhof
058b012e6c 2024.7.2 (#121671) 2024-07-10 13:18:48 +02:00
Franck Nijhof
71370758a8 Bump version to 2024.7.2 2024-07-10 12:06:02 +02:00
Franck Nijhof
38a44676eb Block variable <=3.4.4 custom integration from breaking the recorder (#121670) 2024-07-10 12:01:11 +02:00
Marcel van der Veldt
05ce3d35b3 Matter lock state follow-up (#121669) 2024-07-10 12:01:08 +02:00
Marcel van der Veldt
2151086b0a Fix state for Matter Locks (including optional door sensor) (#121665) 2024-07-10 12:01:05 +02:00
Franck Nijhof
9c83af3789 Block places <=2.7.0 custom integration from breaking the recorder (#121662) 2024-07-10 12:01:01 +02:00
tronikos
ac3eecc879 Handle errors in Fully Kiosk camera (#121659) 2024-07-10 12:00:58 +02:00
Franck Nijhof
ec0910e3da Block icloud3 custom integration from breaking the recorder (#121658) 2024-07-10 12:00:55 +02:00
Maikel Punie
fd0c26cd56 Small fix in velbus cover for the assumed states (#121656) 2024-07-10 12:00:52 +02:00
Paul Bottein
a4c5dee082 Update frontend to 20240710.0 (#121651) 2024-07-10 12:00:48 +02:00
Joakim Plate
37c09dbdb6 Allow ambilight when we have connection (philips_js) (#121620) 2024-07-10 12:00:45 +02:00
Arie Catsman
73d1973625 Bump pyenphase to 1.20.6 (#121583)
bump pyenphase to 1.20.6
2024-07-10 12:00:42 +02:00
Glenn Waters
5a04a886cf Fix upb config flow connect (#121571) 2024-07-10 12:00:39 +02:00
Franck Nijhof
50802f84f0 Update tailscale to 0.6.1 (#121557) 2024-07-10 12:00:36 +02:00
Franck Nijhof
138b68ecc0 Update vehicle to 2.2.2 (#121556) 2024-07-10 12:00:33 +02:00
Christoph
e0b01ee94e Remove homematic state_class from GAS_POWER sensor (#121533) 2024-07-10 12:00:30 +02:00
J. Nick Koston
4f2c3df518 Fix person tracking in unifiprotect (#121528) 2024-07-10 12:00:26 +02:00
Paulus Schoutsen
51a6bb1c22 Include hass device ID in mobile app get_config webhook (#121496) 2024-07-10 12:00:23 +02:00
Ovidiu D. Nițan
6bf9ec69f3 Bump xiaomi-ble to 0.30.2 (#121471) 2024-07-10 12:00:19 +02:00
Joost Lekkerkerker
21309eeb5d Bump xiaomi-ble to 0.30.1 (#120743) 2024-07-10 12:00:14 +02:00
J. Nick Koston
0a1b46c52f Bump yalexs to 6.4.2 (#121467) 2024-07-10 11:52:56 +02:00
Jason R. Coombs
9512f9eec3 Bump jaraco.abode to 5.2.1 (#121446)
Bump dependency on jaraco.abode to 5.2.1.

Closes #121300
2024-07-10 11:52:53 +02:00
jan iversen
ab94422c18 Bump pymodbus to 3.6.9 (#121445)
Bump pymodbus 3.6.9.
2024-07-10 11:52:50 +02:00
Joost Lekkerkerker
ec105e5265 Fix Mealie URL field (#121434) 2024-07-10 11:52:47 +02:00
Joost Lekkerkerker
cadd8521ae Sort mealie mealplans (#121433) 2024-07-10 11:52:43 +02:00
Joost Lekkerkerker
8825c50671 Fix MPD config flow (#121431) 2024-07-10 11:52:40 +02:00
Michael
a72cc3c248 Allow current empty feeds to be configured in Feedreader (#121421) 2024-07-10 11:52:37 +02:00
G Johansson
780f7254c1 Fix feature flag in climate (#121398) 2024-07-10 11:52:34 +02:00
G Johansson
37621e77ae Fix timezone issue in smhi weather (#121389) 2024-07-10 11:52:31 +02:00
G Johansson
8017386c73 Fix unnecessary logging of turn on/off feature flags in Climate (#121387) 2024-07-10 11:52:28 +02:00
G Johansson
a5f4c25a2c Bump psutil to 6.0.0 (#121385) 2024-07-10 11:52:25 +02:00
Brett Adams
1d7bddf449 Fix initial Wall Connector values in Tessie (#121353) 2024-07-10 11:52:21 +02:00
Luke Lashley
711bdaf373 Bump anova-wifi to 0.17.0 (#121337)
* Bump anova-wifi to 0.16.0

* Bump to .17
2024-07-10 11:52:18 +02:00
Jan Temešinko
803d9c5a8e Fix ombi configuration validation (#121314) 2024-07-10 11:52:15 +02:00
Rasmus Lundsgaard
1133c41fa8 Fix empty list in kodi media_player (#121250)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2024-07-10 11:52:12 +02:00
Alan
a06af7ee93 LLM to handle int attributes (#121037) 2024-07-10 11:52:08 +02:00
Robert C. Maehl
c54717707e Direct Users to App-Specific Passwords for iCloud integration to prevent MFA spam (#120945)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2024-07-10 11:52:05 +02:00
J. Nick Koston
440d83d754 Remove legacy foreign key constraint from sqlite states table (#120779) 2024-07-10 11:51:59 +02:00
Franck Nijhof
1cf62916a7 2024.7.1 (#121289) 2024-07-05 17:25:40 +02:00
Bram Kragten
e3958d4adb Update frontend to 20240705.0 (#121295) 2024-07-05 15:04:01 +02:00
Franck Nijhof
dfccd4abf9 Bump version to 2024.7.1 2024-07-05 11:21:36 +02:00
Steven B
994d6f552c Fix tplink light effect behaviour when activating a scene (#121288) 2024-07-05 11:21:07 +02:00
G Johansson
b015611a2a Bump python-holidays to 0.52 (#121283) 2024-07-05 11:21:04 +02:00
Shay Levy
f4e362c5d0 Bump aiowebostv to 0.4.2 (#121258) 2024-07-05 11:21:00 +02:00
Jordi
a542236614 Bump aioaquacell to 0.1.8 (#121253) 2024-07-05 11:20:57 +02:00
Shay Levy
651439ea06 Fix WebOS TV media player status when OFF after IDLE (#121251) 2024-07-05 11:20:54 +02:00
Robert Resch
eda450838e Bump deebot-client to 8.1.1 (#121241) 2024-07-05 11:20:50 +02:00
hahn-th
b906daa493 Revert Homematic IP Cloud unique ID changes (#121231) 2024-07-05 11:20:47 +02:00
Thomas55555
ac668dce7d Fix work area sensor in Husqvarna Automower (#121228) 2024-07-05 11:20:44 +02:00
Luke Lashley
1bb4d62a3e Bump anova-wifi to 0.15.0 (#121222) 2024-07-05 11:20:40 +02:00
Marcel van der Veldt
0b970f9a85 Listen for attribute changes of OnOff cluster in appliances (#121198) 2024-07-05 11:20:37 +02:00
Marcel van der Veldt
d2b695e7b5 Fix Matter light discovery schema for DimmerSwitch (#121185) 2024-07-05 11:20:34 +02:00
Steven B
b2f23c1a5e Bump python-kasa to 0.7.0.3 (#121183) 2024-07-05 11:20:31 +02:00
Gerben Jongerius
f403afb012 Bump youless library version 2.1.2 (#121181) 2024-07-05 11:20:27 +02:00
Maciej Bieniek
ee276aff44 Fix pulse counter frequency sensors for Shelly Plus Uni (#121178)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-07-05 11:20:23 +02:00
Maikel Punie
0acd1dc5d1 Bump velbusaio to 2024.7.5 (#121156)
* Bump velbusaio to 2024.7.4

* bump to 2024.7.5 to remove print functions
2024-07-05 11:20:20 +02:00
Martin Weinelt
21815e1621 Fix broken pathlib import in august integration (#121135) 2024-07-05 11:20:17 +02:00
J. Nick Koston
15933bb16f Bump inkbird-ble to 0.5.8 (#121134) 2024-07-05 11:20:13 +02:00
Pavel Skuratovich
930cd0dc50 Starline: Fix "Error updating SLNet token" message in Log (#121122)
Fixes https://github.com/home-assistant/core/issues/116715
2024-07-05 11:20:10 +02:00
Christoph
fc4af48179 Fix HmIP-ESI GAS sensor DeviceClass (#121106)
should be SensorDeviceClass:GAS instead of SensorDeviceClass:VOLUME to be supported in the Energy Dashboard
2024-07-05 11:20:07 +02:00
Marcel van der Veldt
ba1cf84ea5 Fix locking/unlocking transition state in Matter lock platform (#121099) 2024-07-05 11:20:04 +02:00
dougiteixeira
59cf01e252 Add device class translations in Random (#120890) 2024-07-05 11:20:00 +02:00
Allen Porter
46e681f4fc Improve redaction for stream error messages (#120867) 2024-07-05 11:19:56 +02:00
1643 changed files with 80156 additions and 18357 deletions

View File

@@ -190,7 +190,7 @@ jobs:
echo "${{ github.sha }};${{ github.ref }};${{ github.event_name }};${{ github.actor }}" > rootfs/OFFICIAL_IMAGE
- name: Login to GitHub Container Registry
uses: docker/login-action@v3.2.0
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -256,7 +256,7 @@ jobs:
fi
- name: Login to GitHub Container Registry
uses: docker/login-action@v3.2.0
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -329,14 +329,14 @@ jobs:
- name: Login to DockerHub
if: matrix.registry == 'docker.io/homeassistant'
uses: docker/login-action@v3.2.0
uses: docker/login-action@v3.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
if: matrix.registry == 'ghcr.io/home-assistant'
uses: docker/login-action@v3.2.0
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}

View File

@@ -86,7 +86,7 @@ jobs:
tests_glob: ${{ steps.info.outputs.tests_glob }}
tests: ${{ steps.info.outputs.tests }}
skip_coverage: ${{ steps.info.outputs.skip_coverage }}
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.7
@@ -218,7 +218,7 @@ jobs:
pre-commit:
name: Prepare pre-commit base
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -266,7 +266,7 @@ jobs:
lint-ruff-format:
name: Check ruff-format
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- info
- pre-commit
@@ -306,7 +306,7 @@ jobs:
lint-ruff:
name: Check ruff
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- info
- pre-commit
@@ -345,7 +345,7 @@ jobs:
RUFF_OUTPUT_FORMAT: github
lint-other:
name: Check other linters
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- info
- pre-commit
@@ -437,7 +437,7 @@ jobs:
base:
name: Prepare dependencies
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs: info
timeout-minutes: 60
strategy:
@@ -514,7 +514,7 @@ jobs:
hassfest:
name: Check hassfest
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -552,7 +552,7 @@ jobs:
gen-requirements-all:
name: Check all requirements
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -584,7 +584,7 @@ jobs:
audit-licenses:
name: Audit licenses
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- info
- base
@@ -624,7 +624,7 @@ jobs:
pylint:
name: Check pylint
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
timeout-minutes: 20
if: |
github.event.inputs.mypy-only != 'true'
@@ -669,7 +669,7 @@ jobs:
pylint-tests:
name: Check pylint on tests
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
timeout-minutes: 20
if: |
(github.event.inputs.mypy-only != 'true' || github.event.inputs.pylint-only == 'true')
@@ -714,7 +714,7 @@ jobs:
mypy:
name: Check mypy
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
github.event.inputs.pylint-only != 'true'
|| github.event.inputs.mypy-only == 'true'
@@ -775,7 +775,7 @@ jobs:
mypy homeassistant/components/${{ needs.info.outputs.integrations_glob }}
prepare-pytest-full:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
(github.event_name != 'push' || github.event.repository.full_name == 'home-assistant/core')
&& github.event.inputs.lint-only != 'true'
@@ -825,7 +825,7 @@ jobs:
overwrite: true
pytest-full:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
(github.event_name != 'push' || github.event.repository.full_name == 'home-assistant/core')
&& github.event.inputs.lint-only != 'true'
@@ -904,6 +904,7 @@ jobs:
cov_params+=(--cov-report=xml)
fi
echo "Test group ${{ matrix.group }}: $(sed -n "${{ matrix.group }},1p" pytest_buckets.txt)"
python3 -b -X dev -m pytest \
-qq \
--timeout=9 \
@@ -936,7 +937,7 @@ jobs:
./script/check_dirty
pytest-mariadb:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
services:
mariadb:
image: ${{ matrix.mariadb-group }}
@@ -1189,7 +1190,7 @@ jobs:
coverage-full:
name: Upload test coverage to Codecov (full suite)
if: needs.info.outputs.skip_coverage != 'true'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- info
- pytest-full
@@ -1213,7 +1214,7 @@ jobs:
version: v0.6.0
pytest-partial:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: |
(github.event_name != 'push' || github.event.repository.full_name == 'home-assistant/core')
&& github.event.inputs.lint-only != 'true'
@@ -1328,7 +1329,7 @@ jobs:
coverage-partial:
name: Upload test coverage to Codecov (partial suite)
if: needs.info.outputs.skip_coverage != 'true'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- info
- pytest-partial

View File

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

View File

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

View File

@@ -120,6 +120,7 @@ homeassistant.components.bond.*
homeassistant.components.braviatv.*
homeassistant.components.brother.*
homeassistant.components.browser.*
homeassistant.components.bryant_evolution.*
homeassistant.components.bthome.*
homeassistant.components.button.*
homeassistant.components.calendar.*
@@ -167,6 +168,7 @@ homeassistant.components.ecowitt.*
homeassistant.components.efergy.*
homeassistant.components.electrasmart.*
homeassistant.components.electric_kiwi.*
homeassistant.components.elevenlabs.*
homeassistant.components.elgato.*
homeassistant.components.elkm1.*
homeassistant.components.emulated_hue.*
@@ -255,6 +257,7 @@ homeassistant.components.integration.*
homeassistant.components.intent.*
homeassistant.components.intent_script.*
homeassistant.components.ios.*
homeassistant.components.iotty.*
homeassistant.components.ipp.*
homeassistant.components.iqvia.*
homeassistant.components.islamic_prayer_times.*
@@ -279,6 +282,7 @@ homeassistant.components.lidarr.*
homeassistant.components.lifx.*
homeassistant.components.light.*
homeassistant.components.linear_garage_door.*
homeassistant.components.linkplay.*
homeassistant.components.litejet.*
homeassistant.components.litterrobot.*
homeassistant.components.local_ip.*

View File

@@ -197,7 +197,8 @@ build.json @home-assistant/supervisor
/tests/components/bluemaestro/ @bdraco
/homeassistant/components/blueprint/ @home-assistant/core
/tests/components/blueprint/ @home-assistant/core
/homeassistant/components/bluesound/ @thrawnarn
/homeassistant/components/bluesound/ @thrawnarn @LouisChrist
/tests/components/bluesound/ @thrawnarn @LouisChrist
/homeassistant/components/bluetooth/ @bdraco
/tests/components/bluetooth/ @bdraco
/homeassistant/components/bluetooth_adapters/ @bdraco
@@ -220,6 +221,8 @@ build.json @home-assistant/supervisor
/tests/components/brottsplatskartan/ @gjohansson-ST
/homeassistant/components/brunt/ @eavanvalkenburg
/tests/components/brunt/ @eavanvalkenburg
/homeassistant/components/bryant_evolution/ @danielsmyers
/tests/components/bryant_evolution/ @danielsmyers
/homeassistant/components/bsblan/ @liudger
/tests/components/bsblan/ @liudger
/homeassistant/components/bt_smarthub/ @typhoon2099
@@ -373,6 +376,8 @@ build.json @home-assistant/supervisor
/tests/components/electrasmart/ @jafar-atili
/homeassistant/components/electric_kiwi/ @mikey0000
/tests/components/electric_kiwi/ @mikey0000
/homeassistant/components/elevenlabs/ @sorgfresser
/tests/components/elevenlabs/ @sorgfresser
/homeassistant/components/elgato/ @frenck
/tests/components/elgato/ @frenck
/homeassistant/components/elkm1/ @gwww @bdraco
@@ -384,6 +389,7 @@ build.json @home-assistant/supervisor
/tests/components/elvia/ @ludeeus
/homeassistant/components/emby/ @mezz64
/homeassistant/components/emoncms/ @borpin @alexandrecuer
/tests/components/emoncms/ @borpin @alexandrecuer
/homeassistant/components/emonitor/ @bdraco
/tests/components/emonitor/ @bdraco
/homeassistant/components/emulated_hue/ @bdraco @Tho85
@@ -505,6 +511,7 @@ build.json @home-assistant/supervisor
/homeassistant/components/generic_hygrostat/ @Shulyaka
/tests/components/generic_hygrostat/ @Shulyaka
/homeassistant/components/geniushub/ @manzanotti
/tests/components/geniushub/ @manzanotti
/homeassistant/components/geo_json_events/ @exxamalte
/tests/components/geo_json_events/ @exxamalte
/homeassistant/components/geo_location/ @home-assistant/core
@@ -695,6 +702,8 @@ build.json @home-assistant/supervisor
/tests/components/ios/ @robbiet480
/homeassistant/components/iotawatt/ @gtdiehl @jyavenard
/tests/components/iotawatt/ @gtdiehl @jyavenard
/homeassistant/components/iotty/ @pburgio
/tests/components/iotty/ @pburgio
/homeassistant/components/iperf3/ @rohankapoorcom
/homeassistant/components/ipma/ @dgomes
/tests/components/ipma/ @dgomes
@@ -703,6 +712,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/iqvia/ @bachya
/tests/components/iqvia/ @bachya
/homeassistant/components/irish_rail_transport/ @ttroy50
/homeassistant/components/iron_os/ @tr4nt0r
/tests/components/iron_os/ @tr4nt0r
/homeassistant/components/isal/ @bdraco
/tests/components/isal/ @bdraco
/homeassistant/components/islamic_prayer_times/ @engrbm87 @cpfair
@@ -791,6 +802,8 @@ build.json @home-assistant/supervisor
/tests/components/light/ @home-assistant/core
/homeassistant/components/linear_garage_door/ @IceBotYT
/tests/components/linear_garage_door/ @IceBotYT
/homeassistant/components/linkplay/ @Velleman
/tests/components/linkplay/ @Velleman
/homeassistant/components/linux_battery/ @fabaff
/homeassistant/components/litejet/ @joncar
/tests/components/litejet/ @joncar
@@ -833,7 +846,8 @@ build.json @home-assistant/supervisor
/tests/components/lyric/ @timmo001
/homeassistant/components/madvr/ @iloveicedgreentea
/tests/components/madvr/ @iloveicedgreentea
/homeassistant/components/mastodon/ @fabaff
/homeassistant/components/mastodon/ @fabaff @andrew-codechimp
/tests/components/mastodon/ @fabaff @andrew-codechimp
/homeassistant/components/matrix/ @PaarthShah
/tests/components/matrix/ @PaarthShah
/homeassistant/components/matter/ @home-assistant/matter
@@ -1039,8 +1053,8 @@ build.json @home-assistant/supervisor
/tests/components/otbr/ @home-assistant/core
/homeassistant/components/ourgroceries/ @OnFreund
/tests/components/ourgroceries/ @OnFreund
/homeassistant/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev @tronix117
/tests/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev @tronix117
/homeassistant/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev @tronix117 @alexfp14
/tests/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev @tronix117 @alexfp14
/homeassistant/components/ovo_energy/ @timmo001
/tests/components/ovo_energy/ @timmo001
/homeassistant/components/p1_monitor/ @klaasnicolaas
@@ -1432,6 +1446,8 @@ build.json @home-assistant/supervisor
/tests/components/tellduslive/ @fredrike
/homeassistant/components/template/ @PhracturedBlue @tetienne @home-assistant/core
/tests/components/template/ @PhracturedBlue @tetienne @home-assistant/core
/homeassistant/components/tesla_fleet/ @Bre77
/tests/components/tesla_fleet/ @Bre77
/homeassistant/components/tesla_wall_connector/ @einarhauks
/tests/components/tesla_wall_connector/ @einarhauks
/homeassistant/components/teslemetry/ @Bre77

View File

@@ -12,7 +12,7 @@ ENV \
ARG QEMU_CPU
# Install uv
RUN pip3 install uv==0.2.13
RUN pip3 install uv==0.2.27
WORKDIR /usr/src

View File

@@ -223,8 +223,10 @@ CRITICAL_INTEGRATIONS = {
SETUP_ORDER = (
# Load logging and http deps as soon as possible
("logging, http deps", LOGGING_AND_HTTP_DEPS_INTEGRATIONS),
# Setup frontend and recorder
("frontend, recorder", {*FRONTEND_INTEGRATIONS, *RECORDER_INTEGRATIONS}),
# Setup frontend
("frontend", FRONTEND_INTEGRATIONS),
# Setup recorder
("recorder", RECORDER_INTEGRATIONS),
# Start up debuggers. Start these first in case they want to wait.
("debugger", DEBUGGER_INTEGRATIONS),
)
@@ -906,7 +908,13 @@ async def _async_resolve_domains_to_setup(
await asyncio.gather(*resolve_dependencies_tasks)
for itg in integrations_to_process:
for dep in itg.all_dependencies:
try:
all_deps = itg.all_dependencies
except RuntimeError:
# Integration.all_dependencies raises RuntimeError if
# dependencies could not be resolved
continue
for dep in all_deps:
if dep in domains_to_setup:
continue
domains_to_setup.add(dep)

View File

@@ -1,5 +1,5 @@
{
"domain": "logitech",
"name": "Logitech",
"integrations": ["harmony", "ue_smart_radio", "squeezebox"]
"integrations": ["harmony", "squeezebox"]
}

View File

@@ -1,5 +1,5 @@
{
"domain": "tesla",
"name": "Tesla",
"integrations": ["powerwall", "tesla_wall_connector"]
"integrations": ["powerwall", "tesla_wall_connector", "tesla_fleet"]
}

View File

@@ -206,7 +206,8 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
"""Set the HVAC Mode and State."""
if hvac_mode == HVACMode.OFF:
return await self.async_turn_off()
await self.async_turn_off()
return
if hvac_mode == HVACMode.HEAT_COOL and self.preset_mode != ADVANTAGE_AIR_MYAUTO:
raise ServiceValidationError("Heat/Cool is not supported in this mode")
await self.async_update_ac(

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/aemet",
"iot_class": "cloud_polling",
"loggers": ["aemet_opendata"],
"requirements": ["AEMET-OpenData==0.5.2"]
"requirements": ["AEMET-OpenData==0.5.3"]
}

View File

@@ -4,7 +4,7 @@ from __future__ import annotations
from dataclasses import dataclass
from airgradient import AirGradientClient
from airgradient import AirGradientClient, get_model_name
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, Platform
@@ -35,7 +35,7 @@ class AirGradientData:
type AirGradientConfigEntry = ConfigEntry[AirGradientData]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: AirGradientConfigEntry) -> bool:
"""Set up Airgradient from a config entry."""
client = AirGradientClient(
@@ -53,7 +53,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, measurement_coordinator.serial_number)},
manufacturer="AirGradient",
model=measurement_coordinator.data.model,
model=get_model_name(measurement_coordinator.data.model),
model_id=measurement_coordinator.data.model,
serial_number=measurement_coordinator.data.serial_number,
sw_version=measurement_coordinator.data.firmware_version,
)
@@ -68,6 +69,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(
hass: HomeAssistant, entry: AirGradientConfigEntry
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@@ -2,9 +2,13 @@
from typing import Any
from airgradient import AirGradientClient, AirGradientError, ConfigurationControl
from airgradient import (
AirGradientClient,
AirGradientError,
AirGradientParseError,
ConfigurationControl,
)
from awesomeversion import AwesomeVersion
from mashumaro import MissingField
import voluptuous as vol
from homeassistant.components import zeroconf
@@ -83,10 +87,10 @@ class AirGradientConfigFlow(ConfigFlow, domain=DOMAIN):
self.client = AirGradientClient(user_input[CONF_HOST], session=session)
try:
current_measures = await self.client.get_current_measures()
except AirGradientParseError:
return self.async_abort(reason="invalid_version")
except AirGradientError:
errors["base"] = "cannot_connect"
except MissingField:
return self.async_abort(reason="invalid_version")
else:
await self.async_set_unique_id(current_measures.serial_number)
self._abort_if_unique_id_configured()

View File

@@ -19,7 +19,6 @@ if TYPE_CHECKING:
class AirGradientCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
"""Class to manage fetching AirGradient data."""
_update_interval: timedelta
config_entry: AirGradientConfigEntry
def __init__(self, hass: HomeAssistant, client: AirGradientClient) -> None:
@@ -28,7 +27,7 @@ class AirGradientCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
hass,
logger=LOGGER,
name=f"AirGradient {client.host}",
update_interval=self._update_interval,
update_interval=timedelta(minutes=1),
)
self.client = client
assert self.config_entry.unique_id
@@ -47,8 +46,6 @@ class AirGradientCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
class AirGradientMeasurementCoordinator(AirGradientCoordinator[Measures]):
"""Class to manage fetching AirGradient data."""
_update_interval = timedelta(minutes=1)
async def _update_data(self) -> Measures:
return await self.client.get_current_measures()
@@ -56,7 +53,5 @@ class AirGradientMeasurementCoordinator(AirGradientCoordinator[Measures]):
class AirGradientConfigCoordinator(AirGradientCoordinator[Config]):
"""Class to manage fetching AirGradient data."""
_update_interval = timedelta(minutes=5)
async def _update_data(self) -> Config:
return await self.client.get_config()

View File

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

View File

@@ -156,7 +156,8 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
raise ValueError(f"Unsupported HVAC mode: {hvac_mode}")
if hvac_mode == HVACMode.OFF:
return await self.async_turn_off()
await self.async_turn_off()
return
await self._airtouch.SetCoolingModeForAc(
self._ac_number, HA_STATE_TO_AT[hvac_mode]
)
@@ -262,7 +263,8 @@ class AirtouchGroup(CoordinatorEntity, ClimateEntity):
raise ValueError(f"Unsupported HVAC mode: {hvac_mode}")
if hvac_mode == HVACMode.OFF:
return await self.async_turn_off()
await self.async_turn_off()
return
if self.hvac_mode == HVACMode.OFF:
await self.async_turn_on()
self._unit = self._airtouch.GetGroups()[self._group_number]

View File

@@ -11,7 +11,7 @@ from homeassistant.exceptions import ConfigEntryNotReady
from .const import DOMAIN
PLATFORMS: list[Platform] = [Platform.CLIMATE]
PLATFORMS: list[Platform] = [Platform.CLIMATE, Platform.COVER]
type Airtouch5ConfigEntry = ConfigEntry[Airtouch5SimpleClient]

View File

@@ -121,6 +121,7 @@ class Airtouch5ClimateEntity(ClimateEntity, Airtouch5Entity):
"""Base class for Airtouch5 Climate Entities."""
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_translation_key = DOMAIN
_attr_target_temperature_step = 1
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False

View File

@@ -0,0 +1,134 @@
"""Representation of the Damper for AirTouch 5 Devices."""
import logging
from typing import Any
from airtouch5py.airtouch5_simple_client import Airtouch5SimpleClient
from airtouch5py.packets.zone_control import (
ZoneControlZone,
ZoneSettingPower,
ZoneSettingValue,
)
from airtouch5py.packets.zone_name import ZoneName
from airtouch5py.packets.zone_status import ZoneStatusZone
from homeassistant.components.cover import (
ATTR_POSITION,
CoverDeviceClass,
CoverEntity,
CoverEntityFeature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import Airtouch5ConfigEntry
from .const import DOMAIN
from .entity import Airtouch5Entity
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: Airtouch5ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Airtouch 5 Cover entities."""
client = config_entry.runtime_data
# Each zone has a cover for its open percentage
async_add_entities(
Airtouch5ZoneOpenPercentage(
client, zone, client.latest_zone_status[zone.zone_number].has_sensor
)
for zone in client.zones
)
class Airtouch5ZoneOpenPercentage(CoverEntity, Airtouch5Entity):
"""How open the damper is in each zone."""
_attr_device_class = CoverDeviceClass.DAMPER
_attr_translation_key = "damper"
# Zones with temperature sensors shouldn't be manually controlled.
# We allow it but warn the user in the integration documentation.
_attr_supported_features = (
CoverEntityFeature.SET_POSITION
| CoverEntityFeature.OPEN
| CoverEntityFeature.CLOSE
)
def __init__(
self, client: Airtouch5SimpleClient, zone_name: ZoneName, has_sensor: bool
) -> None:
"""Initialise the Cover Entity."""
super().__init__(client)
self._zone_name = zone_name
self._attr_unique_id = f"zone_{zone_name.zone_number}_open_percentage"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, f"zone_{zone_name.zone_number}")},
name=zone_name.zone_name,
manufacturer="Polyaire",
model="AirTouch 5",
)
@callback
def _async_update_attrs(self, data: dict[int, ZoneStatusZone]) -> None:
if self._zone_name.zone_number not in data:
return
status = data[self._zone_name.zone_number]
self._attr_current_cover_position = int(status.open_percentage * 100)
if status.open_percentage == 0:
self._attr_is_closed = True
else:
self._attr_is_closed = False
self.async_write_ha_state()
async def async_added_to_hass(self) -> None:
"""Add data updated listener after this object has been initialized."""
await super().async_added_to_hass()
self._client.zone_status_callbacks.append(self._async_update_attrs)
self._async_update_attrs(self._client.latest_zone_status)
async def async_will_remove_from_hass(self) -> None:
"""Remove data updated listener after this object has been initialized."""
await super().async_will_remove_from_hass()
self._client.zone_status_callbacks.remove(self._async_update_attrs)
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the damper."""
await self._set_cover_position(100)
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close damper."""
await self._set_cover_position(0)
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Update the damper to a specific position."""
if (position := kwargs.get(ATTR_POSITION)) is None:
_LOGGER.debug("Argument `position` is missing in set_cover_position")
return
await self._set_cover_position(position)
async def _set_cover_position(self, position_percent: float) -> None:
power: ZoneSettingPower
if position_percent == 0:
power = ZoneSettingPower.SET_TO_OFF
else:
power = ZoneSettingPower.SET_TO_ON
zcz = ZoneControlZone(
self._zone_name.zone_number,
ZoneSettingValue.SET_OPEN_PERCENTAGE,
power,
position_percent / 100.0,
)
packet = self._client.data_packet_factory.zone_control([zcz])
await self._client.send_packet(packet)

View File

@@ -6,15 +6,12 @@ from airtouch5py.airtouch5_simple_client import Airtouch5SimpleClient
from homeassistant.core import callback
from homeassistant.helpers.entity import Entity
from .const import DOMAIN
class Airtouch5Entity(Entity):
"""Base class for Airtouch5 entities."""
_attr_should_poll = False
_attr_has_entity_name = True
_attr_translation_key = DOMAIN
def __init__(self, client: Airtouch5SimpleClient) -> None:
"""Initialise the Entity."""

View File

@@ -27,6 +27,11 @@
}
}
}
},
"cover": {
"damper": {
"name": "[%key:component::cover::entity_component::damper::name%]"
}
}
}
}

View File

@@ -11,5 +11,5 @@
"documentation": "https://www.home-assistant.io/integrations/airzone",
"iot_class": "local_polling",
"loggers": ["aioairzone"],
"requirements": ["aioairzone==0.8.0"]
"requirements": ["aioairzone==0.8.1"]
}

View File

@@ -14,6 +14,7 @@ from aioairzone_cloud.const import (
AZD_FLOOR_DEMAND,
AZD_PROBLEMS,
AZD_SYSTEMS,
AZD_THERMOSTAT_BATTERY_LOW,
AZD_WARNINGS,
AZD_ZONES,
)
@@ -88,6 +89,10 @@ ZONE_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]
key=AZD_AQ_ACTIVE,
translation_key="air_quality_active",
),
AirzoneBinarySensorEntityDescription(
device_class=BinarySensorDeviceClass.BATTERY,
key=AZD_THERMOSTAT_BATTERY_LOW,
),
AirzoneBinarySensorEntityDescription(
device_class=BinarySensorDeviceClass.RUNNING,
key=AZD_FLOOR_DEMAND,

View File

@@ -13,9 +13,12 @@ from aioairzone_cloud.const import (
AZD_GROUPS,
AZD_HOT_WATERS,
AZD_INSTALLATIONS,
AZD_MODEL,
AZD_NAME,
AZD_SYSTEM_ID,
AZD_SYSTEMS,
AZD_THERMOSTAT_FW,
AZD_THERMOSTAT_MODEL,
AZD_WEBSERVER,
AZD_WEBSERVERS,
AZD_ZONES,
@@ -69,6 +72,7 @@ class AirzoneAidooEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, aidoo_id)},
manufacturer=MANUFACTURER,
model=aidoo_data[AZD_MODEL],
name=aidoo_data[AZD_NAME],
via_device=(DOMAIN, aidoo_data[AZD_WEBSERVER]),
)
@@ -111,6 +115,7 @@ class AirzoneGroupEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, group_id)},
model="Group",
manufacturer=MANUFACTURER,
name=group_data[AZD_NAME],
)
@@ -154,6 +159,7 @@ class AirzoneHotWaterEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, dhw_id)},
manufacturer=MANUFACTURER,
model="Hot Water",
name=dhw_data[AZD_NAME],
via_device=(DOMAIN, dhw_data[AZD_WEBSERVER]),
)
@@ -195,6 +201,7 @@ class AirzoneInstallationEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, inst_id)},
manufacturer=MANUFACTURER,
model="Installation",
name=inst_data[AZD_NAME],
)
@@ -240,9 +247,11 @@ class AirzoneSystemEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, system_id)},
model=system_data.get(AZD_MODEL),
manufacturer=MANUFACTURER,
name=system_data[AZD_NAME],
via_device=(DOMAIN, system_data[AZD_WEBSERVER]),
sw_version=system_data.get(AZD_FIRMWARE),
)
def get_airzone_value(self, key: str) -> Any:
@@ -270,6 +279,7 @@ class AirzoneWebServerEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
connections={(dr.CONNECTION_NETWORK_MAC, ws_id)},
identifiers={(DOMAIN, ws_id)},
model="WebServer",
manufacturer=MANUFACTURER,
name=ws_data[AZD_NAME],
sw_version=ws_data[AZD_FIRMWARE],
@@ -300,9 +310,11 @@ class AirzoneZoneEntity(AirzoneEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, zone_id)},
model=zone_data.get(AZD_THERMOSTAT_MODEL),
manufacturer=MANUFACTURER,
name=zone_data[AZD_NAME],
via_device=(DOMAIN, self.system_id),
sw_version=zone_data.get(AZD_THERMOSTAT_FW),
)
def get_airzone_value(self, key: str) -> Any:

View File

@@ -0,0 +1,15 @@
{
"entity": {
"sensor": {
"cpu_usage": {
"default": "mdi:cpu-32-bit"
},
"free_memory": {
"default": "mdi:memory"
},
"thermostat_coverage": {
"default": "mdi:signal"
}
}
}
}

View File

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

View File

@@ -10,8 +10,12 @@ from aioairzone_cloud.const import (
AZD_AQ_PM_1,
AZD_AQ_PM_2P5,
AZD_AQ_PM_10,
AZD_CPU_USAGE,
AZD_HUMIDITY,
AZD_MEMORY_FREE,
AZD_TEMP,
AZD_THERMOSTAT_BATTERY,
AZD_THERMOSTAT_COVERAGE,
AZD_WEBSERVERS,
AZD_WIFI_RSSI,
AZD_ZONES,
@@ -28,6 +32,7 @@ from homeassistant.const import (
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfInformation,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
@@ -52,6 +57,22 @@ AIDOO_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
)
WEBSERVER_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
SensorEntityDescription(
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
key=AZD_CPU_USAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
translation_key="cpu_usage",
),
SensorEntityDescription(
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
key=AZD_MEMORY_FREE,
native_unit_of_measurement=UnitOfInformation.BYTES,
state_class=SensorStateClass.MEASUREMENT,
translation_key="free_memory",
),
SensorEntityDescription(
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
entity_category=EntityCategory.DIAGNOSTIC,
@@ -98,6 +119,20 @@ ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
device_class=SensorDeviceClass.BATTERY,
key=AZD_THERMOSTAT_BATTERY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
key=AZD_THERMOSTAT_COVERAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
translation_key="thermostat_coverage",
),
)

View File

@@ -37,6 +37,17 @@
"auto": "Auto"
}
}
},
"sensor": {
"cpu_usage": {
"name": "CPU usage"
},
"free_memory": {
"name": "Free memory"
},
"thermostat_coverage": {
"name": "Signal percentage"
}
}
}
}

View File

@@ -8,6 +8,7 @@ from datetime import timedelta
import logging
from typing import TYPE_CHECKING, Any
import aiohttp
from aiohttp import web
from amcrest import AmcrestError
from haffmpeg.camera import CameraMjpeg
@@ -244,7 +245,9 @@ class AmcrestCam(Camera):
websession = async_get_clientsession(self.hass)
streaming_url = self._api.mjpeg_url(typeno=self._resolution)
stream_coro = websession.get(
streaming_url, auth=self._token, timeout=CAMERA_WEB_SESSION_TIMEOUT
streaming_url,
auth=self._token,
timeout=aiohttp.ClientTimeout(total=CAMERA_WEB_SESSION_TIMEOUT),
)
return await async_aiohttp_proxy_web(self.hass, request, stream_coro)

View File

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

View File

@@ -13,6 +13,7 @@ from homeassistant.components.sensor import (
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
PERCENTAGE,
STATE_UNKNOWN,
UnitOfApparentPower,
UnitOfElectricCurrent,
UnitOfElectricPotential,
@@ -25,7 +26,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .const import DOMAIN, LASTSTEST
from .coordinator import APCUPSdCoordinator
PARALLEL_UPDATES = 0
@@ -156,8 +157,8 @@ SENSORS: dict[str, SensorEntityDescription] = {
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
),
"laststest": SensorEntityDescription(
key="laststest",
LASTSTEST: SensorEntityDescription(
key=LASTSTEST,
translation_key="last_self_test",
),
"lastxfer": SensorEntityDescription(
@@ -417,7 +418,12 @@ async def async_setup_entry(
available_resources: set[str] = {k.lower() for k, _ in coordinator.data.items()}
entities = []
for resource in available_resources:
# "laststest" is a special sensor that only appears when the APC UPS daemon has done a
# periodical (or manual) self test since last daemon restart. It might not be available
# when we set up the integration, and we do not know if it would ever be available. Here we
# add it anyway and mark it as unknown initially.
for resource in available_resources | {LASTSTEST}:
if resource not in SENSORS:
_LOGGER.warning("Invalid resource from APCUPSd: %s", resource.upper())
continue
@@ -473,6 +479,14 @@ class APCUPSdSensor(CoordinatorEntity[APCUPSdCoordinator], SensorEntity):
def _update_attrs(self) -> None:
"""Update sensor attributes based on coordinator data."""
key = self.entity_description.key.upper()
# For most sensors the key will always be available for each refresh. However, some sensors
# (e.g., "laststest") will only appear after certain event occurs (e.g., a self test is
# performed) and may disappear again after certain event. So we mark the state as "unknown"
# when it becomes unknown after such events.
if key not in self.coordinator.data:
self._attr_native_value = STATE_UNKNOWN
return
self._attr_native_value, inferred_unit = infer_unit(self.coordinator.data[key])
if not self.native_unit_of_measurement:
self._attr_native_unit_of_measurement = inferred_unit

View File

@@ -45,7 +45,7 @@ from homeassistant.exceptions import (
TemplateError,
Unauthorized,
)
from homeassistant.helpers import config_validation as cv, template
from homeassistant.helpers import config_validation as cv, recorder, template
from homeassistant.helpers.json import json_dumps, json_fragment
from homeassistant.helpers.service import async_get_all_descriptions
from homeassistant.helpers.typing import ConfigType
@@ -119,7 +119,10 @@ class APICoreStateView(HomeAssistantView):
to check if Home Assistant is running.
"""
hass = request.app[KEY_HASS]
return self.json({"state": hass.state.value})
migration = recorder.async_migration_in_progress(hass)
live = recorder.async_migration_is_live(hass)
recorder_state = {"migration_in_progress": migration, "migration_is_live": live}
return self.json({"state": hass.state.value, "recorder_state": recorder_state})
class APIEventStream(HomeAssistantView):
@@ -387,6 +390,27 @@ class APIDomainServicesView(HomeAssistantView):
)
context = self.context(request)
if not hass.services.has_service(domain, service):
raise HTTPBadRequest from ServiceNotFound(domain, service)
if response_requested := "return_response" in request.query:
if (
hass.services.supports_response(domain, service)
is ha.SupportsResponse.NONE
):
return self.json_message(
"Service does not support responses. Remove return_response from request.",
HTTPStatus.BAD_REQUEST,
)
elif (
hass.services.supports_response(domain, service) is ha.SupportsResponse.ONLY
):
return self.json_message(
"Service call requires responses but caller did not ask for responses. "
"Add ?return_response to query parameters.",
HTTPStatus.BAD_REQUEST,
)
changed_states: list[json_fragment] = []
@ha.callback
@@ -403,13 +427,14 @@ class APIDomainServicesView(HomeAssistantView):
try:
# shield the service call from cancellation on connection drop
await shield(
response = await shield(
hass.services.async_call(
domain,
service,
data, # type: ignore[arg-type]
blocking=True,
context=context,
return_response=response_requested,
)
)
except (vol.Invalid, ServiceNotFound) as ex:
@@ -417,6 +442,11 @@ class APIDomainServicesView(HomeAssistantView):
finally:
cancel_listen()
if response_requested:
return self.json(
{"changed_states": changed_states, "service_response": response}
)
return self.json(changed_states)

View File

@@ -60,6 +60,7 @@ AUTH_EXCEPTIONS = (
exceptions.NoCredentialsError,
)
CONNECTION_TIMEOUT_EXCEPTIONS = (
OSError,
asyncio.CancelledError,
TimeoutError,
exceptions.ConnectionLostError,

View File

@@ -7,12 +7,13 @@ from dataclasses import dataclass
from APsystemsEZ1 import APsystemsEZ1M
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_IP_ADDRESS, Platform
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT, Platform
from homeassistant.core import HomeAssistant
from .const import DEFAULT_PORT
from .coordinator import ApSystemsDataCoordinator
PLATFORMS: list[Platform] = [Platform.NUMBER, Platform.SENSOR]
PLATFORMS: list[Platform] = [Platform.NUMBER, Platform.SENSOR, Platform.SWITCH]
@dataclass
@@ -28,7 +29,11 @@ type ApSystemsConfigEntry = ConfigEntry[ApSystemsData]
async def async_setup_entry(hass: HomeAssistant, entry: ApSystemsConfigEntry) -> bool:
"""Set up this integration using UI."""
api = APsystemsEZ1M(ip_address=entry.data[CONF_IP_ADDRESS], timeout=8)
api = APsystemsEZ1M(
ip_address=entry.data[CONF_IP_ADDRESS],
port=entry.data.get(CONF_PORT, DEFAULT_PORT),
timeout=8,
)
coordinator = ApSystemsDataCoordinator(hass, api)
await coordinator.async_config_entry_first_refresh()
assert entry.unique_id

View File

@@ -7,14 +7,16 @@ from APsystemsEZ1 import APsystemsEZ1M
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from .const import DOMAIN
from .const import DEFAULT_PORT, DOMAIN
DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_IP_ADDRESS): str,
vol.Required(CONF_IP_ADDRESS): cv.string,
vol.Optional(CONF_PORT): cv.port,
}
)
@@ -32,7 +34,11 @@ class APsystemsLocalAPIFlow(ConfigFlow, domain=DOMAIN):
if user_input is not None:
session = async_get_clientsession(self.hass, False)
api = APsystemsEZ1M(user_input[CONF_IP_ADDRESS], session=session)
api = APsystemsEZ1M(
ip_address=user_input[CONF_IP_ADDRESS],
port=user_input.get(CONF_PORT, DEFAULT_PORT),
session=session,
)
try:
device_info = await api.get_device_info()
except (TimeoutError, ClientConnectionError):

View File

@@ -4,3 +4,4 @@ from logging import Logger, getLogger
LOGGER: Logger = getLogger(__package__)
DOMAIN = "apsystems"
DEFAULT_PORT = 8050

View File

@@ -3,7 +3,11 @@
"step": {
"user": {
"data": {
"ip_address": "[%key:common::config_flow::data::ip%]"
"ip_address": "[%key:common::config_flow::data::ip%]",
"port": "[%key:common::config_flow::data::port%]"
},
"data_description": {
"port": "The integration will default to 8050, if not set, which should be suitable for most installs"
}
}
},
@@ -16,18 +20,43 @@
},
"entity": {
"sensor": {
"total_power": { "name": "Total power" },
"total_power_p1": { "name": "Power of P1" },
"total_power_p2": { "name": "Power of P2" },
"lifetime_production": { "name": "Total lifetime production" },
"lifetime_production_p1": { "name": "Lifetime production of P1" },
"lifetime_production_p2": { "name": "Lifetime production of P2" },
"today_production": { "name": "Production of today" },
"today_production_p1": { "name": "Production of today from P1" },
"today_production_p2": { "name": "Production of today from P2" }
"total_power": {
"name": "Total power"
},
"total_power_p1": {
"name": "Power of P1"
},
"total_power_p2": {
"name": "Power of P2"
},
"lifetime_production": {
"name": "Total lifetime production"
},
"lifetime_production_p1": {
"name": "Lifetime production of P1"
},
"lifetime_production_p2": {
"name": "Lifetime production of P2"
},
"today_production": {
"name": "Production of today"
},
"today_production_p1": {
"name": "Production of today from P1"
},
"today_production_p2": {
"name": "Production of today from P2"
}
},
"number": {
"max_output": { "name": "Max output" }
"max_output": {
"name": "Max output"
}
},
"switch": {
"inverter_status": {
"name": "Inverter status"
}
}
}
}

View File

@@ -0,0 +1,56 @@
"""The power switch which can be toggled via the APsystems local API integration."""
from __future__ import annotations
from typing import Any
from aiohttp.client_exceptions import ClientConnectionError
from APsystemsEZ1 import Status
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ApSystemsConfigEntry, ApSystemsData
from .entity import ApSystemsEntity
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ApSystemsConfigEntry,
add_entities: AddEntitiesCallback,
) -> None:
"""Set up the switch platform."""
add_entities([ApSystemsInverterSwitch(config_entry.runtime_data)], True)
class ApSystemsInverterSwitch(ApSystemsEntity, SwitchEntity):
"""The switch class for APSystems switches."""
_attr_device_class = SwitchDeviceClass.SWITCH
_attr_translation_key = "inverter_status"
def __init__(self, data: ApSystemsData) -> None:
"""Initialize the switch."""
super().__init__(data)
self._api = data.coordinator.api
self._attr_unique_id = f"{data.device_id}_inverter_status"
async def async_update(self) -> None:
"""Update switch status and availability."""
try:
status = await self._api.get_device_power_status()
except (TimeoutError, ClientConnectionError):
self._attr_available = False
else:
self._attr_available = True
self._attr_is_on = status == Status.normal
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
await self._api.set_device_power_status(0)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
await self._api.set_device_power_status(1)

View File

@@ -19,7 +19,10 @@ class AsekoEntity(CoordinatorEntity[AsekoDataUpdateCoordinator]):
super().__init__(coordinator)
self._unit = unit
self._device_model = f"ASIN AQUA {self._unit.type}"
if self._unit.type == "Remote":
self._device_model = "ASIN Pool"
else:
self._device_model = f"ASIN AQUA {self._unit.type}"
self._device_name = self._unit.name if self._unit.name else self._device_model
self._attr_device_info = DeviceInfo(

View File

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

View File

@@ -16,6 +16,10 @@ from .const import (
DATA_LAST_WAKE_UP,
DOMAIN,
EVENT_RECORDING,
SAMPLE_CHANNELS,
SAMPLE_RATE,
SAMPLE_WIDTH,
SAMPLES_PER_CHUNK,
)
from .error import PipelineNotFound
from .pipeline import (
@@ -53,6 +57,10 @@ __all__ = (
"PipelineNotFound",
"WakeWordSettings",
"EVENT_RECORDING",
"SAMPLES_PER_CHUNK",
"SAMPLE_RATE",
"SAMPLE_WIDTH",
"SAMPLE_CHANNELS",
)
CONFIG_SCHEMA = vol.Schema(

View File

@@ -0,0 +1,72 @@
"""Audio enhancement for Assist."""
from abc import ABC, abstractmethod
from dataclasses import dataclass
import logging
from pymicro_vad import MicroVad
from .const import BYTES_PER_CHUNK
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, slots=True)
class EnhancedAudioChunk:
"""Enhanced audio chunk and metadata."""
audio: bytes
"""Raw PCM audio @ 16Khz with 16-bit mono samples"""
timestamp_ms: int
"""Timestamp relative to start of audio stream (milliseconds)"""
is_speech: bool | None
"""True if audio chunk likely contains speech, False if not, None if unknown"""
class AudioEnhancer(ABC):
"""Base class for audio enhancement."""
def __init__(
self, auto_gain: int, noise_suppression: int, is_vad_enabled: bool
) -> None:
"""Initialize audio enhancer."""
self.auto_gain = auto_gain
self.noise_suppression = noise_suppression
self.is_vad_enabled = is_vad_enabled
@abstractmethod
def enhance_chunk(self, audio: bytes, timestamp_ms: int) -> EnhancedAudioChunk:
"""Enhance chunk of PCM audio @ 16Khz with 16-bit mono samples."""
class MicroVadEnhancer(AudioEnhancer):
"""Audio enhancer that just runs microVAD."""
def __init__(
self, auto_gain: int, noise_suppression: int, is_vad_enabled: bool
) -> None:
"""Initialize audio enhancer."""
super().__init__(auto_gain, noise_suppression, is_vad_enabled)
self.vad: MicroVad | None = None
self.threshold = 0.5
if self.is_vad_enabled:
self.vad = MicroVad()
_LOGGER.debug("Initialized microVAD with threshold=%s", self.threshold)
def enhance_chunk(self, audio: bytes, timestamp_ms: int) -> EnhancedAudioChunk:
"""Enhance 10ms chunk of PCM audio @ 16Khz with 16-bit mono samples."""
is_speech: bool | None = None
if self.vad is not None:
# Run VAD
assert len(audio) == BYTES_PER_CHUNK
speech_prob = self.vad.Process10ms(audio)
is_speech = speech_prob > self.threshold
return EnhancedAudioChunk(
audio=audio, timestamp_ms=timestamp_ms, is_speech=is_speech
)

View File

@@ -15,3 +15,10 @@ DATA_LAST_WAKE_UP = f"{DOMAIN}.last_wake_up"
WAKE_WORD_COOLDOWN = 2 # seconds
EVENT_RECORDING = f"{DOMAIN}_recording"
SAMPLE_RATE = 16000 # hertz
SAMPLE_WIDTH = 2 # bytes
SAMPLE_CHANNELS = 1 # mono
MS_PER_CHUNK = 10
SAMPLES_PER_CHUNK = SAMPLE_RATE // (1000 // MS_PER_CHUNK) # 10 ms @ 16Khz
BYTES_PER_CHUNK = SAMPLES_PER_CHUNK * SAMPLE_WIDTH * SAMPLE_CHANNELS # 16-bit

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/assist_pipeline",
"iot_class": "local_push",
"quality_scale": "internal",
"requirements": ["webrtc-noise-gain==1.2.3"]
"requirements": ["pymicro-vad==1.0.1"]
}

View File

@@ -13,14 +13,11 @@ from pathlib import Path
from queue import Empty, Queue
from threading import Thread
import time
from typing import TYPE_CHECKING, Any, Final, Literal, cast
from typing import Any, Literal, cast
import wave
import voluptuous as vol
if TYPE_CHECKING:
from webrtc_noise_gain import AudioProcessor
from homeassistant.components import (
conversation,
media_source,
@@ -52,12 +49,19 @@ from homeassistant.util import (
)
from homeassistant.util.limited_size_dict import LimitedSizeDict
from .audio_enhancer import AudioEnhancer, EnhancedAudioChunk, MicroVadEnhancer
from .const import (
BYTES_PER_CHUNK,
CONF_DEBUG_RECORDING_DIR,
DATA_CONFIG,
DATA_LAST_WAKE_UP,
DATA_MIGRATIONS,
DOMAIN,
MS_PER_CHUNK,
SAMPLE_CHANNELS,
SAMPLE_RATE,
SAMPLE_WIDTH,
SAMPLES_PER_CHUNK,
WAKE_WORD_COOLDOWN,
)
from .error import (
@@ -111,9 +115,6 @@ STORED_PIPELINE_RUNS = 10
SAVE_DELAY = 10
AUDIO_PROCESSOR_SAMPLES: Final = 160 # 10 ms @ 16 Khz
AUDIO_PROCESSOR_BYTES: Final = AUDIO_PROCESSOR_SAMPLES * 2 # 16-bit samples
@callback
def _async_resolve_default_pipeline_settings(
@@ -503,8 +504,8 @@ class AudioSettings:
is_vad_enabled: bool = True
"""True if VAD is used to determine the end of the voice command."""
is_chunking_enabled: bool = True
"""True if audio is automatically split into 10 ms chunks (required for VAD, etc.)"""
silence_seconds: float = 0.5
"""Seconds of silence after voice command has ended."""
def __post_init__(self) -> None:
"""Verify settings post-initialization."""
@@ -514,9 +515,6 @@ class AudioSettings:
if (self.auto_gain_dbfs < 0) or (self.auto_gain_dbfs > 31):
raise ValueError("auto_gain_dbfs must be in [0, 31]")
if self.needs_processor and (not self.is_chunking_enabled):
raise ValueError("Chunking must be enabled for audio processing")
@property
def needs_processor(self) -> bool:
"""True if an audio processor is needed."""
@@ -527,20 +525,6 @@ class AudioSettings:
)
@dataclass(frozen=True, slots=True)
class ProcessedAudioChunk:
"""Processed audio chunk and metadata."""
audio: bytes
"""Raw PCM audio @ 16Khz with 16-bit mono samples"""
timestamp_ms: int
"""Timestamp relative to start of audio stream (milliseconds)"""
is_speech: bool | None
"""True if audio chunk likely contains speech, False if not, None if unknown"""
@dataclass
class PipelineRun:
"""Running context for a pipeline."""
@@ -573,10 +557,12 @@ class PipelineRun:
debug_recording_queue: Queue[str | bytes | None] | None = None
"""Queue to communicate with debug recording thread"""
audio_processor: AudioProcessor | None = None
audio_enhancer: AudioEnhancer | None = None
"""VAD/noise suppression/auto gain"""
audio_processor_buffer: AudioBuffer = field(init=False, repr=False)
audio_chunking_buffer: AudioBuffer = field(
default_factory=lambda: AudioBuffer(BYTES_PER_CHUNK)
)
"""Buffer used when splitting audio into chunks for audio processing"""
_device_id: str | None = None
@@ -601,17 +587,12 @@ class PipelineRun:
pipeline_data.pipeline_runs.add_run(self)
# Initialize with audio settings
self.audio_processor_buffer = AudioBuffer(AUDIO_PROCESSOR_BYTES)
if self.audio_settings.needs_processor:
# Delay import of webrtc so HA start up is not crashing
# on older architectures (armhf).
#
# pylint: disable=import-outside-toplevel
from webrtc_noise_gain import AudioProcessor
self.audio_processor = AudioProcessor(
if self.audio_settings.needs_processor and (self.audio_enhancer is None):
# Default audio enhancer
self.audio_enhancer = MicroVadEnhancer(
self.audio_settings.auto_gain_dbfs,
self.audio_settings.noise_suppression_level,
self.audio_settings.is_vad_enabled,
)
def __eq__(self, other: object) -> bool:
@@ -688,8 +669,8 @@ class PipelineRun:
async def wake_word_detection(
self,
stream: AsyncIterable[ProcessedAudioChunk],
audio_chunks_for_stt: list[ProcessedAudioChunk],
stream: AsyncIterable[EnhancedAudioChunk],
audio_chunks_for_stt: list[EnhancedAudioChunk],
) -> wake_word.DetectionResult | None:
"""Run wake-word-detection portion of pipeline. Returns detection result."""
metadata_dict = asdict(
@@ -732,10 +713,11 @@ class PipelineRun:
# Audio chunk buffer. This audio will be forwarded to speech-to-text
# after wake-word-detection.
num_audio_chunks_to_buffer = int(
(wake_word_settings.audio_seconds_to_buffer * 16000)
/ AUDIO_PROCESSOR_SAMPLES
(wake_word_settings.audio_seconds_to_buffer * SAMPLE_RATE)
/ SAMPLES_PER_CHUNK
)
stt_audio_buffer: deque[ProcessedAudioChunk] | None = None
stt_audio_buffer: deque[EnhancedAudioChunk] | None = None
if num_audio_chunks_to_buffer > 0:
stt_audio_buffer = deque(maxlen=num_audio_chunks_to_buffer)
@@ -797,7 +779,7 @@ class PipelineRun:
# speech-to-text so the user does not have to pause before
# speaking the voice command.
audio_chunks_for_stt.extend(
ProcessedAudioChunk(
EnhancedAudioChunk(
audio=chunk_ts[0], timestamp_ms=chunk_ts[1], is_speech=False
)
for chunk_ts in result.queued_audio
@@ -819,18 +801,17 @@ class PipelineRun:
async def _wake_word_audio_stream(
self,
audio_stream: AsyncIterable[ProcessedAudioChunk],
stt_audio_buffer: deque[ProcessedAudioChunk] | None,
audio_stream: AsyncIterable[EnhancedAudioChunk],
stt_audio_buffer: deque[EnhancedAudioChunk] | None,
wake_word_vad: VoiceActivityTimeout | None,
sample_rate: int = 16000,
sample_width: int = 2,
sample_rate: int = SAMPLE_RATE,
sample_width: int = SAMPLE_WIDTH,
) -> AsyncIterable[tuple[bytes, int]]:
"""Yield audio chunks with timestamps (milliseconds since start of stream).
Adds audio to a ring buffer that will be forwarded to speech-to-text after
detection. Times out if VAD detects enough silence.
"""
chunk_seconds = AUDIO_PROCESSOR_SAMPLES / sample_rate
async for chunk in audio_stream:
if self.abort_wake_word_detection:
raise WakeWordDetectionAborted
@@ -845,6 +826,7 @@ class PipelineRun:
stt_audio_buffer.append(chunk)
if wake_word_vad is not None:
chunk_seconds = (len(chunk.audio) // sample_width) / sample_rate
if not wake_word_vad.process(chunk_seconds, chunk.is_speech):
raise WakeWordTimeoutError(
code="wake-word-timeout", message="Wake word was not detected"
@@ -881,7 +863,7 @@ class PipelineRun:
async def speech_to_text(
self,
metadata: stt.SpeechMetadata,
stream: AsyncIterable[ProcessedAudioChunk],
stream: AsyncIterable[EnhancedAudioChunk],
) -> str:
"""Run speech-to-text portion of pipeline. Returns the spoken text."""
# Create a background task to prepare the conversation agent
@@ -916,7 +898,9 @@ class PipelineRun:
# Transcribe audio stream
stt_vad: VoiceCommandSegmenter | None = None
if self.audio_settings.is_vad_enabled:
stt_vad = VoiceCommandSegmenter()
stt_vad = VoiceCommandSegmenter(
silence_seconds=self.audio_settings.silence_seconds
)
result = await self.stt_provider.async_process_audio_stream(
metadata,
@@ -957,18 +941,18 @@ class PipelineRun:
async def _speech_to_text_stream(
self,
audio_stream: AsyncIterable[ProcessedAudioChunk],
audio_stream: AsyncIterable[EnhancedAudioChunk],
stt_vad: VoiceCommandSegmenter | None,
sample_rate: int = 16000,
sample_width: int = 2,
sample_rate: int = SAMPLE_RATE,
sample_width: int = SAMPLE_WIDTH,
) -> AsyncGenerator[bytes]:
"""Yield audio chunks until VAD detects silence or speech-to-text completes."""
chunk_seconds = AUDIO_PROCESSOR_SAMPLES / sample_rate
sent_vad_start = False
async for chunk in audio_stream:
self._capture_chunk(chunk.audio)
if stt_vad is not None:
chunk_seconds = (len(chunk.audio) // sample_width) / sample_rate
if not stt_vad.process(chunk_seconds, chunk.is_speech):
# Silence detected at the end of voice command
self.process_event(
@@ -1072,8 +1056,8 @@ class PipelineRun:
tts_options[tts.ATTR_PREFERRED_FORMAT] = self.tts_audio_output
if self.tts_audio_output == "wav":
# 16 Khz, 16-bit mono
tts_options[tts.ATTR_PREFERRED_SAMPLE_RATE] = 16000
tts_options[tts.ATTR_PREFERRED_SAMPLE_CHANNELS] = 1
tts_options[tts.ATTR_PREFERRED_SAMPLE_RATE] = SAMPLE_RATE
tts_options[tts.ATTR_PREFERRED_SAMPLE_CHANNELS] = SAMPLE_CHANNELS
try:
options_supported = await tts.async_support_options(
@@ -1218,53 +1202,31 @@ class PipelineRun:
self.debug_recording_thread = None
async def process_volume_only(
self,
audio_stream: AsyncIterable[bytes],
sample_rate: int = 16000,
sample_width: int = 2,
) -> AsyncGenerator[ProcessedAudioChunk]:
self, audio_stream: AsyncIterable[bytes]
) -> AsyncGenerator[EnhancedAudioChunk]:
"""Apply volume transformation only (no VAD/audio enhancements) with optional chunking."""
ms_per_sample = sample_rate // 1000
ms_per_chunk = (AUDIO_PROCESSOR_SAMPLES // sample_width) // ms_per_sample
timestamp_ms = 0
async for chunk in audio_stream:
if self.audio_settings.volume_multiplier != 1.0:
chunk = _multiply_volume(chunk, self.audio_settings.volume_multiplier)
if self.audio_settings.is_chunking_enabled:
# 10 ms chunking
for chunk_10ms in chunk_samples(
chunk, AUDIO_PROCESSOR_BYTES, self.audio_processor_buffer
):
yield ProcessedAudioChunk(
audio=chunk_10ms,
timestamp_ms=timestamp_ms,
is_speech=None, # no VAD
)
timestamp_ms += ms_per_chunk
else:
# No chunking
yield ProcessedAudioChunk(
audio=chunk,
for sub_chunk in chunk_samples(
chunk, BYTES_PER_CHUNK, self.audio_chunking_buffer
):
yield EnhancedAudioChunk(
audio=sub_chunk,
timestamp_ms=timestamp_ms,
is_speech=None, # no VAD
)
timestamp_ms += (len(chunk) // sample_width) // ms_per_sample
timestamp_ms += MS_PER_CHUNK
async def process_enhance_audio(
self,
audio_stream: AsyncIterable[bytes],
sample_rate: int = 16000,
sample_width: int = 2,
) -> AsyncGenerator[ProcessedAudioChunk]:
"""Split audio into 10 ms chunks and apply VAD/noise suppression/auto gain/volume transformation."""
assert self.audio_processor is not None
self, audio_stream: AsyncIterable[bytes]
) -> AsyncGenerator[EnhancedAudioChunk]:
"""Split audio into chunks and apply VAD/noise suppression/auto gain/volume transformation."""
assert self.audio_enhancer is not None
ms_per_sample = sample_rate // 1000
ms_per_chunk = (AUDIO_PROCESSOR_SAMPLES // sample_width) // ms_per_sample
timestamp_ms = 0
async for dirty_samples in audio_stream:
if self.audio_settings.volume_multiplier != 1.0:
# Static gain
@@ -1272,18 +1234,12 @@ class PipelineRun:
dirty_samples, self.audio_settings.volume_multiplier
)
# Split into 10ms chunks for audio enhancements/VAD
for dirty_10ms_chunk in chunk_samples(
dirty_samples, AUDIO_PROCESSOR_BYTES, self.audio_processor_buffer
# Split into chunks for audio enhancements/VAD
for dirty_chunk in chunk_samples(
dirty_samples, BYTES_PER_CHUNK, self.audio_chunking_buffer
):
ap_result = self.audio_processor.Process10ms(dirty_10ms_chunk)
yield ProcessedAudioChunk(
audio=ap_result.audio,
timestamp_ms=timestamp_ms,
is_speech=ap_result.is_speech,
)
timestamp_ms += ms_per_chunk
yield self.audio_enhancer.enhance_chunk(dirty_chunk, timestamp_ms)
timestamp_ms += MS_PER_CHUNK
def _multiply_volume(chunk: bytes, volume_multiplier: float) -> bytes:
@@ -1323,9 +1279,9 @@ def _pipeline_debug_recording_thread_proc(
wav_path = run_recording_dir / f"{message}.wav"
wav_writer = wave.open(str(wav_path), "wb")
wav_writer.setframerate(16000)
wav_writer.setsampwidth(2)
wav_writer.setnchannels(1)
wav_writer.setframerate(SAMPLE_RATE)
wav_writer.setsampwidth(SAMPLE_WIDTH)
wav_writer.setnchannels(SAMPLE_CHANNELS)
elif isinstance(message, bytes):
# Chunk of 16-bit mono audio at 16Khz
if wav_writer is not None:
@@ -1368,8 +1324,8 @@ class PipelineInput:
"""Run pipeline."""
self.run.start(device_id=self.device_id)
current_stage: PipelineStage | None = self.run.start_stage
stt_audio_buffer: list[ProcessedAudioChunk] = []
stt_processed_stream: AsyncIterable[ProcessedAudioChunk] | None = None
stt_audio_buffer: list[EnhancedAudioChunk] = []
stt_processed_stream: AsyncIterable[EnhancedAudioChunk] | None = None
if self.stt_stream is not None:
if self.run.audio_settings.needs_processor:
@@ -1423,7 +1379,7 @@ class PipelineInput:
# Send audio in the buffer first to speech-to-text, then move on to stt_stream.
# This is basically an async itertools.chain.
async def buffer_then_audio_stream() -> (
AsyncGenerator[ProcessedAudioChunk]
AsyncGenerator[EnhancedAudioChunk]
):
# Buffered audio
for chunk in stt_audio_buffer:

View File

@@ -2,11 +2,13 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from collections.abc import Iterable
from collections.abc import Callable, Iterable
from dataclasses import dataclass
from enum import StrEnum
from typing import Final, cast
import logging
from typing import Final
_LOGGER = logging.getLogger(__name__)
_SAMPLE_RATE: Final = 16000 # Hz
_SAMPLE_WIDTH: Final = 2 # bytes
@@ -32,44 +34,6 @@ class VadSensitivity(StrEnum):
return 1.0
class VoiceActivityDetector(ABC):
"""Base class for voice activity detectors (VAD)."""
@abstractmethod
def is_speech(self, chunk: bytes) -> bool:
"""Return True if audio chunk contains speech."""
@property
@abstractmethod
def samples_per_chunk(self) -> int | None:
"""Return number of samples per chunk or None if chunking is not required."""
class WebRtcVad(VoiceActivityDetector):
"""Voice activity detector based on webrtc."""
def __init__(self) -> None:
"""Initialize webrtcvad."""
# Delay import of webrtc so HA start up is not crashing
# on older architectures (armhf).
#
# pylint: disable=import-outside-toplevel
from webrtc_noise_gain import AudioProcessor
# Just VAD: no noise suppression or auto gain
self._audio_processor = AudioProcessor(0, 0)
def is_speech(self, chunk: bytes) -> bool:
"""Return True if audio chunk contains speech."""
result = self._audio_processor.Process10ms(chunk)
return cast(bool, result.is_speech)
@property
def samples_per_chunk(self) -> int | None:
"""Return 10 ms."""
return int(0.01 * _SAMPLE_RATE) # 10 ms
class AudioBuffer:
"""Fixed-sized audio buffer with variable internal length."""
@@ -116,7 +80,7 @@ class VoiceCommandSegmenter:
speech_seconds: float = 0.3
"""Seconds of speech before voice command has started."""
silence_seconds: float = 0.5
silence_seconds: float = 1.0
"""Seconds of silence after voice command has ended."""
timeout_seconds: float = 15.0
@@ -159,6 +123,10 @@ class VoiceCommandSegmenter:
"""
self._timeout_seconds_left -= chunk_seconds
if self._timeout_seconds_left <= 0:
_LOGGER.warning(
"VAD end of speech detection timed out after %s seconds",
self.timeout_seconds,
)
self.reset()
return False
@@ -169,29 +137,38 @@ class VoiceCommandSegmenter:
if self._speech_seconds_left <= 0:
# Inside voice command
self.in_command = True
self._silence_seconds_left = self.silence_seconds
_LOGGER.debug("Voice command started")
else:
# Reset if enough silence
self._reset_seconds_left -= chunk_seconds
if self._reset_seconds_left <= 0:
self._speech_seconds_left = self.speech_seconds
self._reset_seconds_left = self.reset_seconds
elif not is_speech:
# Silence in command
self._reset_seconds_left = self.reset_seconds
self._silence_seconds_left -= chunk_seconds
if self._silence_seconds_left <= 0:
# Command finished successfully
self.reset()
_LOGGER.debug("Voice command finished")
return False
else:
# Reset if enough speech
# Speech in command.
# Reset silence counter if enough speech.
self._reset_seconds_left -= chunk_seconds
if self._reset_seconds_left <= 0:
self._silence_seconds_left = self.silence_seconds
self._reset_seconds_left = self.reset_seconds
return True
def process_with_vad(
self,
chunk: bytes,
vad: VoiceActivityDetector,
vad_samples_per_chunk: int | None,
vad_is_speech: Callable[[bytes], bool],
leftover_chunk_buffer: AudioBuffer | None,
) -> bool:
"""Process an audio chunk using an external VAD.
@@ -200,20 +177,20 @@ class VoiceCommandSegmenter:
Returns False when voice command is finished.
"""
if vad.samples_per_chunk is None:
if vad_samples_per_chunk is None:
# No chunking
chunk_seconds = (len(chunk) // _SAMPLE_WIDTH) / _SAMPLE_RATE
is_speech = vad.is_speech(chunk)
is_speech = vad_is_speech(chunk)
return self.process(chunk_seconds, is_speech)
if leftover_chunk_buffer is None:
raise ValueError("leftover_chunk_buffer is required when vad uses chunking")
# With chunking
seconds_per_chunk = vad.samples_per_chunk / _SAMPLE_RATE
bytes_per_chunk = vad.samples_per_chunk * _SAMPLE_WIDTH
seconds_per_chunk = vad_samples_per_chunk / _SAMPLE_RATE
bytes_per_chunk = vad_samples_per_chunk * _SAMPLE_WIDTH
for vad_chunk in chunk_samples(chunk, bytes_per_chunk, leftover_chunk_buffer):
is_speech = vad.is_speech(vad_chunk)
is_speech = vad_is_speech(vad_chunk)
if not self.process(seconds_per_chunk, is_speech):
return False

View File

@@ -24,6 +24,9 @@ from .const import (
DEFAULT_WAKE_WORD_TIMEOUT,
DOMAIN,
EVENT_RECORDING,
SAMPLE_CHANNELS,
SAMPLE_RATE,
SAMPLE_WIDTH,
)
from .error import PipelineNotFound
from .pipeline import (
@@ -92,7 +95,6 @@ def async_register_websocket_api(hass: HomeAssistant) -> None:
vol.Optional("volume_multiplier"): float,
# Advanced use cases/testing
vol.Optional("no_vad"): bool,
vol.Optional("no_chunking"): bool,
}
},
extra=vol.ALLOW_EXTRA,
@@ -170,9 +172,14 @@ async def websocket_run(
# Yield until we receive an empty chunk
while chunk := await audio_queue.get():
if incoming_sample_rate != 16000:
if incoming_sample_rate != SAMPLE_RATE:
chunk, state = audioop.ratecv(
chunk, 2, 1, incoming_sample_rate, 16000, state
chunk,
SAMPLE_WIDTH,
SAMPLE_CHANNELS,
incoming_sample_rate,
SAMPLE_RATE,
state,
)
yield chunk
@@ -206,7 +213,6 @@ async def websocket_run(
auto_gain_dbfs=msg_input.get("auto_gain_dbfs", 0),
volume_multiplier=msg_input.get("volume_multiplier", 1.0),
is_vad_enabled=not msg_input.get("no_vad", False),
is_chunking_enabled=not msg_input.get("no_chunking", False),
)
elif start_stage == PipelineStage.INTENT:
# Input to conversation agent
@@ -424,9 +430,9 @@ def websocket_list_languages(
connection.send_result(
msg["id"],
{
"languages": sorted(pipeline_languages)
if pipeline_languages
else pipeline_languages
"languages": (
sorted(pipeline_languages) if pipeline_languages else pipeline_languages
)
},
)

View File

@@ -81,6 +81,7 @@ SENSOR_TYPES_VIDEO_DOORBELL = (
SENSOR_TYPES_DOORBELL: tuple[AugustDoorbellBinarySensorEntityDescription, ...] = (
AugustDoorbellBinarySensorEntityDescription(
key="ding",
translation_key="ding",
device_class=BinarySensorDeviceClass.OCCUPANCY,
value_fn=retrieve_ding_activity,
is_time_based=True,

View File

@@ -16,8 +16,6 @@ NOTIFICATION_TITLE = "August"
MANUFACTURER = "August Home Inc."
DEFAULT_AUGUST_CONFIG_FILE = ".august.conf"
DEFAULT_NAME = "August"
DOMAIN = "august"

View File

@@ -40,6 +40,9 @@
},
"entity": {
"binary_sensor": {
"ding": {
"name": "Doorbell ding"
},
"image_capture": {
"name": "Image capture"
}

View File

@@ -94,7 +94,7 @@ async def fetch_redirect_uris(hass: HomeAssistant, url: str) -> list[str]:
try:
async with (
aiohttp.ClientSession() as session,
session.get(url, timeout=5) as resp,
session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp,
):
async for data in resp.content.iter_chunked(1024):
parser.feed(data.decode())

View File

@@ -7,7 +7,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from .const import DOMAIN as AXIS_DOMAIN, PLATFORMS
from .const import PLATFORMS
from .errors import AuthenticationRequired, CannotConnect
from .hub import AxisHub, get_axis_api
@@ -18,8 +18,6 @@ type AxisConfigEntry = ConfigEntry[AxisHub]
async def async_setup_entry(hass: HomeAssistant, config_entry: AxisConfigEntry) -> bool:
"""Set up the Axis integration."""
hass.data.setdefault(AXIS_DOMAIN, {})
try:
api = await get_axis_api(hass, config_entry.data)
except CannotConnect as err:

View File

@@ -18,7 +18,7 @@ from homeassistant.core import Event, HomeAssistant, State
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.entityfilter import FILTER_SCHEMA
from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.json import JSONEncoder
from homeassistant.helpers.json import ExtendedJSONEncoder
from homeassistant.helpers.typing import ConfigType
from homeassistant.util.dt import utcnow
@@ -203,9 +203,7 @@ class AzureDataExplorer:
return None, dropped
if (utcnow() - time_fired).seconds > DEFAULT_MAX_DELAY + self._send_interval:
return None, dropped + 1
if "\n" in state.state:
return None, dropped + 1
json_event = json.dumps(obj=state, cls=JSONEncoder)
json_event = json.dumps(obj=state, cls=ExtendedJSONEncoder)
return (json_event, dropped)

View File

@@ -68,7 +68,7 @@ class AzureDataExplorerClient:
# Queued is the only option supported on free tier of ADX
self.write_client = QueuedIngestClient(kcsb_ingest)
else:
self.write_client = ManagedStreamingIngestClient.from_dm_kcsb(kcsb_ingest)
self.write_client = ManagedStreamingIngestClient(kcsb_ingest)
self.query_client = KustoClient(kcsb_query)

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/azure_data_explorer",
"iot_class": "cloud_push",
"loggers": ["azure"],
"requirements": ["azure-kusto-ingest==3.1.0", "azure-kusto-data[aio]==3.1.0"]
"requirements": ["azure-kusto-ingest==4.5.1", "azure-kusto-data[aio]==4.5.1"]
}

View File

@@ -43,7 +43,10 @@ class BAFFan(BAFEntity, FanEntity):
FanEntityFeature.SET_SPEED
| FanEntityFeature.DIRECTION
| FanEntityFeature.PRESET_MODE
| FanEntityFeature.TURN_OFF
| FanEntityFeature.TURN_ON
)
_enable_turn_on_off_backwards_compatibility = False
_attr_preset_modes = [PRESET_MODE_AUTO]
_attr_speed_count = SPEED_COUNT
_attr_name = None

View File

@@ -32,7 +32,12 @@ async def async_setup_entry(
class BalboaPumpFanEntity(BalboaEntity, FanEntity):
"""Representation of a Balboa Spa pump fan entity."""
_attr_supported_features = FanEntityFeature.SET_SPEED
_attr_supported_features = (
FanEntityFeature.SET_SPEED
| FanEntityFeature.TURN_OFF
| FanEntityFeature.TURN_ON
)
_enable_turn_on_off_backwards_compatibility = False
_attr_translation_key = "pump"
def __init__(self, control: SpaControl) -> None:

View File

@@ -135,6 +135,15 @@ class BangOlufsenConfigFlowHandler(ConfigFlow, domain=DOMAIN):
except AddressValueError:
return self.async_abort(reason="ipv6_address")
# Check connection to ensure valid address is received
self._client = MozartClient(self._host)
async with self._client:
try:
await self._client.get_beolink_self(_request_timeout=3)
except (ClientConnectorError, TimeoutError):
return self.async_abort(reason="invalid_address")
self._model = discovery_info.hostname[:-16].replace("-", " ")
self._serial_number = discovery_info.properties[ATTR_SERIAL_NUMBER]
self._beolink_jid = f"{discovery_info.properties[ATTR_TYPE_NUMBER]}.{discovery_info.properties[ATTR_ITEM_NUMBER]}.{self._serial_number}@products.bang-olufsen.com"

View File

@@ -245,14 +245,36 @@ async def fetch_blueprint_from_website_url(
return ImportedBlueprint(suggested_filename, raw_yaml, blueprint)
async def fetch_blueprint_from_generic_url(
hass: HomeAssistant, url: str
) -> ImportedBlueprint:
"""Get a blueprint from a generic website."""
session = aiohttp_client.async_get_clientsession(hass)
resp = await session.get(url, raise_for_status=True)
raw_yaml = await resp.text()
data = yaml.parse_yaml(raw_yaml)
assert isinstance(data, dict)
blueprint = Blueprint(data)
parsed_import_url = yarl.URL(url)
suggested_filename = f"{parsed_import_url.host}/{parsed_import_url.parts[-1][:-5]}"
return ImportedBlueprint(suggested_filename, raw_yaml, blueprint)
FETCH_FUNCTIONS = (
fetch_blueprint_from_community_post,
fetch_blueprint_from_github_url,
fetch_blueprint_from_github_gist_url,
fetch_blueprint_from_website_url,
fetch_blueprint_from_generic_url,
)
async def fetch_blueprint_from_url(hass: HomeAssistant, url: str) -> ImportedBlueprint:
"""Get a blueprint from a url."""
for func in (
fetch_blueprint_from_community_post,
fetch_blueprint_from_github_url,
fetch_blueprint_from_github_gist_url,
fetch_blueprint_from_website_url,
):
for func in FETCH_FUNCTIONS:
with suppress(UnsupportedUrl):
imported_bp = await func(hass, url)
imported_bp.blueprint.update_metadata(source_url=url)

View File

@@ -21,7 +21,7 @@ from homeassistant.const import (
CONF_PATH,
__version__,
)
from homeassistant.core import DOMAIN as HA_DOMAIN, HomeAssistant, callback
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.util import yaml
@@ -372,7 +372,7 @@ class DomainBlueprints:
shutil.copytree(
integration.file_path / BLUEPRINT_FOLDER,
self.blueprint_folder / HA_DOMAIN,
self.blueprint_folder / HOMEASSISTANT_DOMAIN,
)
await self.hass.async_add_executor_job(populate)

View File

@@ -1 +1,70 @@
"""The bluesound component."""
from dataclasses import dataclass
import aiohttp
from pyblu import Player, SyncStatus
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
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 .media_player import setup_services
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
PLATFORMS = [Platform.MEDIA_PLAYER]
@dataclass
class BluesoundData:
"""Bluesound data class."""
player: Player
sync_status: SyncStatus
type BluesoundConfigEntry = ConfigEntry[BluesoundData]
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Bluesound."""
if DOMAIN not in hass.data:
hass.data[DOMAIN] = []
setup_services(hass)
return True
async def async_setup_entry(
hass: HomeAssistant, config_entry: BluesoundConfigEntry
) -> bool:
"""Set up the Bluesound entry."""
host = config_entry.data[CONF_HOST]
port = config_entry.data[CONF_PORT]
session = async_get_clientsession(hass)
async with Player(host, port, session=session, default_timeout=10) as player:
try:
sync_status = await player.sync_status(timeout=1)
except TimeoutError as ex:
raise ConfigEntryNotReady(
f"Timeout while connecting to {host}:{port}"
) from ex
except aiohttp.ClientError as ex:
raise ConfigEntryNotReady(f"Error connecting to {host}:{port}") from ex
config_entry.runtime_data = BluesoundData(player, sync_status)
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)

View File

@@ -0,0 +1,150 @@
"""Config flow for bluesound."""
import logging
from typing import Any
import aiohttp
from pyblu import Player, SyncStatus
import voluptuous as vol
from homeassistant.components import zeroconf
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
from .media_player import DEFAULT_PORT
from .utils import format_unique_id
_LOGGER = logging.getLogger(__name__)
class BluesoundConfigFlow(ConfigFlow, domain=DOMAIN):
"""Bluesound config flow."""
VERSION = 1
MINOR_VERSION = 1
def __init__(self) -> None:
"""Initialize the config flow."""
self._host: str | None = None
self._port = DEFAULT_PORT
self._sync_status: SyncStatus | None = None
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a flow initiated by the user."""
errors: dict[str, str] = {}
if user_input is not None:
session = async_get_clientsession(self.hass)
async with Player(
user_input[CONF_HOST], user_input[CONF_PORT], session=session
) as player:
try:
sync_status = await player.sync_status(timeout=1)
except (TimeoutError, aiohttp.ClientError):
errors["base"] = "cannot_connect"
else:
await self.async_set_unique_id(
format_unique_id(sync_status.mac, user_input[CONF_PORT])
)
self._abort_if_unique_id_configured(
updates={
CONF_HOST: user_input[CONF_HOST],
}
)
return self.async_create_entry(
title=sync_status.name,
data=user_input,
)
return self.async_show_form(
step_id="user",
errors=errors,
data_schema=vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Optional(CONF_PORT, default=11000): int,
}
),
)
async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
"""Import bluesound config entry from configuration.yaml."""
session = async_get_clientsession(self.hass)
async with Player(
import_data[CONF_HOST], import_data[CONF_PORT], session=session
) as player:
try:
sync_status = await player.sync_status(timeout=1)
except (TimeoutError, aiohttp.ClientError):
return self.async_abort(reason="cannot_connect")
await self.async_set_unique_id(
format_unique_id(sync_status.mac, import_data[CONF_PORT])
)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=sync_status.name,
data=import_data,
)
async def async_step_zeroconf(
self, discovery_info: zeroconf.ZeroconfServiceInfo
) -> ConfigFlowResult:
"""Handle a flow initialized by zeroconf discovery."""
if discovery_info.port is not None:
self._port = discovery_info.port
session = async_get_clientsession(self.hass)
try:
async with Player(
discovery_info.host, self._port, session=session
) as player:
sync_status = await player.sync_status(timeout=1)
except (TimeoutError, aiohttp.ClientError):
return self.async_abort(reason="cannot_connect")
await self.async_set_unique_id(format_unique_id(sync_status.mac, self._port))
self._host = discovery_info.host
self._sync_status = sync_status
self._abort_if_unique_id_configured(
updates={
CONF_HOST: self._host,
}
)
self.context.update(
{
"title_placeholders": {"name": sync_status.name},
"configuration_url": f"http://{discovery_info.host}",
}
)
return await self.async_step_confirm()
async def async_step_confirm(self, user_input=None) -> ConfigFlowResult:
"""Confirm the zeroconf setup."""
assert self._sync_status is not None
assert self._host is not None
if user_input is not None:
return self.async_create_entry(
title=self._sync_status.name,
data={
CONF_HOST: self._host,
CONF_PORT: self._port,
},
)
return self.async_show_form(
step_id="confirm",
description_placeholders={
"name": self._sync_status.name,
"host": self._host,
},
)

View File

@@ -1,7 +1,10 @@
"""Constants for the Bluesound HiFi wireless speakers and audio integrations component."""
DOMAIN = "bluesound"
INTEGRATION_TITLE = "Bluesound"
SERVICE_CLEAR_TIMER = "clear_sleep_timer"
SERVICE_JOIN = "join"
SERVICE_SET_TIMER = "set_sleep_timer"
SERVICE_UNJOIN = "unjoin"
ATTR_BLUESOUND_GROUP = "bluesound_group"
ATTR_MASTER = "master"

View File

@@ -1,8 +1,15 @@
{
"domain": "bluesound",
"name": "Bluesound",
"codeowners": ["@thrawnarn"],
"after_dependencies": ["zeroconf"],
"codeowners": ["@thrawnarn", "@LouisChrist"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/bluesound",
"iot_class": "local_polling",
"requirements": ["xmltodict==0.13.0"]
"requirements": ["pyblu==0.4.0"],
"zeroconf": [
{
"type": "_musc._tcp.local."
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,30 @@
{
"config": {
"step": {
"user": {
"data": {
"host": "[%key:common::config_flow::data::host%]",
"port": "[%key:common::config_flow::data::port%]"
},
"data_description": {
"host": "Hostname or IP address of your Bluesound player",
"port": "Port of your Bluesound player. This is usually 11000."
}
},
"confirm": {
"title": "Discover Bluesound player",
"description": "[%key:common::config_flow::description::confirm_setup%]"
}
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
}
},
"services": {
"join": {
"name": "Join",

View File

@@ -0,0 +1,8 @@
"""Utility functions for the Bluesound component."""
from homeassistant.helpers.device_registry import format_mac
def format_unique_id(mac: str, port: int) -> str:
"""Generate a unique ID based on the MAC address and port number."""
return f"{format_mac(mac)}-{port}"

View File

@@ -18,7 +18,7 @@
"bleak-retry-connector==3.5.0",
"bluetooth-adapters==0.19.3",
"bluetooth-auto-recovery==1.4.2",
"bluetooth-data-tools==1.19.3",
"bluetooth-data-tools==1.19.4",
"dbus-fast==2.22.1",
"habluetooth==3.1.3"
]

View File

@@ -2,6 +2,7 @@
from __future__ import annotations
from collections import defaultdict
from dataclasses import dataclass
from fnmatch import translate
from functools import lru_cache
@@ -173,10 +174,10 @@ class BluetoothMatcherIndexBase[
def __init__(self) -> None:
"""Initialize the matcher index."""
self.local_name: dict[str, list[_T]] = {}
self.service_uuid: dict[str, list[_T]] = {}
self.service_data_uuid: dict[str, list[_T]] = {}
self.manufacturer_id: dict[int, list[_T]] = {}
self.local_name: defaultdict[str, list[_T]] = defaultdict(list)
self.service_uuid: defaultdict[str, list[_T]] = defaultdict(list)
self.service_data_uuid: defaultdict[str, list[_T]] = defaultdict(list)
self.manufacturer_id: defaultdict[int, list[_T]] = defaultdict(list)
self.service_uuid_set: set[str] = set()
self.service_data_uuid_set: set[str] = set()
self.manufacturer_id_set: set[int] = set()
@@ -190,26 +191,22 @@ class BluetoothMatcherIndexBase[
"""
# Local name is the cheapest to match since its just a dict lookup
if LOCAL_NAME in matcher:
self.local_name.setdefault(
_local_name_to_index_key(matcher[LOCAL_NAME]), []
).append(matcher)
self.local_name[_local_name_to_index_key(matcher[LOCAL_NAME])].append(
matcher
)
return True
# Manufacturer data is 2nd cheapest since its all ints
if MANUFACTURER_ID in matcher:
self.manufacturer_id.setdefault(matcher[MANUFACTURER_ID], []).append(
matcher
)
self.manufacturer_id[matcher[MANUFACTURER_ID]].append(matcher)
return True
if SERVICE_UUID in matcher:
self.service_uuid.setdefault(matcher[SERVICE_UUID], []).append(matcher)
self.service_uuid[matcher[SERVICE_UUID]].append(matcher)
return True
if SERVICE_DATA_UUID in matcher:
self.service_data_uuid.setdefault(matcher[SERVICE_DATA_UUID], []).append(
matcher
)
self.service_data_uuid[matcher[SERVICE_DATA_UUID]].append(matcher)
return True
return False
@@ -260,32 +257,38 @@ class BluetoothMatcherIndexBase[
if ble_device_matches(matcher, service_info)
)
if self.service_data_uuid_set and service_info.service_data:
if (
(service_data_uuid_set := self.service_data_uuid_set)
and (service_data := service_info.service_data)
and (matched_uuids := service_data_uuid_set.intersection(service_data))
):
matches.extend(
matcher
for service_data_uuid in self.service_data_uuid_set.intersection(
service_info.service_data
)
for service_data_uuid in matched_uuids
for matcher in self.service_data_uuid[service_data_uuid]
if ble_device_matches(matcher, service_info)
)
if self.manufacturer_id_set and service_info.manufacturer_data:
if (
(manufacturer_id_set := self.manufacturer_id_set)
and (manufacturer_data := service_info.manufacturer_data)
and (matched_ids := manufacturer_id_set.intersection(manufacturer_data))
):
matches.extend(
matcher
for manufacturer_id in self.manufacturer_id_set.intersection(
service_info.manufacturer_data
)
for manufacturer_id in matched_ids
for matcher in self.manufacturer_id[manufacturer_id]
if ble_device_matches(matcher, service_info)
)
if self.service_uuid_set and service_info.service_uuids:
if (
(service_uuid_set := self.service_uuid_set)
and (service_uuids := service_info.service_uuids)
and (matched_uuids := service_uuid_set.intersection(service_uuids))
):
matches.extend(
matcher
for service_uuid in self.service_uuid_set.intersection(
service_info.service_uuids
)
for service_uuid in matched_uuids
for matcher in self.service_uuid[service_uuid]
if ble_device_matches(matcher, service_info)
)
@@ -310,7 +313,9 @@ class BluetoothCallbackMatcherIndex(
def __init__(self) -> None:
"""Initialize the matcher index."""
super().__init__()
self.address: dict[str, list[BluetoothCallbackMatcherWithCallback]] = {}
self.address: defaultdict[str, list[BluetoothCallbackMatcherWithCallback]] = (
defaultdict(list)
)
self.connectable: list[BluetoothCallbackMatcherWithCallback] = []
def add_callback_matcher(
@@ -323,7 +328,7 @@ class BluetoothCallbackMatcherIndex(
We put them in the bucket that they are most likely to match.
"""
if ADDRESS in matcher:
self.address.setdefault(matcher[ADDRESS], []).append(matcher)
self.address[matcher[ADDRESS]].append(matcher)
return
if super().add(matcher):

View File

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

View File

@@ -86,7 +86,8 @@
"name": "Charging Mode",
"state": {
"immediate_charging": "Immediate charging",
"delayed_charging": "Delayed charging"
"delayed_charging": "Delayed charging",
"no_action": "No action"
}
}
},

View File

@@ -69,7 +69,7 @@ class BondFan(BondEntity, FanEntity):
super().__init__(data, device)
if self._device.has_action(Action.BREEZE_ON):
self._attr_preset_modes = [PRESET_MODE_BREEZE]
features = FanEntityFeature(0)
features = FanEntityFeature.TURN_OFF | FanEntityFeature.TURN_ON
if self._device.supports_speed():
features |= FanEntityFeature.SET_SPEED
if self._device.supports_direction():

View File

@@ -4,8 +4,8 @@ from __future__ import annotations
import logging
from bring_api.bring import Bring
from bring_api.exceptions import (
from bring_api import (
Bring,
BringAuthException,
BringParseException,
BringRequestException,

View File

@@ -6,9 +6,12 @@ from collections.abc import Mapping
import logging
from typing import Any
from bring_api.bring import Bring
from bring_api.exceptions import BringAuthException, BringRequestException
from bring_api.types import BringAuthResponse
from bring_api import (
Bring,
BringAuthException,
BringAuthResponse,
BringRequestException,
)
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
@@ -58,7 +61,7 @@ class BringConfigFlow(ConfigFlow, domain=DOMAIN):
):
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=self.info["name"] or user_input[CONF_EMAIL], data=user_input
title=self.info.get("name") or user_input[CONF_EMAIL], data=user_input
)
return self.async_show_form(

View File

@@ -5,8 +5,8 @@ from __future__ import annotations
from datetime import timedelta
import logging
from bring_api.bring import Bring
from bring_api.exceptions import (
from bring_api import (
Bring,
BringAuthException,
BringParseException,
BringRequestException,

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/bring",
"integration_type": "service",
"iot_class": "cloud_polling",
"requirements": ["bring-api==0.7.1"]
"requirements": ["bring-api==0.8.1"]
}

View File

@@ -5,8 +5,12 @@ from __future__ import annotations
from typing import TYPE_CHECKING
import uuid
from bring_api.exceptions import BringRequestException
from bring_api.types import BringItem, BringItemOperation, BringNotificationType
from bring_api import (
BringItem,
BringItemOperation,
BringNotificationType,
BringRequestException,
)
import voluptuous as vol
from homeassistant.components.todo import (

View File

@@ -1,5 +1,6 @@
"""Support for Broadlink climate devices."""
from enum import IntEnum
from typing import Any
from homeassistant.components.climate import (
@@ -19,6 +20,14 @@ from .device import BroadlinkDevice
from .entity import BroadlinkEntity
class SensorMode(IntEnum):
"""Thermostat sensor modes."""
INNER_SENSOR_CONTROL = 0
OUTER_SENSOR_CONTROL = 1
INNER_SENSOR_CONTROL_OUTER_LIMIT = 2
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
@@ -50,6 +59,7 @@ class BroadlinkThermostat(BroadlinkEntity, ClimateEntity):
super().__init__(device)
self._attr_unique_id = device.unique_id
self._attr_hvac_mode = None
self.sensor_mode = SensorMode.INNER_SENSOR_CONTROL
async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
@@ -61,6 +71,8 @@ class BroadlinkThermostat(BroadlinkEntity, ClimateEntity):
@callback
def _update_state(self, data: dict[str, Any]) -> None:
"""Update data."""
if (sensor := data.get("sensor")) is not None:
self.sensor_mode = SensorMode(sensor)
if data.get("power"):
if data.get("auto_mode"):
self._attr_hvac_mode = HVACMode.AUTO
@@ -74,8 +86,10 @@ class BroadlinkThermostat(BroadlinkEntity, ClimateEntity):
else:
self._attr_hvac_mode = HVACMode.OFF
self._attr_hvac_action = HVACAction.OFF
self._attr_current_temperature = data.get("room_temp")
if self.sensor_mode is SensorMode.OUTER_SENSOR_CONTROL:
self._attr_current_temperature = data.get("external_temp")
else:
self._attr_current_temperature = data.get("room_temp")
self._attr_target_temperature = data.get("thermostat_temp")
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
@@ -85,7 +99,9 @@ class BroadlinkThermostat(BroadlinkEntity, ClimateEntity):
else:
await self._device.async_request(self._device.api.set_power, 1)
mode = 0 if hvac_mode == HVACMode.HEAT else 1
await self._device.async_request(self._device.api.set_mode, mode, 0)
await self._device.async_request(
self._device.api.set_mode, mode, 0, self.sensor_mode.value
)
self._attr_hvac_mode = hvac_mode
self.async_write_ha_state()

View File

@@ -0,0 +1,84 @@
"""The Bryant Evolution integration."""
from __future__ import annotations
import logging
from evolutionhttp import BryantEvolutionLocalClient
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_FILENAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from . import names
from .const import CONF_SYSTEM_ZONE, DOMAIN
PLATFORMS: list[Platform] = [Platform.CLIMATE]
type BryantEvolutionLocalClients = dict[tuple[int, int], BryantEvolutionLocalClient]
type BryantEvolutionConfigEntry = ConfigEntry[BryantEvolutionLocalClients]
_LOGGER = logging.getLogger(__name__)
async def _can_reach_device(client: BryantEvolutionLocalClient) -> bool:
"""Return whether we can reach the device at the given filename."""
# Verify that we can read current temperature to check that the
# (filename, system, zone) is valid.
return await client.read_current_temperature() is not None
async def async_setup_entry(
hass: HomeAssistant, entry: BryantEvolutionConfigEntry
) -> bool:
"""Set up Bryant Evolution from a config entry."""
# Add a device for the SAM itself.
sam_uid = names.sam_device_uid(entry)
device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, sam_uid)},
manufacturer="Bryant",
name="System Access Module",
)
# Add a device for each system.
for sys_id in (1, 2):
if not any(sz[0] == sys_id for sz in entry.data[CONF_SYSTEM_ZONE]):
_LOGGER.debug(
"Skipping system %s because it is not configured for this integration: %s",
sys_id,
entry.data[CONF_SYSTEM_ZONE],
)
continue
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, names.system_device_uid(sam_uid, sys_id))},
via_device=(DOMAIN, names.sam_device_uid(entry)),
manufacturer="Bryant",
name=f"System {sys_id}",
)
# Create a client for every zone.
entry.runtime_data = {}
for sz in entry.data[CONF_SYSTEM_ZONE]:
try:
client = await BryantEvolutionLocalClient.get_client(
sz[0], sz[1], entry.data[CONF_FILENAME]
)
if not await _can_reach_device(client):
raise ConfigEntryNotReady
entry.runtime_data[tuple(sz)] = client
except FileNotFoundError as f:
raise ConfigEntryNotReady from f
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_unload_entry(
hass: HomeAssistant, entry: BryantEvolutionConfigEntry
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@@ -0,0 +1,252 @@
"""Support for Bryant Evolution HVAC systems."""
from datetime import timedelta
import logging
from typing import Any
from evolutionhttp import BryantEvolutionLocalClient
from homeassistant.components.climate import (
ClimateEntity,
ClimateEntityFeature,
HVACAction,
HVACMode,
)
from homeassistant.const import UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import BryantEvolutionConfigEntry, names
from .const import CONF_SYSTEM_ZONE, DOMAIN
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=60)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: BryantEvolutionConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up a config entry."""
# Add a climate entity for each system/zone.
sam_uid = names.sam_device_uid(config_entry)
entities: list[Entity] = []
for sz in config_entry.data[CONF_SYSTEM_ZONE]:
system_id = sz[0]
zone_id = sz[1]
client = config_entry.runtime_data.get(tuple(sz))
climate = BryantEvolutionClimate(
client,
system_id,
zone_id,
sam_uid,
)
entities.append(climate)
async_add_entities(entities, update_before_add=True)
class BryantEvolutionClimate(ClimateEntity):
"""ClimateEntity for Bryant Evolution HVAC systems.
Design note: this class updates using polling. However, polling
is very slow (~1500 ms / parameter). To improve the user
experience on updates, we also locally update this instance and
call async_write_ha_state as well.
"""
_attr_has_entity_name = True
_attr_temperature_unit = UnitOfTemperature.FAHRENHEIT
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_attr_hvac_modes = [
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
]
_attr_fan_modes = ["auto", "low", "med", "high"]
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,
client: BryantEvolutionLocalClient,
system_id: int,
zone_id: int,
sam_uid: str,
) -> None:
"""Initialize an entity from parts."""
self._client = client
self._attr_name = None
self._attr_unique_id = names.zone_entity_uid(sam_uid, system_id, zone_id)
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._attr_unique_id)},
manufacturer="Bryant",
via_device=(DOMAIN, names.system_device_uid(sam_uid, system_id)),
name=f"System {system_id} Zone {zone_id}",
)
async def async_update(self) -> None:
"""Update the entity state."""
self._attr_current_temperature = await self._client.read_current_temperature()
if (fan_mode := await self._client.read_fan_mode()) is not None:
self._attr_fan_mode = fan_mode.lower()
else:
self._attr_fan_mode = None
self._attr_target_temperature = None
self._attr_target_temperature_high = None
self._attr_target_temperature_low = None
self._attr_hvac_mode = await self._read_hvac_mode()
# Set target_temperature or target_temperature_{high, low} based on mode.
match self._attr_hvac_mode:
case HVACMode.HEAT:
self._attr_target_temperature = (
await self._client.read_heating_setpoint()
)
case HVACMode.COOL:
self._attr_target_temperature = (
await self._client.read_cooling_setpoint()
)
case HVACMode.HEAT_COOL:
self._attr_target_temperature_high = (
await self._client.read_cooling_setpoint()
)
self._attr_target_temperature_low = (
await self._client.read_heating_setpoint()
)
case HVACMode.OFF:
pass
case _:
_LOGGER.error("Unknown HVAC mode %s", self._attr_hvac_mode)
# Note: depends on current temperature and target temperature low read
# above.
self._attr_hvac_action = await self._read_hvac_action()
async def _read_hvac_mode(self) -> HVACMode:
mode_and_active = await self._client.read_hvac_mode()
if not mode_and_active:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_read_hvac_mode"
)
mode = mode_and_active[0]
mode_enum = {
"HEAT": HVACMode.HEAT,
"COOL": HVACMode.COOL,
"AUTO": HVACMode.HEAT_COOL,
"OFF": HVACMode.OFF,
}.get(mode.upper())
if mode_enum is None:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="failed_to_parse_hvac_mode",
translation_placeholders={"mode": mode},
)
return mode_enum
async def _read_hvac_action(self) -> HVACAction:
"""Return the current running hvac operation."""
mode_and_active = await self._client.read_hvac_mode()
if not mode_and_active:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_read_hvac_action"
)
mode, is_active = mode_and_active
if not is_active:
return HVACAction.OFF
match mode.upper():
case "HEAT":
return HVACAction.HEATING
case "COOL":
return HVACAction.COOLING
case "OFF":
return HVACAction.OFF
case "AUTO":
# In AUTO, we need to figure out what the actual action is
# based on the setpoints.
if (
self.current_temperature is not None
and self.target_temperature_low is not None
):
if self.current_temperature > self.target_temperature_low:
# If the system is on and the current temperature is
# higher than the point at which heating would activate,
# then we must be cooling.
return HVACAction.COOLING
return HVACAction.HEATING
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="failed_to_parse_hvac_mode",
translation_placeholders={
"mode_and_active": mode_and_active,
"current_temperature": str(self.current_temperature),
"target_temperature_low": str(self.target_temperature_low),
},
)
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
"""Set new target hvac mode."""
if hvac_mode == HVACMode.HEAT_COOL:
hvac_mode = HVACMode.AUTO
if not await self._client.set_hvac_mode(hvac_mode):
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_set_hvac_mode"
)
self._attr_hvac_mode = hvac_mode
self._async_write_ha_state()
async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
if kwargs.get("target_temp_high"):
temp = int(kwargs["target_temp_high"])
if not await self._client.set_cooling_setpoint(temp):
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_set_clsp"
)
self._attr_target_temperature_high = temp
if kwargs.get("target_temp_low"):
temp = int(kwargs["target_temp_low"])
if not await self._client.set_heating_setpoint(temp):
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_set_htsp"
)
self._attr_target_temperature_low = temp
if kwargs.get("temperature"):
temp = int(kwargs["temperature"])
fn = (
self._client.set_heating_setpoint
if self.hvac_mode == HVACMode.HEAT
else self._client.set_cooling_setpoint
)
if not await fn(temp):
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_set_temp"
)
self._attr_target_temperature = temp
# If we get here, we must have changed something unless HA allowed an
# invalid service call (without any recognized kwarg).
self._async_write_ha_state()
async def async_set_fan_mode(self, fan_mode: str) -> None:
"""Set new target fan mode."""
if not await self._client.set_fan_mode(fan_mode):
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="failed_to_set_fan_mode"
)
self._attr_fan_mode = fan_mode.lower()
self.async_write_ha_state()

View File

@@ -0,0 +1,87 @@
"""Config flow for Bryant Evolution integration."""
from __future__ import annotations
import logging
from typing import Any
from evolutionhttp import BryantEvolutionLocalClient
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_FILENAME
from homeassistant.helpers.typing import UNDEFINED
from .const import CONF_SYSTEM_ZONE, DOMAIN
_LOGGER = logging.getLogger(__name__)
STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_FILENAME, default="/dev/ttyUSB0"): str,
}
)
async def _enumerate_sz(tty: str) -> list[tuple[int, int]]:
"""Return (system, zone) tuples for each system+zone accessible through tty."""
return [
(system_id, zone.zone_id)
for system_id in (1, 2)
for zone in await BryantEvolutionLocalClient.enumerate_zones(system_id, tty)
]
class BryantConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Bryant Evolution."""
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
try:
system_zone = await _enumerate_sz(user_input[CONF_FILENAME])
except FileNotFoundError:
_LOGGER.error("Could not open %s: not found", user_input[CONF_FILENAME])
errors["base"] = "cannot_connect"
else:
if len(system_zone) != 0:
return self.async_create_entry(
title=f"SAM at {user_input[CONF_FILENAME]}",
data={
CONF_FILENAME: user_input[CONF_FILENAME],
CONF_SYSTEM_ZONE: system_zone,
},
)
errors["base"] = "cannot_connect"
return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle integration reconfiguration."""
errors: dict[str, str] = {}
if user_input is not None:
system_zone = await _enumerate_sz(user_input[CONF_FILENAME])
if len(system_zone) != 0:
our_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"]
)
assert our_entry is not None, "Could not find own entry"
return self.async_update_reload_and_abort(
entry=our_entry,
data={
CONF_FILENAME: user_input[CONF_FILENAME],
CONF_SYSTEM_ZONE: system_zone,
},
unique_id=UNDEFINED,
reason="reconfigured",
)
errors["base"] = "cannot_connect"
return self.async_show_form(
step_id="reconfigure", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
)

View File

@@ -0,0 +1,4 @@
"""Constants for the Bryant Evolution integration."""
DOMAIN = "bryant_evolution"
CONF_SYSTEM_ZONE = "system_zone"

View File

@@ -0,0 +1,10 @@
{
"domain": "bryant_evolution",
"name": "Bryant Evolution",
"codeowners": ["@danielsmyers"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/bryant_evolution",
"integration_type": "device",
"iot_class": "local_polling",
"requirements": ["evolutionhttp==0.0.18"]
}

View File

@@ -0,0 +1,18 @@
"""Functions to generate names for devices and entities."""
from homeassistant.config_entries import ConfigEntry
def sam_device_uid(entry: ConfigEntry) -> str:
"""Return the UID for the SAM device."""
return entry.entry_id
def system_device_uid(sam_uid: str, system_id: int) -> str:
"""Return the UID for a given system (e.g., 1) under a SAM."""
return f"{sam_uid}-S{system_id}"
def zone_entity_uid(sam_uid: str, system_id: int, zone_id: int) -> str:
"""Return the UID for a given system and zone (e.g., 1 and 2) under a SAM."""
return f"{sam_uid}-S{system_id}-Z{zone_id}"

View File

@@ -0,0 +1,48 @@
{
"config": {
"step": {
"user": {
"data": {
"filename": "Serial port filename"
}
}
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}
},
"exceptions": {
"failed_to_read_hvac_mode": {
"message": "Failed to read current HVAC mode"
},
"failed_to_parse_hvac_mode": {
"message": "Cannot parse response to HVACMode: {mode}"
},
"failed_to_read_hvac_action": {
"message": "Failed to read current HVAC action"
},
"failed_to_parse_hvac_action": {
"message": "Could not determine HVAC action: {mode_and_active}, {self.current_temperature}, {self.target_temperature_low}"
},
"failed_to_set_hvac_mode": {
"message": "Failed to set HVAC mode"
},
"failed_to_set_clsp": {
"message": "Failed to set cooling setpoint"
},
"failed_to_set_htsp": {
"message": "Failed to set heating setpoint"
},
"failed_to_set_temp": {
"message": "Failed to set temperature"
},
"failed_to_set_fan_mode": {
"message": "Failed to set fan mode"
}
}
}

View File

@@ -2,6 +2,7 @@
from __future__ import annotations
from functools import partial
import logging
from bthome_ble import BTHomeBluetoothDeviceData, SensorUpdate
@@ -12,7 +13,6 @@ from homeassistant.components.bluetooth import (
BluetoothScanningMode,
BluetoothServiceInfoBleak,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
@@ -29,6 +29,7 @@ from .const import (
BTHomeBleEvent,
)
from .coordinator import BTHomePassiveBluetoothProcessorCoordinator
from .types import BTHomeConfigEntry
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.EVENT, Platform.SENSOR]
@@ -37,16 +38,14 @@ _LOGGER = logging.getLogger(__name__)
def process_service_info(
hass: HomeAssistant,
entry: ConfigEntry,
data: BTHomeBluetoothDeviceData,
service_info: BluetoothServiceInfoBleak,
entry: BTHomeConfigEntry,
device_registry: DeviceRegistry,
service_info: BluetoothServiceInfoBleak,
) -> SensorUpdate:
"""Process a BluetoothServiceInfoBleak, running side effects and returning sensor data."""
coordinator = entry.runtime_data
data = coordinator.device_data
update = data.update(service_info)
coordinator: BTHomePassiveBluetoothProcessorCoordinator = hass.data[DOMAIN][
entry.entry_id
]
discovered_event_classes = coordinator.discovered_event_classes
if entry.data.get(CONF_SLEEPY_DEVICE, False) != data.sleepy_device:
hass.config_entries.async_update_entry(
@@ -117,7 +116,7 @@ def format_discovered_event_class(address: str) -> SignalType[str, BTHomeBleEven
return SignalType(f"{DOMAIN}_discovered_event_class_{address}")
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: BTHomeConfigEntry) -> bool:
"""Set up BTHome Bluetooth from a config entry."""
address = entry.unique_id
assert address is not None
@@ -128,34 +127,26 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
data = BTHomeBluetoothDeviceData(**kwargs)
device_registry = dr.async_get(hass)
coordinator = hass.data.setdefault(DOMAIN, {})[entry.entry_id] = (
BTHomePassiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address=address,
mode=BluetoothScanningMode.PASSIVE,
update_method=lambda service_info: process_service_info(
hass, entry, data, service_info, device_registry
),
device_data=data,
discovered_event_classes=set(
entry.data.get(CONF_DISCOVERED_EVENT_CLASSES, [])
),
connectable=False,
entry=entry,
)
event_classes = set(entry.data.get(CONF_DISCOVERED_EVENT_CLASSES, ()))
coordinator = BTHomePassiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address=address,
mode=BluetoothScanningMode.PASSIVE,
update_method=partial(process_service_info, hass, entry, device_registry),
device_data=data,
discovered_event_classes=event_classes,
connectable=False,
entry=entry,
)
entry.runtime_data = coordinator
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(
coordinator.async_start()
) # only start after all platforms have had a chance to subscribe
# only start after all platforms have had a chance to subscribe
entry.async_on_unload(coordinator.async_start())
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: BTHomeConfigEntry) -> bool:
"""Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@@ -7,7 +7,6 @@ from bthome_ble import (
SensorUpdate,
)
from homeassistant import config_entries
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
@@ -21,12 +20,9 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.sensor import sensor_device_info_to_hass_device_info
from .const import DOMAIN
from .coordinator import (
BTHomePassiveBluetoothDataProcessor,
BTHomePassiveBluetoothProcessorCoordinator,
)
from .coordinator import BTHomePassiveBluetoothDataProcessor
from .device import device_key_to_bluetooth_entity_key
from .types import BTHomeConfigEntry
BINARY_SENSOR_DESCRIPTIONS = {
BTHomeBinarySensorDeviceClass.BATTERY: BinarySensorEntityDescription(
@@ -172,13 +168,11 @@ def sensor_update_to_bluetooth_data_update(
async def async_setup_entry(
hass: HomeAssistant,
entry: config_entries.ConfigEntry,
entry: BTHomeConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the BTHome BLE binary sensors."""
coordinator: BTHomePassiveBluetoothProcessorCoordinator = hass.data[DOMAIN][
entry.entry_id
]
coordinator = entry.runtime_data
processor = BTHomePassiveBluetoothDataProcessor(
sensor_update_to_bluetooth_data_update
)

View File

@@ -13,10 +13,10 @@ from homeassistant.components.bluetooth.passive_update_processor import (
PassiveBluetoothDataProcessor,
PassiveBluetoothProcessorCoordinator,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .const import CONF_SLEEPY_DEVICE
from .types import BTHomeConfigEntry
class BTHomePassiveBluetoothProcessorCoordinator(
@@ -33,7 +33,7 @@ class BTHomePassiveBluetoothProcessorCoordinator(
update_method: Callable[[BluetoothServiceInfoBleak], SensorUpdate],
device_data: BTHomeBluetoothDeviceData,
discovered_event_classes: set[str],
entry: ConfigEntry,
entry: BTHomeConfigEntry,
connectable: bool = False,
) -> None:
"""Initialize the BTHome Bluetooth Passive Update Processor Coordinator."""

View File

@@ -9,7 +9,6 @@ from homeassistant.components.event import (
EventEntity,
EventEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_connect
@@ -24,7 +23,7 @@ from .const import (
EVENT_TYPE,
BTHomeBleEvent,
)
from .coordinator import BTHomePassiveBluetoothProcessorCoordinator
from .types import BTHomeConfigEntry
DESCRIPTIONS_BY_EVENT_CLASS = {
EVENT_CLASS_BUTTON: EventEntityDescription(
@@ -103,13 +102,11 @@ class BTHomeEventEntity(EventEntity):
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: BTHomeConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up BTHome event."""
coordinator: BTHomePassiveBluetoothProcessorCoordinator = hass.data[DOMAIN][
entry.entry_id
]
coordinator = entry.runtime_data
address = coordinator.address
ent_reg = er.async_get(hass)
async_add_entities(

View File

@@ -9,7 +9,6 @@ from bthome_ble.const import (
ExtendedSensorDeviceClass as BTHomeExtendedSensorDeviceClass,
)
from homeassistant import config_entries
from homeassistant.components.bluetooth.passive_update_processor import (
PassiveBluetoothDataUpdate,
PassiveBluetoothProcessorEntity,
@@ -45,12 +44,9 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.sensor import sensor_device_info_to_hass_device_info
from .const import DOMAIN
from .coordinator import (
BTHomePassiveBluetoothDataProcessor,
BTHomePassiveBluetoothProcessorCoordinator,
)
from .coordinator import BTHomePassiveBluetoothDataProcessor
from .device import device_key_to_bluetooth_entity_key
from .types import BTHomeConfigEntry
SENSOR_DESCRIPTIONS = {
# Acceleration (m/s²)
@@ -394,13 +390,11 @@ def sensor_update_to_bluetooth_data_update(
async def async_setup_entry(
hass: HomeAssistant,
entry: config_entries.ConfigEntry,
entry: BTHomeConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the BTHome BLE sensors."""
coordinator: BTHomePassiveBluetoothProcessorCoordinator = hass.data[DOMAIN][
entry.entry_id
]
coordinator = entry.runtime_data
processor = BTHomePassiveBluetoothDataProcessor(
sensor_update_to_bluetooth_data_update
)

View File

@@ -0,0 +1,10 @@
"""The BTHome Bluetooth integration."""
from typing import TYPE_CHECKING
from homeassistant.config_entries import ConfigEntry
if TYPE_CHECKING:
from .coordinator import BTHomePassiveBluetoothProcessorCoordinator
type BTHomeConfigEntry = ConfigEntry[BTHomePassiveBluetoothProcessorCoordinator]

View File

@@ -115,7 +115,9 @@ class BuienradarCam(Camera):
headers = {}
try:
async with session.get(url, timeout=5, headers=headers) as res:
async with session.get(
url, timeout=aiohttp.ClientTimeout(total=5), headers=headers
) as res:
res.raise_for_status()
if res.status == 304:

View File

@@ -19,9 +19,9 @@
"step": {
"init": {
"data": {
"country_code": "Country code of the country to display camera images.",
"delta": "Time interval in seconds between camera image updates",
"timeframe": "Minutes to look ahead for precipitation forecast"
"country_code": "Country to display camera images for.",
"delta": "Interval between camera image updates",
"timeframe": "Time to look ahead for precipitation forecast"
}
}
}

View File

@@ -248,7 +248,7 @@ async def _fetch_playlist(hass, url, supported_content_types):
"""Fetch a playlist from the given url."""
try:
session = aiohttp_client.async_get_clientsession(hass, verify_ssl=False)
async with session.get(url, timeout=5) as resp:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp:
charset = resp.charset or "utf-8"
if resp.content_type in supported_content_types:
raise PlaylistSupported

View File

@@ -914,12 +914,37 @@ async def async_service_temperature_set(
"""Handle set temperature service."""
hass = entity.hass
kwargs = {}
min_temp = entity.min_temp
max_temp = entity.max_temp
temp_unit = entity.temperature_unit
for value, temp in service_call.data.items():
if value in CONVERTIBLE_ATTRIBUTE:
kwargs[value] = TemperatureConverter.convert(
temp, hass.config.units.temperature_unit, entity.temperature_unit
kwargs[value] = check_temp = TemperatureConverter.convert(
temp, hass.config.units.temperature_unit, temp_unit
)
_LOGGER.debug(
"Check valid temperature %d %s (%d %s) in range %d %s - %d %s",
check_temp,
entity.temperature_unit,
temp,
hass.config.units.temperature_unit,
min_temp,
temp_unit,
max_temp,
temp_unit,
)
if check_temp < min_temp or check_temp > max_temp:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="temp_out_of_range",
translation_placeholders={
"check_temp": str(check_temp),
"min_temp": str(min_temp),
"max_temp": str(max_temp),
},
)
else:
kwargs[value] = temp

View File

@@ -10,7 +10,6 @@ from homeassistant.const import ATTR_TEMPERATURE
from homeassistant.core import Context, HomeAssistant, State
from .const import (
ATTR_AUX_HEAT,
ATTR_FAN_MODE,
ATTR_HUMIDITY,
ATTR_HVAC_MODE,
@@ -20,7 +19,6 @@ from .const import (
ATTR_TARGET_TEMP_LOW,
DOMAIN,
HVAC_MODES,
SERVICE_SET_AUX_HEAT,
SERVICE_SET_FAN_MODE,
SERVICE_SET_HUMIDITY,
SERVICE_SET_HVAC_MODE,
@@ -56,9 +54,6 @@ async def _async_reproduce_states(
if state.state in HVAC_MODES:
await call_service(SERVICE_SET_HVAC_MODE, [], {ATTR_HVAC_MODE: state.state})
if ATTR_AUX_HEAT in state.attributes:
await call_service(SERVICE_SET_AUX_HEAT, [ATTR_AUX_HEAT])
if (
(ATTR_TEMPERATURE in state.attributes)
or (ATTR_TARGET_TEMP_HIGH in state.attributes)

View File

@@ -266,6 +266,9 @@
},
"not_valid_fan_mode": {
"message": "Fan mode {mode} is not valid. Valid fan modes are: {modes}."
},
"temp_out_of_range": {
"message": "Provided temperature {check_temp} is not valid. Accepted range is {min_temp} to {max_temp}."
}
}
}

View File

@@ -6,7 +6,7 @@ from collections.abc import Callable, Coroutine
from typing import Any
import uuid
from hass_nabucasa.voice import MAP_VOICE
from hass_nabucasa.voice import MAP_VOICE, Gender
from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.auth.models import User
@@ -91,8 +91,8 @@ class CloudPreferencesStore(Store):
# The new second item is the voice name.
default_tts_voice = old_data.get(PREF_TTS_DEFAULT_VOICE)
if default_tts_voice and (voice_item_two := default_tts_voice[1]) in (
"female",
"male",
Gender.FEMALE,
Gender.MALE,
):
language: str = default_tts_voice[0]
if voice := MAP_VOICE.get((language, voice_item_two)):

View File

@@ -13,7 +13,7 @@ from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import Event, HomeAssistant
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import dispatcher_send
@@ -76,7 +76,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
ccb.connect()
# Schedule disconnect on shutdown
def _shutdown(_event):
def _shutdown(_event: Event) -> None:
ccb.disconnect()
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
@@ -90,7 +90,15 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
class ComfoConnectBridge:
"""Representation of a ComfoConnect bridge."""
def __init__(self, hass, bridge, name, token, friendly_name, pin):
def __init__(
self,
hass: HomeAssistant,
bridge: Bridge,
name: str,
token: str,
friendly_name: str,
pin: int,
) -> None:
"""Initialize the ComfoConnect bridge."""
self.name = name
self.hass = hass
@@ -104,17 +112,17 @@ class ComfoConnectBridge:
)
self.comfoconnect.callback_sensor = self.sensor_callback
def connect(self):
def connect(self) -> None:
"""Connect with the bridge."""
_LOGGER.debug("Connecting with bridge")
self.comfoconnect.connect(True)
def disconnect(self):
def disconnect(self) -> None:
"""Disconnect from the bridge."""
_LOGGER.debug("Disconnecting from bridge")
self.comfoconnect.disconnect()
def sensor_callback(self, var, value):
def sensor_callback(self, var: str, value: str) -> None:
"""Notify listeners that we have received an update."""
_LOGGER.debug("Received update for %s: %s", var, value)
dispatcher_send(

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