Compare commits

...

188 Commits

Author SHA1 Message Date
Franck Nijhof
1b9f27fab7 Bump version to 2024.7.0b9 2024-07-02 22:15:17 +02:00
Bram Kragten
d1e76d5c3c Update frontend to 20240702.0 (#121032) 2024-07-02 22:15:09 +02:00
Jan-Philipp Benecke
4377f4cbea Temporarily set apprise log level to debug in tests (#121029)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-07-02 22:15:05 +02:00
Franck Nijhof
6b045a7d7b Bump version to 2024.7.0b8 2024-07-02 21:09:55 +02:00
Marcel van der Veldt
1fa6972a66 Handle mains power for Matter appliances (#121023) 2024-07-02 21:09:39 +02:00
Marcel van der Veldt
b3e833f677 Fix setting target temperature for single setpoint Matter thermostat (#121011) 2024-07-02 21:09:36 +02:00
starkillerOG
807ed0ce10 Do not hold core startup with reolink firmware check task (#120985) 2024-07-02 21:09:32 +02:00
starkillerOG
5cb41106b5 Reolink replace automatic removal of devices by manual removal (#120981)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-07-02 21:09:28 +02:00
Joost Lekkerkerker
98a2e46d4a Remove Aladdin Connect integration (#120980) 2024-07-02 21:08:14 +02:00
Joost Lekkerkerker
24afbde79e Bump yt-dlp to 2024.07.01 (#120978) 2024-07-02 21:05:52 +02:00
starkillerOG
65d2ca53cb Bump reolink-aio to 0.9.4 (#120964) 2024-07-02 21:05:49 +02:00
Joost Lekkerkerker
23b905b422 Bump airgradient to 0.6.1 (#120962) 2024-07-02 21:05:46 +02:00
Joost Lekkerkerker
de458493f8 Fix missing airgradient string (#120957) 2024-07-02 21:05:42 +02:00
Erik Montnemery
efd3252849 Create log files in an executor thread (#120912) 2024-07-02 21:05:39 +02:00
Jesse Hills
3b6acd5380 [ESPHome] Disable dashboard based update entities by default (#120907)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2024-07-02 21:05:36 +02:00
Teemu R
1e6dc74812 Minor polishing for tplink (#120868) 2024-07-02 21:05:22 +02:00
Franck Nijhof
74687f3b60 Bump version to 2024.7.0b7 2024-07-01 19:44:51 +02:00
Markus Jacobsen
2f307d6a8a Fix Bang & Olufsen jumping volume bar (#120946) 2024-07-01 19:44:37 +02:00
J. Nick Koston
d8f55763c5 Downgrade logging previously reported asyncio block to debug (#120942) 2024-07-01 19:44:34 +02:00
Steven B
4b2be448f0 Bump python-kasa to 0.7.0.2 (#120940) 2024-07-01 19:44:31 +02:00
Marcel van der Veldt
8a7e2c05a5 Mark dry/fan-only climate modes as supported for Panasonic room air conditioner (#120939) 2024-07-01 19:44:28 +02:00
Paulus Schoutsen
887ab1dc58 Bump openai to 1.35.1 (#120926)
Bump openai to 1.35.7
2024-07-01 19:44:25 +02:00
Jan Bouwhuis
a787ce8633 Bump incomfort-client dependency to 0.6.3 (#120913) 2024-07-01 19:44:22 +02:00
Robert Resch
88ed43c779 Improve add user error messages (#120909) 2024-07-01 19:44:19 +02:00
dougiteixeira
16d7764f18 Add missing translations for device class in Template (#120893) 2024-07-01 19:44:15 +02:00
dougiteixeira
a0f8012f48 Add missing translations for device class in SQL (#120892) 2024-07-01 19:44:12 +02:00
dougiteixeira
5a052feb87 Add missing translations for device class in Scrape (#120891) 2024-07-01 19:44:09 +02:00
Allen Porter
779a7ddaa2 Bump ical to 8.1.1 (#120888) 2024-07-01 19:44:06 +02:00
Shay Levy
a9740faeda Fix Shelly device shutdown (#120881) 2024-07-01 19:44:03 +02:00
Thomas55555
3a0e85beb8 Bump aioautomower to 2024.6.4 (#120875) 2024-07-01 19:43:59 +02:00
Yuxin Wang
c19fb35d02 Add handling for different STATFLAG formats in APCUPSD (#120870)
* Add handling for different STATFLAG formats

* Just use removesuffix
2024-07-01 19:43:56 +02:00
J. Nick Koston
6f716c1753 Fix publish cancellation handling in MQTT (#120826) 2024-07-01 19:43:53 +02:00
Jan Bouwhuis
40384b9acd Split mqtt client tests (#120636) 2024-07-01 19:43:50 +02:00
Jan Bouwhuis
3bbf8df6d6 Cleanup mqtt platform tests part 4 (init) (#120574) 2024-07-01 19:43:46 +02:00
Franck Nijhof
14af3661f3 Bump version to 2024.7.0b6 2024-06-30 20:42:10 +02:00
Michael
af733425c2 Bump pyfritzhome to 0.6.12 (#120861) 2024-06-30 20:41:51 +02:00
Allen Porter
4fc89e8861 Rollback PyFlume to 0.6.5 (#120846) 2024-06-30 20:39:47 +02:00
Tsvi Mostovicz
bcec268c04 Fix Jewish calendar unique id move to entity (#120842) 2024-06-30 20:39:44 +02:00
Shay Levy
becf9fcce2 Bump aiowebostv to 0.4.1 (#120838) 2024-06-30 20:39:41 +02:00
Etienne Soufflet
ad9e0ef8e4 Fix Tado fan mode (#120809) 2024-06-30 20:39:38 +02:00
Simon Lamon
f58eafe8fc Fix routes with transfer in nmbs integration (#120808) 2024-06-30 20:39:35 +02:00
mkmer
a7246400b3 Allow EM heat on from any mode in Honeywell (#120750) 2024-06-30 20:39:32 +02:00
Joost Lekkerkerker
38a30b343d Bump pizzapi to 0.0.6 (#120691) 2024-06-30 20:39:28 +02:00
Franck Nijhof
08a0eaf184 Bump version to 2024.7.0b5 2024-06-29 17:51:45 +02:00
Joost Lekkerkerker
3ee8f6edba Use meal note as fallback in Mealie (#120828) 2024-06-29 17:51:34 +02:00
Joost Lekkerkerker
e866417c01 Add icons to Airgradient (#120820) 2024-06-29 17:51:31 +02:00
Joost Lekkerkerker
05c63eb884 Bump python-opensky to 1.0.1 (#120818) 2024-06-29 17:51:28 +02:00
Joost Lekkerkerker
bb52bfd73d Add unique id to Mealie config entry (#120816) 2024-06-29 17:51:25 +02:00
Joost Lekkerkerker
7319492bf3 Bump aiomealie to 0.5.0 (#120815) 2024-06-29 17:51:21 +02:00
J. Nick Koston
66932e3d9a Fix unneeded dict values for MATCH_ALL recorder attrs exclude (#120804)
* Small cleanup to handling MATCH_ALL recorder attrs exclude

* Fix unneeded dict values for MATCH_ALL recorder attrs exclude

The exclude is a set so the dict values were not needed

* Fix unneeded dict values for MATCH_ALL recorder attrs exclude

The exclude is a set so the dict values were not needed

* Fix unneeded dict values for MATCH_ALL recorder attrs exclude

The exclude is a set so the dict values were not needed
2024-06-29 17:51:18 +02:00
J. Nick Koston
0ec07001bd Fix blocking I/O in xmpp notify to read uploaded files (#120801)
detected by ruff in https://github.com/home-assistant/core/pull/120799
2024-06-29 17:51:15 +02:00
J. Nick Koston
0dcfd38cdc Fix missing f-string in loop util (#120800) 2024-06-29 17:51:12 +02:00
Klaas Schoute
b45eff9a2b Bump gridnet lib to v5.0.1 (#120793) 2024-06-29 17:51:09 +02:00
Klaas Schoute
ec577c7bd3 Bump odp-amsterdam lib to v6.0.2 (#120788) 2024-06-29 17:51:06 +02:00
Paul Bottein
723c4a1eb5 Update frontend to 20240628.0 (#120785)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-06-29 17:51:02 +02:00
Klaas Schoute
b30b4d5a3a Bump energyzero lib to v2.1.1 (#120783) 2024-06-29 17:50:59 +02:00
Matthew FitzGerald-Chamberlain
8165acddeb Bump pyaprilaire to 0.7.4 (#120782) 2024-06-29 17:50:56 +02:00
Joost Lekkerkerker
0f3ed3bb67 Bump aiowithings to 3.0.2 (#120765) 2024-06-29 17:50:53 +02:00
Maciej Bieniek
d1a96ef362 Do not call async_delete_issue() if there is no issue to delete in Shelly integration (#120762)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-06-29 17:50:50 +02:00
J. Nick Koston
917eeba984 Increase mqtt availablity timeout to 50s (#120760) 2024-06-29 17:50:46 +02:00
Clifford Roche
59bb8b360e Bump greeclimate to 1.4.6 (#120758) 2024-06-29 17:50:43 +02:00
Klaas Schoute
6028e5b77a Bump p1monitor lib to v3.0.1 (#120756) 2024-06-29 17:50:40 +02:00
Klaas Schoute
83df470307 Bump easyenergy lib to v2.1.2 (#120753) 2024-06-29 17:50:37 +02:00
Joost Lekkerkerker
20ac0aa7b1 Bump govee-local-api to 1.5.1 (#120747) 2024-06-29 17:50:34 +02:00
Joost Lekkerkerker
f57c942901 Bump sense-energy to 0.12.4 (#120744)
* Bump sense-energy to 0.12.4

* Fix
2024-06-29 17:50:31 +02:00
Alexey ALERT Rubashёff
8994ab1686 Add warm water remaining volume sensor to Overkiz (#120718)
* warm water remaining volume sensor

* Update homeassistant/components/overkiz/sensor.py

Co-authored-by: Dave T <17680170+davet2001@users.noreply.github.com>

---------

Co-authored-by: Dave T <17680170+davet2001@users.noreply.github.com>
2024-06-29 17:50:28 +02:00
Alexey ALERT Rubashёff
b350ba9657 Add electrical consumption sensor to Overkiz (#120717)
electrical consumption sensor
2024-06-29 17:50:25 +02:00
wittypluck
5fd589053a Reject small uptime updates for Unifi clients (#120398)
Extend logic to reject small uptime updates to Unifi clients + add unit tests
2024-06-29 17:50:22 +02:00
Allen Porter
2d5961fa4f Bump gcal_sync to 6.1.3 (#120278) 2024-06-29 17:50:18 +02:00
Franck Nijhof
d7a59748cf Bump version to 2024.7.0b4 2024-06-28 13:38:24 +02:00
tronikos
cada78496b Fix Google Generative AI: 400 Request contains an invalid argument (#120741) 2024-06-28 13:31:00 +02:00
Illia
c5fa9ad272 Bump asyncarve to 0.1.1 (#120740) 2024-06-28 13:30:51 +02:00
epenet
fe8b5656dd Separate renault strings (#120737) 2024-06-28 13:30:48 +02:00
epenet
0ae11b0335 Bump renault-api to 0.2.4 (#120727) 2024-06-28 13:30:45 +02:00
Dave Leaver
76780ca04e Bump airtouch5py to 1.2.0 (#120715)
* Bump airtouch5py to fix console 1.2.0

* Bump airtouch5py again
2024-06-28 13:30:38 +02:00
Brett Adams
3932ce57b9 Check Tessie scopes to fix startup bug (#120710)
* Add scope check

* Add tests

* Bump Teslemetry
2024-06-28 13:30:35 +02:00
dougiteixeira
35d145d3bc Link the Statistics helper entity to the source entity device (#120705) 2024-06-28 13:30:30 +02:00
Maciej Bieniek
1227d56aa2 Bump nextdns to version 3.1.0 (#120703)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
2024-06-28 13:30:27 +02:00
Joost Lekkerkerker
ef3ecb6183 Bump apsystems-ez1 to 1.3.3 (#120702) 2024-06-28 13:30:18 +02:00
Joost Lekkerkerker
ca515f740e Bump panasonic_viera to 0.4.2 (#120692)
* Bump panasonic_viera to 0.4.2

* Bump panasonic_viera to 0.4.2

* Bump panasonic_viera to 0.4.2

* Fix Keys
2024-06-28 13:30:15 +02:00
Erik Montnemery
876fb234ce Bump hatasmota to 0.9.2 (#120670) 2024-06-28 13:30:10 +02:00
Erik Montnemery
f28cbf1909 Set stateclass on unknown numeric Tasmota sensors (#120650) 2024-06-28 13:30:06 +02:00
Franck Nijhof
9b5d0f72dc Bump version to 2024.7.0b3 2024-06-27 22:20:25 +02:00
Steven B
23056f839b Update tplink unlink identifiers to deal with ids from other domains (#120596) 2024-06-27 22:20:02 +02:00
Joost Lekkerkerker
0b8dd738f1 Bump ttls to 1.8.3 (#120700) 2024-06-27 22:19:25 +02:00
Glenn Waters
411633d3b3 Bump Environment Canada to 0.7.1 (#120699) 2024-06-27 22:19:22 +02:00
Thomas55555
f3ab3bd5cb Bump aioautomower to 2024.6.3 (#120697) 2024-06-27 22:19:19 +02:00
Bram Kragten
476b9909ac Update frontend to 20240627.0 (#120693) 2024-06-27 22:19:16 +02:00
Glenn Waters
e756328d52 Bump upb-lib to 0.5.7 (#120689) 2024-06-27 22:19:13 +02:00
J. Nick Koston
b9c9921847 Add newer models to unifi integrations discovery (#120688) 2024-06-27 22:19:10 +02:00
MatthewFlamm
09dbd8e7eb Use more observations in NWS (#120687)
Use more observations
2024-06-27 22:19:07 +02:00
Glenn Waters
07dd832c58 Bump Environment Canada to 0.7.0 (#120686) 2024-06-27 22:19:04 +02:00
J. Nick Koston
f9c5661c66 Bump unifi-discovery to 1.2.0 (#120684) 2024-06-27 22:19:01 +02:00
J. Nick Koston
94f8f8281f Bump uiprotect to 4.2.0 (#120669) 2024-06-27 22:18:58 +02:00
Erik Montnemery
f6aa25c717 Fix docstring for EventStateEventData (#120662) 2024-06-27 22:18:55 +02:00
Jesse Hills
f9ca85735d [esphome] Add more tests to bring integration to 100% coverage (#120661) 2024-06-27 22:18:52 +02:00
Joost Lekkerkerker
be086c581c Fix Airgradient ABC days name (#120659) 2024-06-27 22:18:49 +02:00
Joost Lekkerkerker
03d198dd64 Fix unknown attribute in MPD (#120657) 2024-06-27 22:18:47 +02:00
Joost Lekkerkerker
a8d6866f9f Disable polling for Knocki (#120656) 2024-06-27 22:18:44 +02:00
Brett Adams
0e1dc9878f Fix values at startup for Tessie (#120652) 2024-06-27 22:18:41 +02:00
Erik Montnemery
6849597764 Bump hatasmota to 0.9.1 (#120649) 2024-06-27 22:18:38 +02:00
Josef Zweck
3022d3bfa0 Move Auto On/off switches to Config EntityCategory (#120648) 2024-06-27 22:18:35 +02:00
Erik Montnemery
4836d6620b Add snapshots to tasmota sensor test (#120647) 2024-06-27 22:18:32 +02:00
Erik Montnemery
b290e95350 Improve typing of state event helpers (#120639) 2024-06-27 22:18:29 +02:00
Josef Zweck
89ac3ce832 Fix the version that raises the issue (#120638) 2024-06-27 22:18:26 +02:00
Erik Montnemery
1933454b76 Rename async_track_state_reported_event to async_track_state_report_event (#120637)
* Rename async_track_state_reported_event to async_track_state_report_event

* Update tests
2024-06-27 22:18:23 +02:00
J. Nick Koston
38601d48ff Add async_track_state_reported_event to fix integration performance regression (#120622)
split from https://github.com/home-assistant/core/pull/120621
2024-06-27 22:18:20 +02:00
J. Nick Koston
7256f23376 Fix performance regression in integration from state_reported (#120621)
* Fix performance regression in integration from state_reported

Because the callbacks were no longer indexed by entity id, users
saw upwards of 1M calls/min

https://github.com/home-assistant/core/pull/113869/files#r1655580523

* Update homeassistant/helpers/event.py

* coverage

---------

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2024-06-27 22:18:17 +02:00
J. Nick Koston
7519603bf5 Bump uiprotect to 4.0.0 (#120617) 2024-06-27 22:18:14 +02:00
Luke Lashley
ef47daad9d Bump anova_wifi to 0.14.0 (#120616) 2024-06-27 22:18:11 +02:00
Erik Montnemery
18d283bed6 Don't allow updating a device to have no connections or identifiers (#120603)
* Don't allow updating a device to have no connections or identifiers

* Move check to the top of the function
2024-06-27 22:18:08 +02:00
Steven B
210e906a4d Store tplink credentials_hash outside of device_config (#120597) 2024-06-27 22:17:51 +02:00
J. Nick Koston
dcffd6bd7a Remove unused fields from unifiprotect event sensors (#120568) 2024-06-27 22:14:15 +02:00
Alexey ALERT Rubashёff
2c2261254b Improve AtlanticDomesticHotWaterProductionMBLComponent support in Overkiz (#114178)
* add overkiz AtlanticDHW support

Adds support of Overkiz water heater entity selection based on device controllable_name
Adds support of Atlantic water heater based on Atlantic Steatite Cube WI-FI VM 150 S4CS 2400W
Adds more Overkiz water heater binary_sensors, numbers, and sensors

* Changed class annotation

* min_temp and max_temp as properties

* reverted binary_sensors, number, sensor to make separate PRs

* Update homeassistant/components/overkiz/water_heater_entities/atlantic_dhw.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* Update homeassistant/components/overkiz/water_heater_entities/atlantic_dhw.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* Update homeassistant/components/overkiz/water_heater_entities/atlantic_dhw.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* Update homeassistant/components/overkiz/water_heater.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* Update homeassistant/components/overkiz/water_heater_entities/atlantic_dhw.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* Update homeassistant/components/overkiz/water_heater_entities/atlantic_dhw.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* review fixes, typos, and pylint

* review fix

* review fix

* ruff

* temperature properties changed to constructor attributes

* logger removed

* constants usage consistency

* redundant mapping removed

* Update homeassistant/components/overkiz/water_heater_entities/atlantic_dhw.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* boost mode method annotation typo

* removed away mode for atlantic dwh

* absence and boost mode attributes now support 'prog' state

* heating status bugfix

* electrical consumption sensor

* warm water remaining volume sensor

* away mode reintroduced

* mypy check

* boost plus state support

* Update homeassistant/components/overkiz/sensor.py

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>

* sensors reverted to separate them into their own PR

* check away and boost modes on before switching them off

* atlantic_dhw renamed to atlantic_domestic_hot_water_production

* annotation changed

* AtlanticDomesticHotWaterProductionMBLComponent file renamed, annotation change reverted

---------

Co-authored-by: Mick Vleeshouwer <mick@imick.nl>
2024-06-27 22:14:13 +02:00
Jesse Hills
53e49861a1 Mark esphome integration as platinum (#112565)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-06-27 22:14:08 +02:00
Franck Nijhof
3da8d0a741 Bump version to 2024.7.0b2 2024-06-26 23:55:20 +02:00
Paul Bottein
0701b0daa9 Update frontend to 20240626.2 (#120614) 2024-06-26 23:55:11 +02:00
Luca Angemi
bea6fe30b8 Fix telegram bot thread_id key error (#120613) 2024-06-26 23:55:08 +02:00
Franck Nijhof
7d5d81b229 Bump version to 2024.7.0b1 2024-06-26 22:51:27 +02:00
Franck Nijhof
242b3fa609 Update adguardhome to 0.7.0 (#120605) 2024-06-26 22:48:39 +02:00
Marc Mueller
74204e2ee6 Fix mqtt test fixture usage (#120602) 2024-06-26 22:47:52 +02:00
Jan Bouwhuis
da01635a07 Prevent changes to mutable bmw_connected_drive fixture data (#120600) 2024-06-26 22:47:32 +02:00
Shay Levy
b5c34808e6 Add last_error reporting to Shelly diagnostics (#120595) 2024-06-26 22:47:09 +02:00
Erik Montnemery
80e70993c8 Remove deprecated run_immediately flag from integration sensor (#120593) 2024-06-26 22:46:50 +02:00
Max
2e01e169ef Correct deprecation warning async_register_static_paths (#120592) 2024-06-26 22:46:30 +02:00
Markus Jacobsen
b35442ed2d Improve Bang & Olufsen error messages (#120587)
* Convert logger messages to raised errors where applicable

* Modify exception types

* Improve deezer / tidal error message

* Update homeassistant/components/bang_olufsen/strings.json

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>

* Update homeassistant/components/bang_olufsen/media_player.py

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>

---------

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
2024-06-26 22:46:27 +02:00
Michael Hansen
1b45069620 Bump intents to 2024.6.26 (#120584)
Bump intents
2024-06-26 22:46:23 +02:00
Shay Levy
d3d0e05817 Change Shelly connect task log message level to error (#120582) 2024-06-26 22:46:20 +02:00
TheJulianJES
3d164c6721 Bump ZHA dependencies (#120581) 2024-06-26 22:46:17 +02:00
Florian
6dd1e09354 Don't allow switch toggle when device in locked in AVM FRITZ!SmartHome (#120132)
* fix: set state of the FritzBox-Switch to disabled if the option for manuel switching in the userinterface is disabled

* feat: raise an error instead of disabling switch

* feat: rename method signature

* fix: tests

* fix: wrong import

* feat: Update homeassistant/components/fritzbox/strings.json

Update error message

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>

* Update tests/components/fritzbox/test_switch.py

feat: update test

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>

* make ruff happy

* fix expected error message check

---------

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
2024-06-26 22:46:13 +02:00
Shay Levy
ba456f2564 Align Shelly sleeping devices timeout with non-sleeping (#118969) 2024-06-26 22:46:06 +02:00
Franck Nijhof
3492171ff8 Bump version to 2024.7.0b0 2024-06-26 16:17:57 +02:00
Gerben Jongerius
f5c640ee5b Add additional tests to youless integration (#118869) 2024-06-26 16:11:21 +02:00
epenet
713abf4c6b Refactor PLATFORM_SCHEMA imports in tests (#120566) 2024-06-26 16:09:20 +02:00
Bouwe Westerdijk
32c07180f6 Delete removed device(s) at runtime in Plugwise (#120296) 2024-06-26 16:08:32 +02:00
Mr. Bubbles
55101fcc45 Add platinum scale to pyLoad integration (#120542)
Add platinum scale
2024-06-26 16:06:55 +02:00
G Johansson
3d5d4f8ddb Add config flow to statistics (#120496) 2024-06-26 16:06:35 +02:00
treetip
30a3e9af2b Add profile duration sensor for Vallox integration (#120240) 2024-06-26 15:54:13 +02:00
Erik Montnemery
862cd76f89 Add explanatory comment in tests/patch_time.py (#120572) 2024-06-26 15:49:34 +02:00
epenet
f65d91f6d2 Refactor PLATFORM_SCHEMA imports in platforms (#120564) 2024-06-26 15:44:59 +02:00
epenet
f4fa5b581e Import PLATFORM_SCHEMA from platform not from helpers (#120565) 2024-06-26 15:43:48 +02:00
Mr. Bubbles
294e1d4fc4 Fix class name and deprecation version (#120570) 2024-06-26 15:42:03 +02:00
Joost Lekkerkerker
66a803e56c Disable Aladdin Connect (#120558)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-06-26 15:41:20 +02:00
Luke Lashley
d0f82d6f02 Add support for Dyad vacuums to Roborock (#115331) 2024-06-26 15:40:19 +02:00
Bouwe Westerdijk
4defc4a58f Implement a reboot-button for Plugwise (#120554)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2024-06-26 15:28:50 +02:00
Mr. Bubbles
af9b4b98ca Add value_fn to switch entity description in pyLoad (#120569) 2024-06-26 15:09:42 +02:00
Mr. Bubbles
43d686e0f1 Redact the hostname in pyLoad diagnostics (#120567) 2024-06-26 14:59:14 +02:00
Mr. Bubbles
7eb9875a9e Add Base class for entities in PyLoad integration (#120563)
* Add Base class for entities

* Remove constructors
2024-06-26 14:45:04 +02:00
Teemu R
fc2968bc1b Adjust tplink codeowners (#120561) 2024-06-26 14:35:22 +02:00
Luke Lashley
b9be491016 Add options flow to Roborock (#104345)
Co-authored-by: Robert Resch <robert@resch.dev>
2024-06-26 14:32:26 +02:00
Brett Adams
ec16fc235b Add new coordinators to Tessie (#118452)
* WIP

* wip

* Add energy classes

* Add basis for Testing

* Bump Library

* fix case

* bump library

* bump library again

* bump library for teslemetry

* reorder

* Fix super

* Update strings.json

* Tests

* Small tweaks

* Bump

* Bump teslemetry

* Remove version

* Add WC states

* Bump to match dev

* Review feedback

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

* Review feedback

* Review feedback 1

* Review feedback 2

* TessieWallConnectorStates Enum

* fixes

* Fix translations and value

* Update homeassistant/components/tessie/strings.json

* Update homeassistant/components/tessie/strings.json

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-06-26 14:23:06 +02:00
epenet
fd67fe417e Use ruff to force alias when importing PLATFORM_SCHEMA (#120539) 2024-06-26 14:22:52 +02:00
Joost Lekkerkerker
e39d26bdc0 Add switch platform to Airgradient (#120559) 2024-06-26 14:21:30 +02:00
Michael Hansen
d515a7f063 Add created_seconds to timer info and pass to ESPHome devices (#120364) 2024-06-26 14:20:11 +02:00
Mr. Bubbles
f5ff19d602 Add measurement unit and state_class to sensors in pyLoad (#120551) 2024-06-26 14:14:48 +02:00
Luke Lashley
69e0227682 Add Roborock to strict typing (#120379) 2024-06-26 14:13:49 +02:00
Joost Lekkerkerker
0d2aeb846f Increase max temperature to 40 for Tado (#120560) 2024-06-26 14:05:24 +02:00
Mr. Bubbles
1d0aa6bff0 Update docstrings in pyLoad tests (#120556) 2024-06-26 13:40:20 +02:00
Bouwe Westerdijk
b07453dca4 Implement remaining select-adaptions for Plugwise (#120544) 2024-06-26 13:37:08 +02:00
Mr. Bubbles
972b85a75b Fix class and variable naming errors in pyLoad integration (#120547) 2024-06-26 13:36:25 +02:00
Mr. Bubbles
13a9efb6a6 Convert dataclass to dict in pyLoad diagnostics (#120552) 2024-06-26 13:36:01 +02:00
Erik Montnemery
a36c40a434 Use state_reported events in Riemann sum sensor (#113869) 2024-06-26 13:35:01 +02:00
Bram Kragten
f0590f08b1 Update frontend to 20240626.0 (#120546) 2024-06-26 13:26:53 +02:00
Robert Resch
e8a3e3c8db Fix airgradient select entities (#120549) 2024-06-26 13:19:34 +02:00
Mr. Bubbles
34e266762e Remove unnecessary icon states in pyLoad integration (#120548)
Remove unnecessary icon states
2024-06-26 13:09:50 +02:00
Joost Lekkerkerker
7ef1db0549 Fix release in MPD issue (#120545) 2024-06-26 12:52:31 +02:00
epenet
be7a2c2cc2 Revert "Force alias when importing scene PLATFORM_SCHEMA" (#120540)
Revert "Force alias when importing scene PLATFORM_SCHEMA (#120534)"

This reverts commit 348ceca19f.
2024-06-26 12:40:41 +02:00
Richard Kroegel
d5bcfe9822 Improve BMW tests (#119171)
Co-authored-by: Richard <rikroe@users.noreply.github.com>
2024-06-26 12:27:55 +02:00
Erik Montnemery
9bbeb5d608 Add primary_config_entry attribute to device registry entries (#119959)
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Robert Resch <robert@resch.dev>
2024-06-26 12:26:24 +02:00
Erik Montnemery
f55ddfecf4 Correct type annotations in integration sensor tests (#120541) 2024-06-26 12:25:02 +02:00
epenet
36d8ffa79a Force alias when importing media player PLATFORM_SCHEMA (#120537) 2024-06-26 12:19:04 +02:00
Joost Lekkerkerker
fac8349c37 Add learning offset select to Airgradient (#120532) 2024-06-26 12:18:33 +02:00
Bouwe Westerdijk
d00fe1ce7f Import DOMAIN constants for Plugwise and implement (#120530) 2024-06-26 12:17:17 +02:00
epenet
c49fce5541 Force alias when importing sensor PLATFORM_SCHEMA (#120536) 2024-06-26 12:14:13 +02:00
epenet
348ceca19f Force alias when importing scene PLATFORM_SCHEMA (#120534) 2024-06-26 12:11:22 +02:00
epenet
32bab97f00 Force alias when importing light PLATFORM_SCHEMA (#120529) 2024-06-26 11:53:15 +02:00
epenet
912136be25 Force alias when importing lock PLATFORM_SCHEMA (#120531) 2024-06-26 11:52:57 +02:00
Brett Adams
d4dc7d76d9 Refactor Tessie for future PR (#120406)
* Bump tessie-api

* Refactor

* revert bump

* Fix cover

* Apply suggestions from code review

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

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
2024-06-26 11:46:30 +02:00
epenet
a8bf671663 Force alias when importing remote PLATFORM_SCHEMA (#120533) 2024-06-26 11:45:57 +02:00
Mr. Bubbles
42d235ce4d Add diagnostics platform to pyLoad integration (#120535) 2024-06-26 11:44:58 +02:00
Stefan Agner
44aad2b821 Improve Matter Server version incompatibility handling (#120416)
* Improve Matter Server version incompatibility handling

Improve the handling of Matter Server version. Noteably fix the issues
raised (add strings for the issue) and split the version check into
two cases: One if the server is too old and one if the server is too
new.

* Bump Python Matter Server library to 6.2.0b1

* Address review feedback
2024-06-26 11:43:51 +02:00
epenet
7b7b97a7a4 Force alias when importing event and fan PLATFORM_SCHEMA (#120524) 2024-06-26 11:35:39 +02:00
hahn-th
ae73500beb Add HmIP-ESI (#116863) 2024-06-26 11:33:44 +02:00
Marc Mueller
d527113d59 Improve schema typing (3) (#120521) 2024-06-26 11:30:07 +02:00
epenet
afbd24adfe Force alias when importing image processing PLATFORM_SCHEMA (#120527) 2024-06-26 11:29:52 +02:00
epenet
2c17d84fab Force alias when importing cover PLATFORM_SCHEMA (#120522) 2024-06-26 11:25:14 +02:00
epenet
17946c4b45 Force alias when importing geo location PLATFORM_SCHEMA (#120525) 2024-06-26 11:24:45 +02:00
epenet
59ae297ccd Force alias when importing humidifier PLATFORM_SCHEMA (#120526) 2024-06-26 11:24:21 +02:00
665 changed files with 16519 additions and 5436 deletions

View File

@@ -58,11 +58,6 @@ omit =
homeassistant/components/airvisual/sensor.py
homeassistant/components/airvisual_pro/__init__.py
homeassistant/components/airvisual_pro/sensor.py
homeassistant/components/aladdin_connect/__init__.py
homeassistant/components/aladdin_connect/api.py
homeassistant/components/aladdin_connect/application_credentials.py
homeassistant/components/aladdin_connect/cover.py
homeassistant/components/aladdin_connect/sensor.py
homeassistant/components/alarmdecoder/__init__.py
homeassistant/components/alarmdecoder/alarm_control_panel.py
homeassistant/components/alarmdecoder/binary_sensor.py
@@ -1690,8 +1685,6 @@ omit =
homeassistant/components/yolink/siren.py
homeassistant/components/yolink/switch.py
homeassistant/components/yolink/valve.py
homeassistant/components/youless/__init__.py
homeassistant/components/youless/sensor.py
homeassistant/components/zabbix/*
homeassistant/components/zamg/coordinator.py
homeassistant/components/zengge/light.py

View File

@@ -370,6 +370,7 @@ homeassistant.components.rhasspy.*
homeassistant.components.ridwell.*
homeassistant.components.ring.*
homeassistant.components.rituals_perfume_genie.*
homeassistant.components.roborock.*
homeassistant.components.roku.*
homeassistant.components.romy.*
homeassistant.components.rpi_power.*

View File

@@ -80,8 +80,6 @@ build.json @home-assistant/supervisor
/tests/components/airzone/ @Noltari
/homeassistant/components/airzone_cloud/ @Noltari
/tests/components/airzone_cloud/ @Noltari
/homeassistant/components/aladdin_connect/ @swcloudgenie
/tests/components/aladdin_connect/ @swcloudgenie
/homeassistant/components/alarm_control_panel/ @home-assistant/core
/tests/components/alarm_control_panel/ @home-assistant/core
/homeassistant/components/alert/ @home-assistant/core @frenck
@@ -1460,8 +1458,8 @@ build.json @home-assistant/supervisor
/tests/components/tomorrowio/ @raman325 @lymanepp
/homeassistant/components/totalconnect/ @austinmroczek
/tests/components/totalconnect/ @austinmroczek
/homeassistant/components/tplink/ @rytilahti @thegardenmonkey @bdraco @sdb9696
/tests/components/tplink/ @rytilahti @thegardenmonkey @bdraco @sdb9696
/homeassistant/components/tplink/ @rytilahti @bdraco @sdb9696
/tests/components/tplink/ @rytilahti @bdraco @sdb9696
/homeassistant/components/tplink_omada/ @MarkGodwin
/tests/components/tplink_omada/ @MarkGodwin
/homeassistant/components/traccar/ @ludeeus

View File

@@ -55,13 +55,6 @@ class InvalidUser(HomeAssistantError):
Will not be raised when validating authentication.
"""
class InvalidUsername(InvalidUser):
"""Raised when invalid username is specified.
Will not be raised when validating authentication.
"""
def __init__(
self,
*args: object,
@@ -77,6 +70,13 @@ class InvalidUsername(InvalidUser):
)
class InvalidUsername(InvalidUser):
"""Raised when invalid username is specified.
Will not be raised when validating authentication.
"""
class Data:
"""Hold the user data."""
@@ -216,7 +216,7 @@ class Data:
break
if index is None:
raise InvalidUser
raise InvalidUser(translation_key="user_not_found")
self.users.pop(index)
@@ -232,7 +232,7 @@ class Data:
user["password"] = self.hash_password(new_password, True).decode()
break
else:
raise InvalidUser
raise InvalidUser(translation_key="user_not_found")
@callback
def _validate_new_username(self, new_username: str) -> None:
@@ -275,7 +275,7 @@ class Data:
self._async_check_for_not_normalized_usernames(self._data)
break
else:
raise InvalidUser
raise InvalidUser(translation_key="user_not_found")
async def async_save(self) -> None:
"""Save data."""

View File

@@ -8,7 +8,7 @@ import contextlib
from functools import partial
from itertools import chain
import logging
import logging.handlers
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
import mimetypes
from operator import contains, itemgetter
import os
@@ -257,12 +257,12 @@ async def async_setup_hass(
) -> core.HomeAssistant | None:
"""Set up Home Assistant."""
def create_hass() -> core.HomeAssistant:
async def create_hass() -> core.HomeAssistant:
"""Create the hass object and do basic setup."""
hass = core.HomeAssistant(runtime_config.config_dir)
loader.async_setup(hass)
async_enable_logging(
await async_enable_logging(
hass,
runtime_config.verbose,
runtime_config.log_rotate_days,
@@ -287,7 +287,7 @@ async def async_setup_hass(
async with hass.timeout.async_timeout(10):
await hass.async_stop()
hass = create_hass()
hass = await create_hass()
if runtime_config.skip_pip or runtime_config.skip_pip_packages:
_LOGGER.warning(
@@ -326,13 +326,13 @@ async def async_setup_hass(
if config_dict is None:
recovery_mode = True
await stop_hass(hass)
hass = create_hass()
hass = await create_hass()
elif not basic_setup_success:
_LOGGER.warning("Unable to set up core integrations. Activating recovery mode")
recovery_mode = True
await stop_hass(hass)
hass = create_hass()
hass = await create_hass()
elif any(domain not in hass.config.components for domain in CRITICAL_INTEGRATIONS):
_LOGGER.warning(
@@ -345,7 +345,7 @@ async def async_setup_hass(
recovery_mode = True
await stop_hass(hass)
hass = create_hass()
hass = await create_hass()
if old_logging:
hass.data[DATA_LOGGING] = old_logging
@@ -523,8 +523,7 @@ async def async_from_config_dict(
return hass
@core.callback
def async_enable_logging(
async def async_enable_logging(
hass: core.HomeAssistant,
verbose: bool = False,
log_rotate_days: int | None = None,
@@ -607,23 +606,9 @@ def async_enable_logging(
if (err_path_exists and os.access(err_log_path, os.W_OK)) or (
not err_path_exists and os.access(err_dir, os.W_OK)
):
err_handler: (
logging.handlers.RotatingFileHandler
| logging.handlers.TimedRotatingFileHandler
err_handler = await hass.async_add_executor_job(
_create_log_file, err_log_path, log_rotate_days
)
if log_rotate_days:
err_handler = logging.handlers.TimedRotatingFileHandler(
err_log_path, when="midnight", backupCount=log_rotate_days
)
else:
err_handler = _RotatingFileHandlerWithoutShouldRollOver(
err_log_path, backupCount=1
)
try:
err_handler.doRollover()
except OSError as err:
_LOGGER.error("Error rolling over log file: %s", err)
err_handler.setLevel(logging.INFO if verbose else logging.WARNING)
err_handler.setFormatter(logging.Formatter(fmt, datefmt=FORMAT_DATETIME))
@@ -640,7 +625,29 @@ def async_enable_logging(
async_activate_log_queue_handler(hass)
class _RotatingFileHandlerWithoutShouldRollOver(logging.handlers.RotatingFileHandler):
def _create_log_file(
err_log_path: str, log_rotate_days: int | None
) -> RotatingFileHandler | TimedRotatingFileHandler:
"""Create log file and do roll over."""
err_handler: RotatingFileHandler | TimedRotatingFileHandler
if log_rotate_days:
err_handler = TimedRotatingFileHandler(
err_log_path, when="midnight", backupCount=log_rotate_days
)
else:
err_handler = _RotatingFileHandlerWithoutShouldRollOver(
err_log_path, backupCount=1
)
try:
err_handler.doRollover()
except OSError as err:
_LOGGER.error("Error rolling over log file: %s", err)
return err_handler
class _RotatingFileHandlerWithoutShouldRollOver(RotatingFileHandler):
"""RotatingFileHandler that does not check if it should roll over on every log."""
def shouldRollover(self, record: logging.LogRecord) -> bool:

View File

@@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "local_polling",
"loggers": ["adguardhome"],
"requirements": ["adguardhome==0.6.3"]
"requirements": ["adguardhome==0.7.0"]
}

View File

@@ -10,7 +10,7 @@ import voluptuous as vol
from homeassistant.components.cover import (
ATTR_POSITION,
DEVICE_CLASSES_SCHEMA,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as COVER_PLATFORM_SCHEMA,
CoverEntity,
CoverEntityFeature,
)
@@ -36,7 +36,7 @@ CONF_ADS_VAR_OPEN = "adsvar_open"
CONF_ADS_VAR_CLOSE = "adsvar_close"
CONF_ADS_VAR_STOP = "adsvar_stop"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = COVER_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_ADS_VAR_POSITION): cv.string,

View File

@@ -9,7 +9,7 @@ import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
@@ -29,7 +29,7 @@ from . import (
)
DEFAULT_NAME = "ADS Light"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_ADS_VAR_BRIGHTNESS): cv.string,

View File

@@ -4,7 +4,10 @@ from __future__ import annotations
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
@@ -22,7 +25,7 @@ from . import (
)
DEFAULT_NAME = "ADS sensor"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_ADS_FACTOR): cv.positive_int,

View File

@@ -9,10 +9,7 @@ from typing import Final, final
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType, StateType
@@ -21,6 +18,11 @@ from .const import DOMAIN
_LOGGER: Final = logging.getLogger(__name__)
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL: Final = timedelta(seconds=30)
ATTR_AQI: Final = "air_quality_index"
ATTR_CO2: Final = "carbon_dioxide"
ATTR_CO: Final = "carbon_monoxide"
@@ -33,10 +35,6 @@ ATTR_PM_10: Final = "particulate_matter_10"
ATTR_PM_2_5: Final = "particulate_matter_2_5"
ATTR_SO2: Final = "sulphur_dioxide"
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
SCAN_INTERVAL: Final = timedelta(seconds=30)
PROP_TO_ATTR: Final[dict[str, str]] = {
"air_quality_index": ATTR_AQI,
"carbon_dioxide": ATTR_CO2,

View File

@@ -20,6 +20,7 @@ PLATFORMS: list[Platform] = [
Platform.NUMBER,
Platform.SELECT,
Platform.SENSOR,
Platform.SWITCH,
]

View File

@@ -8,6 +8,34 @@
"default": "mdi:lightbulb-on-outline"
}
},
"number": {
"led_bar_brightness": {
"default": "mdi:brightness-percent"
},
"display_brightness": {
"default": "mdi:brightness-percent"
}
},
"select": {
"configuration_control": {
"default": "mdi:cloud-cog"
},
"display_temperature_unit": {
"default": "mdi:thermometer-lines"
},
"led_bar_mode": {
"default": "mdi:led-strip"
},
"nox_index_learning_time_offset": {
"default": "mdi:clock-outline"
},
"voc_index_learning_time_offset": {
"default": "mdi:clock-outline"
},
"co2_automatic_baseline_calibration": {
"default": "mdi:molecule-co2"
}
},
"sensor": {
"total_volatile_organic_component_index": {
"default": "mdi:molecule"
@@ -17,6 +45,32 @@
},
"pm003_count": {
"default": "mdi:blur"
},
"led_bar_brightness": {
"default": "mdi:brightness-percent"
},
"display_brightness": {
"default": "mdi:brightness-percent"
},
"display_temperature_unit": {
"default": "mdi:thermometer-lines"
},
"led_bar_mode": {
"default": "mdi:led-strip"
},
"nox_index_learning_time_offset": {
"default": "mdi:clock-outline"
},
"voc_index_learning_time_offset": {
"default": "mdi:clock-outline"
},
"co2_automatic_baseline_calibration": {
"default": "mdi:molecule-co2"
}
},
"switch": {
"post_data_to_airgradient": {
"default": "mdi:cogs"
}
}
}

View File

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

View File

@@ -79,6 +79,63 @@ LED_BAR_ENTITIES: tuple[AirGradientSelectEntityDescription, ...] = (
),
)
LEARNING_TIME_OFFSET_OPTIONS = [
"12",
"60",
"120",
"360",
"720",
]
ABC_DAYS = [
"1",
"8",
"30",
"90",
"180",
"0",
]
def _get_value(value: int, values: list[str]) -> str | None:
str_value = str(value)
return str_value if str_value in values else None
CONTROL_ENTITIES: tuple[AirGradientSelectEntityDescription, ...] = (
AirGradientSelectEntityDescription(
key="nox_index_learning_time_offset",
translation_key="nox_index_learning_time_offset",
options=LEARNING_TIME_OFFSET_OPTIONS,
entity_category=EntityCategory.CONFIG,
value_fn=lambda config: _get_value(
config.nox_learning_offset, LEARNING_TIME_OFFSET_OPTIONS
),
set_value_fn=lambda client, value: client.set_nox_learning_offset(int(value)),
),
AirGradientSelectEntityDescription(
key="voc_index_learning_time_offset",
translation_key="voc_index_learning_time_offset",
options=LEARNING_TIME_OFFSET_OPTIONS,
entity_category=EntityCategory.CONFIG,
value_fn=lambda config: _get_value(
config.tvoc_learning_offset, LEARNING_TIME_OFFSET_OPTIONS
),
set_value_fn=lambda client, value: client.set_tvoc_learning_offset(int(value)),
),
AirGradientSelectEntityDescription(
key="co2_automatic_baseline_calibration",
translation_key="co2_automatic_baseline_calibration",
options=ABC_DAYS,
entity_category=EntityCategory.CONFIG,
value_fn=lambda config: _get_value(
config.co2_automatic_baseline_calibration_days, ABC_DAYS
),
set_value_fn=lambda client,
value: client.set_co2_automatic_baseline_calibration(int(value)),
),
)
async def async_setup_entry(
hass: HomeAssistant,
@@ -104,7 +161,10 @@ async def async_setup_entry(
coordinator.data.configuration_control is ConfigurationControl.LOCAL
and not added_entities
):
entities: list[AirGradientSelect] = []
entities: list[AirGradientSelect] = [
AirGradientSelect(coordinator, description)
for description in CONTROL_ENTITIES
]
if "I" in model:
entities.extend(
AirGradientSelect(coordinator, description)
@@ -123,7 +183,9 @@ async def async_setup_entry(
and added_entities
):
entity_registry = er.async_get(hass)
for entity_description in DISPLAY_SELECT_TYPES + LED_BAR_ENTITIES:
for entity_description in (
DISPLAY_SELECT_TYPES + LED_BAR_ENTITIES + CONTROL_ENTITIES
):
unique_id = f"{coordinator.serial_number}-{entity_description.key}"
if entity_id := entity_registry.async_get_entity_id(
SELECT_DOMAIN, DOMAIN, unique_id

View File

@@ -16,6 +16,7 @@
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
"invalid_version": "This firmware version is unsupported. Please upgrade the firmware of the device to at least version 3.1.1."
},
"error": {
@@ -69,6 +70,37 @@
"co2": "Carbon dioxide",
"pm": "Particulate matter"
}
},
"nox_index_learning_time_offset": {
"name": "NOx index learning offset",
"state": {
"12": "12 hours",
"60": "60 hours",
"120": "120 hours",
"360": "360 hours",
"720": "720 hours"
}
},
"voc_index_learning_time_offset": {
"name": "VOC index learning offset",
"state": {
"12": "[%key:component::airgradient::entity::select::nox_index_learning_time_offset::state::12%]",
"60": "[%key:component::airgradient::entity::select::nox_index_learning_time_offset::state::60%]",
"120": "[%key:component::airgradient::entity::select::nox_index_learning_time_offset::state::120%]",
"360": "[%key:component::airgradient::entity::select::nox_index_learning_time_offset::state::360%]",
"720": "[%key:component::airgradient::entity::select::nox_index_learning_time_offset::state::720%]"
}
},
"co2_automatic_baseline_calibration": {
"name": "CO2 automatic baseline duration",
"state": {
"1": "1 day",
"8": "8 days",
"30": "30 days",
"90": "90 days",
"180": "180 days",
"0": "[%key:common::state::off%]"
}
}
},
"sensor": {
@@ -98,10 +130,10 @@
"name": "Carbon dioxide automatic baseline calibration"
},
"nox_learning_offset": {
"name": "NOx learning offset"
"name": "[%key:component::airgradient::entity::select::nox_index_learning_time_offset::name%]"
},
"tvoc_learning_offset": {
"name": "VOC learning offset"
"name": "[%key:component::airgradient::entity::select::voc_index_learning_time_offset::name%]"
},
"led_bar_mode": {
"name": "[%key:component::airgradient::entity::select::led_bar_mode::name%]",
@@ -124,6 +156,11 @@
"display_brightness": {
"name": "[%key:component::airgradient::entity::number::display_brightness::name%]"
}
},
"switch": {
"post_data_to_airgradient": {
"name": "Post data to Airgradient"
}
}
}
}

View File

@@ -0,0 +1,110 @@
"""Support for AirGradient switch entities."""
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any
from airgradient import AirGradientClient, Config
from airgradient.models import ConfigurationControl
from homeassistant.components.switch import (
DOMAIN as SWITCH_DOMAIN,
SwitchEntity,
SwitchEntityDescription,
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirGradientConfigEntry
from .const import DOMAIN
from .coordinator import AirGradientConfigCoordinator
from .entity import AirGradientEntity
@dataclass(frozen=True, kw_only=True)
class AirGradientSwitchEntityDescription(SwitchEntityDescription):
"""Describes AirGradient switch entity."""
value_fn: Callable[[Config], bool]
set_value_fn: Callable[[AirGradientClient, bool], Awaitable[None]]
POST_DATA_TO_AIRGRADIENT = AirGradientSwitchEntityDescription(
key="post_data_to_airgradient",
translation_key="post_data_to_airgradient",
entity_category=EntityCategory.CONFIG,
value_fn=lambda config: config.post_data_to_airgradient,
set_value_fn=lambda client, value: client.enable_sharing_data(enable=value),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AirGradientConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up AirGradient switch entities based on a config entry."""
coordinator = entry.runtime_data.config
added_entities = False
@callback
def _async_check_entities() -> None:
nonlocal added_entities
if (
coordinator.data.configuration_control is ConfigurationControl.LOCAL
and not added_entities
):
async_add_entities(
[AirGradientSwitch(coordinator, POST_DATA_TO_AIRGRADIENT)]
)
added_entities = True
elif (
coordinator.data.configuration_control is not ConfigurationControl.LOCAL
and added_entities
):
entity_registry = er.async_get(hass)
unique_id = f"{coordinator.serial_number}-{POST_DATA_TO_AIRGRADIENT.key}"
if entity_id := entity_registry.async_get_entity_id(
SWITCH_DOMAIN, DOMAIN, unique_id
):
entity_registry.async_remove(entity_id)
added_entities = False
coordinator.async_add_listener(_async_check_entities)
_async_check_entities()
class AirGradientSwitch(AirGradientEntity, SwitchEntity):
"""Defines an AirGradient switch entity."""
entity_description: AirGradientSwitchEntityDescription
coordinator: AirGradientConfigCoordinator
def __init__(
self,
coordinator: AirGradientConfigCoordinator,
description: AirGradientSwitchEntityDescription,
) -> None:
"""Initialize AirGradient switch."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
@property
def is_on(self) -> bool:
"""Return the state of the switch."""
return self.entity_description.value_fn(self.coordinator.data)
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
await self.entity_description.set_value_fn(self.coordinator.client, True)
await self.coordinator.async_request_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
await self.entity_description.set_value_fn(self.coordinator.client, False)
await self.coordinator.async_request_refresh()

View File

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

View File

@@ -2,93 +2,37 @@
from __future__ import annotations
from genie_partner_sdk.client import AladdinConnectClient
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.config_entry_oauth2_flow import (
OAuth2Session,
async_get_config_entry_implementation,
)
from homeassistant.helpers import issue_registry as ir
from .api import AsyncConfigEntryAuth
from .const import DOMAIN
from .coordinator import AladdinConnectCoordinator
PLATFORMS: list[Platform] = [Platform.COVER, Platform.SENSOR]
type AladdinConnectConfigEntry = ConfigEntry[AladdinConnectCoordinator]
DOMAIN = "aladdin_connect"
async def async_setup_entry(
hass: HomeAssistant, entry: AladdinConnectConfigEntry
) -> bool:
"""Set up Aladdin Connect Genie from a config entry."""
implementation = await async_get_config_entry_implementation(hass, entry)
session = OAuth2Session(hass, entry, implementation)
auth = AsyncConfigEntryAuth(async_get_clientsession(hass), session)
coordinator = AladdinConnectCoordinator(hass, AladdinConnectClient(auth))
await coordinator.async_setup()
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
async_remove_stale_devices(hass, entry)
return True
async def async_unload_entry(
hass: HomeAssistant, entry: AladdinConnectConfigEntry
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_migrate_entry(
hass: HomeAssistant, config_entry: AladdinConnectConfigEntry
) -> bool:
"""Migrate old config."""
if config_entry.version < 2:
config_entry.async_start_reauth(hass)
hass.config_entries.async_update_entry(
config_entry,
version=2,
minor_version=1,
)
return True
def async_remove_stale_devices(
hass: HomeAssistant, config_entry: AladdinConnectConfigEntry
) -> None:
"""Remove stale devices from device registry."""
device_registry = dr.async_get(hass)
device_entries = dr.async_entries_for_config_entry(
device_registry, config_entry.entry_id
async def async_setup_entry(hass: HomeAssistant, _: ConfigEntry) -> bool:
"""Set up Aladdin Connect from a config entry."""
ir.async_create_issue(
hass,
DOMAIN,
DOMAIN,
is_fixable=False,
severity=ir.IssueSeverity.ERROR,
translation_key="integration_removed",
translation_placeholders={
"entries": "/config/integrations/integration/aladdin_connect",
},
)
all_device_ids = {door.unique_id for door in config_entry.runtime_data.doors}
for device_entry in device_entries:
device_id: str | None = None
return True
for identifier in device_entry.identifiers:
if identifier[0] == DOMAIN:
device_id = identifier[1]
break
if device_id is None or device_id not in all_device_ids:
# If device_id is None an invalid device entry was found for this config entry.
# If the device_id is not in existing device ids it's a stale device entry.
# Remove config entry from this device entry in either case.
device_registry.async_update_device(
device_entry.id, remove_config_entry_id=config_entry.entry_id
)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
if all(
config_entry.state is ConfigEntryState.NOT_LOADED
for config_entry in hass.config_entries.async_entries(DOMAIN)
if config_entry.entry_id != entry.entry_id
):
ir.async_delete_issue(hass, DOMAIN, DOMAIN)
return True

View File

@@ -1,32 +0,0 @@
"""API for Aladdin Connect Genie bound to Home Assistant OAuth."""
from typing import cast
from aiohttp import ClientSession
from genie_partner_sdk.auth import Auth
from homeassistant.helpers.config_entry_oauth2_flow import OAuth2Session
API_URL = "https://twdvzuefzh.execute-api.us-east-2.amazonaws.com/v1"
API_KEY = "k6QaiQmcTm2zfaNns5L1Z8duBtJmhDOW8JawlCC3"
class AsyncConfigEntryAuth(Auth): # type: ignore[misc]
"""Provide Aladdin Connect Genie authentication tied to an OAuth2 based config entry."""
def __init__(
self,
websession: ClientSession,
oauth_session: OAuth2Session,
) -> None:
"""Initialize Aladdin Connect Genie auth."""
super().__init__(
websession, API_URL, oauth_session.token["access_token"], API_KEY
)
self._oauth_session = oauth_session
async def async_get_access_token(self) -> str:
"""Return a valid access token."""
await self._oauth_session.async_ensure_token_valid()
return cast(str, self._oauth_session.token["access_token"])

View File

@@ -1,14 +0,0 @@
"""application_credentials platform the Aladdin Connect Genie integration."""
from homeassistant.components.application_credentials import AuthorizationServer
from homeassistant.core import HomeAssistant
from .const import OAUTH2_AUTHORIZE, OAUTH2_TOKEN
async def async_get_authorization_server(hass: HomeAssistant) -> AuthorizationServer:
"""Return authorization server."""
return AuthorizationServer(
authorize_url=OAUTH2_AUTHORIZE,
token_url=OAUTH2_TOKEN,
)

View File

@@ -1,70 +1,11 @@
"""Config flow for Aladdin Connect Genie."""
"""Config flow for Aladdin Connect integration."""
from collections.abc import Mapping
import logging
from typing import Any
from homeassistant.config_entries import ConfigFlow
import jwt
from homeassistant.config_entries import ConfigEntry, ConfigFlowResult
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN
from homeassistant.helpers.config_entry_oauth2_flow import AbstractOAuth2FlowHandler
from .const import DOMAIN
from . import DOMAIN
class AladdinConnectOAuth2FlowHandler(AbstractOAuth2FlowHandler, domain=DOMAIN):
"""Config flow to handle Aladdin Connect Genie OAuth2 authentication."""
class AladdinConnectConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Aladdin Connect."""
DOMAIN = DOMAIN
VERSION = 2
MINOR_VERSION = 1
reauth_entry: ConfigEntry | None = None
async def async_step_reauth(
self, user_input: Mapping[str, Any]
) -> ConfigFlowResult:
"""Perform reauth upon API auth error or upgrade from v1 to v2."""
self.reauth_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"]
)
return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm(
self, user_input: Mapping[str, Any] | None = None
) -> ConfigFlowResult:
"""Dialog that informs the user that reauth is required."""
if user_input is None:
return self.async_show_form(step_id="reauth_confirm")
return await self.async_step_user()
async def async_oauth_create_entry(self, data: dict[str, Any]) -> ConfigFlowResult:
"""Create an oauth config entry or update existing entry for reauth."""
token_payload = jwt.decode(
data[CONF_TOKEN][CONF_ACCESS_TOKEN], options={"verify_signature": False}
)
if not self.reauth_entry:
await self.async_set_unique_id(token_payload["sub"])
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=token_payload["username"],
data=data,
)
if self.reauth_entry.unique_id == token_payload["username"]:
return self.async_update_reload_and_abort(
self.reauth_entry,
data=data,
unique_id=token_payload["sub"],
)
if self.reauth_entry.unique_id == token_payload["sub"]:
return self.async_update_reload_and_abort(self.reauth_entry, data=data)
return self.async_abort(reason="wrong_account")
@property
def logger(self) -> logging.Logger:
"""Return logger."""
return logging.getLogger(__name__)
VERSION = 1

View File

@@ -1,6 +0,0 @@
"""Constants for the Aladdin Connect Genie integration."""
DOMAIN = "aladdin_connect"
OAUTH2_AUTHORIZE = "https://app.aladdinconnect.net/login.html"
OAUTH2_TOKEN = "https://twdvzuefzh.execute-api.us-east-2.amazonaws.com/v1/oauth2/token"

View File

@@ -1,38 +0,0 @@
"""Define an object to coordinate fetching Aladdin Connect data."""
from datetime import timedelta
import logging
from genie_partner_sdk.client import AladdinConnectClient
from genie_partner_sdk.model import GarageDoor
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
class AladdinConnectCoordinator(DataUpdateCoordinator[None]):
"""Aladdin Connect Data Update Coordinator."""
def __init__(self, hass: HomeAssistant, acc: AladdinConnectClient) -> None:
"""Initialize."""
super().__init__(
hass,
logger=_LOGGER,
name=DOMAIN,
update_interval=timedelta(seconds=15),
)
self.acc = acc
self.doors: list[GarageDoor] = []
async def async_setup(self) -> None:
"""Fetch initial data."""
self.doors = await self.acc.get_doors()
async def _async_update_data(self) -> None:
"""Fetch data from API endpoint."""
for door in self.doors:
await self.acc.update_door(door.device_id, door.door_number)

View File

@@ -1,84 +0,0 @@
"""Cover Entity for Genie Garage Door."""
from typing import Any
from genie_partner_sdk.model import GarageDoor
from homeassistant.components.cover import (
CoverDeviceClass,
CoverEntity,
CoverEntityFeature,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AladdinConnectConfigEntry, AladdinConnectCoordinator
from .entity import AladdinConnectEntity
async def async_setup_entry(
hass: HomeAssistant,
config_entry: AladdinConnectConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Aladdin Connect platform."""
coordinator = config_entry.runtime_data
async_add_entities(AladdinDevice(coordinator, door) for door in coordinator.doors)
class AladdinDevice(AladdinConnectEntity, CoverEntity):
"""Representation of Aladdin Connect cover."""
_attr_device_class = CoverDeviceClass.GARAGE
_attr_supported_features = CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
_attr_name = None
def __init__(
self, coordinator: AladdinConnectCoordinator, device: GarageDoor
) -> None:
"""Initialize the Aladdin Connect cover."""
super().__init__(coordinator, device)
self._attr_unique_id = device.unique_id
async def async_open_cover(self, **kwargs: Any) -> None:
"""Issue open command to cover."""
await self.coordinator.acc.open_door(
self._device.device_id, self._device.door_number
)
async def async_close_cover(self, **kwargs: Any) -> None:
"""Issue close command to cover."""
await self.coordinator.acc.close_door(
self._device.device_id, self._device.door_number
)
@property
def is_closed(self) -> bool | None:
"""Update is closed attribute."""
value = self.coordinator.acc.get_door_status(
self._device.device_id, self._device.door_number
)
if value is None:
return None
return bool(value == "closed")
@property
def is_closing(self) -> bool | None:
"""Update is closing attribute."""
value = self.coordinator.acc.get_door_status(
self._device.device_id, self._device.door_number
)
if value is None:
return None
return bool(value == "closing")
@property
def is_opening(self) -> bool | None:
"""Update is opening attribute."""
value = self.coordinator.acc.get_door_status(
self._device.device_id, self._device.door_number
)
if value is None:
return None
return bool(value == "opening")

View File

@@ -1,27 +0,0 @@
"""Defines a base Aladdin Connect entity."""
from genie_partner_sdk.model import GarageDoor
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import AladdinConnectCoordinator
class AladdinConnectEntity(CoordinatorEntity[AladdinConnectCoordinator]):
"""Defines a base Aladdin Connect entity."""
_attr_has_entity_name = True
def __init__(
self, coordinator: AladdinConnectCoordinator, device: GarageDoor
) -> None:
"""Initialize the entity."""
super().__init__(coordinator)
self._device = device
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, device.unique_id)},
name=device.name,
manufacturer="Overhead Door",
)

View File

@@ -1,10 +1,9 @@
{
"domain": "aladdin_connect",
"name": "Aladdin Connect",
"codeowners": ["@swcloudgenie"],
"config_flow": true,
"dependencies": ["application_credentials"],
"codeowners": [],
"documentation": "https://www.home-assistant.io/integrations/aladdin_connect",
"integration_type": "system",
"iot_class": "cloud_polling",
"requirements": ["genie-partner-sdk==1.0.2"]
"requirements": []
}

View File

@@ -1,80 +0,0 @@
"""Support for Aladdin Connect Garage Door sensors."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from genie_partner_sdk.client import AladdinConnectClient
from genie_partner_sdk.model import GarageDoor
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import PERCENTAGE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AladdinConnectConfigEntry, AladdinConnectCoordinator
from .entity import AladdinConnectEntity
@dataclass(frozen=True, kw_only=True)
class AccSensorEntityDescription(SensorEntityDescription):
"""Describes AladdinConnect sensor entity."""
value_fn: Callable[[AladdinConnectClient, str, int], float | None]
SENSORS: tuple[AccSensorEntityDescription, ...] = (
AccSensorEntityDescription(
key="battery_level",
device_class=SensorDeviceClass.BATTERY,
entity_registry_enabled_default=False,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=AladdinConnectClient.get_battery_status,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AladdinConnectConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Aladdin Connect sensor devices."""
coordinator = entry.runtime_data
async_add_entities(
AladdinConnectSensor(coordinator, door, description)
for description in SENSORS
for door in coordinator.doors
)
class AladdinConnectSensor(AladdinConnectEntity, SensorEntity):
"""A sensor implementation for Aladdin Connect devices."""
entity_description: AccSensorEntityDescription
def __init__(
self,
coordinator: AladdinConnectCoordinator,
device: GarageDoor,
description: AccSensorEntityDescription,
) -> None:
"""Initialize a sensor for an Aladdin Connect device."""
super().__init__(coordinator, device)
self.entity_description = description
self._attr_unique_id = f"{device.unique_id}-{description.key}"
@property
def native_value(self) -> float | None:
"""Return the state of the sensor."""
return self.entity_description.value_fn(
self.coordinator.acc, self._device.device_id, self._device.door_number
)

View File

@@ -1,29 +1,8 @@
{
"config": {
"step": {
"pick_implementation": {
"title": "[%key:common::config_flow::title::oauth2_pick_implementation%]"
},
"reauth_confirm": {
"title": "[%key:common::config_flow::title::reauth%]",
"description": "Aladdin Connect needs to re-authenticate your account"
}
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
"oauth_error": "[%key:common::config_flow::abort::oauth2_error%]",
"oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]",
"oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]",
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]",
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]",
"no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]",
"user_rejected_authorize": "[%key:common::config_flow::abort::oauth2_user_rejected_authorize%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
},
"create_entry": {
"default": "[%key:common::config_flow::create_entry::authenticated%]"
"issues": {
"integration_removed": {
"title": "The Aladdin Connect integration has been removed",
"description": "The Aladdin Connect integration has been removed from Home Assistant.\n\nTo resolve this issue, please remove the (now defunct) integration entries from your Home Assistant setup. [Click here to see your existing Aladdin Connect integration entries]({entries})."
}
}
}

View File

@@ -52,8 +52,10 @@ from .const import ( # noqa: F401
_LOGGER: Final = logging.getLogger(__name__)
SCAN_INTERVAL: Final = timedelta(seconds=30)
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
PLATFORM_SCHEMA: Final = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE: Final = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL: Final = timedelta(seconds=30)
CONF_DEFAULT_CODE = "default_code"
@@ -61,8 +63,6 @@ ALARM_SERVICE_SCHEMA: Final = make_entity_service_schema(
{vol.Optional(ATTR_CODE): cv.string}
)
PLATFORM_SCHEMA: Final = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE: Final = cv.PLATFORM_SCHEMA_BASE
# mypy: disallow-any-generics

View File

@@ -10,7 +10,10 @@ from alpha_vantage.timeseries import TimeSeries
import voluptuous as vol
from homeassistant.components import persistent_notification
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_API_KEY, CONF_CURRENCY, CONF_NAME
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
@@ -59,7 +62,7 @@ CURRENCY_SCHEMA = vol.Schema(
}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_FOREIGN_EXCHANGE): vol.All(cv.ensure_list, [CURRENCY_SCHEMA]),

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/anova",
"iot_class": "cloud_push",
"loggers": ["anova_wifi"],
"requirements": ["anova-wifi==0.12.0"]
"requirements": ["anova-wifi==0.14.0"]
}

View File

@@ -68,4 +68,8 @@ class OnlineStatus(CoordinatorEntity[APCUPSdCoordinator], BinarySensorEntity):
"""Returns true if the UPS is online."""
# Check if ONLINE bit is set in STATFLAG.
key = self.entity_description.key.upper()
return int(self.coordinator.data[key], 16) & _VALUE_ONLINE_MASK != 0
# The daemon could either report just a hex ("0x05000008"), or a hex with a "Status Flag"
# suffix ("0x05000008 Status Flag") in older versions.
# Here we trim the suffix if it exists to support both.
flag = self.coordinator.data[key].removesuffix(" Status Flag")
return int(flag, 16) & _VALUE_ONLINE_MASK != 0

View File

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

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/apsystems",
"integration_type": "device",
"iot_class": "local_polling",
"requirements": ["apsystems-ez1==1.3.1"]
"requirements": ["apsystems-ez1==1.3.3"]
}

View File

@@ -7,7 +7,7 @@ from dataclasses import dataclass
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
@@ -104,7 +104,7 @@ SENSOR_TYPES: tuple[AquaLogicSensorEntityDescription, ...] = (
SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_MONITORED_CONDITIONS, default=SENSOR_KEYS): vol.All(
cv.ensure_list, [vol.In(SENSOR_KEYS)]

View File

@@ -10,7 +10,7 @@ import sharp_aquos_rc
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -37,7 +37,7 @@ DEFAULT_PASSWORD = "password"
DEFAULT_TIMEOUT = 0.5
DEFAULT_RETRIES = 2
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -9,7 +9,10 @@ import logging
import requests
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import (
CONF_MONITORED_VARIABLES,
CONF_NAME,
@@ -41,7 +44,7 @@ PIN_VARIABLE_SCHEMA = vol.Schema(
}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_RESOURCE): cv.url,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/arve",
"iot_class": "cloud_polling",
"requirements": ["asyncarve==0.0.9"]
"requirements": ["asyncarve==0.1.1"]
}

View File

@@ -9,7 +9,7 @@ from pyatome.client import AtomeClient, PyAtomeError
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorStateClass,
@@ -49,7 +49,7 @@ WEEKLY_TYPE = "week"
MONTHLY_TYPE = "month"
YEARLY_TYPE = "year"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,

View File

@@ -37,7 +37,10 @@
"message": "Username \"{username}\" already exists"
},
"username_not_normalized": {
"message": "Username \"{new_username}\" is not normalized"
"message": "Username \"{new_username}\" is not normalized. Please make sure the username is lowercase and does not contain any whitespace."
},
"user_not_found": {
"message": "User not found"
}
},
"issues": {

View File

@@ -10,7 +10,7 @@ import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
@@ -35,7 +35,7 @@ DEVICE_SCHEMA = vol.Schema(
}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA},
vol.Optional(CONF_USERNAME): cv.string,

View File

@@ -45,7 +45,7 @@ from homeassistant.components.media_player import (
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_MODEL
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@@ -316,7 +316,7 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity):
@callback
def _async_update_playback_error(self, data: PlaybackError) -> None:
"""Show playback error."""
_LOGGER.error(data.error)
raise HomeAssistantError(data.error)
@callback
def _async_update_playback_progress(self, data: PlaybackProgress) -> None:
@@ -366,7 +366,7 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity):
@property
def volume_level(self) -> float | None:
"""Volume level of the media player (0..1)."""
if self._volume.level and self._volume.level.level:
if self._volume.level and self._volume.level.level is not None:
return float(self._volume.level.level / 100)
return None
@@ -516,7 +516,9 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity):
self.async_write_ha_state()
else:
_LOGGER.error("Seeking is currently only supported when using Deezer")
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="non_deezer_seeking"
)
async def async_media_previous_track(self) -> None:
"""Send the previous track command."""
@@ -529,12 +531,14 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity):
async def async_select_source(self, source: str) -> None:
"""Select an input source."""
if source not in self._sources.values():
_LOGGER.error(
"Invalid source: %s. Valid sources are: %s",
source,
list(self._sources.values()),
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_source",
translation_placeholders={
"invalid_source": source,
"valid_sources": ",".join(list(self._sources.values())),
},
)
return
key = [x for x in self._sources if self._sources[x] == source][0]
@@ -559,12 +563,14 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity):
media_type = MediaType.MUSIC
if media_type not in VALID_MEDIA_TYPES:
_LOGGER.error(
"%s is an invalid type. Valid values are: %s",
media_type,
VALID_MEDIA_TYPES,
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_media_type",
translation_placeholders={
"invalid_media_type": media_type,
"valid_media_types": ",".join(VALID_MEDIA_TYPES),
},
)
return
if media_source.is_media_source_id(media_id):
sourced_media = await media_source.async_resolve_media(
@@ -681,7 +687,14 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity):
)
except ApiException as error:
_LOGGER.error(json.loads(error.body)["message"])
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="play_media_error",
translation_placeholders={
"media_type": media_type,
"error_message": json.loads(error.body)["message"],
},
) from error
async def async_browse_media(
self,

View File

@@ -28,6 +28,18 @@
"exceptions": {
"m3u_invalid_format": {
"message": "Media sources with the .m3u extension are not supported."
},
"non_deezer_seeking": {
"message": "Seeking is currently only supported when using Deezer"
},
"invalid_source": {
"message": "Invalid source: {invalid_source}. Valid sources are: {valid_sources}"
},
"invalid_media_type": {
"message": "{invalid_media_type} is an invalid type. Valid values are: {valid_media_types}."
},
"play_media_error": {
"message": "An error occurred while attempting to play {media_type}: {error_message}."
}
}
}

View File

@@ -10,7 +10,7 @@ import requests
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
@@ -80,7 +80,7 @@ SENSOR_TYPES_UPTIME: tuple[SensorEntityDescription, ...] = (
SENSOR_KEYS: list[str] = [desc.key for desc in (*SENSOR_TYPES, *SENSOR_TYPES_UPTIME)]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_MONITORED_VARIABLES): vol.All(
cv.ensure_list, [vol.In(SENSOR_KEYS)]

View File

@@ -6,7 +6,7 @@ from beewi_smartclim import BeewiSmartClimPoller
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
)
@@ -26,7 +26,7 @@ SENSOR_TYPES = [
[SensorDeviceClass.BATTERY, "Battery", PERCENTAGE],
]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_MAC): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -14,10 +14,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.deprecation import (
DeprecatedConstantEnum,
all_with_deprecated_constants,
@@ -30,11 +27,11 @@ from homeassistant.helpers.typing import ConfigType
_LOGGER = logging.getLogger(__name__)
DOMAIN = "binary_sensor"
SCAN_INTERVAL = timedelta(seconds=30)
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = timedelta(seconds=30)
class BinarySensorDeviceClass(StrEnum):

View File

@@ -9,7 +9,7 @@ from blockchain import exchangerates, statistics
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
SensorEntityDescription,
)
@@ -127,7 +127,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
OPTION_KEYS = [desc.key for desc in SENSOR_TYPES]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_DISPLAY_OPTIONS, default=[]): vol.All(
cv.ensure_list, [vol.In(OPTION_KEYS)]

View File

@@ -7,7 +7,10 @@ from contextlib import suppress
from bizkaibus.bizkaibus import BizkaibusData
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_NAME, UnitOfTime
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
@@ -21,7 +24,7 @@ CONF_ROUTE = "route"
DEFAULT_NAME = "Next bus"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_STOP_ID): cv.string,
vol.Required(CONF_ROUTE): cv.string,

View File

@@ -10,7 +10,7 @@ import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_HS_COLOR,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
@@ -25,7 +25,7 @@ CONF_SERIAL = "serial"
DEFAULT_NAME = "Blinkstick"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_SERIAL): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -8,7 +8,10 @@ import logging
from pyblockchain import get_balance, validate_address
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
@@ -23,7 +26,7 @@ DEFAULT_NAME = "Bitcoin Balance"
SCAN_INTERVAL = timedelta(minutes=5)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_ADDRESSES): [cv.string],
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -5,7 +5,7 @@ from __future__ import annotations
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
)
@@ -63,7 +63,7 @@ SENSOR_DEVICE_CLASS = {
# Which sensors to format numerically
FORMAT_NUMBERS = ["Temperature", "Pressure", "Voltage"]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_MONITORED_CONDITIONS, default=SENSOR_TYPES): vol.All(
cv.ensure_list, [vol.In(SENSOR_TYPES)]

View File

@@ -18,7 +18,7 @@ import xmltodict
from homeassistant.components import media_source
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
BrowseMedia,
MediaPlayerEntity,
MediaPlayerEntityFeature,
@@ -70,7 +70,7 @@ UPDATE_CAPTURE_INTERVAL = timedelta(minutes=30)
UPDATE_PRESETS_INTERVAL = timedelta(minutes=30)
UPDATE_SERVICES_INTERVAL = timedelta(minutes=30)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_HOSTS): vol.All(
cv.ensure_list,

View File

@@ -72,7 +72,10 @@ def _async_migrate_options_from_data_if_missing(
options = dict(entry.options)
if CONF_READ_ONLY in data or list(options) != list(DEFAULT_OPTIONS):
options = dict(DEFAULT_OPTIONS, **options)
options = dict(
DEFAULT_OPTIONS,
**{k: v for k, v in options.items() if k in DEFAULT_OPTIONS},
)
options[CONF_READ_ONLY] = data.pop(CONF_READ_ONLY, False)
hass.config_entries.async_update_entry(entry, data=data, options=options)

View File

@@ -13,10 +13,7 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.restore_state import RestoreEntity
@@ -25,14 +22,15 @@ from homeassistant.util import dt as dt_util
from .const import DOMAIN, SERVICE_PRESS
SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = timedelta(seconds=30)
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
_LOGGER = logging.getLogger(__name__)
class ButtonDeviceClass(StrEnum):
"""Device class for buttons."""

View File

@@ -29,12 +29,7 @@ from homeassistant.core import (
callback,
)
from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
time_period_str,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.event import async_track_point_in_time
@@ -74,6 +69,8 @@ _LOGGER = logging.getLogger(__name__)
DOMAIN = "calendar"
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = datetime.timedelta(seconds=60)
# Don't support rrules more often than daily
@@ -469,7 +466,7 @@ def extract_offset(summary: str, offset_prefix: str) -> tuple[str, datetime.time
else:
time = f"0:{time}"
offset_time = time_period_str(time)
offset_time = cv.time_period_str(time)
summary = (summary[: search.start()] + summary[search.end() :]).strip()
return (summary, offset_time)
return (summary, datetime.timedelta())

View File

@@ -48,11 +48,7 @@ from homeassistant.const import (
)
from homeassistant.core import Event, HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.deprecation import (
DeprecatedConstantEnum,
all_with_deprecated_constants,
@@ -87,14 +83,16 @@ from .prefs import CameraPreferences, DynamicStreamSettings # noqa: F401
_LOGGER = logging.getLogger(__name__)
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL: Final = timedelta(seconds=30)
SERVICE_ENABLE_MOTION: Final = "enable_motion_detection"
SERVICE_DISABLE_MOTION: Final = "disable_motion_detection"
SERVICE_SNAPSHOT: Final = "snapshot"
SERVICE_PLAY_STREAM: Final = "play_stream"
SCAN_INTERVAL: Final = timedelta(seconds=30)
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
ATTR_FILENAME: Final = "filename"
ATTR_MEDIA_PLAYER: Final = "media_player"
ATTR_FORMAT: Final = "format"

View File

@@ -8,7 +8,7 @@ from typing import Any
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
)
@@ -27,7 +27,7 @@ from .const import DEFAULT_PORT, DOMAIN
SCAN_INTERVAL = timedelta(hours=12)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,

View File

@@ -8,7 +8,7 @@ from pychannels import Channels
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -26,7 +26,7 @@ DATA_CHANNELS = "channels"
DEFAULT_NAME = "Channels"
DEFAULT_PORT = 57000
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -9,7 +9,7 @@ from clementineremote import ClementineRemote
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -26,7 +26,7 @@ DEFAULT_PORT = 5500
SCAN_INTERVAL = timedelta(seconds=5)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_ACCESS_TOKEN): cv.positive_int,

View File

@@ -25,13 +25,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import issue_registry as ir
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
make_entity_service_schema,
)
from homeassistant.helpers import config_validation as cv, issue_registry as ir
from homeassistant.helpers.deprecation import (
all_with_deprecated_constants,
check_if_deprecated_constant,
@@ -117,24 +111,25 @@ from .const import ( # noqa: F401
HVACMode,
)
_LOGGER = logging.getLogger(__name__)
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = timedelta(seconds=60)
DEFAULT_MIN_TEMP = 7
DEFAULT_MAX_TEMP = 35
DEFAULT_MIN_HUMIDITY = 30
DEFAULT_MAX_HUMIDITY = 99
ENTITY_ID_FORMAT = DOMAIN + ".{}"
SCAN_INTERVAL = timedelta(seconds=60)
CONVERTIBLE_ATTRIBUTE = [ATTR_TEMPERATURE, ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH]
_LOGGER = logging.getLogger(__name__)
SET_TEMPERATURE_SCHEMA = vol.All(
cv.has_at_least_one_key(
ATTR_TEMPERATURE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW
),
make_entity_service_schema(
cv.make_entity_service_schema(
{
vol.Exclusive(ATTR_TEMPERATURE, "temperature"): vol.Coerce(float),
vol.Inclusive(ATTR_TARGET_TEMP_HIGH, "temperature"): vol.Coerce(float),

View File

@@ -9,7 +9,7 @@ from pycmus import exceptions, remote
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -26,7 +26,7 @@ _LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "cmus"
DEFAULT_PORT = 3000
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Inclusive(CONF_HOST, "remote"): cv.string,
vol.Inclusive(CONF_PASSWORD, "remote"): cv.string,

View File

@@ -11,7 +11,7 @@ import aiohttp
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
SensorEntityDescription,
)
@@ -57,7 +57,7 @@ SENSORS_SCHEMA = vol.Schema(
}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{vol.Required(CONF_MONITORED_FEEDS): [SENSORS_SCHEMA]}
)

View File

@@ -31,7 +31,7 @@ from pycomfoconnect import (
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
@@ -263,7 +263,7 @@ SENSOR_TYPES = (
),
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_RESOURCES, default=[]): vol.All(
cv.ensure_list, [vol.In([desc.key for desc in SENSOR_TYPES])]

View File

@@ -53,11 +53,7 @@ async def websocket_create(
)
return
try:
await provider.async_add_auth(msg["username"], msg["password"])
except auth_ha.InvalidUser:
connection.send_error(msg["id"], "username_exists", "Username already exists")
return
await provider.async_add_auth(msg["username"], msg["password"])
credentials = await provider.async_get_or_create_credentials(
{"username": msg["username"]}
@@ -94,13 +90,7 @@ async def websocket_delete(
connection.send_result(msg["id"])
return
try:
await provider.async_remove_auth(msg["username"])
except auth_ha.InvalidUser:
connection.send_error(
msg["id"], "auth_not_found", "Given username was not found."
)
return
await provider.async_remove_auth(msg["username"])
connection.send_result(msg["id"])
@@ -187,14 +177,8 @@ async def websocket_admin_change_password(
)
return
try:
await provider.async_change_password(username, msg["password"])
connection.send_result(msg["id"])
except auth_ha.InvalidUser:
connection.send_error(
msg["id"], "credentials_not_found", "Credentials not found"
)
return
await provider.async_change_password(username, msg["password"])
connection.send_result(msg["id"])
@websocket_api.websocket_command(

View File

@@ -5,7 +5,10 @@ from __future__ import annotations
from typing import Any
import uuid
from homeassistant.components.scene import DOMAIN, PLATFORM_SCHEMA
from homeassistant.components.scene import (
DOMAIN,
PLATFORM_SCHEMA as SCENE_PLATFORM_SCHEMA,
)
from homeassistant.config import SCENE_CONFIG_PATH
from homeassistant.const import CONF_ID, SERVICE_RELOAD
from homeassistant.core import DOMAIN as HA_DOMAIN, HomeAssistant, callback
@@ -14,6 +17,8 @@ from homeassistant.helpers import config_validation as cv, entity_registry as er
from .const import ACTION_DELETE
from .view import EditIdBasedConfigView
PLATFORM_SCHEMA = SCENE_PLATFORM_SCHEMA
@callback
def async_setup(hass: HomeAssistant) -> bool:

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/conversation",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["hassil==1.7.1", "home-assistant-intents==2024.6.21"]
"requirements": ["hassil==1.7.1", "home-assistant-intents==2024.6.26"]
}

View File

@@ -30,10 +30,7 @@ from homeassistant.const import (
STATE_OPENING,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.deprecation import (
DeprecatedConstantEnum,
all_with_deprecated_constants,
@@ -49,9 +46,10 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=15)
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = timedelta(seconds=15)
class CoverDeviceClass(StrEnum):

View File

@@ -9,7 +9,10 @@ from typing import Any
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_HOST, CONF_PORT, PERCENTAGE
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
@@ -47,7 +50,7 @@ SCAN_INTERVAL = timedelta(minutes=1)
PRINTER_STATES = {3: "idle", 4: "printing", 5: "stopped"}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_PRINTERS): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_IS_CUPS_SERVER, default=DEFAULT_IS_CUPS_SERVER): cv.boolean,

View File

@@ -8,7 +8,10 @@ import logging
import requests
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_API_KEY, CONF_BASE, CONF_NAME, CONF_QUOTE
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
@@ -24,7 +27,7 @@ DEFAULT_NAME = "CurrencyLayer Sensor"
SCAN_INTERVAL = timedelta(hours=4)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Required(CONF_QUOTE): vol.All(cv.ensure_list, [cv.string]),

View File

@@ -13,21 +13,19 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_DATE
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN, SERVICE_SET_VALUE
SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
__all__ = ["DOMAIN", "DateEntity", "DateEntityDescription"]

View File

@@ -12,10 +12,6 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
)
from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType
@@ -23,11 +19,13 @@ from homeassistant.util import dt as dt_util
from .const import ATTR_DATETIME, DOMAIN, SERVICE_SET_VALUE
SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
__all__ = ["ATTR_DATETIME", "DOMAIN", "DateTimeEntity", "DateTimeEntityDescription"]

View File

@@ -16,7 +16,7 @@ import voluptuous as vol
from homeassistant import util
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
@@ -48,7 +48,7 @@ DEVICE_SCHEMA = vol.Schema(
PLATFORM_SCHEMA = vol.Schema(
vol.All(
PLATFORM_SCHEMA.extend(
LIGHT_PLATFORM_SCHEMA.extend(
{vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA}}
),
_name_validator,

View File

@@ -15,7 +15,7 @@ from homeassistant.components import persistent_notification
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_TRANSITION,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
LightEntityFeature,
@@ -29,7 +29,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
# Validation of the user's configuration
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
{vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string}
)

View File

@@ -10,7 +10,7 @@ from pydelijn.common import HttpException
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
)
@@ -31,7 +31,7 @@ CONF_NUMBER_OF_DEPARTURES = "number_of_departures"
DEFAULT_NAME = "De Lijn"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Required(CONF_NEXT_DEPARTURE): [

View File

@@ -8,7 +8,7 @@ import telnetlib # pylint: disable=deprecated-module
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -38,7 +38,7 @@ SUPPORT_MEDIA_MODES = (
| MediaPlayerEntityFeature.PLAY
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -9,7 +9,11 @@ from typing import TYPE_CHECKING
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, RestoreSensor, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
RestoreSensor,
SensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
@@ -62,7 +66,7 @@ UNIT_TIME = {
DEFAULT_ROUND = 3
DEFAULT_TIME_WINDOW = 0
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME): cv.string,
vol.Required(CONF_SOURCE): cv.entity_id,

View File

@@ -10,7 +10,7 @@ import discogs_client
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
SensorEntityDescription,
)
@@ -58,7 +58,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
)
SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_TOKEN): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -6,15 +6,16 @@ import io
import face_recognition
from homeassistant.components.image_processing import ImageProcessingFaceEntity
from homeassistant.components.image_processing import (
PLATFORM_SCHEMA as IMAGE_PROCESSING_PLATFORM_SCHEMA,
ImageProcessingFaceEntity,
)
from homeassistant.const import ATTR_LOCATION, CONF_ENTITY_ID, CONF_NAME, CONF_SOURCE
from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.components.image_processing import ( # noqa: F401, isort:skip
PLATFORM_SCHEMA,
)
PLATFORM_SCHEMA = IMAGE_PROCESSING_PLATFORM_SCHEMA
def setup_platform(

View File

@@ -10,7 +10,7 @@ import voluptuous as vol
from homeassistant.components.image_processing import (
CONF_CONFIDENCE,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as IMAGE_PROCESSING_PLATFORM_SCHEMA,
ImageProcessingFaceEntity,
)
from homeassistant.const import ATTR_NAME, CONF_ENTITY_ID, CONF_NAME, CONF_SOURCE
@@ -23,7 +23,7 @@ _LOGGER = logging.getLogger(__name__)
CONF_FACES = "faces"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = IMAGE_PROCESSING_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_FACES): {cv.string: cv.isfile},
vol.Optional(CONF_CONFIDENCE, default=0.6): vol.Coerce(float),

View File

@@ -4,11 +4,11 @@ from datetime import timedelta
import logging
from pizzapi import Address, Customer, Order
from pizzapi.address import StoreException
import voluptuous as vol
from homeassistant.components import http
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
@@ -118,7 +118,7 @@ class Dominos:
self.country = conf.get(ATTR_COUNTRY)
try:
self.closest_store = self.address.closest_store()
except StoreException:
except Exception: # noqa: BLE001
self.closest_store = None
def handle_order(self, call: ServiceCall) -> None:
@@ -139,7 +139,7 @@ class Dominos:
"""Update the shared closest store (if open)."""
try:
self.closest_store = self.address.closest_store()
except StoreException:
except Exception: # noqa: BLE001
self.closest_store = None
return False
return True
@@ -219,7 +219,7 @@ class DominosOrder(Entity):
"""Update the order state and refreshes the store."""
try:
self.dominos.update_closest_store()
except StoreException:
except Exception: # noqa: BLE001
self._orderable = False
return
@@ -227,13 +227,13 @@ class DominosOrder(Entity):
order = self.order()
order.pay_with()
self._orderable = True
except StoreException:
except Exception: # noqa: BLE001
self._orderable = False
def order(self):
"""Create the order object."""
if self.dominos.closest_store is None:
raise StoreException
raise HomeAssistantError("No store available")
order = Order(
self.dominos.closest_store,
@@ -252,7 +252,7 @@ class DominosOrder(Entity):
try:
order = self.order()
order.place()
except StoreException:
except Exception: # noqa: BLE001
self._orderable = False
_LOGGER.warning(
"Attempted to order Dominos - Order invalid or store closed"

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/dominos",
"iot_class": "cloud_polling",
"loggers": ["pizzapi"],
"requirements": ["pizzapi==0.0.3"]
"requirements": ["pizzapi==0.0.6"]
}

View File

@@ -13,7 +13,7 @@ import voluptuous as vol
from homeassistant.components.image_processing import (
CONF_CONFIDENCE,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as IMAGE_PROCESSING_PLATFORM_SCHEMA,
ImageProcessingEntity,
)
from homeassistant.const import (
@@ -66,7 +66,7 @@ LABEL_SCHEMA = vol.Schema(
}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = IMAGE_PROCESSING_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_URL): cv.string,
vol.Required(CONF_DETECTOR): cv.string,

View File

@@ -9,7 +9,7 @@ import re
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
@@ -78,7 +78,7 @@ SENSOR_TYPES: tuple[DovadoSensorEntityDescription, ...] = (
SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{vol.Required(CONF_SENSORS): vol.All(cv.ensure_list, [vol.In(SENSOR_KEYS)])}
)

View File

@@ -9,7 +9,7 @@ import requests
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorStateClass,
@@ -30,7 +30,7 @@ DEFAULT_NAME = "Current Energy Usage"
DEFAULT_VERSION = 1
DOMAIN = "dte_energy_bridge"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_IP_ADDRESS): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -13,7 +13,10 @@ from http import HTTPStatus
import requests
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONF_NAME, UnitOfTime
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
@@ -38,7 +41,7 @@ DEFAULT_NAME = "Next Bus"
SCAN_INTERVAL = timedelta(minutes=1)
TIME_STR_FORMAT = "%H:%M"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_STOP_ID): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -9,7 +9,10 @@ import logging
import dweepy
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import (
CONF_DEVICE,
CONF_NAME,
@@ -27,7 +30,7 @@ DEFAULT_NAME = "Dweet.io Sensor"
SCAN_INTERVAL = timedelta(minutes=1)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_DEVICE): cv.string,
vol.Required(CONF_VALUE_TEMPLATE): cv.template,

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.1"]
"requirements": ["easyenergy==2.1.2"]
}

View File

@@ -13,7 +13,7 @@ from pyebox.client import PyEboxError
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
@@ -139,7 +139,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SENSOR_TYPE_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_MONITORED_VARIABLES): vol.All(
cv.ensure_list, [vol.In(SENSOR_TYPE_KEYS)]

View File

@@ -12,7 +12,7 @@ from beacontools import BeaconScanner, EddystoneFilter, EddystoneTLMFrame
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
)
@@ -43,7 +43,7 @@ BEACON_SCHEMA = vol.Schema(
}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_BT_DEVICE_ID, default=0): cv.positive_int,
vol.Required(CONF_BEACONS): vol.Schema({cv.string: BEACON_SCHEMA}),

View File

@@ -9,7 +9,7 @@ import eliqonline
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorStateClass,
@@ -29,7 +29,7 @@ DEFAULT_NAME = "ELIQ Online"
SCAN_INTERVAL = timedelta(seconds=60)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_ACCESS_TOKEN): cv.string,
vol.Required(CONF_CHANNEL_ID): cv.positive_int,

View File

@@ -8,7 +8,7 @@ from pyemby import EmbyServer
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -47,7 +47,7 @@ SUPPORT_EMBY = (
| MediaPlayerEntityFeature.PLAY
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,

View File

@@ -10,7 +10,7 @@ from pyemoncms import EmoncmsClient
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorStateClass,
@@ -54,7 +54,7 @@ DEFAULT_UNIT = UnitOfPower.WATT
ONLY_INCL_EXCL_NONE = "only_include_exclude_or_none"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Required(CONF_URL): cv.string,

View File

@@ -6,5 +6,5 @@
"iot_class": "local_push",
"loggers": ["sense_energy"],
"quality_scale": "internal",
"requirements": ["sense-energy==0.12.2"]
"requirements": ["sense-energy==0.12.4"]
}

View File

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

View File

@@ -11,6 +11,7 @@ from openwebif.enums import PowerState, RemoteControlCodes, SetVolumeOption
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
@@ -26,8 +27,7 @@ from homeassistant.const import (
CONF_USERNAME,
)
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
@@ -57,7 +57,7 @@ ATTR_MEDIA_START_TIME = "media_start_time"
_LOGGER = getLogger(__name__)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -10,7 +10,7 @@ import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
@@ -26,7 +26,7 @@ CONF_SENDER_ID = "sender_id"
DEFAULT_NAME = "EnOcean Light"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_ID, default=[]): vol.All(cv.ensure_list, [vol.Coerce(int)]),
vol.Required(CONF_SENDER_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]),

View File

@@ -9,7 +9,7 @@ from enocean.utils import combine_hex
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
RestoreSensor,
SensorDeviceClass,
SensorEntityDescription,
@@ -87,7 +87,7 @@ SENSOR_DESC_WINDOWHANDLE = EnOceanSensorEntityDescription(
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View File

@@ -8,7 +8,10 @@ from random import randint
from enturclient import EnturPublicTransportData
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import (
CONF_LATITUDE,
CONF_LONGITUDE,
@@ -46,7 +49,7 @@ ICONS = {
SCAN_INTERVAL = timedelta(seconds=45)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_STOP_IDS): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_EXPAND_PLATFORMS, default=True): cv.boolean,

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/environment_canada",
"iot_class": "cloud_polling",
"loggers": ["env_canada"],
"requirements": ["env-canada==0.6.3"]
"requirements": ["env-canada==0.7.1"]
}

View File

@@ -19,7 +19,6 @@ from homeassistant.const import (
PERCENTAGE,
UV_INDEX,
UnitOfLength,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfSpeed,
UnitOfTemperature,
@@ -114,14 +113,6 @@ SENSOR_TYPES: tuple[ECSensorEntityDescription, ...] = (
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: data.conditions.get("pop", {}).get("value"),
),
ECSensorEntityDescription(
key="precip_yesterday",
translation_key="precip_yesterday",
device_class=SensorDeviceClass.PRECIPITATION,
native_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.conditions.get("precip_yesterday", {}).get("value"),
),
ECSensorEntityDescription(
key="pressure",
translation_key="pressure",

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