Compare commits

...

257 Commits

Author SHA1 Message Date
Franck Nijhof
8c605c29c3 Bump version to 2024.2.0b9 2024-02-06 22:49:53 +01:00
Joakim Sørensen
74a75e709f Bump awesomeversion from 23.11.0 to 24.2.0 (#109830) 2024-02-06 22:49:41 +01:00
J. Nick Koston
2103875ff7 Bump aioesphomeapi to 21.0.2 (#109824) 2024-02-06 22:49:38 +01:00
Erik Montnemery
5c83b774bb Bump python-otbr-api to 2.6.0 (#109823) 2024-02-06 22:49:34 +01:00
Joost Lekkerkerker
2c870f9da9 Bump aioecowitt to 2024.2.0 (#109817) 2024-02-06 22:49:31 +01:00
Maciej Bieniek
40adb3809f Ignore trackable without details in Tractive integration (#109814)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-02-06 22:49:28 +01:00
wittypluck
8aa1242221 Mark Unifi bandwidth sensors as unavailable when client disconnects (#109812)
* Set sensor as unavailable instead of resetting value to 0 on disconnect

* Update unit test on unavailable bandwidth sensor
2024-02-06 22:49:25 +01:00
J. Nick Koston
8569ddc5f9 Fix entity services targeting entities outside the platform when using areas/devices (#109810) 2024-02-06 22:49:22 +01:00
Franck Nijhof
7032415528 Don't block Supervisor entry setup with refreshing updates (#109809) 2024-02-06 22:49:19 +01:00
puddly
d099fb2a26 Pin chacha20poly1305-reuseable>=0.12.1 (#109807)
* Pin `chacha20poly1305-reuseable`
Prevents a runtime `assert isinstance(cipher, AESGCM)` error

* Update `gen_requirements_all.py` as well
2024-02-06 22:49:16 +01:00
Jan-Philipp Benecke
35fad52913 Bump aioelectricitymaps to 0.3.1 (#109797) 2024-02-06 22:49:13 +01:00
Vilppu Vuorinen
c170132827 Update MELCloud codeowners (#109793)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-02-06 22:49:10 +01:00
Matthias Alphart
439f82a4ec Update xknx to 2.12.0 and xknxproject to 3.5.0 (#109787) 2024-02-06 22:49:07 +01:00
Steven B
2481d14632 Bump ring_doorbell to 0.8.7 (#109783) 2024-02-06 22:49:04 +01:00
Steven B
3cf826dc93 Bump ring_doorbell to 0.8.6 (#109199) 2024-02-06 22:48:59 +01:00
Jan-Philipp Benecke
e25ddf9650 Change state class of Tesla wall connector session energy entity (#109778) 2024-02-06 22:46:34 +01:00
puddly
8d79ac67f5 Bump ZHA dependencies (#109770)
* Bump ZHA dependencies

* Bump universal-silabs-flasher to 0.0.18

* Flip `Server_to_Client` enum in ZHA unit test

* Bump zigpy to 0.62.2
2024-02-06 22:46:31 +01:00
David F. Mulcahey
5025c15165 Buffer JsonDecodeError in Flo (#109767) 2024-02-06 22:46:28 +01:00
Joost Lekkerkerker
ffd5e04a29 Fix Radarr health check singularity (#109762)
* Fix Radarr health check singularity

* Fix comment
2024-02-06 22:46:25 +01:00
G Johansson
9fcdfd1b16 Bump holidays to 0.42 (#109760) 2024-02-06 22:46:21 +01:00
Vilppu Vuorinen
c1e5b2e6cc Fix compatibility issues with older pymelcloud version (#109757) 2024-02-06 22:42:58 +01:00
suaveolent
31c0d21204 Improve lupusec code quality (#109727)
* renamed async_add_devices

* fixed typo

* patch class instead of __init__

* ensure non blocking get_alarm

* exception handling

* added test case for json decode error

* avoid blockign calls

---------

Co-authored-by: suaveolent <suaveolent@users.noreply.github.com>
2024-02-06 22:42:54 +01:00
spycle
3ba63fc78f Fix keymitt_ble config-flow (#109644)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-02-06 22:42:51 +01:00
spycle
0395315267 Bump pyMicrobot to 0.0.10 (#109628) 2024-02-06 22:42:48 +01:00
TheJulianJES
6b354457c2 Fix ZHA creating unnecessary "summ received" entity after upgrade (#109268)
* Do not create `current_summ_received` entity until initialized once

* Update zha_devices_list.py to not expect summation received entities

The attribute isn't initialized for these devices in the test (which our check now expects it to be), hence we need to remove them from this list.

* Update sensor tests to have initial state for current_summ_received entity

The attribute needs to be initialized for it to be created which we do by plugging the attribute read.
The test expects the initial state to be "unknown", but hence we plugged the attribute (to create the entity), the state is whatever we plug the attribute read as.

* Update sensor tests to expect not updating current_summ_received entity if it doesn't exist
2024-02-06 22:42:43 +01:00
Franck Nijhof
df88335370 Bump version to 2024.2.0b8 2024-02-05 20:27:40 +01:00
Joost Lekkerkerker
4c6c5ee63d Handle startup error in Analytics insights (#109755) 2024-02-05 20:27:29 +01:00
Vilppu Vuorinen
65476914ed Reduce MELCloud poll frequency to avoid throttling (#109750) 2024-02-05 20:27:26 +01:00
Bouwe Westerdijk
d30a2e3611 Fix incorrectly assigning supported features for plugwise climates (#109749) 2024-02-05 20:27:23 +01:00
G Johansson
eb510e3630 Add missing new climate feature flags to Mill (#109748) 2024-02-05 20:27:20 +01:00
Michael
532df5b5f1 Use tracked entity friendly name for proximity sensors (#109744)
user tracked entity friendly name
2024-02-05 20:27:17 +01:00
Jan Bouwhuis
1534f99c80 Fix generic camera error when template renders to an invalid URL (#109737) 2024-02-05 20:27:14 +01:00
Cyrill Raccaud
a19aa9595a Bump python-bring-api to 3.0.0 (#109720) 2024-02-05 20:27:11 +01:00
Joost Lekkerkerker
e3191d098f Add strings to Ruuvitag BLE (#109717) 2024-02-05 20:27:08 +01:00
Bram Kragten
cc36071612 Update frontend to 20240205.0 (#109716) 2024-02-05 20:27:04 +01:00
Joakim Sørensen
2d90ee8237 Fix log string in Traccar Server Coordinator (#109709) 2024-02-05 20:27:01 +01:00
Simone Chemelli
16266703df Queue climate calls for Comelit SimpleHome (#109707) 2024-02-05 20:26:58 +01:00
Joost Lekkerkerker
dd2cc52119 Set Analytics Insights as diagnostic (#109702)
* Set Analytics Insights as diagnostic

* Set Analytics Insights as diagnostic
2024-02-05 20:26:54 +01:00
Joost Lekkerkerker
c48c8c25fa Remove obsolete check from Proximity (#109701) 2024-02-05 20:26:51 +01:00
Joost Lekkerkerker
83a5659d57 Set shorthand attribute in Epion (#109695) 2024-02-05 20:26:48 +01:00
Joost Lekkerkerker
3183cd346d Add data descriptions to analytics insights (#109694) 2024-02-05 20:26:45 +01:00
Marcel van der Veldt
5930c841d7 Bump python matter server to 5.4.1 (#109692) 2024-02-05 20:26:42 +01:00
Myles Eftos
f05ba22b5c Show site state in Amberelectric config flow (#104702) 2024-02-05 20:26:38 +01:00
Franck Nijhof
ecc6cc280a Bump version to 2024.2.0b7 2024-02-05 09:41:55 +01:00
David F. Mulcahey
f50afd6004 Buffer TImeoutError in Flo (#109675) 2024-02-05 09:41:45 +01:00
Michael
44ecaa740b Add missing translation string to Home Assistant Analytics Insights (#109666)
add missing string
2024-02-05 09:41:42 +01:00
Michael
91b1a8e962 Add icon translation to proximity (#109664)
add icon translations
2024-02-05 09:41:39 +01:00
Malte Franken
74f1b18b73 Bump georss-generic-client to 0.8 (#109658) 2024-02-05 09:41:36 +01:00
Michael
8ab1c044bd Add zone related sensors in proximity (#109630)
* move legacy needed convertions into legacy entity

* add zone related sensors

* fix test coverage

* fix typing

* fix entity name translations

* rename placeholder to tracked_entity
2024-02-05 09:41:33 +01:00
Leah Oswald
66d8856033 Fix home connect remaining progress time (#109525)
* fix remaining progress time for home connect component

The home connect API is sending some default values (on dishwashers) for
the remaining progress time after the program finished. This is a problem
because this value is stored and on every API event, for example opening
the door of a dishwasher, the value for remaining progress time is
updated with this wrong value. So I see a wrong value the whole time the
dishwasher is not running and therefore has no remaining progress time.
This coming fixes this problem and adds a check if the appliance is in
running, pause or finished state, because there we have valid data. In
the other states the new code just returns none like on other edge
cases. Now there is no value if there is no program running.

* fix some formating according to the ruff rules

* fix some formating according to the ruff rules again

* fix alphabetic order of imports

* add check if keys exist in dict before accessing them

check if BSH_OPERATION_STATE and ATTR_VALUE key values exist before
accessing them later in the elif statement

* fix formating because forgotten local ruff run
2024-02-05 09:41:30 +01:00
Kevin Worrel
5c1e4379a9 Screenlogic service refactor (#109041) 2024-02-05 09:41:27 +01:00
ollo69
bca9826e18 Don't create AsusWRT loadavg sensors when unavailable (#106790) 2024-02-05 09:41:23 +01:00
Franck Nijhof
3a067d445d Bump version to 2024.2.0b6 2024-02-04 23:25:49 +01:00
Franck Nijhof
4d7c96205d Fix Tuya reauth_successful translation string (#109659) 2024-02-04 23:25:41 +01:00
Jan-Philipp Benecke
3934524d4a Add icon translations to Utility meter helper (#109656) 2024-02-04 23:25:37 +01:00
Franck Nijhof
5747f8ce9d Improve Tuya token/reauth handling (#109653) 2024-02-04 23:25:34 +01:00
Joost Lekkerkerker
02ebf1d7f8 Add icon translations to Random (#109652) 2024-02-04 23:25:31 +01:00
Joost Lekkerkerker
d789e83879 Add icon translations to Counter (#109651) 2024-02-04 23:25:28 +01:00
Joost Lekkerkerker
ce29b4a7e3 Add icon translations to derivative (#109650) 2024-02-04 23:25:25 +01:00
Joost Lekkerkerker
e2695ba88f Allow the helper integrations to omit icon translation field (#109648) 2024-02-04 23:25:22 +01:00
G Johansson
7ca83a7648 Add debug logger for cpu temp in System Monitor (#109627) 2024-02-04 23:25:19 +01:00
G Johansson
c0efec4a84 Fix repairs for remove dates in Workday (#109626) 2024-02-04 23:25:16 +01:00
Franck Nijhof
f766fbfb98 Fix Tuya QR code expiry, use native QR selector (#109615)
* Fix Tuya QR code expiry, use native QR selector

* Adjust tests
2024-02-04 23:25:14 +01:00
Franck Nijhof
bd78c44ac5 Update orjson to 3.9.13 (#109614) 2024-02-04 23:25:11 +01:00
Jan Bouwhuis
fd2469e2a7 Fix imap message part decoding (#109523) 2024-02-04 23:25:08 +01:00
Cody C
a7010e3e80 Handle GeoJSON int to str conversion when the name is an int (#108937)
Co-authored-by: Chris Roberts <NasaGeek@users.noreply.github.com>
2024-02-04 23:25:04 +01:00
Franck Nijhof
d379a9aaae Bump version to 2024.2.0b5 2024-02-04 15:59:46 +01:00
Michael
2dc630a4af Redact location names in proximity diagnostics (#109600) 2024-02-04 15:59:34 +01:00
Josef Zweck
ba0c065750 Bugfix lamarzocco issue (#109596) 2024-02-04 15:59:31 +01:00
tronikos
4fca06256b Fix Google generative AI service example (#109594)
Update strings.json
2024-02-04 15:59:28 +01:00
J. Nick Koston
0a25788822 Bump yalexs-ble to 2.4.1 (#109585)
changelog: https://github.com/bdraco/yalexs-ble/compare/v2.4.0...v2.4.1
2024-02-04 15:59:25 +01:00
G Johansson
94e1eaa15d Fix overkiz climate feature flags for valve heating (#109582)
* Fix overkiz climate feature flags for valve heating

* Update homeassistant/components/overkiz/climate_entities/valve_heating_temperature_interface.py
2024-02-04 15:59:22 +01:00
G Johansson
dfc26e4509 Fix group sensor uom's in not convertable device classes (#109580) 2024-02-04 15:59:20 +01:00
Matrix
b14add5914 Fix yolink abnormal status when LeakSensor detection mode changes to "no water detect" (#109575)
Add no water detect support
2024-02-04 15:59:17 +01:00
G Johansson
7be6aa455e Add back logging for core for feature flags in climate (#109572) 2024-02-04 15:59:14 +01:00
G Johansson
40636f2273 Add new climate feature flags to lyric (#109571) 2024-02-04 15:59:11 +01:00
G Johansson
f91f98e309 Add new climate feature flags to lookin (#109570) 2024-02-04 15:59:08 +01:00
G Johansson
838b1338b8 Add migrated climate feature flags to livisi (#109569) 2024-02-04 15:59:05 +01:00
G Johansson
d3aa7375f0 Add new climate feature flags to lightwave (#109568) 2024-02-04 15:59:02 +01:00
G Johansson
514ce59a8f Add new climate feature flags to lcn (#109566) 2024-02-04 15:58:59 +01:00
G Johansson
25063821e1 Add new climate feature flags to izone (#109565) 2024-02-04 15:58:56 +01:00
G Johansson
b3c257fb79 Add new climate feature flags to isy994 (#109564) 2024-02-04 15:58:53 +01:00
G Johansson
cb02c2e6d0 Fix new climate feature flags in intesishome (#109563) 2024-02-04 15:58:50 +01:00
G Johansson
1000fae905 Add new climate feature flags to intellifire (#109562) 2024-02-04 15:58:47 +01:00
G Johansson
30b9a28502 Add new climate feature flags to insteon (#109560) 2024-02-04 15:58:44 +01:00
G Johansson
42bf086c97 Add migrated climate feature flags to incomfort (#109559) 2024-02-04 15:58:41 +01:00
G Johansson
064f412da4 Add new climate feature flags to iaqualink (#109558) 2024-02-04 15:58:38 +01:00
G Johansson
122652b396 Add new climate feature flags to huum (#109557)
Adds new climate feature flags to huum
2024-02-04 15:58:36 +01:00
G Johansson
32b25c7e53 Add new climate feature flags to honeywell (#109556)
Adds new climate feature flags to honeywell
2024-02-04 15:58:33 +01:00
G Johansson
83c487a319 Add migrated climate feature flags to homematicip_cloud (#109555)
Adds migrated climate feature flags to homematicip_cloud
2024-02-04 15:58:30 +01:00
G Johansson
75c0c7bda0 Add new climate feature flags to homematic (#109554)
Adds new climate feature flags to homematic
2024-02-04 15:58:27 +01:00
G Johansson
4d7abbf8c5 Add new climate feature flags to hive (#109553)
Adds new climate feature flags to hive
2024-02-04 15:58:24 +01:00
G Johansson
bf4bc9d935 Add new climate feature flags to hisense (#109552)
Adds new climate feature flags to hisense
2024-02-04 15:58:21 +01:00
G Johansson
e1699b4d65 Add new climate feature flags to heatmiser (#109551)
Adds new climate feature flags to heatmiser
2024-02-04 15:58:18 +01:00
G Johansson
67362db547 Add new climate feature flags to gree (#109550)
Adds new climate feature flags to gree
2024-02-04 15:58:15 +01:00
G Johansson
dafdcd369c Add new climate feature flags to geniushub (#109549)
Adds new climate feature flags to geniushub
2024-02-04 15:58:12 +01:00
G Johansson
384070c158 Add new climate feature flags to generic_thermostat (#109548)
Adds new climate feature flags to generic_thermostat
2024-02-04 15:58:09 +01:00
G Johansson
46016004fa Add migrated climate feature flags to fritzbox (#109547)
Adds migrated climate feature flags to fritzbox
2024-02-04 15:58:07 +01:00
G Johansson
38fcc88c57 Add new climate feature flags to freedompro (#109546)
Adds new climate feature flags to freedompro
2024-02-04 15:58:04 +01:00
G Johansson
9cde864224 Add new climate feature flags to escea (#109545)
Adds new climate feature flags to escea
2024-02-04 15:58:01 +01:00
G Johansson
439f1766a0 Add new climate feature flags to ephember (#109544)
Adds new climate feature flags to ephember
2024-02-04 15:57:58 +01:00
G Johansson
12e32fb799 Adds new climate feature flags to elkm1 (#109543) 2024-02-04 15:57:55 +01:00
G Johansson
14ad2e91f3 Add new climate feature flags to electrasmart (#109542)
Adds new climate feature flags to electrasmart
2024-02-04 15:57:52 +01:00
G Johansson
8c0cd6bbab Add new climate feature flags to econet (#109541)
Adds new climate feature flags to econet
2024-02-04 15:57:49 +01:00
G Johansson
c02e96c5c0 Add new climate feature flags to ecobee (#109540)
Adds new climate feature flags to ecobee
2024-02-04 15:57:46 +01:00
G Johansson
3a08e3bec6 Add new climate feature flags to duotecno (#109539)
Adds new climate feature flags to duotecno
2024-02-04 15:57:43 +01:00
G Johansson
a62c05b983 Add migrated climate feature flags to devolo home control (#109538)
Adds migrated climate feature flags to devolo home control
2024-02-04 15:57:40 +01:00
G Johansson
79846d5668 Add migrated climate feature flags to daikin (#109537)
Adds migrated climate feature flags to daikin
2024-02-04 15:57:38 +01:00
G Johansson
482032cb87 Add migrated climate feature flags to coolmaster (#109536)
Adds migrated climate feature flags to coolmaster
2024-02-04 15:57:35 +01:00
G Johansson
9ebf985010 Add new climate feature flags to comelit (#109535)
Adds new climate feature flags to comelit
2024-02-04 15:57:32 +01:00
G Johansson
f16c0bd559 Add new climate feature flags to ccm15 (#109534)
Adds new climate feature flags to ccm15
2024-02-04 15:57:29 +01:00
Cody C
1df5ad23ef Fix empty error modal when adding duplicate Thread integration (#109530) 2024-02-04 15:57:26 +01:00
David F. Mulcahey
d99ba75ed8 Prevent Flo devices and entities from going unavailable when a single refresh fails (#109522)
* Prevent Flo devices and entities from going unavailable when a single refresh fails

* review comment
2024-02-04 15:57:23 +01:00
TheJulianJES
ceeef1eacc Move climate feature flags to child classes for airzone_cloud (#109515) 2024-02-04 15:57:20 +01:00
Klaas Schoute
856780ed30 Bump easyenergy lib to v2.1.1 (#109510) 2024-02-04 15:57:17 +01:00
Joakim Plate
500b0a9b52 Correct flow rate conversion review after merge (#109501) 2024-02-04 15:57:14 +01:00
G Johansson
855edba3a2 Add new climate feature flags for plugwise (#109464) 2024-02-04 15:57:11 +01:00
G Johansson
e7203d6015 Add new climate feature flags to switcher_kis (#109459) 2024-02-04 15:57:08 +01:00
G Johansson
97446a5af3 Add migrated climate feature flag to switchbee (#109458) 2024-02-04 15:57:05 +01:00
G Johansson
ac2e05b5c0 Add climate feature flags to spider (#109456) 2024-02-04 15:57:02 +01:00
G Johansson
af07ac120e Add new climate feature flags to tuya (#109434) 2024-02-04 15:57:00 +01:00
G Johansson
f2de666c54 Add new climate feature flags to esphome (#109428) 2024-02-04 15:56:57 +01:00
G Johansson
38288dd68e Add new climate feature flags for airtouch5 (#109422)
* Add new climate feature flags for airtouch5

* adapt
2024-02-04 15:56:54 +01:00
G Johansson
3e2f97d105 Add ClimateEntityFeatures to airtouch4 (#109421)
* Add ClimateEntityFeatures to airtouch4

* adapt
2024-02-04 15:56:51 +01:00
Michael
5f014f42ac Avoid duplicate entity names in proximity (#109413)
* avoid duplicate config entry title

* consecutive range 2..10

* use existing logic
2024-02-04 15:56:48 +01:00
Josef Zweck
4b2adab24d Revert "Add webhook support to tedee integration (#106846)" (#109408) 2024-02-04 15:56:45 +01:00
Franck Nijhof
ef6fed5067 Bump version to 2024.2.0b4 2024-02-03 14:42:00 +01:00
Jan-Philipp Benecke
0a627aed6d Fix Tankerkoenig diagnostics file to use right format (#109494)
Fix tankerkoenig diagnostics file
2024-02-03 14:40:26 +01:00
Joakim Sørensen
cb03a6e29b Change IoT class for Traccar Client (#109493) 2024-02-03 14:40:23 +01:00
Joakim Sørensen
e630027455 Extend the history of Elvia history to 3 years (#109490)
Extend the history of Elvia data to 3 years
2024-02-03 14:40:21 +01:00
G Johansson
280d7ef4ec Add new climate feature flags to deconz (#109482) 2024-02-03 14:40:18 +01:00
G Johansson
93b7ffa807 Add new climate feature flags to demo (#109481) 2024-02-03 14:40:15 +01:00
G Johansson
cc8e9ac141 Adds new climate feature flags to bsblan (#109480) 2024-02-03 14:40:12 +01:00
G Johansson
2724b115da Adds new climate feature flags to broadlink (#109479) 2024-02-03 14:40:09 +01:00
G Johansson
150fb151fa Add new climate feature flags to blebox (#109478) 2024-02-03 14:40:06 +01:00
G Johansson
4b8cb35ba0 Adds migrated climate feature flags in balboa (#109477) 2024-02-03 14:40:03 +01:00
G Johansson
5cce878b85 Adds new climate feature flags in baf (#109476) 2024-02-03 14:40:00 +01:00
G Johansson
92ebc5b436 Adds new climate feature flags to ambiclimate (#109475) 2024-02-03 14:39:57 +01:00
G Johansson
463320c8ee Adds migrated climate feature flags in nuheat (#109474) 2024-02-03 14:39:54 +01:00
G Johansson
3bf5fa9302 Adds migrated climate feature flags to nobo_hub (#109473) 2024-02-03 14:39:51 +01:00
G Johansson
650ab70444 Add migrated climate feature flags to nexia (#109472) 2024-02-03 14:39:48 +01:00
G Johansson
bb8a74a3f4 Add new climate feature flags to mysensors (#109471)
Adds new climate feature flags to mysensors
2024-02-03 14:39:45 +01:00
G Johansson
49445c46a0 Add migrated climate feature flags to moehlenhoff (#109470) 2024-02-03 14:39:42 +01:00
G Johansson
490101fa92 Adds new climate feature flags to melissa (#109469) 2024-02-03 14:39:39 +01:00
G Johansson
2ac4bb8e9f Add new feature flags to melcloud (#109468) 2024-02-03 14:39:36 +01:00
G Johansson
1c0a6970e2 Adds new climate feature flags to maxcube (#109467) 2024-02-03 14:39:33 +01:00
G Johansson
f3f69a8107 Add new climate feature flags to radiotherm (#109466) 2024-02-03 14:39:30 +01:00
G Johansson
a77bcccbbb Adds migrated climate feature flags for proliphix (#109465) 2024-02-03 14:39:28 +01:00
G Johansson
e98da8596a Add migrated climate feature flags to overkiz (#109463) 2024-02-03 14:39:25 +01:00
G Johansson
5843c93371 Add migrated climate feature flags to opentherm_gw (#109462) 2024-02-03 14:39:22 +01:00
G Johansson
5991b06574 Add new climate feature flags to oem (#109461) 2024-02-03 14:39:19 +01:00
G Johansson
fecdfbfb9f Add new climate feature flags to stiebel_eltron (#109457) 2024-02-03 14:39:16 +01:00
G Johansson
8cfe3821da Add migrated climate feature flags to senz (#109455) 2024-02-03 14:39:13 +01:00
G Johansson
cba67d1525 Add new climate feature flags to screenlogic (#109454) 2024-02-03 14:39:10 +01:00
G Johansson
39df394414 Add migrated climate feature flags to schluter (#109452) 2024-02-03 14:39:07 +01:00
G Johansson
db91a40b55 Add migrated climate feature flags to touchline (#109451) 2024-02-03 14:39:04 +01:00
G Johansson
3181358484 Add migrated climate feature flags to toon (#109450) 2024-02-03 14:39:01 +01:00
G Johansson
776e2da4e6 Add migrated climate feature flags to tolo (#109449) 2024-02-03 14:38:58 +01:00
G Johansson
72ffdf4f4b Add new climate feature flags to tfiac (#109448) 2024-02-03 14:38:55 +01:00
G Johansson
36bba95fd0 Add migrated climate feature flags for tessie (#109447) 2024-02-03 14:38:52 +01:00
G Johansson
13fc69d8a8 Add migrated climate feature flags to teslemetry (#109446) 2024-02-03 14:38:49 +01:00
G Johansson
94464f220c Add migrated climate feature flags to zwave_me (#109445) 2024-02-03 14:38:46 +01:00
G Johansson
13decb9b10 Add new climate feature flags to zhong_hong (#109444) 2024-02-03 14:38:44 +01:00
G Johansson
b6226acd2b Add migrated climate feature flags to zha (#109443) 2024-02-03 14:38:41 +01:00
G Johansson
d04282a41c Add new climate feature flags to yolink (#109442) 2024-02-03 14:38:38 +01:00
G Johansson
a671d0bc6c Add migrated climate feature flags to xs1 (#109441) 2024-02-03 14:38:35 +01:00
G Johansson
6c84e8dff0 Add new climate feature flags to whirlpool (#109440) 2024-02-03 14:38:32 +01:00
G Johansson
57279b1c7b Add migrated climate feature flags to vicare (#109439) 2024-02-03 14:38:29 +01:00
G Johansson
a5646e0df2 Add migrated feature flags to vera (#109438) 2024-02-03 14:38:26 +01:00
Teemu R
63ad3ebdf4 Add new OUIs for tplink (#109437) 2024-02-03 14:38:23 +01:00
G Johansson
f2a9ef6591 Add new climate feature flags to venstar (#109436) 2024-02-03 14:38:21 +01:00
G Johansson
2a5bb66c06 Adds migrated climate entity feature for velbus (#109435) 2024-02-03 14:38:18 +01:00
G Johansson
0c0be6d6a1 Add migrated climate feature flags to homekit_controller (#109433) 2024-02-03 14:38:15 +01:00
G Johansson
e99a58ad53 Add new climate feature flags to flexit_bacnet (#109431) 2024-02-03 14:38:12 +01:00
G Johansson
6c4b773bc1 Add migrated climate entity features to flexit (#109430) 2024-02-03 14:38:09 +01:00
G Johansson
c571f36c6c Add new climate feature flags to evohome (#109429) 2024-02-03 14:38:06 +01:00
G Johansson
f1b041afbe Add migrated climate feature flags to smarttub (#109427) 2024-02-03 14:38:03 +01:00
G Johansson
183af92658 Add migrated climate feature flags to smartthings (#109426) 2024-02-03 14:38:00 +01:00
G Johansson
d71dd12263 Add migrated climate feature flags to shelly (#109425) 2024-02-03 14:37:57 +01:00
G Johansson
18a7aa20b4 Adds new climate feature flags for airzone_cloud (#109424) 2024-02-03 14:37:54 +01:00
G Johansson
f8fde71ef3 Add new climate feature flags to airzone (#109423) 2024-02-03 14:37:51 +01:00
G Johansson
966798b588 Add migrated ClimateEntityFeatures to advantage_air (#109420)
* Add migrated ClimateEntityFeatures to advantage_air

* AdvantageAirZone
2024-02-03 14:37:48 +01:00
G Johansson
66b6f81996 Add migrated ClimateEntityFeature to MQTT (#109419) 2024-02-03 14:37:45 +01:00
G Johansson
4a1a5b9e87 Adds migrated ClimateEntityFeature to Netatmo (#109418) 2024-02-03 14:37:42 +01:00
G Johansson
f01f033b3f Add ClimateEntityFeatures to Nest (#109417) 2024-02-03 14:37:39 +01:00
G Johansson
cd884de79e Add new ClimateEntityFeature for Tado (#109416) 2024-02-03 14:37:36 +01:00
G Johansson
14be7e4a72 Add Mill migrated ClimateEntityFeatures (#109415) 2024-02-03 14:37:32 +01:00
Jc2k
2be71d53c5 Bump aiohomekit to 3.1.4 (#109414) 2024-02-03 14:37:25 +01:00
Michael Hansen
1c960d300d Bump intents to 2024.2.2 (#109412)
Bump intents to 2024.2.2
2024-02-03 14:35:31 +01:00
Michael Hansen
87a1482e4d Pass slots to error messages instead of IDs [rework] (#109410)
Co-authored-by: tetele <tm.sandu@gmail.com>
2024-02-03 14:33:14 +01:00
Jan-Philipp Benecke
24b8e60978 Bump aiotankerkoenig to 0.3.0 (#109404) 2024-02-03 14:23:42 +01:00
Jurriaan Pruis
404e30911b Bump matrix-nio to 0.24.0 (#109403)
Update matrix-nio to 0.24.0
2024-02-03 14:23:38 +01:00
wilburCforce
9c599f7513 Fix device type in Lutron (#109401)
remove testing code
2024-02-03 14:23:35 +01:00
Jan-Philipp Benecke
f3e8360949 Bump aioelectricitymaps to 0.3.0 (#109399)
* Bump aioelectricitymaps to 0.3.0

* Fix tests
2024-02-03 14:23:32 +01:00
Teemu R
43f8731f8a Bump python-kasa to 0.6.2.1 (#109397) 2024-02-03 14:23:29 +01:00
Michael Hansen
4a60d36216 More thorough checks in ESPHome voice assistant UDP server (#109394)
* More thorough checks in UDP server

* Simplify and change to stop_requested

* Check transport
2024-02-03 14:23:26 +01:00
Michael
07a1ee0baa Add diagnostics to proximity (#109393) 2024-02-03 14:23:23 +01:00
Franck Nijhof
a57c30be88 Update elgato to 5.1.2 (#109391) 2024-02-03 14:23:20 +01:00
jjlawren
b1bf69689e Do not suggest area for portable Sonos speakers (#109350)
* Do not suggest area for portable speakers

* Update tests

* Improve readability, update tests
2024-02-03 14:23:17 +01:00
Christopher Fenner
4735aadaa8 Ignore gateway devices in ViCare integration (#106477)
* filter unsupported devices

* Update __init__.py

* use debug

* remove dead code
2024-02-03 14:23:13 +01:00
Franck Nijhof
f18f161efa Bump version to 2024.2.0b3 2024-02-02 17:36:51 +01:00
Bram Kragten
3c90e3d83f Update frontend to 20240202.0 (#109388) 2024-02-02 17:36:43 +01:00
Robert Resch
57a43ef151 Improve Ecovacs naming (#109372) 2024-02-02 17:36:40 +01:00
Franck Nijhof
6afc6ca126 Remove suggested area from Verisure (#109364) 2024-02-02 17:36:37 +01:00
Joakim Sørensen
92a3edc536 Specify end_time when importing Elvia data to deal with drift (#109361) 2024-02-02 17:36:34 +01:00
Robert Resch
e91e67b400 Bump deebot_client to 5.1.0 (#109360) 2024-02-02 17:36:31 +01:00
Franck Nijhof
7a7bcf1a92 Update cryptography to 42.0.2 (#109359) 2024-02-02 17:36:28 +01:00
karwosts
1383a0c13a Missing template helper translation keys (#109347) 2024-02-02 17:36:24 +01:00
J. Nick Koston
12e3077895 Ensure the purge entities service cleans up the states_meta table (#109344) 2024-02-02 17:36:21 +01:00
G Johansson
05c0973937 Add Adax migrated ClimateEntityFeatures (#109341) 2024-02-02 17:36:18 +01:00
G Johansson
7467d588c8 Add sensibo migrated ClimateEntityFeatures (#109340)
Adds sensibo migrated ClimateEntityFeatures
2024-02-02 17:36:15 +01:00
jan iversen
0c82e0a618 Correct modbus commit validation, too strict on integers (#109338) 2024-02-02 17:36:12 +01:00
J. Nick Koston
5a4f88349a Fix stale camera error message in img_util (#109325) 2024-02-02 17:36:09 +01:00
G Johansson
e720e82fd6 Add migrated ClimateEntityFeature for Nibe Heat Pump (#109140) 2024-02-02 17:36:05 +01:00
G Johansson
8ed0af2fb7 Add TURN_ON/OFF ClimateEntityFeature for KNX (#109138) 2024-02-02 17:36:02 +01:00
G Johansson
550c0bf3c3 Add migrated ClimateEntityFeature for SwitchBot Cloud (#109136) 2024-02-02 17:35:59 +01:00
G Johansson
8bb98b4146 Add TURN_ON/OFF ClimateEntityFeature for Modbus (#109133) 2024-02-02 17:35:56 +01:00
G Johansson
bd5bc6b83d Add TURN_ON/OFF ClimateEntityFeature for Matter (#108974)
* Add TURN_ON/OFF ClimateEntityFeature for Matter

* Adjust matter
2024-02-02 17:35:53 +01:00
G Johansson
a2b6b0a0bc Add TURN_ON/OFF ClimateEntityFeature for Fibaro (#108963) 2024-02-02 17:35:50 +01:00
G Johansson
41ad3d8987 Add migrated ClimateEntityFeature for Atag (#108961) 2024-02-02 17:35:45 +01:00
mkmer
3e7dc3588d Add independent session in honeywell (#108435) 2024-02-02 17:35:42 +01:00
Cyrill Raccaud
66d802b5e5 Follow up swiss_public_transport migration fix of unique ids (#107873)
improve migration fix of unique ids
- follow up to #107087
2024-02-02 17:35:38 +01:00
Franck Nijhof
f77bd13cc0 Bump version to 2024.2.0b2 2024-02-01 22:29:58 +01:00
Paul Bottein
fe4ad30ade Add device class to tesla wall connector session energy (#109333) 2024-02-01 22:29:49 +01:00
Joakim Sørensen
15a1a4bfdf Fix custom attribute lookup in Traccar Server (#109331) 2024-02-01 22:29:46 +01:00
Franck Nijhof
3d80c4f7f6 Update Home Assistant base image to 2024.02.0 (#109329) 2024-02-01 22:29:42 +01:00
Michael Hansen
0015af0b3c Move default response out of sentence trigger registration and into agent (#109317)
* Move default response out of trigger and into agent

* Add test
2024-02-01 22:29:39 +01:00
J. Nick Koston
a535bda821 Fix race in loading service descriptions (#109316) 2024-02-01 22:29:36 +01:00
Maciej Bieniek
ca539630a6 Do not use a battery device class for Shelly analog input sensor (#109311)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-02-01 22:29:32 +01:00
Josef Zweck
faf2a90cd1 Bump pytedee_async to 0.2.13 (#109307)
bump
2024-02-01 22:29:30 +01:00
Robert Resch
6aba79d7b9 Verify Ecovacs mqtt config (#109306) 2024-02-01 22:29:26 +01:00
Ståle Storø Hauknes
b464e77112 Bump airthings-ble to 0.6.1 (#109302)
Bump airthings-ble
2024-02-01 22:29:23 +01:00
Josh Pettersen
a8b39ce332 Remove battery charge sensor from powerwall (#109271) 2024-02-01 22:29:19 +01:00
Michael Hansen
77b25553e3 Migrate to new intent error response keys (#109269) 2024-02-01 22:29:16 +01:00
G Johansson
c31dfd6d00 Don't log warning for core integrations on new feature flags in Climate (#109250)
* Don't log for core integration on Climate new feature flags

* Add test

* Fix test
2024-02-01 22:29:12 +01:00
Brett Adams
647ac10dd9 Add climate turn on/off feature to Teslemetry (#109241) 2024-02-01 22:29:06 +01:00
Brett Adams
50dfe4dec0 Add climate on/off feature to Tessie (#109239) 2024-02-01 22:29:03 +01:00
Raman Gupta
52a8216150 Add translations for zwave_js entities and services (#109188) 2024-02-01 22:28:59 +01:00
Franck Nijhof
c98228110a Bump version to 2024.2.0b1 2024-02-01 12:19:53 +01:00
Joakim Sørensen
403c2d8440 Bump hass-nabucasa from 0.75.1 to 0.76.0 (#109296) 2024-02-01 12:19:43 +01:00
Franck Nijhof
e4fc35c563 Fix device class repairs issues UOM placeholders in Group (#109294) 2024-02-01 12:19:41 +01:00
Jan Bouwhuis
e2bbdda016 Remove quality scale platinum from daikin integration (#109292) 2024-02-01 12:19:37 +01:00
Josef Zweck
0070d2171f Fix two icon translations for La Marzocco (#109284) 2024-02-01 12:19:34 +01:00
Luis Andrade
74ce778691 bugfix: name missing in getLogger (#109282) 2024-02-01 12:19:31 +01:00
Jan Bouwhuis
fc6cc45ee2 Fix dalkin climate warnings (#109279) 2024-02-01 12:19:28 +01:00
Jan-Philipp Benecke
1353c1d24c Address late review of Tankerkoenig package move (#109277) 2024-02-01 12:19:25 +01:00
J. Nick Koston
0b6df23ee5 Fix app name sorting in apple_tv (#109274) 2024-02-01 12:19:22 +01:00
J. Nick Koston
e34ebcb195 Restore support for packages being installed from urls with fragments (#109267) 2024-02-01 12:19:19 +01:00
TheJulianJES
29f4c2d513 Fix ZHA update entity not updating installed version (#109260) 2024-02-01 12:19:16 +01:00
Ernst Klamer
70f0d77ba5 Fix Xiaomi-ble automations for multiple button devices (#109251) 2024-02-01 12:19:13 +01:00
Michael
133b68a68d Apply review comments on proximity (#109249)
use a named tuple as TrackedEntityDescriptor
2024-02-01 12:19:10 +01:00
Raman Gupta
3f619a8022 Remove deprecation warnings for zwave_js climate TURN_ON/TURN_OFF features (#109242) 2024-02-01 12:19:07 +01:00
J. Nick Koston
ada37f558c Bump govee-ble to 0.31.0 (#109235) 2024-02-01 12:19:02 +01:00
Joost Lekkerkerker
f76689fb75 Pass verify_ssl to created session in Omada (#109212)
* Pass verify_ssl to created session in Omada

* Fix tests

* Fix tests
2024-02-01 12:18:59 +01:00
Raman Gupta
16ad2728a6 Make zwave_js last seen sensor enabled by default (#109191)
* Make zwave_js last seen sensor enabled by default

* Add test

* Fix test

* improve tests
2024-02-01 12:18:56 +01:00
Brett Adams
ddc1c4bb27 Fix time to arrival to timestamp in Tessie (#109172)
* Fix time to arrival

* Update snapshot

* Freeze time for snapshot

* Fix docstring

* Add available_fn

* Update snapshot

* Dont use variance for full charge

* Remove unrelated changes

* Revert snapshot

* Rename hours_to_datetime
2024-02-01 12:18:53 +01:00
Chris Talkington
bbe4483b4a Update rokuecp to 0.19 (#109100) 2024-02-01 12:18:49 +01:00
368 changed files with 4559 additions and 2091 deletions

View File

@@ -786,8 +786,6 @@ build.json @home-assistant/supervisor
/homeassistant/components/media_source/ @hunterjm
/tests/components/media_source/ @hunterjm
/homeassistant/components/mediaroom/ @dgomes
/homeassistant/components/melcloud/ @vilppuvuorinen
/tests/components/melcloud/ @vilppuvuorinen
/homeassistant/components/melissa/ @kennedyshead
/tests/components/melissa/ @kennedyshead
/homeassistant/components/melnor/ @vanstinator

View File

@@ -1,10 +1,10 @@
image: ghcr.io/home-assistant/{arch}-homeassistant
build_from:
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2024.01.0
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2024.01.0
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2024.01.0
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2024.01.0
i386: ghcr.io/home-assistant/i386-homeassistant-base:2024.01.0
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2024.02.0
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2024.02.0
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2024.02.0
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2024.02.0
i386: ghcr.io/home-assistant/i386-homeassistant-base:2024.02.0
codenotary:
signer: notary@home-assistant.io
base_image: notary@home-assistant.io

View File

@@ -74,6 +74,7 @@ class AdaxDevice(ClimateEntity):
)
_attr_target_temperature_step = PRECISION_WHOLE
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, heater_data: dict[str, Any], adax_data_handler: Adax) -> None:
"""Initialize the heater."""

View File

@@ -83,6 +83,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
_attr_max_temp = 32
_attr_min_temp = 16
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, instance: AdvantageAirData, ac_key: str) -> None:
"""Initialize an AdvantageAir AC unit."""
@@ -202,11 +203,16 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
"""AdvantageAir MyTemp Zone control."""
_attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT_COOL]
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_target_temperature_step = PRECISION_WHOLE
_attr_max_temp = 32
_attr_min_temp = 16
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, instance: AdvantageAirData, ac_key: str, zone_key: str) -> None:
"""Initialize an AdvantageAir Zone control."""

View File

@@ -24,5 +24,5 @@
"dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/airthings_ble",
"iot_class": "local_polling",
"requirements": ["airthings-ble==0.6.0"]
"requirements": ["airthings-ble==0.6.1"]
}

View File

@@ -88,9 +88,13 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
_attr_name = None
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, coordinator, ac_number, info):
"""Initialize the climate device."""
@@ -192,9 +196,14 @@ class AirtouchGroup(CoordinatorEntity, ClimateEntity):
_attr_has_entity_name = True
_attr_name = None
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_hvac_modes = AT_GROUP_MODES
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, coordinator, group_number, info):
"""Initialize the climate device."""

View File

@@ -120,15 +120,12 @@ class Airtouch5ClimateEntity(ClimateEntity, Airtouch5Entity):
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_target_temperature_step = 1
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
class Airtouch5AC(Airtouch5ClimateEntity):
"""Representation of the AC unit. Used to control the overall HVAC Mode."""
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
)
def __init__(self, client: Airtouch5SimpleClient, ability: AcAbility) -> None:
"""Initialise the Climate Entity."""
super().__init__(client)
@@ -152,6 +149,14 @@ class Airtouch5AC(Airtouch5ClimateEntity):
if ability.supports_mode_heat:
self._attr_hvac_modes.append(HVACMode.HEAT)
self._attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
)
if len(self.hvac_modes) > 1:
self._attr_supported_features |= (
ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
self._attr_fan_modes = []
if ability.supports_fan_speed_quiet:
self._attr_fan_modes.append(FAN_DIFFUSE)
@@ -262,7 +267,10 @@ class Airtouch5Zone(Airtouch5ClimateEntity):
_attr_hvac_modes = [HVACMode.OFF, HVACMode.FAN_ONLY]
_attr_preset_modes = [PRESET_NONE, PRESET_BOOST]
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
def __init__(

View File

@@ -117,6 +117,7 @@ class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
_attr_name = None
_speeds: dict[int, str] = {}
_speeds_reverse: dict[str, int] = {}
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,
@@ -129,7 +130,11 @@ class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
super().__init__(coordinator, entry, system_zone_id, zone_data)
self._attr_unique_id = f"{self._attr_unique_id}_{system_zone_id}"
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
self._attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
self._attr_target_temperature_step = API_TEMPERATURE_STEP
self._attr_temperature_unit = TEMP_UNIT_LIB_TO_HASS[
self.get_airzone_value(AZD_TEMP_UNIT)

View File

@@ -144,8 +144,8 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity):
"""Define an Airzone Cloud climate."""
_attr_name = None
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
@callback
def _handle_coordinator_update(self) -> None:
@@ -175,6 +175,12 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity):
class AirzoneDeviceClimate(AirzoneClimate):
"""Define an Airzone Cloud Device base class."""
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
async def async_turn_on(self) -> None:
"""Turn the entity on."""
params = {
@@ -212,6 +218,12 @@ class AirzoneDeviceClimate(AirzoneClimate):
class AirzoneDeviceGroupClimate(AirzoneClimate):
"""Define an Airzone Cloud DeviceGroup base class."""
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
async def async_turn_on(self) -> None:
"""Turn the entity on."""
params = {

View File

@@ -3,18 +3,46 @@ from __future__ import annotations
import amberelectric
from amberelectric.api import amber_api
from amberelectric.model.site import Site
from amberelectric.model.site import Site, SiteStatus
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_API_TOKEN
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.selector import (
SelectOptionDict,
SelectSelector,
SelectSelectorConfig,
SelectSelectorMode,
)
from .const import CONF_SITE_ID, CONF_SITE_NAME, CONF_SITE_NMI, DOMAIN
from .const import CONF_SITE_ID, CONF_SITE_NAME, DOMAIN
API_URL = "https://app.amber.com.au/developers"
def generate_site_selector_name(site: Site) -> str:
"""Generate the name to show in the site drop down in the configuration flow."""
if site.status == SiteStatus.CLOSED:
return site.nmi + " (Closed: " + site.closed_on.isoformat() + ")" # type: ignore[no-any-return]
if site.status == SiteStatus.PENDING:
return site.nmi + " (Pending)" # type: ignore[no-any-return]
return site.nmi # type: ignore[no-any-return]
def filter_sites(sites: list[Site]) -> list[Site]:
"""Deduplicates the list of sites."""
filtered: list[Site] = []
filtered_nmi: set[str] = set()
for site in sorted(sites, key=lambda site: site.status.value):
if site.status == SiteStatus.ACTIVE or site.nmi not in filtered_nmi:
filtered.append(site)
filtered_nmi.add(site.nmi)
return filtered
class AmberElectricConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow."""
@@ -31,7 +59,7 @@ class AmberElectricConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
api: amber_api.AmberApi = amber_api.AmberApi.create(configuration)
try:
sites: list[Site] = api.get_sites()
sites: list[Site] = filter_sites(api.get_sites())
if len(sites) == 0:
self._errors[CONF_API_TOKEN] = "no_site"
return None
@@ -86,38 +114,31 @@ class AmberElectricConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
assert self._sites is not None
assert self._api_token is not None
api_token = self._api_token
if user_input is not None:
site_nmi = user_input[CONF_SITE_NMI]
sites = [site for site in self._sites if site.nmi == site_nmi]
site = sites[0]
site_id = site.id
site_id = user_input[CONF_SITE_ID]
name = user_input.get(CONF_SITE_NAME, site_id)
return self.async_create_entry(
title=name,
data={
CONF_SITE_ID: site_id,
CONF_API_TOKEN: api_token,
CONF_SITE_NMI: site.nmi,
},
data={CONF_SITE_ID: site_id, CONF_API_TOKEN: self._api_token},
)
user_input = {
CONF_API_TOKEN: api_token,
CONF_SITE_NMI: "",
CONF_SITE_NAME: "",
}
return self.async_show_form(
step_id="site",
data_schema=vol.Schema(
{
vol.Required(
CONF_SITE_NMI, default=user_input[CONF_SITE_NMI]
): vol.In([site.nmi for site in self._sites]),
vol.Optional(
CONF_SITE_NAME, default=user_input[CONF_SITE_NAME]
): str,
vol.Required(CONF_SITE_ID): SelectSelector(
SelectSelectorConfig(
options=[
SelectOptionDict(
value=site.id,
label=generate_site_selector_name(site),
)
for site in self._sites
],
mode=SelectSelectorMode.DROPDOWN,
)
),
vol.Optional(CONF_SITE_NAME): str,
}
),
errors=self._errors,

View File

@@ -6,7 +6,6 @@ from homeassistant.const import Platform
DOMAIN = "amberelectric"
CONF_SITE_NAME = "site_name"
CONF_SITE_ID = "site_id"
CONF_SITE_NMI = "site_nmi"
ATTRIBUTION = "Data provided by Amber Electric"

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/amberelectric",
"iot_class": "cloud_polling",
"loggers": ["amberelectric"],
"requirements": ["amberelectric==1.0.4"]
"requirements": ["amberelectric==1.1.0"]
}

View File

@@ -153,10 +153,15 @@ class AmbiclimateEntity(ClimateEntity):
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_target_temperature_step = 1
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF]
_attr_has_entity_name = True
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, heater: AmbiclimateDevice, store: Store[dict[str, Any]]) -> None:
"""Initialize the thermostat."""

View File

@@ -3,11 +3,15 @@ from __future__ import annotations
from dataclasses import dataclass
from python_homeassistant_analytics import HomeassistantAnalyticsClient
from python_homeassistant_analytics import (
HomeassistantAnalyticsClient,
HomeassistantAnalyticsConnectionError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import CONF_TRACKED_INTEGRATIONS, DOMAIN
@@ -28,7 +32,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Homeassistant Analytics from a config entry."""
client = HomeassistantAnalyticsClient(session=async_get_clientsession(hass))
integrations = await client.get_integrations()
try:
integrations = await client.get_integrations()
except HomeassistantAnalyticsConnectionError as ex:
raise ConfigEntryNotReady("Could not fetch integration list") from ex
names = {}
for integration in entry.options[CONF_TRACKED_INTEGRATIONS]:

View File

@@ -10,6 +10,7 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@@ -93,6 +94,7 @@ class HomeassistantAnalyticsSensor(
"""Home Assistant Analytics Sensor."""
_attr_has_entity_name = True
_attr_entity_category = EntityCategory.DIAGNOSTIC
entity_description: AnalyticsSensorEntityDescription

View File

@@ -3,7 +3,12 @@
"step": {
"user": {
"data": {
"tracked_integrations": "Integrations"
"tracked_integrations": "Integrations",
"tracked_custom_integrations": "Custom integrations"
},
"data_description": {
"tracked_integrations": "Select the integrations you want to track",
"tracked_custom_integrations": "Select the custom integrations you want to track"
}
}
},
@@ -16,7 +21,12 @@
"step": {
"init": {
"data": {
"tracked_integrations": "[%key:component::analytics_insights::config::step::user::data::tracked_integrations%]"
"tracked_integrations": "[%key:component::analytics_insights::config::step::user::data::tracked_integrations%]",
"tracked_custom_integrations": "[%key:component::analytics_insights::config::step::user::data::tracked_custom_integrations%]"
},
"data_description": {
"tracked_integrations": "[%key:component::analytics_insights::config::step::user::data_description::tracked_integrations%]",
"tracked_custom_integrations": "[%key:component::analytics_insights::config::step::user::data_description::tracked_custom_integrations%]"
}
}
},

View File

@@ -155,7 +155,7 @@ class AppleTvMediaPlayer(AppleTVEntity, MediaPlayerEntity):
else:
self._app_list = {
app_name: app.identifier
for app in sorted(apps, key=lambda app: app_name.lower())
for app in sorted(apps, key=lambda app: (app.name or "").lower())
if (app_name := app.name) is not None
}
self.async_write_ha_state()

View File

@@ -11,6 +11,7 @@ from typing import Any, TypeVar, cast
from aioasuswrt.asuswrt import AsusWrt as AsusWrtLegacy
from aiohttp import ClientSession
from pyasuswrt import AsusWrtError, AsusWrtHttp
from pyasuswrt.exceptions import AsusWrtNotAvailableInfoError
from homeassistant.const import (
CONF_HOST,
@@ -354,13 +355,14 @@ class AsusWrtHttpBridge(AsusWrtBridge):
async def async_get_available_sensors(self) -> dict[str, dict[str, Any]]:
"""Return a dictionary of available sensors for this bridge."""
sensors_temperatures = await self._get_available_temperature_sensors()
sensors_loadavg = await self._get_loadavg_sensors_availability()
sensors_types = {
SENSORS_TYPE_BYTES: {
KEY_SENSORS: SENSORS_BYTES,
KEY_METHOD: self._get_bytes,
},
SENSORS_TYPE_LOAD_AVG: {
KEY_SENSORS: SENSORS_LOAD_AVG,
KEY_SENSORS: sensors_loadavg,
KEY_METHOD: self._get_load_avg,
},
SENSORS_TYPE_RATES: {
@@ -393,6 +395,16 @@ class AsusWrtHttpBridge(AsusWrtBridge):
return []
return available_sensors
async def _get_loadavg_sensors_availability(self) -> list[str]:
"""Check if load avg is available on the router."""
try:
await self._api.async_get_loadavg()
except AsusWrtNotAvailableInfoError:
return []
except AsusWrtError:
pass
return SENSORS_LOAD_AVG
@handle_errors_and_zip(AsusWrtError, SENSORS_BYTES)
async def _get_bytes(self) -> Any:
"""Fetch byte information from the router."""

View File

@@ -46,6 +46,7 @@ class AtagThermostat(AtagEntity, ClimateEntity):
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
)
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, coordinator, atag_id):
"""Initialize an Atag climate device."""

View File

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

View File

@@ -33,10 +33,15 @@ async def async_setup_entry(
class BAFAutoComfort(BAFEntity, ClimateEntity):
"""BAF climate auto comfort."""
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_hvac_modes = [HVACMode.OFF, HVACMode.FAN_ONLY]
_attr_translation_key = "auto_comfort"
_enable_turn_on_off_backwards_compatibility = False
@callback
def _async_update_attrs(self) -> None:

View File

@@ -63,6 +63,7 @@ class BalboaClimateEntity(BalboaEntity, ClimateEntity):
)
_attr_translation_key = DOMAIN
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, client: SpaClient) -> None:
"""Initialize the climate entity."""

View File

@@ -53,8 +53,13 @@ async def async_setup_entry(
class BleBoxClimateEntity(BleBoxEntity[blebox_uniapi.climate.Climate], ClimateEntity):
"""Representation of a BleBox climate feature (saunaBox)."""
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
@property
def hvac_modes(self):

View File

@@ -14,6 +14,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError, ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
from .coordinator import BringDataUpdateCoordinator
@@ -29,14 +30,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
email = entry.data[CONF_EMAIL]
password = entry.data[CONF_PASSWORD]
bring = Bring(email, password)
def login_and_load_lists() -> None:
bring.login()
bring.loadLists()
session = async_get_clientsession(hass)
bring = Bring(email, password, sessionAsync=session)
try:
await hass.async_add_executor_job(login_and_load_lists)
await bring.loginAsync()
await bring.loadListsAsync()
except BringRequestException as e:
raise ConfigEntryNotReady(
f"Timeout while connecting for email '{email}'"

View File

@@ -11,6 +11,7 @@ import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.selector import (
TextSelector,
TextSelectorConfig,
@@ -48,14 +49,14 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
bring = Bring(user_input[CONF_EMAIL], user_input[CONF_PASSWORD])
def login_and_load_lists() -> None:
bring.login()
bring.loadLists()
session = async_get_clientsession(self.hass)
bring = Bring(
user_input[CONF_EMAIL], user_input[CONF_PASSWORD], sessionAsync=session
)
try:
await self.hass.async_add_executor_job(login_and_load_lists)
await bring.loginAsync()
await bring.loadListsAsync()
except BringRequestException:
errors["base"] = "cannot_connect"
except BringAuthException:

View File

@@ -40,9 +40,7 @@ class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]):
async def _async_update_data(self) -> dict[str, BringData]:
try:
lists_response = await self.hass.async_add_executor_job(
self.bring.loadLists
)
lists_response = await self.bring.loadListsAsync()
except BringRequestException as e:
raise UpdateFailed("Unable to connect and retrieve data from bring") from e
except BringParseException as e:
@@ -51,9 +49,7 @@ class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]):
list_dict = {}
for lst in lists_response["lists"]:
try:
items = await self.hass.async_add_executor_job(
self.bring.getItems, lst["listUuid"]
)
items = await self.bring.getItemsAsync(lst["listUuid"])
except BringRequestException as e:
raise UpdateFailed(
"Unable to connect and retrieve data from bring"

View File

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

View File

@@ -91,11 +91,8 @@ class BringTodoListEntity(
async def async_create_todo_item(self, item: TodoItem) -> None:
"""Add an item to the To-do list."""
try:
await self.hass.async_add_executor_job(
self.coordinator.bring.saveItem,
self.bring_list["listUuid"],
item.summary,
item.description or "",
await self.coordinator.bring.saveItemAsync(
self.bring_list["listUuid"], item.summary, item.description or ""
)
except BringRequestException as e:
raise HomeAssistantError("Unable to save todo item for bring") from e
@@ -126,16 +123,14 @@ class BringTodoListEntity(
assert item.uid
if item.status == TodoItemStatus.COMPLETED:
await self.hass.async_add_executor_job(
self.coordinator.bring.removeItem,
await self.coordinator.bring.removeItemAsync(
bring_list["listUuid"],
item.uid,
)
elif item.summary == item.uid:
try:
await self.hass.async_add_executor_job(
self.coordinator.bring.updateItem,
await self.coordinator.bring.updateItemAsync(
bring_list["listUuid"],
item.uid,
item.description or "",
@@ -144,13 +139,11 @@ class BringTodoListEntity(
raise HomeAssistantError("Unable to update todo item for bring") from e
else:
try:
await self.hass.async_add_executor_job(
self.coordinator.bring.removeItem,
await self.coordinator.bring.removeItemAsync(
bring_list["listUuid"],
item.uid,
)
await self.hass.async_add_executor_job(
self.coordinator.bring.saveItem,
await self.coordinator.bring.saveItemAsync(
bring_list["listUuid"],
item.summary,
item.description or "",
@@ -164,8 +157,8 @@ class BringTodoListEntity(
"""Delete an item from the To-do list."""
for uid in uids:
try:
await self.hass.async_add_executor_job(
self.coordinator.bring.removeItem, self.bring_list["listUuid"], uid
await self.coordinator.bring.removeItemAsync(
self.bring_list["listUuid"], uid
)
except BringRequestException as e:
raise HomeAssistantError("Unable to delete todo item for bring") from e

View File

@@ -35,9 +35,14 @@ class BroadlinkThermostat(ClimateEntity, BroadlinkEntity):
_attr_has_entity_name = True
_attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF, HVACMode.AUTO]
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_target_temperature_step = PRECISION_HALVES
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, device: BroadlinkDevice) -> None:
"""Initialize the climate entity."""

View File

@@ -73,12 +73,16 @@ class BSBLANClimate(
_attr_name = None
# Determine preset modes
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_preset_modes = PRESET_MODES
# Determine hvac modes
_attr_hvac_modes = HVAC_MODES
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,

View File

@@ -98,6 +98,6 @@ class TurboJPEGSingleton:
TurboJPEGSingleton.__instance = TurboJPEG()
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
"Error loading libturbojpeg; Cameras may impact HomeKit performance"
"Error loading libturbojpeg; Camera snapshot performance will be sub-optimal"
)
TurboJPEGSingleton.__instance = False

View File

@@ -64,8 +64,11 @@ class CCM15Climate(CoordinatorEntity[CCM15Coordinator], ClimateEntity):
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self, ac_host: str, ac_index: int, coordinator: CCM15Coordinator

View File

@@ -8,5 +8,5 @@
"integration_type": "system",
"iot_class": "cloud_push",
"loggers": ["hass_nabucasa"],
"requirements": ["hass-nabucasa==0.75.1"]
"requirements": ["hass-nabucasa==0.76.0"]
}

View File

@@ -4,8 +4,11 @@ from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from aioelectricitymaps import ElectricityMaps
from aioelectricitymaps.exceptions import ElectricityMapsError, InvalidToken
from aioelectricitymaps import (
ElectricityMaps,
ElectricityMapsError,
ElectricityMapsInvalidTokenError,
)
import voluptuous as vol
from homeassistant import config_entries
@@ -146,7 +149,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
try:
await fetch_latest_carbon_intensity(self.hass, em, data)
except InvalidToken:
except ElectricityMapsInvalidTokenError:
errors["base"] = "invalid_auth"
except ElectricityMapsError:
errors["base"] = "unknown"

View File

@@ -4,9 +4,12 @@ from __future__ import annotations
from datetime import timedelta
import logging
from aioelectricitymaps import ElectricityMaps
from aioelectricitymaps.exceptions import ElectricityMapsError, InvalidToken
from aioelectricitymaps.models import CarbonIntensityResponse
from aioelectricitymaps import (
CarbonIntensityResponse,
ElectricityMaps,
ElectricityMapsError,
ElectricityMapsInvalidTokenError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
@@ -43,7 +46,7 @@ class CO2SignalCoordinator(DataUpdateCoordinator[CarbonIntensityResponse]):
return await fetch_latest_carbon_intensity(
self.hass, self.client, self.config_entry.data
)
except InvalidToken as err:
except ElectricityMapsInvalidTokenError as err:
raise ConfigEntryAuthFailed from err
except ElectricityMapsError as err:
raise UpdateFailed(str(err)) from err

View File

@@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["aioelectricitymaps"],
"requirements": ["aioelectricitymaps==0.2.0"]
"requirements": ["aioelectricitymaps==0.3.1"]
}

View File

@@ -1,12 +1,11 @@
"""Support for climates."""
from __future__ import annotations
import asyncio
from enum import StrEnum
from typing import Any
from aiocomelit import ComelitSerialBridgeObject
from aiocomelit.const import CLIMATE, SLEEP_BETWEEN_CALLS
from aiocomelit.const import CLIMATE
from homeassistant.components.climate import (
ClimateEntity,
@@ -91,11 +90,16 @@ class ComelitClimateEntity(CoordinatorEntity[ComelitSerialBridge], ClimateEntity
_attr_hvac_modes = [HVACMode.AUTO, HVACMode.COOL, HVACMode.HEAT, HVACMode.OFF]
_attr_max_temp = 30
_attr_min_temp = 5
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_target_temperature_step = PRECISION_TENTHS
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_has_entity_name = True
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,
@@ -186,7 +190,6 @@ class ComelitClimateEntity(CoordinatorEntity[ComelitSerialBridge], ClimateEntity
await self.coordinator.api.set_clima_status(
self._device.index, ClimaAction.MANUAL
)
await asyncio.sleep(SLEEP_BETWEEN_CALLS)
await self.coordinator.api.set_clima_status(
self._device.index, ClimaAction.SET, target_temp
)
@@ -198,7 +201,6 @@ class ComelitClimateEntity(CoordinatorEntity[ComelitSerialBridge], ClimateEntity
await self.coordinator.api.set_clima_status(
self._device.index, ClimaAction.ON
)
await asyncio.sleep(SLEEP_BETWEEN_CALLS)
await self.coordinator.api.set_clima_status(
self._device.index, MODE_TO_ACTION[hvac_mode]
)

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/comelit",
"iot_class": "local_polling",
"loggers": ["aiocomelit"],
"requirements": ["aiocomelit==0.8.2"]
"requirements": ["aiocomelit==0.8.3"]
}

View File

@@ -349,7 +349,7 @@ async def websocket_hass_agent_debug(
},
# Slot values that would be received by the intent
"slots": { # direct access to values
entity_key: entity.value
entity_key: entity.text or entity.value
for entity_key, entity in result.entities.items()
},
# Extra slot details, such as the originally matched text

View File

@@ -1,4 +1,5 @@
"""Standard conversation implementation for Home Assistant."""
from __future__ import annotations
import asyncio
@@ -12,22 +13,15 @@ import re
from typing import IO, Any
from hassil.expression import Expression, ListReference, Sequence
from hassil.intents import (
Intents,
ResponseType,
SlotList,
TextSlotList,
WildcardSlotList,
)
from hassil.intents import Intents, SlotList, TextSlotList, WildcardSlotList
from hassil.recognize import (
MISSING_ENTITY,
RecognizeResult,
UnmatchedEntity,
UnmatchedTextEntity,
recognize_all,
)
from hassil.util import merge_dict
from home_assistant_intents import get_intents, get_languages
from home_assistant_intents import ErrorKey, get_intents, get_languages
import yaml
from homeassistant import core, setup
@@ -238,7 +232,10 @@ class DefaultAgent(AbstractConversationAgent):
)
)
# Use last non-empty result as response
# Use last non-empty result as response.
#
# There may be multiple copies of a trigger running when editing in
# the UI, so it's critical that we filter out empty responses here.
response_text: str | None = None
for trigger_response in trigger_responses:
response_text = response_text or trigger_response
@@ -246,7 +243,7 @@ class DefaultAgent(AbstractConversationAgent):
# Convert to conversation result
response = intent.IntentResponse(language=language)
response.response_type = intent.IntentResponseType.ACTION_DONE
response.async_set_speech(response_text or "")
response.async_set_speech(response_text or "Done")
return ConversationResult(response=response)
@@ -259,7 +256,7 @@ class DefaultAgent(AbstractConversationAgent):
return _make_error_result(
language,
intent.IntentResponseErrorCode.NO_INTENT_MATCH,
self._get_error_text(ResponseType.NO_INTENT, lang_intents),
self._get_error_text(ErrorKey.NO_INTENT, lang_intents),
conversation_id,
)
@@ -268,14 +265,14 @@ class DefaultAgent(AbstractConversationAgent):
_LOGGER.debug(
"Recognized intent '%s' for template '%s' but had unmatched: %s",
result.intent.name,
result.intent_sentence.text
if result.intent_sentence is not None
else "",
(
result.intent_sentence.text
if result.intent_sentence is not None
else ""
),
result.unmatched_entities_list,
)
error_response_type, error_response_args = _get_unmatched_response(
result.unmatched_entities
)
error_response_type, error_response_args = _get_unmatched_response(result)
return _make_error_result(
language,
intent.IntentResponseErrorCode.NO_VALID_TARGETS,
@@ -291,7 +288,8 @@ class DefaultAgent(AbstractConversationAgent):
# Slot values to pass to the intent
slots = {
entity.name: {"value": entity.value} for entity in result.entities_list
entity.name: {"value": entity.value, "text": entity.text or entity.value}
for entity in result.entities_list
}
try:
@@ -325,7 +323,7 @@ class DefaultAgent(AbstractConversationAgent):
return _make_error_result(
language,
intent.IntentResponseErrorCode.FAILED_TO_HANDLE,
self._get_error_text(ResponseType.HANDLE_ERROR, lang_intents),
self._get_error_text(ErrorKey.HANDLE_ERROR, lang_intents),
conversation_id,
)
except intent.IntentUnexpectedError:
@@ -333,7 +331,7 @@ class DefaultAgent(AbstractConversationAgent):
return _make_error_result(
language,
intent.IntentResponseErrorCode.UNKNOWN,
self._get_error_text(ResponseType.HANDLE_ERROR, lang_intents),
self._get_error_text(ErrorKey.HANDLE_ERROR, lang_intents),
conversation_id,
)
@@ -480,9 +478,11 @@ class DefaultAgent(AbstractConversationAgent):
for entity_name, entity_value in recognize_result.entities.items()
},
# First matched or unmatched state
"state": template.TemplateState(self.hass, state1)
if state1 is not None
else None,
"state": (
template.TemplateState(self.hass, state1)
if state1 is not None
else None
),
"query": {
# Entity states that matched the query (e.g, "on")
"matched": [
@@ -740,7 +740,7 @@ class DefaultAgent(AbstractConversationAgent):
if not entity:
# Default name
entity_names.append((state.name, state.name, context))
entity_names.append((state.name, state.entity_id, context))
continue
if entity.aliases:
@@ -748,10 +748,10 @@ class DefaultAgent(AbstractConversationAgent):
if not alias.strip():
continue
entity_names.append((alias, alias, context))
entity_names.append((alias, state.entity_id, context))
# Default name
entity_names.append((state.name, state.name, context))
entity_names.append((state.name, state.entity_id, context))
# Expose all areas
areas = ar.async_get(self.hass)
@@ -791,11 +791,11 @@ class DefaultAgent(AbstractConversationAgent):
if device_area is None:
return None
return {"area": device_area.id}
return {"area": {"value": device_area.id, "text": device_area.name}}
def _get_error_text(
self,
response_type: ResponseType,
error_key: ErrorKey,
lang_intents: LanguageIntents | None,
**response_args,
) -> str:
@@ -803,7 +803,7 @@ class DefaultAgent(AbstractConversationAgent):
if lang_intents is None:
return _DEFAULT_ERROR_TEXT
response_key = response_type.value
response_key = error_key.value
response_str = (
lang_intents.error_responses.get(response_key) or _DEFAULT_ERROR_TEXT
)
@@ -916,59 +916,72 @@ def _make_error_result(
return ConversationResult(response, conversation_id)
def _get_unmatched_response(
unmatched_entities: dict[str, UnmatchedEntity],
) -> tuple[ResponseType, dict[str, Any]]:
error_response_type = ResponseType.NO_INTENT
error_response_args: dict[str, Any] = {}
def _get_unmatched_response(result: RecognizeResult) -> tuple[ErrorKey, dict[str, Any]]:
"""Get key and template arguments for error when there are unmatched intent entities/slots."""
if unmatched_name := unmatched_entities.get("name"):
# Unmatched device or entity
assert isinstance(unmatched_name, UnmatchedTextEntity)
error_response_type = ResponseType.NO_ENTITY
error_response_args["entity"] = unmatched_name.text
# Filter out non-text and missing context entities
unmatched_text: dict[str, str] = {
key: entity.text.strip()
for key, entity in result.unmatched_entities.items()
if isinstance(entity, UnmatchedTextEntity) and entity.text != MISSING_ENTITY
}
elif unmatched_area := unmatched_entities.get("area"):
# Unmatched area
assert isinstance(unmatched_area, UnmatchedTextEntity)
error_response_type = ResponseType.NO_AREA
error_response_args["area"] = unmatched_area.text
if unmatched_area := unmatched_text.get("area"):
# area only
return ErrorKey.NO_AREA, {"area": unmatched_area}
return error_response_type, error_response_args
# Area may still have matched
matched_area: str | None = None
if matched_area_entity := result.entities.get("area"):
matched_area = matched_area_entity.text.strip()
if unmatched_name := unmatched_text.get("name"):
if matched_area:
# device in area
return ErrorKey.NO_ENTITY_IN_AREA, {
"entity": unmatched_name,
"area": matched_area,
}
# device only
return ErrorKey.NO_ENTITY, {"entity": unmatched_name}
# Default error
return ErrorKey.NO_INTENT, {}
def _get_no_states_matched_response(
no_states_error: intent.NoStatesMatchedError,
) -> tuple[ResponseType, dict[str, Any]]:
"""Return error response type and template arguments for error."""
if not (
no_states_error.area
and (no_states_error.device_classes or no_states_error.domains)
):
# Device class and domain must be paired with an area for the error
# message.
return ResponseType.NO_INTENT, {}
) -> tuple[ErrorKey, dict[str, Any]]:
"""Return key and template arguments for error when intent returns no matching states."""
error_response_args: dict[str, Any] = {"area": no_states_error.area}
# Check device classes first, since it's more specific than domain
# Device classes should be checked before domains
if no_states_error.device_classes:
# No exposed entities of a particular class in an area.
# Example: "close the bedroom windows"
#
# Only use the first device class for the error message
error_response_args["device_class"] = next(iter(no_states_error.device_classes))
device_class = next(iter(no_states_error.device_classes)) # first device class
if no_states_error.area:
# device_class in area
return ErrorKey.NO_DEVICE_CLASS_IN_AREA, {
"device_class": device_class,
"area": no_states_error.area,
}
return ResponseType.NO_DEVICE_CLASS, error_response_args
# device_class only
return ErrorKey.NO_DEVICE_CLASS, {"device_class": device_class}
# No exposed entities of a domain in an area.
# Example: "turn on lights in kitchen"
assert no_states_error.domains
#
# Only use the first domain for the error message
error_response_args["domain"] = next(iter(no_states_error.domains))
if no_states_error.domains:
domain = next(iter(no_states_error.domains)) # first domain
if no_states_error.area:
# domain in area
return ErrorKey.NO_DOMAIN_IN_AREA, {
"domain": domain,
"area": no_states_error.area,
}
return ResponseType.NO_DOMAIN, error_response_args
# domain only
return ErrorKey.NO_DOMAIN, {"domain": domain}
# Default error
return ErrorKey.NO_INTENT, {}
def _collect_list_references(expression: Expression, list_names: set[str]) -> None:

View File

@@ -7,5 +7,5 @@
"integration_type": "system",
"iot_class": "local_push",
"quality_scale": "internal",
"requirements": ["hassil==1.6.0", "home-assistant-intents==2024.1.29"]
"requirements": ["hassil==1.6.1", "home-assistant-intents==2024.2.2"]
}

View File

@@ -98,7 +98,12 @@ async def async_attach_trigger(
# mypy does not understand the type narrowing, unclear why
return automation_result.conversation_response # type: ignore[return-value]
return "Done"
# It's important to return None here instead of a string.
#
# When editing in the UI, a copy of this trigger is registered.
# If we return a string from here, there is a race condition between the
# two trigger copies for who will provide a response.
return None
default_agent = await _get_agent_manager(hass).async_get_agent(HOME_ASSISTANT_AGENT)
assert isinstance(default_agent, DefaultAgent)

View File

@@ -54,6 +54,7 @@ class CoolmasterClimate(CoolmasterEntity, ClimateEntity):
"""Representation of a coolmaster climate device."""
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, coordinator, unit_id, info, supported_modes):
"""Initialize the climate device."""

View File

@@ -0,0 +1,8 @@
{
"services": {
"decrement": "mdi:numeric-negative-1",
"increment": "mdi:numeric-positive-1",
"reset": "mdi:refresh",
"set_value": "mdi:counter"
}
}

View File

@@ -128,6 +128,7 @@ class DaikinClimate(ClimateEntity):
_attr_target_temperature_step = 1
_attr_fan_modes: list[str]
_attr_swing_modes: list[str]
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, api: DaikinApi) -> None:
"""Initialize the climate device."""
@@ -142,7 +143,11 @@ class DaikinClimate(ClimateEntity):
ATTR_SWING_MODE: self._attr_swing_modes,
}
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
self._attr_supported_features = (
ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TARGET_TEMPERATURE
)
if api.device.support_away_mode or api.device.support_advanced_modes:
self._attr_supported_features |= ClimateEntityFeature.PRESET_MODE

View File

@@ -6,7 +6,6 @@
"documentation": "https://www.home-assistant.io/integrations/daikin",
"iot_class": "local_polling",
"loggers": ["pydaikin"],
"quality_scale": "platinum",
"requirements": ["pydaikin==2.11.1"],
"zeroconf": ["_dkapi._tcp.local."]
}

View File

@@ -100,6 +100,7 @@ class DeconzThermostat(DeconzDevice[Thermostat], ClimateEntity):
TYPE = DOMAIN
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, device: Thermostat, gateway: DeconzGateway) -> None:
"""Set up thermostat device."""
@@ -119,7 +120,11 @@ class DeconzThermostat(DeconzDevice[Thermostat], ClimateEntity):
HVAC_MODE_TO_DECONZ[item]: item for item in self._attr_hvac_modes
}
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
self._attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
if device.fan_mode:
self._attr_supported_features |= ClimateEntityFeature.FAN_MODE

View File

@@ -97,6 +97,7 @@ class DemoClimate(ClimateEntity):
_attr_name = None
_attr_should_poll = False
_attr_translation_key = "ubercool"
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,
@@ -137,6 +138,9 @@ class DemoClimate(ClimateEntity):
self._attr_supported_features |= (
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
)
self._attr_supported_features |= (
ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
self._target_temperature = target_temperature
self._target_humidity = target_humidity
self._unit_of_measurement = unit_of_measurement

View File

@@ -0,0 +1,9 @@
{
"entity": {
"sensor": {
"derivative": {
"default": "mdi:chart-line"
}
}
}
}

View File

@@ -64,8 +64,6 @@ UNIT_TIME = {
UnitOfTime.DAYS: 24 * 60 * 60,
}
ICON = "mdi:chart-line"
DEFAULT_ROUND = 3
DEFAULT_TIME_WINDOW = 0
@@ -157,9 +155,9 @@ async def async_setup_platform(
class DerivativeSensor(RestoreSensor, SensorEntity):
"""Representation of an derivative sensor."""
"""Representation of a derivative sensor."""
_attr_icon = ICON
_attr_translation_key = "derivative"
_attr_should_poll = False
def __init__(

View File

@@ -56,6 +56,7 @@ class DevoloClimateDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, ClimateEntit
_attr_precision = PRECISION_TENTHS
_attr_hvac_mode = HVACMode.HEAT
_attr_hvac_modes = [HVACMode.HEAT]
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str

View File

@@ -47,12 +47,16 @@ class DuotecnoClimate(DuotecnoEntity, ClimateEntity):
_unit: SensUnit
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_hvac_modes = list(HVACMODE_REVERSE)
_attr_preset_modes = list(PRESETMODES)
_attr_translation_key = "duotecno"
_enable_turn_on_off_backwards_compatibility = False
@property
def current_temperature(self) -> float | None:

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/easyenergy",
"iot_class": "cloud_polling",
"quality_scale": "platinum",
"requirements": ["easyenergy==2.1.0"]
"requirements": ["easyenergy==2.1.1"]
}

View File

@@ -323,6 +323,7 @@ class Thermostat(ClimateEntity):
_attr_fan_modes = [FAN_AUTO, FAN_ON]
_attr_name = None
_attr_has_entity_name = True
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self, data: EcobeeData, thermostat_index: int, thermostat: dict
@@ -375,6 +376,10 @@ class Thermostat(ClimateEntity):
supported = supported | ClimateEntityFeature.TARGET_HUMIDITY
if self.has_aux_heat:
supported = supported | ClimateEntityFeature.AUX_HEAT
if len(self.hvac_modes) > 1 and HVACMode.OFF in self.hvac_modes:
supported = (
supported | ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
return supported
@property

View File

@@ -66,6 +66,7 @@ class EcoNetThermostat(EcoNetEntity, ClimateEntity):
_attr_should_poll = True
_attr_temperature_unit = UnitOfTemperature.FAHRENHEIT
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, thermostat):
"""Initialize."""
@@ -79,12 +80,13 @@ class EcoNetThermostat(EcoNetEntity, ClimateEntity):
ha_mode = ECONET_STATE_TO_HA[mode]
self._attr_hvac_modes.append(ha_mode)
@property
def supported_features(self) -> ClimateEntityFeature:
"""Return the list of supported features."""
if self._econet.supports_humidifier:
return SUPPORT_FLAGS_THERMOSTAT | ClimateEntityFeature.TARGET_HUMIDITY
return SUPPORT_FLAGS_THERMOSTAT
self._attr_supported_features |= SUPPORT_FLAGS_THERMOSTAT
if thermostat.supports_humidifier:
self._attr_supported_features |= ClimateEntityFeature.TARGET_HUMIDITY
if len(self.hvac_modes) > 1 and HVACMode.OFF in self.hvac_modes:
self._attr_supported_features |= (
ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
@property
def current_temperature(self):

View File

@@ -75,7 +75,7 @@ async def _validate_input(
rest_config = create_rest_config(
aiohttp_client.async_get_clientsession(hass),
device_id=device_id,
country=country,
alpha_2_country=country,
override_rest_url=rest_url,
)
@@ -266,6 +266,10 @@ class EcovacsConfigFlow(ConfigFlow, domain=DOMAIN):
# If not we will inform the user about the mismatch.
error = None
placeholders = None
# Convert the country to upper case as ISO 3166-1 alpha-2 country codes are upper case
user_input[CONF_COUNTRY] = user_input[CONF_COUNTRY].upper()
if len(user_input[CONF_COUNTRY]) != 2:
error = "invalid_country_length"
placeholders = {"countries_url": "https://www.iso.org/obp/ui/#search/code/"}

View File

@@ -49,7 +49,7 @@ class EcovacsController:
create_rest_config(
aiohttp_client.async_get_clientsession(self._hass),
device_id=self._device_id,
country=country,
alpha_2_country=country,
override_rest_url=config.get(CONF_OVERRIDE_REST_URL),
),
config[CONF_USERNAME],
@@ -74,11 +74,16 @@ class EcovacsController:
async def initialize(self) -> None:
"""Init controller."""
mqtt_config_verfied = False
try:
devices = await self._api_client.get_devices()
credentials = await self._authenticator.authenticate()
for device_config in devices:
if isinstance(device_config, DeviceInfo):
# MQTT device
if not mqtt_config_verfied:
await self._mqtt.verify_config()
mqtt_config_verfied = True
device = Device(device_config, self._authenticator)
await device.initialize(self._mqtt)
self.devices.append(device)

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/ecovacs",
"iot_class": "cloud_push",
"loggers": ["sleekxmppfs", "sucks", "deebot_client"],
"requirements": ["py-sucks==0.9.8", "deebot-client==5.0.0"]
"requirements": ["py-sucks==0.9.8", "deebot-client==5.1.0"]
}

View File

@@ -47,13 +47,13 @@
"name": "Relocate"
},
"reset_lifespan_brush": {
"name": "Reset brush lifespan"
"name": "Reset main brush lifespan"
},
"reset_lifespan_filter": {
"name": "Reset filter lifespan"
},
"reset_lifespan_side_brush": {
"name": "Reset side brush lifespan"
"name": "Reset side brushes lifespan"
}
},
"image": {
@@ -79,13 +79,13 @@
}
},
"lifespan_brush": {
"name": "Brush lifespan"
"name": "Main brush lifespan"
},
"lifespan_filter": {
"name": "Filter lifespan"
},
"lifespan_side_brush": {
"name": "Side brush lifespan"
"name": "Side brushes lifespan"
},
"network_ip": {
"name": "IP address"
@@ -100,7 +100,7 @@
"name": "Area cleaned"
},
"stats_time": {
"name": "Time cleaned"
"name": "Cleaning duration"
},
"total_stats_area": {
"name": "Total area cleaned"
@@ -109,12 +109,12 @@
"name": "Total cleanings"
},
"total_stats_time": {
"name": "Total time cleaned"
"name": "Total cleaning duration"
}
},
"select": {
"water_amount": {
"name": "Water amount",
"name": "Water flow level",
"state": {
"high": "High",
"low": "Low",
@@ -137,7 +137,7 @@
"name": "Advanced mode"
},
"carpet_auto_fan_boost": {
"name": "Carpet auto fan speed boost"
"name": "Carpet auto-boost suction"
},
"clean_preference": {
"name": "Clean preference"

View File

@@ -38,8 +38,8 @@ class EcowittEntity(Entity):
"""Update the state on callback."""
self.async_write_ha_state()
self.ecowitt.update_cb.append(_update_state) # type: ignore[arg-type] # upstream bug
self.async_on_remove(lambda: self.ecowitt.update_cb.remove(_update_state)) # type: ignore[arg-type] # upstream bug
self.ecowitt.update_cb.append(_update_state)
self.async_on_remove(lambda: self.ecowitt.update_cb.remove(_update_state))
@property
def available(self) -> bool:

View File

@@ -6,5 +6,5 @@
"dependencies": ["webhook"],
"documentation": "https://www.home-assistant.io/integrations/ecowitt",
"iot_class": "local_push",
"requirements": ["aioecowitt==2023.5.0"]
"requirements": ["aioecowitt==2024.2.0"]
}

View File

@@ -111,6 +111,7 @@ class ElectraClimateEntity(ClimateEntity):
_attr_hvac_modes = ELECTRA_MODES
_attr_has_entity_name = True
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, device: ElectraAirConditioner, api: ElectraAPI) -> None:
"""Initialize Electra climate entity."""
@@ -121,6 +122,8 @@ class ElectraClimateEntity(ClimateEntity):
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
swing_modes: list = []

View File

@@ -7,6 +7,6 @@
"integration_type": "device",
"iot_class": "local_polling",
"quality_scale": "platinum",
"requirements": ["elgato==5.1.1"],
"requirements": ["elgato==5.1.2"],
"zeroconf": ["_elg._tcp.local."]
}

View File

@@ -79,6 +79,8 @@ class ElkThermostat(ElkEntity, ClimateEntity):
ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.AUX_HEAT
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_min_temp = 1
_attr_max_temp = 99
@@ -87,6 +89,7 @@ class ElkThermostat(ElkEntity, ClimateEntity):
_attr_target_temperature_step = 1
_attr_fan_modes = [FAN_AUTO, FAN_ON]
_element: Thermostat
_enable_turn_on_off_backwards_compatibility = False
@property
def temperature_unit(self) -> str:

View File

@@ -35,8 +35,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._api_token = api_token = user_input[CONF_API_TOKEN]
client = Elvia(meter_value_token=api_token).meter_value()
try:
end_time = dt_util.utcnow()
results = await client.get_meter_values(
start_time=(dt_util.now() - timedelta(hours=1)).isoformat()
start_time=(end_time - timedelta(hours=1)).isoformat(),
end_time=end_time.isoformat(),
)
except ElviaError.AuthError as exception:

View File

@@ -4,7 +4,7 @@ from __future__ import annotations
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, cast
from elvia import Elvia
from elvia import Elvia, error as ElviaError
from homeassistant.components.recorder.models import StatisticData, StatisticMetaData
from homeassistant.components.recorder.statistics import (
@@ -38,11 +38,18 @@ class ElviaImporter:
self.client = Elvia(meter_value_token=api_token).meter_value()
self.metering_point_id = metering_point_id
async def _fetch_hourly_data(self, since: datetime) -> list[MeterValueTimeSeries]:
async def _fetch_hourly_data(
self,
since: datetime,
until: datetime,
) -> list[MeterValueTimeSeries]:
"""Fetch hourly data."""
LOGGER.debug("Fetching hourly data since %s", since)
start_time = since.isoformat()
end_time = until.isoformat()
LOGGER.debug("Fetching hourly data %s - %s", start_time, end_time)
all_data = await self.client.get_meter_values(
start_time=since.isoformat(),
start_time=start_time,
end_time=end_time,
metering_point_ids=[self.metering_point_id],
)
return all_data["meteringpoints"][0]["metervalue"]["timeSeries"]
@@ -61,18 +68,37 @@ class ElviaImporter:
)
if not last_stats:
# First time we insert 1 years of data (if available)
hourly_data = await self._fetch_hourly_data(
since=dt_util.now() - timedelta(days=365)
)
# First time we insert 3 years of data (if available)
hourly_data: list[MeterValueTimeSeries] = []
until = dt_util.utcnow()
for year in (3, 2, 1):
try:
year_hours = await self._fetch_hourly_data(
since=until - timedelta(days=365 * year),
until=until - timedelta(days=365 * (year - 1)),
)
except ElviaError.ElviaException:
# This will raise if the contract have no data for the
# year, we can safely ignore this
continue
hourly_data.extend(year_hours)
if hourly_data is None or len(hourly_data) == 0:
LOGGER.error("No data available for the metering point")
return
last_stats_time = None
_sum = 0.0
else:
hourly_data = await self._fetch_hourly_data(
since=dt_util.utc_from_timestamp(last_stats[statistic_id][0]["end"])
)
try:
hourly_data = await self._fetch_hourly_data(
since=dt_util.utc_from_timestamp(
last_stats[statistic_id][0]["end"]
),
until=dt_util.utcnow(),
)
except ElviaError.ElviaException as err:
LOGGER.error("Error fetching data: %s", err)
return
if (
hourly_data is None

View File

@@ -83,6 +83,7 @@ class EphEmberThermostat(ClimateEntity):
_attr_hvac_modes = OPERATION_LIST
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, ember, zone):
"""Initialize the thermostat."""
@@ -100,6 +101,9 @@ class EphEmberThermostat(ClimateEntity):
if self._hot_water:
self._attr_supported_features = ClimateEntityFeature.AUX_HEAT
self._attr_target_temperature_step = None
self._attr_supported_features |= (
ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
@property
def current_temperature(self):

View File

@@ -88,9 +88,9 @@ class EpionSensor(CoordinatorEntity[EpionCoordinator], SensorEntity):
super().__init__(coordinator)
self._epion_device_id = epion_device_id
self.entity_description = description
self.unique_id = f"{epion_device_id}_{description.key}"
self._attr_unique_id = f"{epion_device_id}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._epion_device_id)},
identifiers={(DOMAIN, epion_device_id)},
manufacturer="Epion",
name=self.device.get("deviceName"),
sw_version=self.device.get("fwVersion"),

View File

@@ -82,10 +82,14 @@ class ControllerEntity(ClimateEntity):
_attr_precision = PRECISION_WHOLE
_attr_should_poll = False
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_target_temperature_step = PRECISION_WHOLE
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, controller: Controller) -> None:
"""Initialise ControllerDevice."""

View File

@@ -137,6 +137,7 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_translation_key = "climate"
_enable_turn_on_off_backwards_compatibility = False
@callback
def _on_static_info_update(self, static_info: EntityInfo) -> None:
@@ -179,6 +180,8 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
features |= ClimateEntityFeature.FAN_MODE
if self.swing_modes:
features |= ClimateEntityFeature.SWING_MODE
if len(self.hvac_modes) > 1 and HVACMode.OFF in self.hvac_modes:
features |= ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
self._attr_supported_features = features
def _get_precision(self) -> float:

View File

@@ -352,7 +352,6 @@ class ESPHomeManager:
if self.voice_assistant_udp_server is not None:
_LOGGER.warning("Voice assistant UDP server was not stopped")
self.voice_assistant_udp_server.stop()
self.voice_assistant_udp_server.close()
self.voice_assistant_udp_server = None
hass = self.hass

View File

@@ -15,7 +15,7 @@
"iot_class": "local_push",
"loggers": ["aioesphomeapi", "noiseprotocol", "bleak_esphome"],
"requirements": [
"aioesphomeapi==21.0.1",
"aioesphomeapi==21.0.2",
"esphome-dashboard-api==1.2.3",
"bleak-esphome==0.4.1"
],

View File

@@ -1,4 +1,5 @@
"""ESPHome voice assistant support."""
from __future__ import annotations
import asyncio
@@ -67,7 +68,7 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
"""Receive UDP packets and forward them to the voice assistant."""
started = False
stopped = False
stop_requested = False
transport: asyncio.DatagramTransport | None = None
remote_addr: tuple[str, int] | None = None
@@ -92,6 +93,11 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
self._tts_done = asyncio.Event()
self._tts_task: asyncio.Task | None = None
@property
def is_running(self) -> bool:
"""True if the the UDP server is started and hasn't been asked to stop."""
return self.started and (not self.stop_requested)
async def start_server(self) -> int:
"""Start accepting connections."""
@@ -99,7 +105,7 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
"""Accept connection."""
if self.started:
raise RuntimeError("Can only start once")
if self.stopped:
if self.stop_requested:
raise RuntimeError("No longer accepting connections")
self.started = True
@@ -124,7 +130,7 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
@callback
def datagram_received(self, data: bytes, addr: tuple[str, int]) -> None:
"""Handle incoming UDP packet."""
if not self.started or self.stopped:
if not self.is_running:
return
if self.remote_addr is None:
self.remote_addr = addr
@@ -142,19 +148,19 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
def stop(self) -> None:
"""Stop the receiver."""
self.queue.put_nowait(b"")
self.started = False
self.stopped = True
self.close()
def close(self) -> None:
"""Close the receiver."""
self.started = False
self.stopped = True
self.stop_requested = True
if self.transport is not None:
self.transport.close()
async def _iterate_packets(self) -> AsyncIterable[bytes]:
"""Iterate over incoming packets."""
if not self.started or self.stopped:
if not self.is_running:
raise RuntimeError("Not running")
while data := await self.queue.get():
@@ -303,8 +309,11 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
async def _send_tts(self, media_id: str) -> None:
"""Send TTS audio to device via UDP."""
# Always send stream start/end events
self.handle_event(VoiceAssistantEventType.VOICE_ASSISTANT_TTS_STREAM_START, {})
try:
if self.transport is None:
if (not self.is_running) or (self.transport is None):
return
extension, data = await tts.async_get_media_source_audio(
@@ -337,15 +346,11 @@ class VoiceAssistantUDPServer(asyncio.DatagramProtocol):
_LOGGER.debug("Sending %d bytes of audio", audio_bytes_size)
self.handle_event(
VoiceAssistantEventType.VOICE_ASSISTANT_TTS_STREAM_START, {}
)
bytes_per_sample = stt.AudioBitRates.BITRATE_16 // 8
sample_offset = 0
samples_left = audio_bytes_size // bytes_per_sample
while samples_left > 0:
while (samples_left > 0) and self.is_running:
bytes_offset = sample_offset * bytes_per_sample
chunk: bytes = audio_bytes[bytes_offset : bytes_offset + 1024]
samples_in_chunk = len(chunk) // bytes_per_sample

View File

@@ -156,6 +156,7 @@ class EvoClimateEntity(EvoDevice, ClimateEntity):
"""Base for an evohome Climate device."""
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
@property
def hvac_modes(self) -> list[HVACMode]:
@@ -190,7 +191,10 @@ class EvoZone(EvoChild, EvoClimateEntity):
]
self._attr_supported_features = (
ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.TARGET_TEMPERATURE
ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
async def async_zone_svc_request(self, service: str, data: dict[str, Any]) -> None:
@@ -372,6 +376,9 @@ class EvoController(EvoClimateEntity):
]
if self._attr_preset_modes:
self._attr_supported_features = ClimateEntityFeature.PRESET_MODE
self._attr_supported_features |= (
ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
async def async_tcs_svc_request(self, service: str, data: dict[str, Any]) -> None:
"""Process a service request (system mode) for a controller.

View File

@@ -126,6 +126,8 @@ async def async_setup_entry(
class FibaroThermostat(FibaroDevice, ClimateEntity):
"""Representation of a Fibaro Thermostat."""
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, fibaro_device: DeviceModel) -> None:
"""Initialize the Fibaro device."""
super().__init__(fibaro_device)
@@ -209,6 +211,11 @@ class FibaroThermostat(FibaroDevice, ClimateEntity):
if mode in OPMODES_PRESET:
self._attr_preset_modes.append(OPMODES_PRESET[mode])
if HVACMode.OFF in self._attr_hvac_modes and len(self._attr_hvac_modes) > 1:
self._attr_supported_features |= (
ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
async def async_added_to_hass(self) -> None:
"""Call when entity is added to hass."""
_LOGGER.debug(

View File

@@ -69,6 +69,7 @@ class Flexit(ClimateEntity):
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self, hub: ModbusHub, modbus_slave: int | None, name: str | None

View File

@@ -62,13 +62,17 @@ class FlexitClimateEntity(FlexitEntity, ClimateEntity):
]
_attr_supported_features = (
ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.TARGET_TEMPERATURE
ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_target_temperature_step = PRECISION_HALVES
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_max_temp = MAX_TEMP
_attr_min_temp = MIN_TEMP
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, coordinator: FlexitCoordinator) -> None:
"""Initialize the Flexit unit."""

View File

@@ -7,6 +7,7 @@ from typing import Any
from aioflo.api import API
from aioflo.errors import RequestError
from orjson import JSONDecodeError
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
@@ -18,6 +19,8 @@ from .const import DOMAIN as FLO_DOMAIN, LOGGER
class FloDeviceDataUpdateCoordinator(DataUpdateCoordinator): # pylint: disable=hass-enforce-coordinator-module
"""Flo device object."""
_failure_count: int = 0
def __init__(
self, hass: HomeAssistant, api_client: API, location_id: str, device_id: str
) -> None:
@@ -43,8 +46,11 @@ class FloDeviceDataUpdateCoordinator(DataUpdateCoordinator): # pylint: disable=
await self.send_presence_ping()
await self._update_device()
await self._update_consumption_data()
except RequestError as error:
raise UpdateFailed(error) from error
self._failure_count = 0
except (RequestError, TimeoutError, JSONDecodeError) as error:
self._failure_count += 1
if self._failure_count > 3:
raise UpdateFailed(error) from error
@property
def location_id(self) -> str:

View File

@@ -64,10 +64,15 @@ class Device(CoordinatorEntity[FreedomproDataUpdateCoordinator], ClimateEntity):
_attr_hvac_modes = SUPPORTED_HVAC_MODES
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_name = None
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_current_temperature = 0
_attr_target_temperature = 0
_attr_hvac_mode = HVACMode.OFF
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,

View File

@@ -80,6 +80,7 @@ class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
| ClimateEntityFeature.TURN_ON
)
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
@property
def current_temperature(self) -> float:

View File

@@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20240131.0"]
"requirements": ["home-assistant-frontend==20240205.0"]
}

View File

@@ -8,6 +8,7 @@ import logging
from typing import Any
import httpx
import voluptuous as vol
import yarl
from homeassistant.components.camera import Camera, CameraEntityFeature
@@ -140,6 +141,12 @@ class GenericCamera(Camera):
_LOGGER.error("Error parsing template %s: %s", self._still_image_url, err)
return self._last_image
try:
vol.Schema(vol.Url())(url)
except vol.Invalid as err:
_LOGGER.warning("Invalid URL '%s': %s, returning last image", url, err)
return self._last_image
if url == self._last_url and self._limit_refetch:
return self._last_image

View File

@@ -178,6 +178,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
"""Representation of a Generic Thermostat device."""
_attr_should_poll = False
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,
@@ -225,7 +226,11 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
self._target_temp = target_temp
self._attr_temperature_unit = unit
self._attr_unique_id = unique_id
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
self._attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
if len(presets):
self._attr_supported_features |= ClimateEntityFeature.PRESET_MODE
self._attr_preset_modes = [PRESET_NONE] + list(presets.keys())

View File

@@ -50,8 +50,12 @@ class GeniusClimateZone(GeniusHeatingZone, ClimateEntity):
"""Representation of a Genius Hub climate device."""
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, broker, zone) -> None:
"""Initialize the climate device."""

View File

@@ -105,7 +105,8 @@ class GeoJsonLocationEvent(GeolocationEvent):
def _update_from_feed(self, feed_entry: GenericFeedEntry) -> None:
"""Update the internal state from the provided feed entry."""
if feed_entry.properties and "name" in feed_entry.properties:
self._attr_name = feed_entry.properties.get("name")
# The entry name's type can vary, but our own name must be a string
self._attr_name = str(feed_entry.properties["name"])
else:
self._attr_name = feed_entry.title
self._attr_distance = feed_entry.distance_to_home

View File

@@ -5,5 +5,5 @@
"documentation": "https://www.home-assistant.io/integrations/geo_rss_events",
"iot_class": "cloud_polling",
"loggers": ["georss_client", "georss_generic_client"],
"requirements": ["georss-generic-client==0.6"]
"requirements": ["georss-generic-client==0.8"]
}

View File

@@ -35,7 +35,7 @@
"prompt": {
"name": "Prompt",
"description": "The prompt",
"example": "Describe what you see in these images:"
"example": "Describe what you see in these images"
},
"image_filename": {
"name": "Image filename",

View File

@@ -90,5 +90,5 @@
"dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/govee_ble",
"iot_class": "local_push",
"requirements": ["govee-ble==0.27.3"]
"requirements": ["govee-ble==0.31.0"]
}

View File

@@ -113,6 +113,8 @@ class GreeClimateEntity(GreeEntity, ClimateEntity):
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_target_temperature_step = TARGET_TEMPERATURE_STEP
_attr_hvac_modes = [*HVAC_MODES_REVERSE, HVACMode.OFF]
@@ -120,6 +122,7 @@ class GreeClimateEntity(GreeEntity, ClimateEntity):
_attr_fan_modes = [*FAN_MODES_REVERSE]
_attr_swing_modes = SWING_MODES
_attr_name = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, coordinator: DeviceDataUpdateCoordinator) -> None:
"""Initialize the Gree device."""

View File

@@ -1,4 +1,5 @@
"""Platform allowing several sensors to be grouped into one sensor to provide numeric combinations."""
from __future__ import annotations
from collections.abc import Callable
@@ -13,6 +14,7 @@ from homeassistant.components.input_number import DOMAIN as INPUT_NUMBER_DOMAIN
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
from homeassistant.components.sensor import (
CONF_STATE_CLASS,
DEVICE_CLASS_UNITS,
DEVICE_CLASSES_SCHEMA,
DOMAIN,
PLATFORM_SCHEMA as PARENT_PLATFORM_SCHEMA,
@@ -313,6 +315,7 @@ class SensorGroup(GroupEntity, SensorEntity):
self._device_class = device_class
self._native_unit_of_measurement = unit_of_measurement
self._valid_units: set[str | None] = set()
self._can_convert: bool = False
self._attr_name = name
if name == DEFAULT_NAME:
self._attr_name = f"{DEFAULT_NAME} {sensor_type}".capitalize()
@@ -352,10 +355,18 @@ class SensorGroup(GroupEntity, SensorEntity):
self._valid_units
and (uom := state.attributes["unit_of_measurement"])
in self._valid_units
and self._can_convert is True
):
numeric_state = UNIT_CONVERTERS[self.device_class].convert(
numeric_state, uom, self.native_unit_of_measurement
)
if (
self._valid_units
and (uom := state.attributes["unit_of_measurement"])
not in self._valid_units
):
raise HomeAssistantError("Not a valid unit")
sensor_values.append((entity_id, numeric_state, state))
if entity_id in self._state_incorrect:
self._state_incorrect.remove(entity_id)
@@ -536,8 +547,21 @@ class SensorGroup(GroupEntity, SensorEntity):
unit_of_measurements.append(_unit_of_measurement)
# Ensure only valid unit of measurements for the specific device class can be used
if (device_class := self.device_class) in UNIT_CONVERTERS and all(
x in UNIT_CONVERTERS[device_class].VALID_UNITS for x in unit_of_measurements
if (
# Test if uom's in device class is convertible
(device_class := self.device_class) in UNIT_CONVERTERS
and all(
uom in UNIT_CONVERTERS[device_class].VALID_UNITS
for uom in unit_of_measurements
)
) or (
# Test if uom's in device class is not convertible
device_class
and device_class not in UNIT_CONVERTERS
and device_class in DEVICE_CLASS_UNITS
and all(
uom in DEVICE_CLASS_UNITS[device_class] for uom in unit_of_measurements
)
):
async_delete_issue(
self.hass, DOMAIN, f"{self.entity_id}_uoms_not_matching_device_class"
@@ -546,6 +570,7 @@ class SensorGroup(GroupEntity, SensorEntity):
self.hass, DOMAIN, f"{self.entity_id}_uoms_not_matching_no_device_class"
)
return unit_of_measurements[0]
if device_class:
async_create_issue(
self.hass,
@@ -559,7 +584,7 @@ class SensorGroup(GroupEntity, SensorEntity):
"entity_id": self.entity_id,
"device_class": device_class,
"source_entities": ", ".join(self._entity_ids),
"uoms:": ", ".join(unit_of_measurements),
"uoms": ", ".join(unit_of_measurements),
},
)
else:
@@ -574,7 +599,7 @@ class SensorGroup(GroupEntity, SensorEntity):
translation_placeholders={
"entity_id": self.entity_id,
"source_entities": ", ".join(self._entity_ids),
"uoms:": ", ".join(unit_of_measurements),
"uoms": ", ".join(unit_of_measurements),
},
)
return None
@@ -587,5 +612,13 @@ class SensorGroup(GroupEntity, SensorEntity):
if (
device_class := self.device_class
) in UNIT_CONVERTERS and self.native_unit_of_measurement:
self._can_convert = True
return UNIT_CONVERTERS[device_class].VALID_UNITS
if (
device_class
and (device_class) in DEVICE_CLASS_UNITS
and self.native_unit_of_measurement
):
valid_uoms: set = DEVICE_CLASS_UNITS[device_class]
return valid_uoms
return set()

View File

@@ -1001,12 +1001,18 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator): # pylint: disable=has
raise_on_entry_error: bool = False,
) -> None:
"""Refresh data."""
if not scheduled:
if not scheduled and not raise_on_auth_failed:
# Force refreshing updates for non-scheduled updates
# If `raise_on_auth_failed` is set, it means this is
# the first refresh and we do not want to delay
# startup or cause a timeout so we only refresh the
# updates if this is not a scheduled refresh and
# we are not doing the first refresh.
try:
await self.hassio.refresh_updates()
except HassioAPIError as err:
_LOGGER.warning("Error on Supervisor API: %s", err)
await super()._async_refresh(
log_failures, raise_on_auth_failed, scheduled, raise_on_entry_error
)

View File

@@ -459,7 +459,7 @@ class HassIO:
This method returns a coroutine.
"""
return self.send_command("/refresh_updates", timeout=None)
return self.send_command("/refresh_updates", timeout=300)
@api_data
def retrieve_discovery_messages(self) -> Coroutine:

View File

@@ -76,7 +76,12 @@ class HeatmiserV3Thermostat(ClimateEntity):
"""Representation of a HeatmiserV3 thermostat."""
_attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF]
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, therm, device, uh1):
"""Initialize the thermostat."""

View File

@@ -144,6 +144,8 @@ class ClimateAehW4a1(ClimateEntity):
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_attr_fan_modes = FAN_MODES
_attr_swing_modes = SWING_MODES
@@ -152,6 +154,7 @@ class ClimateAehW4a1(ClimateEntity):
_attr_target_temperature_step = 1
_previous_state: HVACMode | str | None = None
_on: str | None = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, device):
"""Initialize the climate device."""

View File

@@ -92,8 +92,12 @@ class HiveClimateEntity(HiveEntity, ClimateEntity):
_attr_hvac_modes = [HVACMode.AUTO, HVACMode.HEAT, HVACMode.OFF]
_attr_preset_modes = [PRESET_BOOST, PRESET_NONE]
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
_enable_turn_on_off_backwards_compatibility = False
def __init__(self, hive_session, hive_device):
"""Initialize the Climate device."""

View File

@@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/holiday",
"iot_class": "local_polling",
"requirements": ["holidays==0.41", "babel==2.13.1"]
"requirements": ["holidays==0.42", "babel==2.13.1"]
}

View File

@@ -10,10 +10,14 @@ BSH_POWER_ON = "BSH.Common.EnumType.PowerState.On"
BSH_POWER_OFF = "BSH.Common.EnumType.PowerState.Off"
BSH_POWER_STANDBY = "BSH.Common.EnumType.PowerState.Standby"
BSH_ACTIVE_PROGRAM = "BSH.Common.Root.ActiveProgram"
BSH_OPERATION_STATE = "BSH.Common.Status.OperationState"
BSH_REMOTE_CONTROL_ACTIVATION_STATE = "BSH.Common.Status.RemoteControlActive"
BSH_REMOTE_START_ALLOWANCE_STATE = "BSH.Common.Status.RemoteControlStartAllowed"
BSH_OPERATION_STATE = "BSH.Common.Status.OperationState"
BSH_OPERATION_STATE_RUN = "BSH.Common.EnumType.OperationState.Run"
BSH_OPERATION_STATE_PAUSE = "BSH.Common.EnumType.OperationState.Pause"
BSH_OPERATION_STATE_FINISHED = "BSH.Common.EnumType.OperationState.Finished"
COOKING_LIGHTING = "Cooking.Common.Setting.Lighting"
COOKING_LIGHTING_BRIGHTNESS = "Cooking.Common.Setting.LightingBrightness"

View File

@@ -10,7 +10,14 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util
from .const import ATTR_VALUE, BSH_OPERATION_STATE, DOMAIN
from .const import (
ATTR_VALUE,
BSH_OPERATION_STATE,
BSH_OPERATION_STATE_FINISHED,
BSH_OPERATION_STATE_PAUSE,
BSH_OPERATION_STATE_RUN,
DOMAIN,
)
from .entity import HomeConnectEntity
_LOGGER = logging.getLogger(__name__)
@@ -69,9 +76,20 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
# if the date is supposed to be in the future but we're
# already past it, set state to None.
self._attr_native_value = None
else:
elif (
BSH_OPERATION_STATE in status
and ATTR_VALUE in status[BSH_OPERATION_STATE]
and status[BSH_OPERATION_STATE][ATTR_VALUE]
in [
BSH_OPERATION_STATE_RUN,
BSH_OPERATION_STATE_PAUSE,
BSH_OPERATION_STATE_FINISHED,
]
):
seconds = self._sign * float(status[self._key][ATTR_VALUE])
self._attr_native_value = dt_util.utcnow() + timedelta(seconds=seconds)
else:
self._attr_native_value = None
else:
self._attr_native_value = status[self._key].get(ATTR_VALUE)
if self._key == BSH_OPERATION_STATE:

View File

@@ -139,6 +139,7 @@ class HomeKitBaseClimateEntity(HomeKitEntity, ClimateEntity):
"""The base HomeKit Controller climate entity."""
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_enable_turn_on_off_backwards_compatibility = False
@callback
def _async_reconfigure(self) -> None:

View File

@@ -14,6 +14,6 @@
"documentation": "https://www.home-assistant.io/integrations/homekit_controller",
"iot_class": "local_push",
"loggers": ["aiohomekit", "commentjson"],
"requirements": ["aiohomekit==3.1.3"],
"requirements": ["aiohomekit==3.1.4"],
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."]
}

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