Compare commits

...

163 Commits

Author SHA1 Message Date
Erik
2f608d8650 Use numerical_value when compiling statistics 2023-02-01 14:03:33 +01:00
Erik
65324431a4 Add numerical_value state attribute to sensor 2023-02-01 13:58:43 +01:00
Franck Nijhof
4dba9c09fc Only report invalid numeric value for sensors once (#87010) 2023-01-31 12:44:18 +01:00
On Freund
35b82db8b0 Rympro integration code fixes (#86734)
* Address review comments

* Add coordinator.py to coveragerc

* Apply suggestions from code review

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>

* Update homeassistant/components/rympro/coordinator.py

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>

* Move SCAN_INTERVAL to coordinator.py

---------

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
2023-01-31 10:40:43 +01:00
Martin Mauch
a28e7e1541 Fix typo in EnOcean (#86868) 2023-01-31 09:49:37 +01:00
Bouwe Westerdijk
7f01d57965 Bump plugwise to v0.27.5 (#87001)
fixes undefined
2023-01-31 09:32:39 +01:00
epenet
0d018d53f1 Don't run tests if ruff fails (#87003) 2023-01-31 09:31:49 +01:00
Michael Davie
be25d17e02 Bump env_canada to 0.5.27 (#86996)
fixes undefined
2023-01-31 08:56:27 +01:00
epenet
7db166b515 Fix tests typing helper (#86956) 2023-01-31 08:48:35 +01:00
Jan Bouwhuis
33ede351f0 Cleanup code for parsing yaml MQTT config (#86944)
* Cleanup code for parsing yaml configs

* Add abstractmethod decorator to async_update

* Replace get() with default-list ensured by schema
2023-01-31 08:24:33 +01:00
Paulus Schoutsen
1c4ba61725 Bump ESPHome Dashboard API 1.2.3 (#86997) 2023-01-31 00:05:59 -05:00
Michael Hansen
f4654128db Add synesthesiam as a codeowner on intent (#86998) 2023-01-30 23:46:42 -05:00
Michael Hansen
be69c81db5 Prioritize entity names over area names in Assist matching (#86982)
* Refactor async_match_states

* Check entity name after state, before aliases

* Give entity name matches priority over area names

* Don't force result to have area

* Add area alias in tests

* Move name/area list creation back

* Clean up PR

* More clean up
2023-01-30 23:46:25 -05:00
Marcel van der Veldt
f8c6e4c20a Add support for Hue Smart Scenes (Natural Lights) (#85517)
* Bump aiohue to 4.6.0

* fix device name for lights

* fix name for groups too

* ignore smart scenes

* bump to 4.6.1 instead

* Add support for Smart Scenes (Natural lights) in Hue

* update base entity class

* fix test fixture

* update tests

* fix scene test

* fix typo

* use underlying scene controller

* use enum value

* update tests

* add current scene name within smart scene

* extra attributes are only valid if the scene is active

* Update v2_resources.json

* typo

* fix after merge
2023-01-30 23:32:37 -05:00
Paulus Schoutsen
d88849fb04 ESPHome handle remove password and no encryption (#86995)
* ESPHome handle remove password and no encryption

* Start reauth for invalid api password

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-01-30 23:05:48 -05:00
PeteRager
e706696271 Nest - Climate shorten line to be less than 88 chars (#86989)
Lines to be less than 88
2023-01-30 19:14:24 -08:00
shbatm
53638ba138 Bump pyisy to 3.1.11 (#86981)
* Bump pyisy to 3.1.10

* Bump pyisy to 3.1.11
2023-01-30 21:36:51 -05:00
puddly
47453420c1 Bump ZHA dependencies (#86979)
Bump ZHA dependency bellows from 0.34.6 to 0.34.7
2023-01-30 21:35:27 -05:00
Bram Kragten
0c383e28c4 Update frontend to 20230130.0 (#86978) 2023-01-30 21:34:26 -05:00
Paulus Schoutsen
98b4a412f7 ESPHome discovered dashboard checks reauth flows (#86993) 2023-01-30 21:32:52 -05:00
GitHub Action
da35ac1942 [ci skip] Translation update 2023-01-31 00:25:29 +00:00
mkmer
365ce55d77 Honeywell auto mode invalid attribute (#86728)
fixes undefined
2023-01-31 00:04:00 +01:00
Michael Hansen
28affe91be Set synesthesiam as codeowner of conversation (#86958) 2023-01-30 23:02:25 +01:00
Paulus Schoutsen
2cdeb6f1cd Check dashboard when showing reauth form (#86980) 2023-01-30 22:46:42 +01:00
Steven Looman
7e206b5854 Fix error on empty location in ssdp messages (#86970) 2023-01-30 22:43:58 +01:00
Franck Nijhof
1edd00c51f Allow any state class when using the precipitation device class (#86977) 2023-01-30 22:43:23 +01:00
ollo69
772df02cce Catch AndroidTV exception on setup (#86819)
fixes undefined
2023-01-30 22:42:32 +01:00
puddly
8337d4613e ZHA config flow cleanup (#86742)
fixes undefined
2023-01-30 22:21:34 +01:00
Steven Looman
50373500c3 Ensure a proper scope_id is given for IPv6 addresses when initializing the SSDP component (#86975)
fixes undefined
2023-01-30 22:14:48 +01:00
Paul Bottein
a8b23d7139 Uses PolledSmartEnergySummation for ZLinky (#86960) 2023-01-30 22:10:55 +01:00
Raman Gupta
c715534821 Bump zwave-js-server-python to 0.45.0 (#86771) 2023-01-30 14:27:37 -05:00
Paulus Schoutsen
e0f8b5bbd1 Fix some mobile app sensor registration/update issues (#86965)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2023-01-30 20:08:19 +01:00
Michael Hansen
f7fdaadde0 Performance improvements for Assist (#86966)
* Move hassil recognize into executor

* Bump hassil to 0.2.6

* Disable template parsing in name/area lists

* Don't iterate over hass.config.components directly
2023-01-30 12:25:22 -06:00
Jan Bouwhuis
e57dad79fc Fix MQTT discovery failing after bad config update (#86935)
* Fix MQTT discovery failing after bad config update

* Update last discovery payload after update success

* Improve test, correct update assignment

* send_discovery_done to finally-catch vol.Error

* Just use try..finally

* Remove extra line

* use elif to avoid log confusion
2023-01-30 19:15:11 +01:00
J. Nick Koston
00118a6f96 Speed up live history setup if there is no pending data to commit (#86942) 2023-01-30 19:00:34 +01:00
J. Nick Koston
f874258e7e Silence spurious warnings about removing ix_states_entity_id with newer installs (#86961)
* Silence spurious warnings about removing ix_states_entity_id with newer installs

https://ptb.discord.com/channels/330944238910963714/427516175237382144/1069648035459641465

* Silence spurious warnings about removing ix_states_entity_id with newer installs

https://ptb.discord.com/channels/330944238910963714/427516175237382144/1069648035459641465
2023-01-30 12:38:33 -05:00
Erik Montnemery
53c5f02ca2 Remove some dead code from recorder (#86697) 2023-01-30 18:37:48 +01:00
Shay Levy
857df05308 Add Shelly Gen2 update entity for sleeping devices (#86837) 2023-01-30 19:05:13 +02:00
PeteRager
d22e670334 Avoid Nest climate set_temperature eating error (#86920)
* Update climate_sdm.py

* Update test case to detect KeyError

* Throw a defined exception if the condition in encoutered

Include keys from device_traits in error message

* Less diagnostic information in error message
2023-01-30 08:01:41 -08:00
Marc Mueller
2c12171e25 Update actions/cache to v3.2.4 (#86943) 2023-01-30 16:42:01 +01:00
Mick Vleeshouwer
98a79dd5a2 Fix ThreeWayHandle sensor in Overkiz integration (#86953)
Fix typo in sensor.py

Fixes https://github.com/home-assistant/core/issues/85913
2023-01-30 17:15:53 +02:00
Tom Puttemans
73cd03255f Ignore empty payloads from DSMR Reader (#86841)
* Ignore empty payloads from DSMR Reader

* Simplify empty payload handling

If the native value hasn't changed, requesting to store it won't have a performance impact.

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

---------

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2023-01-30 08:56:57 -05:00
Erik Montnemery
d4489faa68 Drop minus sign on negative zero (#86939)
* Drop minus sign on negative zero

* Add tests
2023-01-30 08:31:27 -05:00
Maciej Bieniek
5f57648578 Use more human-readable sensor names in Airly (#86893)
* Use more human-readable sensor names

* Use abbreviations for long names
2023-01-30 08:29:06 -05:00
Ben Dews
21d1c647c5 Add configuration options to OpenAI integration (#86768)
* Added multiple features to OpenAI integration

* Fixed failed test

* Removed features and improved tests

* initiated component before starting options flow
2023-01-30 08:24:11 -05:00
Robert Hillis
032a37b121 Address Google mail late review (#86847) 2023-01-30 14:18:56 +01:00
Franck Nijhof
3b5fd4bd06 Enable Ruff TRY004 (#86811) 2023-01-30 14:06:52 +01:00
mkmer
7368c86ecb Add Reauth config flow to honeywell (#86170) 2023-01-30 13:57:14 +01:00
epenet
7e7a27f8b9 Add type hints to http client fixtures (#86795) 2023-01-30 13:40:07 +01:00
Maciej Bieniek
cc36848a6d Use native_precision instead of round in Accuweather (#86869) 2023-01-30 12:36:24 +01:00
Nick Touran
d2e75e4f7a Add Autofocus, IR lamp, and Wiper switches in ONVIF (#84317)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2023-01-30 12:08:07 +01:00
Maciej Bieniek
d485630ce9 Use device class ENUM for Accuweather pressure tendency sensor (#86887)
* Use device class ENUM for pressure tendency sensor

* Format
2023-01-30 12:03:23 +01:00
Franck Nijhof
a4fa0925b7 Small improvement to Withings tests (#86937) 2023-01-30 11:03:42 +01:00
Franck Nijhof
c56832bb2c Enable Ruff SIM300 (#86793) 2023-01-30 11:03:23 +01:00
Franck Nijhof
9ac8f9aa37 Revert "Adjust D-Link entity naming" (#86936) 2023-01-30 10:56:56 +01:00
Robert Hillis
709d1cb8af Adjust D-Link entity naming (#86906) 2023-01-30 10:29:12 +01:00
Franck Nijhof
1958dd5550 Update ruff to v0.0.237 (#86932) 2023-01-30 10:15:24 +01:00
Malte Franken
92a833b192 Bump aio_geojson_generic_client to 0.3 (#86918) 2023-01-30 10:11:41 +01:00
J. Nick Koston
4e9bd09d39 Fix old indices not being removed in schema migration leading to slow MySQL queries (#86917)
fixes #83787
2023-01-29 21:33:23 -05:00
GitHub Action
b82ecfdd28 [ci skip] Translation update 2023-01-30 00:21:11 +00:00
J. Nick Koston
0f4b17755e Improve logging and handling when websocket gets behind (#86854)
fixes undefined
2023-01-29 10:49:27 -10:00
J. Nick Koston
c612a92cfb Use python defaults for comparing State, LazyState, and Event objects (#86856)
* Speed up comparing State and Event objects

Use default python implementation for State and Event __hash__ and __eq__

The default implementation compared based on the id() of the object
which is effectively what we want here anyways. These overrides are
left over from the days when these used to be attrs objects

By avoiding implementing these ourselves all of the equality checks
can happen in native code

* tweak

* adjust tests

* write out some more

* fix test to not compare objects

* more test fixes

* more test fixes

* correct stats tests

* fix more tests

* fix more tests

* update sensor recorder tests
2023-01-29 13:31:43 -05:00
Joakim Sørensen
80ffac48a3 Revert "Mark repo as safe directory to git config (#83755)" (#86888)
This reverts commit dc000d2289.
2023-01-29 13:07:50 -05:00
Allen Porter
4f965f0eca Bump pyrainbird to 2.0.0 (#86851) 2023-01-29 15:11:56 +01:00
Joakim Sørensen
569bf3bb76 Bump pytautulli from 21.11.0 to 23.1.1 (#86891) 2023-01-29 15:07:05 +01:00
Joakim Sørensen
f9e8247401 Bump isort from 5.11.4 to 5.12.0 (#86890) 2023-01-29 15:04:17 +01:00
Malte Franken
344a0c55a5 Add integration_type to geo_json_events (#86878)
define integration type
2023-01-29 15:02:13 +01:00
Thomas Schamm
11e125f2e8 Add Bosch SHC description and host form strings (#86897)
* Add description to setup SHC II. Add missing host info in reauth_confirm

* Remove template value in en.json
2023-01-29 15:00:36 +01:00
J. Nick Koston
691a234090 Cache the names and area lists in the default agent (#86874)
* Cache the names and area lists in the default agent

fixes #86803

* add coverage to make sure the entity cache busts

* add areas test

* cover the last line
2023-01-29 07:16:29 -05:00
Maciej Bieniek
eebc338c3b Support native_precision in Airly integration (#86843)
* Use native_precision

* Refactor extra_state_attributes
2023-01-29 11:44:23 +01:00
J. Nick Koston
58de7b8df0 Fix v32 schema migration when MySQL global.time_zone is configured with non-UTC timezone (#86867)
* Fix v32 schema migration when MySQL timezone is not UTC

* tweak
2023-01-28 22:06:07 -05:00
Martin Hjelmare
b1e939d1f1 Fix tradfri air quality device class (#86861) 2023-01-28 22:05:31 -05:00
J. Nick Koston
ec3475910f Improve websocket throughput of state changes (#86855)
After the start event we tend to get an event storm of state
changes which can get the websocket behind. #86854 will
help with that a bit, but we can reduce the overhead
to build a state diff when the attributes have not
changed
2023-01-28 22:05:06 -05:00
Robert Hillis
799edd90aa Fix D-Link attributes (#86842)
* Fix D-Link attributes

* fix blocking call
2023-01-28 22:03:58 -05:00
GitHub Action
0f6f63da64 [ci skip] Translation update 2023-01-29 00:26:29 +00:00
Paul Bottein
e93bfa6556 Update frontend to 20230128.0 (#86838) 2023-01-28 18:49:29 -05:00
Jan Bouwhuis
6a94a58325 Correct stale doc string for MQTT tag platform (#86862) 2023-01-29 00:23:22 +02:00
PeteRager
a7ddd592fb Nest improve error message on climate actions (#86853)
* Nest - Climate - Error Messages

1. Error messages were incorrect for some methods, for example async_set_temperature was reporting failure to set hvac_mode. This is corrected.
2. Error messages were incomplete and were not including the entity_id,and the operation being performed that failed.
3. Add unit tests to test the exception handling

* Move tests into exiisting error test

* Improve readability of error message
2023-01-28 12:58:28 -08:00
Allen Porter
733798f483 Fix nest climate set temperature error message string (#86852) 2023-01-28 11:02:46 -08:00
J. Nick Koston
af5fd74d6f Bump ismartgate to 5.0.0 (#86830)
python 3.11 support

changelog: https://github.com/bdraco/ismartgate/compare/v4.0.4...v5.0.0
2023-01-28 07:14:36 +01:00
Luca Angemi
efd2817221 Add state class to nest legacy sensors (#86810)
* Add state class to nest legacy sensors

Add state class (measurement) to humidity and temperature for the nest legacy sensors.

* Update

Update
2023-01-27 21:20:51 -08:00
J. Nick Koston
d97a061285 Chunk MariaDB and Postgresql data migration to avoid running out of buffer space (#86680)
* Chunk MariaDB data migration to avoid running out of buffer space

This will make the migration slower but since the innodb_buffer_pool_size
is using the defaul to 128M and not tuned to the db size there is a
risk of running out of buffer space for large databases

* Update homeassistant/components/recorder/migration.py

* hard code since bandit thinks its an injection

* Update homeassistant/components/recorder/migration.py

* guard against manually modified data/corrupt db

* adjust to 10k per chunk

* adjust to 50k per chunk

* memory still just fine at 250k

* but slower

* commit after each chunk to reduce lock pressure

* adjust

* set to 0 if null so we do not loop forever (this should only happen if the data is missing)

* set to 0 if null so we do not loop forever (this should only happen if the data is missing)

* tweak

* tweak

* limit cleanup

* lower limit to give some more buffer

* lower limit to give some more buffer

* where required for sqlite

* sqlite can wipe as many as needed with no limit

* limit on mysql only

* chunk postgres

* fix limit

* tweak

* fix reference

* fix

* tweak for ram

* postgres memory reduction

* defer cleanup

* fix

* same order
2023-01-27 22:39:45 -05:00
shbatm
e2edbc4259 Check for missing ISY994 Z-Wave Properties (#86829)
* Check for missing Z-Wave Properties

* Fix black from mobile
2023-01-27 22:16:28 -05:00
J. Nick Koston
d0c7f42559 Fix Bluetooth discoveries missing between restarts (#86808)
* Fix Bluetooth discoveries missing between restarts

* do not load other integrations

* coverage
2023-01-27 22:16:16 -05:00
Robert Hillis
b69576d6de Add D-link tests (#86825)
* Fix D-Link config flow auth

* Add tests to D-Link

* pyupgrade
2023-01-27 22:15:27 -05:00
Robert Hillis
adb0d85511 Fix D-Link config flow auth (#86824) 2023-01-27 21:38:25 -05:00
GitHub Action
072f228e4d [ci skip] Translation update 2023-01-28 00:23:36 +00:00
Shay Levy
803cd8d9a3 Handle state unknown if last state is missing in Shelly (#86813)
Shelly - handle state unknown if last state is missing
2023-01-27 23:34:56 +01:00
Ville Skyttä
50c2992f36 Drop py39 from black target-version (#86814) 2023-01-27 22:39:52 +02:00
dependabot[bot]
15492aead0 Bump tibdex/github-app-token from 1.7.0 to 1.8.0 (#86767)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-27 20:35:56 +01:00
Bouwe Westerdijk
661f7e1522 Bump plugwise to v0.27.4 (#86812)
fixes undefined
2023-01-27 20:00:44 +01:00
Franck Nijhof
e9543a7254 Enable Ruff PT021 (#86801) 2023-01-27 17:14:04 +01:00
Franck Nijhof
8f74bff354 Enable Ruff PLC0414 (#86799) 2023-01-27 16:32:04 +01:00
Shay Levy
f9f9741d2a Separate Shelly tests parameters in parametrize (#86778)
Shelly tests - separate parameters in parametrize
2023-01-27 14:28:35 +01:00
Franck Nijhof
ef800335fb Enable Ruff PT022 (#86792)
* Enable Ruff PT022

* Adjust found cases
2023-01-27 13:57:06 +01:00
Franck Nijhof
8c993116e1 Enable Ruff SIM401 (#86790)
* Enable Ruff SIM401

* Adjust found cases
2023-01-27 13:08:44 +01:00
Franck Nijhof
bfbf9b9751 Adjusts imports in tests to match our relative import rules (#86788) 2023-01-27 12:51:58 +01:00
Franck Nijhof
89c0b27b42 Migrates tests to use UnitOfPressure enum (#86785) 2023-01-27 12:13:27 +01:00
epenet
561fc2d771 Remove deprecated unit system properties (#86643)
* Remove deprecated unit system properties

* Fix tests
2023-01-27 12:09:26 +01:00
Franck Nijhof
3ff3834cae Re-enable Ruff UP024 (#86784) 2023-01-27 12:03:27 +01:00
Franck Nijhof
a79885ceaf Enable Ruff SIM117 (#86783) 2023-01-27 11:52:49 +01:00
Franck Nijhof
57cf11f067 Enable Ruff PT015 (#86775) 2023-01-27 11:10:29 +01:00
Franck Nijhof
49148421cb Migrates tests to use UnitOfSpeed enum (#86777) 2023-01-27 10:58:55 +01:00
Franck Nijhof
fca3382d37 Migrates tests to use MediaPlayerEntityFeature enum (#86779) 2023-01-27 10:56:40 +01:00
Franck Nijhof
42c4f2f7fa Add ability for pytest to run only on changed tests in codebase (#86776) 2023-01-27 10:35:18 +01:00
Shay Levy
ae6bc96002 Shelly code quality (#86733) 2023-01-27 10:47:05 +02:00
Franck Nijhof
e4a78420b8 Enable Ruff PT013 (#86757)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2023-01-27 09:09:46 +01:00
Malte Franken
bd9a8ba6f1 Bump aio_georss_gdacs to 0.8 (#86761)
bump aio_georss_gdacs to 0.8
2023-01-27 08:44:30 +01:00
Jesse Hills
78207121c0 Remove esphome password from config flow data if not needed (#86763)
* Remove esphome password if not needed

* Add test

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2023-01-26 21:45:51 -05:00
Paulus Schoutsen
687184138c ESPHome update: Store reference to runtime data, not one of its values (#86762)
Store reference to runtime data, not one of its values
2023-01-26 21:45:42 -05:00
Franck Nijhof
e738924780 Enable Ruff SIM105 (#86759)
* Enable Ruff SIM105

* Adjust existing cases
2023-01-26 21:06:22 -05:00
GitHub Action
71d7098530 [ci skip] Translation update 2023-01-27 00:25:12 +00:00
Aaron Bach
020d52c3e2 Fix state class issues in Ambient PWS (#86758)
fixes undefined
2023-01-27 00:14:46 +01:00
Marc Mueller
b84cf3a3d9 Improve bosch_shc config_flow typing (#86739) 2023-01-26 23:39:12 +01:00
Shay Levy
2c8cb13034 Bump aioshelly to 5.3.1 (#86751) 2023-01-27 00:34:31 +02:00
Paulus Schoutsen
9cd48b4999 OpenAI: Fix device without model (#86754) 2023-01-26 23:25:02 +01:00
tronikos
04bc522fa5 Google Assistant SDK: Test unload when enable_conversation_agent (#86707)
Test unload when enable_conversation_agent
2023-01-26 16:17:23 -05:00
Marc Mueller
caa1ba7e13 Improve nuki typing (#86736)
* Use NukiCoordinator

* Make NukiEntity generic

* Remove unnecessary ABC
2023-01-26 23:03:36 +02:00
mkmer
138a522d2e Bump AIOAladdinConnect to 0.1.54 (#86749) 2023-01-26 23:00:54 +02:00
Franck Nijhof
62dcbe5258 Enable Ruff PT001 (#86730) 2023-01-26 18:05:05 +01:00
Franck Nijhof
7ed9967245 Fix state classes for duration device class (#86727) 2023-01-26 17:26:52 +01:00
epenet
b3380261d7 Add hints to get_service in azure service bus (#86694) 2023-01-26 17:20:52 +01:00
Franck Nijhof
eb5d63237c Update ruff to v0.0.235 (#86719) 2023-01-26 17:17:13 +01:00
epenet
2bef69c6a7 Add hints to get_service in integrations (1/2) (#86692) 2023-01-26 16:56:57 +01:00
epenet
0d579f6ac3 Add hints to get_service in integrations (2/2) (#86693) 2023-01-26 16:55:57 +01:00
epenet
8a5a1b810a Add hints to get_service in netgear-lte (#86700) 2023-01-26 16:54:57 +01:00
epenet
95d0329d6c Add hints to get_service in tplink-lte (#86702) 2023-01-26 16:53:24 +01:00
Franck Nijhof
d4955a3d87 Replace assert False by raising an error (#86686) 2023-01-26 16:51:43 +01:00
Michael Hansen
adeaf746ec Use device area id in intent matching (#86678)
* Use device area id when matching

* Normalize whitespace in response

* Add extra test entity
2023-01-26 09:48:49 -06:00
Franck Nijhof
38203003d2 Remove gas device class from current sensor in dsmr_reader (#86725) 2023-01-26 16:44:52 +01:00
epenet
25c451832b Remove pragma: no cover when not raising (#86706) 2023-01-26 16:34:05 +01:00
StefanIacobLivisi
468457eff4 Bump aiolivisi to 0.0.15 (#86721) 2023-01-26 16:28:16 +01:00
epenet
7af86fe130 Improve notify type hints (#86685) 2023-01-26 16:23:03 +01:00
Marc Mueller
54fcf58449 Use mypy caching [ci] (#86715) 2023-01-26 15:59:37 +01:00
Martin Hjelmare
c727f403ff Bump python-matter-server to 2.0.2 (#86712) 2023-01-26 15:43:12 +01:00
Robert Svensson
4181a9baf0 Improve Axis config flow tests (#86644)
* Improve Axis config flow tests

* Don't use prepare_config_entry
2023-01-26 14:29:06 +01:00
David F. Mulcahey
6e285c87c3 Update Inovelli Blue Series switch support in ZHA (#86711) 2023-01-26 08:27:44 -05:00
Patrick ZAJDA
2e70de9dd9 Migrate Nuki to new entity naming style (#80021)
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2023-01-26 13:50:19 +01:00
mkmer
6ea234ed57 Add DeviceInfo to Honeywell (#86179)
* Add DeviceInfo
Add has_entity_name

* has_entity_name to class attribute

* Update homeassistant/components/honeywell/sensor.py

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

* Update homeassistant/components/honeywell/sensor.py

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2023-01-26 13:28:36 +01:00
MHFDoge
282d6af2a2 Add known webostv button to list (#86674)
Add known button to list.
2023-01-26 13:55:07 +02:00
Pascal Reeb
484e73beaa Add device registration to the Nuki component (#79806)
* Add device registration to the Nuki component

* Name is always given by the API

* implement pvizeli's suggestions

* switch device_registry to snake_case

* fix entity naming

* unify manufacturer names
2023-01-26 12:38:10 +01:00
Robert Svensson
9a6e620810 Fix missing interface key in deCONZ logbook (#86684)
fixes undefined
2023-01-26 11:44:01 +01:00
epenet
1139555448 Add hints to get_service in kodi (#86698) 2023-01-26 11:40:48 +01:00
epenet
cbcff6435f Add hints to get_service in joaoapps join (#86699) 2023-01-26 11:15:00 +01:00
Erik Montnemery
fea30c1ce9 Terminate strings at NUL when recording states and events (#86687) 2023-01-26 11:11:03 +01:00
epenet
b9ffc67a44 Add hints to get_service in syslog (#86701) 2023-01-26 11:10:50 +01:00
epenet
ca8cc284ed Add hints to get_service in rest (#86703) 2023-01-26 11:08:06 +01:00
Paulus Schoutsen
ff91fb7d74 Make openai conversation prompt template more readable + test case (#86676) 2023-01-26 11:04:15 +01:00
Franck Nijhof
021ac84405 Add recorder platform to required test category (#86704) 2023-01-26 11:03:56 +01:00
Franck Nijhof
17d3159e77 Remove unneeded use of keys() in ZHA (#86668)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2023-01-26 11:02:46 +01:00
Andrey Kupreychik
fa7ad20372 Update ndms2_client to 0.1.2 (#86624)
fix https://github.com/home-assistant/core/issues/86379
fixes undefined
2023-01-26 08:53:20 +01:00
Paulus Schoutsen
28a3b4a32c Add error handling for OpenAI (#86671)
* Add error handling for OpenAI

* Simplify area filtering

* better prompt
2023-01-25 22:17:19 -05:00
David F. Mulcahey
c395698ea2 Bump ZHA quirks lib (#86669) 2023-01-25 22:15:09 -05:00
Paulus Schoutsen
e06603bbbd Google Assistant: unset agent on unload (#86635) 2023-01-25 21:33:30 -05:00
J. Nick Koston
4cafd393c6 Correct units on mopeka battery voltage sensor (#86663) 2023-01-26 02:14:59 +01:00
Franck Nijhof
e50a531cd9 Code styling tweaks to the tests - Part 2 (#86662)
Co-authored-by: jjlawren <jjlawren@users.noreply.github.com>
2023-01-26 01:23:53 +01:00
GitHub Action
7ab88fa713 [ci skip] Translation update 2023-01-26 00:23:39 +00:00
Franck Nijhof
4955dd3e1b Code styling tweaks to Nexia tests (#86660) 2023-01-25 23:36:17 +01:00
J. Nick Koston
1d1d69ca02 Update scaffold scripts to use async_forward_entry_setups (#86647) 2023-01-25 21:26:31 +01:00
Robert Svensson
a56f6cb863 Assert Axis config entry state not hass.data (#86648) 2023-01-25 21:15:03 +01:00
Franck Nijhof
7d672b4a4d Bump version to 2023.3.0dev0 (#86632) 2023-01-25 20:50:44 +01:00
Paulus Schoutsen
df0fc30695 Fix oauth2 error (#86634) 2023-01-25 20:50:16 +01:00
Joakim Plate
1b97a51b5e Print expected device class units in error log (#86125) 2023-01-25 20:45:50 +01:00
1011 changed files with 13338 additions and 4784 deletions

View File

@@ -205,10 +205,7 @@ omit =
homeassistant/components/discord/notify.py
homeassistant/components/dlib_face_detect/image_processing.py
homeassistant/components/dlib_face_identify/image_processing.py
homeassistant/components/dlink/__init__.py
homeassistant/components/dlink/data.py
homeassistant/components/dlink/entity.py
homeassistant/components/dlink/switch.py
homeassistant/components/dominos/*
homeassistant/components/doods/*
homeassistant/components/doorbird/__init__.py
@@ -1001,6 +998,7 @@ omit =
homeassistant/components/russound_rio/media_player.py
homeassistant/components/russound_rnet/media_player.py
homeassistant/components/rympro/__init__.py
homeassistant/components/rympro/coordinator.py
homeassistant/components/rympro/sensor.py
homeassistant/components/sabnzbd/__init__.py
homeassistant/components/sabnzbd/sensor.py
@@ -1148,7 +1146,6 @@ omit =
homeassistant/components/stream/core.py
homeassistant/components/stream/fmp4utils.py
homeassistant/components/stream/hls.py
homeassistant/components/stream/recorder.py
homeassistant/components/stream/worker.py
homeassistant/components/streamlabswater/*
homeassistant/components/suez_water/*

View File

@@ -30,7 +30,8 @@ on:
env:
CACHE_VERSION: 3
PIP_CACHE_VERSION: 3
HA_SHORT_VERSION: 2023.2
MYPY_CACHE_VERSION: 3
HA_SHORT_VERSION: 2023.3
DEFAULT_PYTHON: "3.10"
ALL_PYTHON_VERSIONS: "['3.10']"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
@@ -187,7 +188,7 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache@v3.2.3
uses: actions/cache@v3.2.4
with:
path: venv
key: >-
@@ -202,7 +203,7 @@ jobs:
pip install "$(cat requirements_test.txt | grep pre-commit)"
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.2.3
uses: actions/cache@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: >-
@@ -231,30 +232,22 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if pre-commit cache restore failed
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
echo "Failed to restore pre-commit environment from cache"
exit 1
- name: Run black (fully)
if: needs.info.outputs.test_full_suite == 'true'
run: |
@@ -285,30 +278,22 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if pre-commit cache restore failed
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
echo "Failed to restore pre-commit environment from cache"
exit 1
- name: Register flake8 problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/flake8.json"
@@ -324,6 +309,7 @@ jobs:
. venv/bin/activate
shopt -s globstar
pre-commit run --hook-stage manual flake8 --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*}
lint-ruff:
name: Check ruff
runs-on: ubuntu-latest
@@ -341,30 +327,22 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if pre-commit cache restore failed
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
echo "Failed to restore pre-commit environment from cache"
exit 1
- name: Register ruff problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/ruff.json"
@@ -380,6 +358,7 @@ jobs:
. venv/bin/activate
shopt -s globstar
pre-commit run --hook-stage manual ruff --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*}
lint-isort:
name: Check isort
runs-on: ubuntu-20.04
@@ -397,30 +376,22 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if pre-commit cache restore failed
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
echo "Failed to restore pre-commit environment from cache"
exit 1
- name: Run isort
run: |
. venv/bin/activate
@@ -443,30 +414,22 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Fail job if pre-commit cache restore failed
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
echo "Failed to restore pre-commit environment from cache"
exit 1
- name: Run pyupgrade (fully)
if: needs.info.outputs.test_full_suite == 'true'
@@ -575,7 +538,7 @@ jobs:
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache@v3.2.3
uses: actions/cache@v3.2.4
with:
path: venv
key: >-
@@ -583,7 +546,7 @@ jobs:
needs.info.outputs.python_cache_key }}
- name: Restore pip wheel cache
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache@v3.2.3
uses: actions/cache@v3.2.4
with:
path: ${{ env.PIP_CACHE }}
key: >-
@@ -637,17 +600,13 @@ jobs:
check-latest: true
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run hassfest
run: |
. venv/bin/activate
@@ -673,17 +632,13 @@ jobs:
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run gen_requirements_all.py
run: |
. venv/bin/activate
@@ -710,17 +665,13 @@ jobs:
check-latest: true
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
@@ -756,19 +707,33 @@ jobs:
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Generate partial mypy restore key
id: generate-mypy-key
run: |
mypy_version=$(cat requirements_test.txt | grep mypy | cut -d '=' -f 3)
echo "version=$mypy_version" >> $GITHUB_OUTPUT
echo "key=mypy-${{ env.MYPY_CACHE_VERSION }}-$mypy_version-${{
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore mypy cache
uses: actions/cache@v3.2.4
with:
path: .mypy_cache
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
steps.generate-mypy-key.outputs.key }}
restore-keys: |
${{ runner.os }}-${{ steps.python.outputs.python-version }}-mypy-${{
env.MYPY_CACHE_VERSION }}-${{ steps.generate-mypy-key.outputs.version }}-${{
env.HA_SHORT_VERSION }}-
- name: Register mypy problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/mypy.json"
@@ -810,17 +775,13 @@ jobs:
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run pip check
run: |
. venv/bin/activate
@@ -840,8 +801,9 @@ jobs:
- gen-requirements-all
- hassfest
- lint-black
- lint-other
- lint-isort
- lint-other
- lint-ruff
- mypy
strategy:
fail-fast: false
@@ -867,16 +829,12 @@ jobs:
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
@@ -965,8 +923,9 @@ jobs:
- gen-requirements-all
- hassfest
- lint-black
- lint-other
- lint-isort
- lint-other
- lint-ruff
- mypy
strategy:
fail-fast: false
@@ -992,16 +951,12 @@ jobs:
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.3
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"

View File

@@ -42,7 +42,7 @@ jobs:
id: token
# Pinned to a specific version of the action for security reasons
# v1.7.0
uses: tibdex/github-app-token@021a2405c7f990db57f5eae5397423dcc554159c
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.ISSUE_TRIAGE_APP_ID }}
private_key: ${{ secrets.ISSUE_TRIAGE_APP_PEM }}

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.231
rev: v0.0.237
hooks:
- id: ruff
args:
@@ -60,7 +60,7 @@ repos:
- --configfile=tests/bandit.yaml
files: ^(homeassistant|script|tests)/.+\.py$
- repo: https://github.com/PyCQA/isort
rev: 5.11.4
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/pre-commit/pre-commit-hooks

14
.vscode/tasks.json vendored
View File

@@ -27,6 +27,20 @@
},
"problemMatcher": []
},
{
"label": "Pytest (changed tests only)",
"type": "shell",
"command": "pytest --timeout=10 --picked",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Flake8",
"type": "shell",

View File

@@ -211,8 +211,8 @@ build.json @home-assistant/supervisor
/tests/components/configurator/ @home-assistant/core
/homeassistant/components/control4/ @lawtancool
/tests/components/control4/ @lawtancool
/homeassistant/components/conversation/ @home-assistant/core
/tests/components/conversation/ @home-assistant/core
/homeassistant/components/conversation/ @home-assistant/core @synesthesiam
/tests/components/conversation/ @home-assistant/core @synesthesiam
/homeassistant/components/coolmaster/ @OnFreund
/tests/components/coolmaster/ @OnFreund
/homeassistant/components/coronavirus/ @home-assistant/core
@@ -566,8 +566,8 @@ build.json @home-assistant/supervisor
/tests/components/integration/ @dgomes
/homeassistant/components/intellifire/ @jeeftor
/tests/components/intellifire/ @jeeftor
/homeassistant/components/intent/ @home-assistant/core
/tests/components/intent/ @home-assistant/core
/homeassistant/components/intent/ @home-assistant/core @synesthesiam
/tests/components/intent/ @home-assistant/core @synesthesiam
/homeassistant/components/intesishome/ @jnimmo
/homeassistant/components/ios/ @robbiet480
/tests/components/ios/ @robbiet480
@@ -1003,8 +1003,8 @@ build.json @home-assistant/supervisor
/tests/components/ruuvi_gateway/ @akx
/homeassistant/components/ruuvitag_ble/ @akx
/tests/components/ruuvitag_ble/ @akx
/homeassistant/components/rympro/ @OnFreund
/tests/components/rympro/ @OnFreund
/homeassistant/components/rympro/ @OnFreund @elad-bar @maorcc
/tests/components/rympro/ @OnFreund @elad-bar @maorcc
/homeassistant/components/sabnzbd/ @shaiu
/tests/components/sabnzbd/ @shaiu
/homeassistant/components/safe_mode/ @home-assistant/core

View File

@@ -19,6 +19,7 @@ coverage:
- homeassistant/components/*/intent.py
- homeassistant/components/*/logbook.py
- homeassistant/components/*/media_source.py
- homeassistant/components/*/recorder.py
- homeassistant/components/*/scene.py
patch:
default:
@@ -36,6 +37,7 @@ coverage:
- homeassistant/components/*/intent.py
- homeassistant/components/*/logbook.py
- homeassistant/components/*/media_source.py
- homeassistant/components/*/recorder.py
- homeassistant/components/*/scene.py
comment: false

View File

@@ -2,7 +2,7 @@
"config": {
"abort": {
"reauth_successful": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u0442\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0435\u0448\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u0430",
"single_instance_allowed": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 Abode."
"single_instance_allowed": "\u0412\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e. \u0412\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f."
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"

View File

@@ -248,7 +248,8 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
metric_unit=UnitOfLength.METERS,
us_customary_unit=UnitOfLength.FEET,
value_fn=lambda data, unit: round(cast(float, data[unit][ATTR_VALUE])),
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
native_precision=0,
),
AccuWeatherSensorDescription(
key="CloudCover",
@@ -300,8 +301,10 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
),
AccuWeatherSensorDescription(
key="PressureTendency",
device_class=SensorDeviceClass.ENUM,
icon="mdi:gauge",
name="Pressure tendency",
options=["falling", "rising", "steady"],
translation_key="pressure_tendency",
value_fn=lambda data, _: cast(str, data["LocalizedText"]).lower(),
),

View File

@@ -1,4 +1,6 @@
"""Config flow to configure Agent devices."""
from contextlib import suppress
from agent import AgentConnectionError, AgentError
from agent.a import Agent
import voluptuous as vol
@@ -31,10 +33,8 @@ class AgentFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
server_origin = generate_url(host, port)
agent_client = Agent(server_origin, async_get_clientsession(self.hass))
try:
with suppress(AgentConnectionError, AgentError):
await agent_client.update()
except (AgentConnectionError, AgentError):
pass
await agent_client.close()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any, cast
from typing import Any
from homeassistant.components.sensor import (
SensorDeviceClass,
@@ -19,11 +19,10 @@ from homeassistant.const import (
UnitOfPressure,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import AirlyDataUpdateCoordinator
@@ -62,7 +61,7 @@ PARALLEL_UPDATES = 1
class AirlySensorEntityDescription(SensorEntityDescription):
"""Class describing Airly sensor entities."""
value: Callable = round
attrs: Callable[[dict[str, Any]], dict[str, Any]] = lambda data: {}
SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
@@ -70,12 +69,19 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
key=ATTR_API_CAQI,
icon="mdi:air-filter",
name=ATTR_API_CAQI,
native_precision=0,
native_unit_of_measurement="CAQI",
attrs=lambda data: {
ATTR_LEVEL: data[ATTR_API_CAQI_LEVEL],
ATTR_ADVICE: data[ATTR_API_ADVICE],
ATTR_DESCRIPTION: data[ATTR_API_CAQI_DESCRIPTION],
},
),
AirlySensorEntityDescription(
key=ATTR_API_PM1,
device_class=SensorDeviceClass.PM1,
name=ATTR_API_PM1,
name="PM1.0",
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -83,28 +89,39 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
key=ATTR_API_PM25,
device_class=SensorDeviceClass.PM25,
name="PM2.5",
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
attrs=lambda data: {
ATTR_LIMIT: data[f"{ATTR_API_PM25}_{SUFFIX_LIMIT}"],
ATTR_PERCENT: round(data[f"{ATTR_API_PM25}_{SUFFIX_PERCENT}"]),
},
),
AirlySensorEntityDescription(
key=ATTR_API_PM10,
device_class=SensorDeviceClass.PM10,
name=ATTR_API_PM10,
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
attrs=lambda data: {
ATTR_LIMIT: data[f"{ATTR_API_PM10}_{SUFFIX_LIMIT}"],
ATTR_PERCENT: round(data[f"{ATTR_API_PM10}_{SUFFIX_PERCENT}"]),
},
),
AirlySensorEntityDescription(
key=ATTR_API_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
name=ATTR_API_HUMIDITY.capitalize(),
native_precision=1,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value=lambda value: round(value, 1),
),
AirlySensorEntityDescription(
key=ATTR_API_PRESSURE,
device_class=SensorDeviceClass.PRESSURE,
name=ATTR_API_PRESSURE.capitalize(),
native_precision=0,
native_unit_of_measurement=UnitOfPressure.HPA,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -112,36 +129,56 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
key=ATTR_API_TEMPERATURE,
device_class=SensorDeviceClass.TEMPERATURE,
name=ATTR_API_TEMPERATURE.capitalize(),
native_precision=1,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value=lambda value: round(value, 1),
),
AirlySensorEntityDescription(
key=ATTR_API_CO,
name=ATTR_API_CO,
name="Carbon monoxide",
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
attrs=lambda data: {
ATTR_LIMIT: data[f"{ATTR_API_CO}_{SUFFIX_LIMIT}"],
ATTR_PERCENT: round(data[f"{ATTR_API_CO}_{SUFFIX_PERCENT}"]),
},
),
AirlySensorEntityDescription(
key=ATTR_API_NO2,
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
name=ATTR_API_NO2,
name="Nitrogen dioxide",
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
attrs=lambda data: {
ATTR_LIMIT: data[f"{ATTR_API_NO2}_{SUFFIX_LIMIT}"],
ATTR_PERCENT: round(data[f"{ATTR_API_NO2}_{SUFFIX_PERCENT}"]),
},
),
AirlySensorEntityDescription(
key=ATTR_API_SO2,
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
name=ATTR_API_SO2,
name="Sulphur dioxide",
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
attrs=lambda data: {
ATTR_LIMIT: data[f"{ATTR_API_SO2}_{SUFFIX_LIMIT}"],
ATTR_PERCENT: round(data[f"{ATTR_API_SO2}_{SUFFIX_PERCENT}"]),
},
),
AirlySensorEntityDescription(
key=ATTR_API_O3,
device_class=SensorDeviceClass.OZONE,
name=ATTR_API_O3,
name="Ozone",
native_precision=0,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
attrs=lambda data: {
ATTR_LIMIT: data[f"{ATTR_API_O3}_{SUFFIX_LIMIT}"],
ATTR_PERCENT: round(data[f"{ATTR_API_O3}_{SUFFIX_PERCENT}"]),
},
),
)
@@ -190,64 +227,15 @@ class AirlySensor(CoordinatorEntity[AirlyDataUpdateCoordinator], SensorEntity):
self._attr_unique_id = (
f"{coordinator.latitude}-{coordinator.longitude}-{description.key}".lower()
)
self._attrs: dict[str, Any] = {}
self._attr_native_value = coordinator.data[description.key]
self._attr_extra_state_attributes = description.attrs(coordinator.data)
self.entity_description = description
@property
def native_value(self) -> StateType:
"""Return the state."""
state = self.coordinator.data[self.entity_description.key]
return cast(StateType, self.entity_description.value(state))
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
if self.entity_description.key == ATTR_API_CAQI:
self._attrs[ATTR_LEVEL] = self.coordinator.data[ATTR_API_CAQI_LEVEL]
self._attrs[ATTR_ADVICE] = self.coordinator.data[ATTR_API_ADVICE]
self._attrs[ATTR_DESCRIPTION] = self.coordinator.data[
ATTR_API_CAQI_DESCRIPTION
]
if self.entity_description.key == ATTR_API_PM25:
self._attrs[ATTR_LIMIT] = self.coordinator.data[
f"{ATTR_API_PM25}_{SUFFIX_LIMIT}"
]
self._attrs[ATTR_PERCENT] = round(
self.coordinator.data[f"{ATTR_API_PM25}_{SUFFIX_PERCENT}"]
)
if self.entity_description.key == ATTR_API_PM10:
self._attrs[ATTR_LIMIT] = self.coordinator.data[
f"{ATTR_API_PM10}_{SUFFIX_LIMIT}"
]
self._attrs[ATTR_PERCENT] = round(
self.coordinator.data[f"{ATTR_API_PM10}_{SUFFIX_PERCENT}"]
)
if self.entity_description.key == ATTR_API_CO:
self._attrs[ATTR_LIMIT] = self.coordinator.data[
f"{ATTR_API_CO}_{SUFFIX_LIMIT}"
]
self._attrs[ATTR_PERCENT] = round(
self.coordinator.data[f"{ATTR_API_CO}_{SUFFIX_PERCENT}"]
)
if self.entity_description.key == ATTR_API_NO2:
self._attrs[ATTR_LIMIT] = self.coordinator.data[
f"{ATTR_API_NO2}_{SUFFIX_LIMIT}"
]
self._attrs[ATTR_PERCENT] = round(
self.coordinator.data[f"{ATTR_API_NO2}_{SUFFIX_PERCENT}"]
)
if self.entity_description.key == ATTR_API_SO2:
self._attrs[ATTR_LIMIT] = self.coordinator.data[
f"{ATTR_API_SO2}_{SUFFIX_LIMIT}"
]
self._attrs[ATTR_PERCENT] = round(
self.coordinator.data[f"{ATTR_API_SO2}_{SUFFIX_PERCENT}"]
)
if self.entity_description.key == ATTR_API_O3:
self._attrs[ATTR_LIMIT] = self.coordinator.data[
f"{ATTR_API_O3}_{SUFFIX_LIMIT}"
]
self._attrs[ATTR_PERCENT] = round(
self.coordinator.data[f"{ATTR_API_O3}_{SUFFIX_PERCENT}"]
)
return self._attrs
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._attr_native_value = self.coordinator.data[self.entity_description.key]
self._attr_extra_state_attributes = self.entity_description.attrs(
self.coordinator.data
)
self.async_write_ha_state()

View File

@@ -12,8 +12,8 @@
"data": {
"api_key": "API \u043a\u043b\u044e\u0447 \u0437\u0430 Airly",
"latitude": "\u0428\u0438\u0440\u0438\u043d\u0430",
"longitude": "\u0414\u044a\u043b\u0436\u0438\u043d\u0430",
"name": "\u0418\u043c\u0435 \u043d\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f\u0442\u0430"
"longitude": "\u0413\u0435\u043e\u0433\u0440\u0430\u0444\u0441\u043a\u0430 \u0434\u044a\u043b\u0436\u0438\u043d\u0430",
"name": "\u0418\u043c\u0435"
},
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\u0442\u043e \u043d\u0430 \u0432\u044a\u0437\u0434\u0443\u0445\u0430 Airly \u0417\u0430 \u0434\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0430\u0442\u0435 \u043a\u043b\u044e\u0447 \u0437\u0430 API, \u043e\u0442\u0438\u0434\u0435\u0442\u0435 \u043d\u0430 https://developer.airly.eu/register"
}

View File

@@ -2,7 +2,7 @@
"domain": "aladdin_connect",
"name": "Aladdin Connect",
"documentation": "https://www.home-assistant.io/integrations/aladdin_connect",
"requirements": ["AIOAladdinConnect==0.1.53"],
"requirements": ["AIOAladdinConnect==0.1.54"],
"codeowners": ["@mkmer"],
"iot_class": "cloud_polling",
"loggers": ["aladdin_connect"],

View File

@@ -3,6 +3,9 @@
"abort": {
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e"
},
"create_entry": {
"default": "\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0430\u043d \u0441 AlarmDecoder."
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
},
@@ -19,5 +22,30 @@
}
}
}
},
"options": {
"step": {
"arm_settings": {
"data": {
"code_arm_required": "\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0435 \u043a\u043e\u0434 \u0437\u0430 \u043f\u043e\u0435\u043c\u0430\u043d\u0435 \u043f\u043e\u0434 \u043e\u0445\u0440\u0430\u043d\u0430"
}
},
"init": {
"data": {
"edit_select": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0435"
}
},
"zone_details": {
"data": {
"zone_name": "\u0418\u043c\u0435 \u043d\u0430 \u0437\u043e\u043d\u0430",
"zone_type": "\u0422\u0438\u043f \u0437\u043e\u043d\u0430"
}
},
"zone_select": {
"data": {
"zone_number": "\u041d\u043e\u043c\u0435\u0440 \u043d\u0430 \u0437\u043e\u043d\u0430"
}
}
}
}
}

View File

@@ -128,7 +128,6 @@ SENSOR_DESCRIPTIONS = (
key=TYPE_AQI_PM25_24H,
name="AQI PM2.5 24h avg",
device_class=SensorDeviceClass.AQI,
state_class=SensorStateClass.TOTAL_INCREASING,
),
SensorEntityDescription(
key=TYPE_AQI_PM25_IN,
@@ -140,7 +139,6 @@ SENSOR_DESCRIPTIONS = (
key=TYPE_AQI_PM25_IN_24H,
name="AQI PM2.5 indoor 24h avg",
device_class=SensorDeviceClass.AQI,
state_class=SensorStateClass.TOTAL_INCREASING,
),
SensorEntityDescription(
key=TYPE_BAROMABSIN,
@@ -182,7 +180,7 @@ SENSOR_DESCRIPTIONS = (
name="Event rain",
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.MEASUREMENT,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=TYPE_FEELSLIKE,
@@ -287,7 +285,6 @@ SENSOR_DESCRIPTIONS = (
name="Last rain",
icon="mdi:water",
device_class=SensorDeviceClass.TIMESTAMP,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=TYPE_LIGHTNING_PER_DAY,
@@ -315,7 +312,7 @@ SENSOR_DESCRIPTIONS = (
name="Monthly rain",
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.MEASUREMENT,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=TYPE_PM25_24H,
@@ -586,7 +583,7 @@ SENSOR_DESCRIPTIONS = (
name="Lifetime rain",
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.MEASUREMENT,
state_class=SensorStateClass.TOTAL_INCREASING,
),
SensorEntityDescription(
key=TYPE_UV,
@@ -599,7 +596,7 @@ SENSOR_DESCRIPTIONS = (
name="Weekly rain",
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.MEASUREMENT,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=TYPE_WINDDIR,

View File

@@ -6,6 +6,13 @@ import os
from typing import Any
from adb_shell.auth.keygen import keygen
from adb_shell.exceptions import (
AdbTimeoutError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
from androidtv.adb_manager.adb_manager_sync import ADBPythonSync, PythonRSASigner
from androidtv.setup_async import (
AndroidTVAsync,
@@ -43,6 +50,18 @@ from .const import (
SIGNAL_CONFIG_ENTITY,
)
ADB_PYTHON_EXCEPTIONS: tuple = (
AdbTimeoutError,
BrokenPipeError,
ConnectionResetError,
ValueError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
ADB_TCP_EXCEPTIONS: tuple = (ConnectionResetError, RuntimeError)
PLATFORMS = [Platform.MEDIA_PLAYER]
RELOAD_OPTIONS = [CONF_STATE_DETECTION_RULES]
@@ -132,9 +151,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Android TV platform."""
state_det_rules = entry.options.get(CONF_STATE_DETECTION_RULES)
aftv, error_message = await async_connect_androidtv(
hass, entry.data, state_detection_rules=state_det_rules
)
if CONF_ADB_SERVER_IP not in entry.data:
exceptions = ADB_PYTHON_EXCEPTIONS
else:
exceptions = ADB_TCP_EXCEPTIONS
try:
aftv, error_message = await async_connect_androidtv(
hass, entry.data, state_detection_rules=state_det_rules
)
except exceptions as exc:
raise ConfigEntryNotReady(exc) from exc
if not aftv:
raise ConfigEntryNotReady(error_message)

View File

@@ -7,13 +7,6 @@ import functools
import logging
from typing import Any, Concatenate, ParamSpec, TypeVar
from adb_shell.exceptions import (
AdbTimeoutError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
from androidtv.constants import APPS, KEYS
from androidtv.exceptions import LockNotAcquiredException
import voluptuous as vol
@@ -42,7 +35,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import get_androidtv_mac
from . import ADB_PYTHON_EXCEPTIONS, ADB_TCP_EXCEPTIONS, get_androidtv_mac
from .const import (
ANDROID_DEV,
ANDROID_DEV_OPT,
@@ -252,19 +245,10 @@ class ADBDevice(MediaPlayerEntity):
# ADB exceptions to catch
if not aftv.adb_server_ip:
# Using "adb_shell" (Python ADB implementation)
self.exceptions = (
AdbTimeoutError,
BrokenPipeError,
ConnectionResetError,
ValueError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
self.exceptions = ADB_PYTHON_EXCEPTIONS
else:
# Using "pure-python-adb" (communicate with ADB server)
self.exceptions = (ConnectionResetError, RuntimeError)
self.exceptions = ADB_TCP_EXCEPTIONS
# Property attributes
self._attr_extra_state_attributes = {

View File

@@ -4,7 +4,8 @@
"already_configured": "Apparaat is al geconfigureerd"
},
"error": {
"cannot_connect": "Kan geen verbinding maken"
"cannot_connect": "Kan geen verbinding maken",
"cannot_receive_deviceinfo": "Kon het MAC adres niet ophalen. Zorg ervoor dat het apparaat aanstaat"
},
"step": {
"user": {

View File

@@ -1,4 +1,6 @@
"""Apprise platform for notify component."""
from __future__ import annotations
import logging
import apprise
@@ -12,7 +14,9 @@ from homeassistant.components.notify import (
BaseNotificationService,
)
from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
@@ -26,7 +30,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
)
def get_service(hass, config, discovery_info=None):
def get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> AppriseNotificationService | None:
"""Get the Apprise notification service."""
# Create our Apprise Instance (reference our asset)
a_obj = apprise.Apprise()

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"reauth_successful": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u0442\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0435\u0448\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u0430"
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435"

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "El servicio ya est\u00e1 configurado"
},
"error": {
"cannot_connect": "No se pudo conectar"
},

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "A szolg\u00e1ltat\u00e1s m\u00e1r konfigur\u00e1lva van"
},
"error": {
"cannot_connect": "Sikertelen csatlakoz\u00e1s"
},

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "Layanan sudah dikonfigurasi"
},
"error": {
"cannot_connect": "Gagal terhubung"
},

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "Dienst is al ingesteld"
},
"error": {
"cannot_connect": "Kan geen verbinding maken"
},

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "Us\u0142uga jest ju\u017c skonfigurowana"
},
"error": {
"cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia"
},

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "O servi\u00e7o j\u00e1 est\u00e1 configurado"
},
"error": {
"cannot_connect": "Falha ao conectar"
},

View File

@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"already_configured": "Slu\u017eba u\u017e je nakonfigurovan\u00e1"
},
"error": {
"cannot_connect": "Nepodarilo sa pripoji\u0165"
},

View File

@@ -438,7 +438,7 @@ def _create_auth_code_store() -> tuple[StoreResultType, RetrieveResultType]:
def store_result(client_id: str, result: Credentials) -> str:
"""Store flow result and return a code to retrieve it."""
if not isinstance(result, Credentials):
raise ValueError("result has to be a Credentials instance")
raise TypeError("result has to be a Credentials instance")
code = uuid.uuid4().hex
temp_results[(client_id, code)] = (

View File

@@ -1,4 +1,6 @@
"""AWS platform for notify component."""
from __future__ import annotations
import asyncio
import base64
import json
@@ -20,7 +22,9 @@ from homeassistant.const import (
CONF_PROFILE_NAME,
CONF_SERVICE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.json import JSONEncoder
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import CONF_CONTEXT, CONF_CREDENTIAL_NAME, CONF_REGION, DATA_SESSIONS
@@ -33,7 +37,11 @@ async def get_available_regions(hass, service):
return await session.get_available_regions(service)
async def async_get_service(hass, config, discovery_info=None):
async def async_get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> AWSNotify | None:
"""Get the AWS notification service."""
if discovery_info is None:
_LOGGER.error("Please config aws notify platform in aws component")

View File

@@ -10,7 +10,7 @@
"already_in_progress": "\u0412 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0442\u0435\u0447\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e.",
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
},
"flow_title": "Axis \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e: {name} ({host})",
"flow_title": "{name} ({host})",
"step": {
"user": {
"data": {

View File

@@ -1,9 +1,11 @@
"""Support for azure service bus notification."""
from __future__ import annotations
import json
import logging
from azure.servicebus import ServiceBusMessage
from azure.servicebus.aio import ServiceBusClient
from azure.servicebus.aio import ServiceBusClient, ServiceBusSender
from azure.servicebus.exceptions import (
MessagingEntityNotFoundError,
ServiceBusConnectionError,
@@ -19,7 +21,9 @@ from homeassistant.components.notify import (
BaseNotificationService,
)
from homeassistant.const import CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
CONF_CONNECTION_STRING = "connection_string"
CONF_QUEUE_NAME = "queue"
@@ -47,11 +51,15 @@ PLATFORM_SCHEMA = vol.All(
_LOGGER = logging.getLogger(__name__)
def get_service(hass, config, discovery_info=None):
def get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> ServiceBusNotificationService | None:
"""Get the notification service."""
connection_string = config[CONF_CONNECTION_STRING]
queue_name = config.get(CONF_QUEUE_NAME)
topic_name = config.get(CONF_TOPIC_NAME)
connection_string: str = config[CONF_CONNECTION_STRING]
queue_name: str | None = config.get(CONF_QUEUE_NAME)
topic_name: str | None = config.get(CONF_TOPIC_NAME)
# Library can do synchronous IO when creating the clients.
# Passes in loop here, but can't run setup on the event loop.
@@ -59,10 +67,11 @@ def get_service(hass, config, discovery_info=None):
connection_string, loop=hass.loop
)
client: ServiceBusSender | None = None
try:
if queue_name:
client = servicebus.get_queue_sender(queue_name)
else:
elif topic_name:
client = servicebus.get_topic_sender(topic_name)
except (ServiceBusConnectionError, MessagingEntityNotFoundError) as err:
_LOGGER.error(
@@ -72,7 +81,7 @@ def get_service(hass, config, discovery_info=None):
)
return None
return ServiceBusNotificationService(client)
return ServiceBusNotificationService(client) if client else None
class ServiceBusNotificationService(BaseNotificationService):

View File

@@ -201,7 +201,7 @@
"on": "Problem"
},
"running": {
"off": "Nicht ausgef\u00fchrt",
"off": "L\u00e4uft nicht",
"on": "L\u00e4uft"
},
"safety": {

View File

@@ -164,10 +164,7 @@ class BlackbirdZone(MediaPlayerEntity):
return
self._attr_state = MediaPlayerState.ON if state.power else MediaPlayerState.OFF
idx = state.av
if idx in self._source_id_name:
self._attr_source = self._source_id_name[idx]
else:
self._attr_source = None
self._attr_source = self._source_id_name.get(idx)
@property
def media_title(self):

View File

@@ -5,7 +5,7 @@
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"step": {

View File

@@ -71,16 +71,14 @@ class BlinkStickLight(LightEntity):
"""Turn the device on."""
if ATTR_HS_COLOR in kwargs:
self._attr_hs_color = kwargs[ATTR_HS_COLOR]
if ATTR_BRIGHTNESS in kwargs:
self._attr_brightness = kwargs[ATTR_BRIGHTNESS]
else:
self._attr_brightness = 255
assert self.brightness is not None
self._attr_is_on = self.brightness > 0
brightness: int = kwargs.get(ATTR_BRIGHTNESS, 255)
self._attr_brightness = brightness
self._attr_is_on = bool(brightness)
assert self.hs_color
rgb_color = color_util.color_hsv_to_RGB(
self.hs_color[0], self.hs_color[1], self.brightness / 255 * 100
self.hs_color[0], self.hs_color[1], brightness / 255 * 100
)
self._stick.set_color(red=rgb_color[0], green=rgb_color[1], blue=rgb_color[2])

View File

@@ -85,7 +85,7 @@ def _dispatch_bleak_callback(
"""Dispatch the callback."""
if not callback:
# Callback destroyed right before being called, ignore
return # pragma: no cover
return
if (uuids := filters.get(FILTER_UUIDS)) and not uuids.intersection(
advertisement_data.service_uuids
@@ -209,6 +209,20 @@ class BluetoothManager:
self._bluetooth_adapters, self.storage
)
self.async_setup_unavailable_tracking()
seen: set[str] = set()
for address, service_info in itertools.chain(
self._connectable_history.items(), self._all_history.items()
):
if address in seen:
continue
seen.add(address)
for domain in self._integration_matcher.match_domains(service_info):
discovery_flow.async_create_flow(
self.hass,
domain,
{"source": config_entries.SOURCE_BLUETOOTH},
service_info,
)
@hass_callback
def async_stop(self, event: Event) -> None:

View File

@@ -285,7 +285,7 @@ class PassiveBluetoothDataProcessor(Generic[_T]):
if not isinstance(new_data, PassiveBluetoothDataUpdate):
self.last_update_success = False # type: ignore[unreachable]
raise ValueError(
raise TypeError(
f"The update_method for {self.coordinator.name} returned"
f" {new_data} instead of a PassiveBluetoothDataUpdate"
)

View File

@@ -1,5 +1,16 @@
{
"config": {
"flow_title": "{name}"
"flow_title": "{name}",
"step": {
"bluetooth_confirm": {
"description": "Vai v\u0113laties iestat\u012bt {name}?"
},
"user": {
"data": {
"address": "Ier\u012bce"
},
"description": "Izv\u0113lieties ier\u012bci, kuru iestat\u012bt"
}
}
}
}

View File

@@ -5,7 +5,7 @@
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"flow_title": "{name} ({host})",

View File

@@ -92,7 +92,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1
info: dict[str, str | None]
host: str | None = None
host: str
async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
"""Perform reauth upon an API authentication error."""
@@ -107,8 +107,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
step_id="reauth_confirm",
data_schema=HOST_SCHEMA,
)
self.host = host = user_input[CONF_HOST]
self.info = await self._get_info(host)
self.host = user_input[CONF_HOST]
self.info = await self._get_info(self.host)
return await self.async_step_credentials()
async def async_step_user(
@@ -117,18 +117,17 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
host = user_input[CONF_HOST]
self.host = user_input[CONF_HOST]
try:
self.info = info = await self._get_info(host)
self.info = await self._get_info(self.host)
except SHCConnectionError:
errors["base"] = "cannot_connect"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
await self.async_set_unique_id(info["unique_id"])
self._abort_if_unique_id_configured({CONF_HOST: host})
self.host = host
await self.async_set_unique_id(self.info["unique_id"])
self._abort_if_unique_id_configured({CONF_HOST: self.host})
return await self.async_step_credentials()
return self.async_show_form(

View File

@@ -14,11 +14,14 @@
}
},
"confirm_discovery": {
"description": "Please press the Bosch Smart Home Controller's front-side button until LED starts flashing.\nReady to continue to set up {model} @ {host} with Home Assistant?"
"description": "Smart Home Controller I: Please press the front-side button until LED starts flashing.\nSmart Home Controller II: Press the function button shortly. Cloud and network lights start blinking orange.\nDevice is now ready to be paired.\n\nReady to continue to set up {model} @ {host} with Home Assistant?"
},
"reauth_confirm": {
"title": "[%key:common::config_flow::title::reauth%]",
"description": "The bosch_shc integration needs to re-authenticate your account"
"description": "The bosch_shc integration needs to re-authenticate your account",
"data": {
"host": "[%key:common::config_flow::data::host%]"
}
}
},
"error": {

View File

@@ -12,6 +12,9 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"reauth_confirm": {
"data": {
"host": "\u0425\u043e\u0441\u0442"
},
"title": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f\u0442\u0430"
},
"user": {

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Prem el bot\u00f3 de la part frontal/lateral del controlador Bosh Smart Home fins que el LED parpellegi.\nPreparat per continuar la configuraci\u00f3 de {model} @ {host} amb Home Assistant?"
"description": "Smart Home Controller I: Prem el bot\u00f3 de la part frontal/lateral fins que el LED parpellegi.\nSmart Home Controller II: Prem el bot\u00f3 de funci\u00f3 breument. Els LEDs d'acc\u00e9s al n\u00favol i de connexi\u00f3 comen\u00e7aran a parpellejar.\nEl dispositiu est\u00e0 llest per a la vinculaci\u00f3.\n\nPreparat per continuar la configuraci\u00f3 de {model} @ {host} amb Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Amfitri\u00f3"
},
"description": "La integraci\u00f3 bosch_shc ha de tornar a autenticar el teu compte",
"title": "Reautenticaci\u00f3 de la integraci\u00f3"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Bitte dr\u00fccke die frontseitige Taste des Bosch Smart Home Controllers, bis die LED zu blinken beginnt.\nBist du bereit, mit der Einrichtung von {model} @ {host} in Home Assistant fortzufahren?"
"description": "Smart Home Controller I: Bitte dr\u00fccke die Taste auf der Vorderseite, bis die LED zu blinken beginnt.\nSmart Home Controller II: Dr\u00fccke kurz die Funktionstaste. Cloud- und Netzwerk-Lampen beginnen orange zu blinken.\nDas Ger\u00e4t ist nun bereit f\u00fcr das Pairing.\n\nBist du bereit, mit der Einrichtung von {model} @ {host} mit Home Assistant fortzufahren?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Host"
},
"description": "Die bosch_shc Integration muss dein Konto neu authentifizieren",
"title": "Integration erneut authentifizieren"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Please press the Bosch Smart Home Controller's front-side button until LED starts flashing.\nReady to continue to set up {model} @ {host} with Home Assistant?"
"description": "Smart Home Controller I: Please press the front-side button until LED starts flashing.\nSmart Home Controller II: Press the function button shortly. Cloud and network lights start blinking orange.\nDevice is now ready to be paired.\n\nReady to continue to set up {model} @ {host} with Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Host"
},
"description": "The bosch_shc integration needs to re-authenticate your account",
"title": "Reauthenticate Integration"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Por favor, pulsa el bot\u00f3n frontal del Smart Home Controller de Bosch hasta que el LED empiece a parpadear.\n\u00bfPreparado para seguir configurando {model} @ {host} con Home Assistant?"
"description": "Smart Home Controller I: por favor, pulsa el bot\u00f3n frontal hasta que el LED comience a parpadear.\nSmart Home Controller II: pulsa el bot\u00f3n de funci\u00f3n brevemente. Las luces de la red y la nube comienzan a parpadear en naranja.\nEl dispositivo ya est\u00e1 listo para emparejarse. \n\n\u00bfPreparado para continuar configurando {model} @ {host} con Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Host"
},
"description": "La integraci\u00f3n bosch_shc necesita volver a autentificar tu cuenta",
"title": "Volver a autenticar la integraci\u00f3n"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Vajuta palun Bosch Smart Home Controlleri esik\u00fclje nuppu kuni LED hakkab vilkuma.\n Kas oled valmis j\u00e4tkama {model} @ {host} seadistamist Home Assistanti abil?"
"description": "Smart Home Controller I: vajuta esik\u00fclje nuppu kuni LED hakkab vilkuma.\nSmart Home Controller II: vajuta l\u00fchidalt funktsiooninuppu. Pilve- ja v\u00f5rgutuled hakkavad oran\u017eilt vilkuma.\nSeade on n\u00fc\u00fcd sidumiseks valmis.\n\nKas oled valmis j\u00e4tkama {model} @ {host} seadistamist Home Assistantiga?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Host"
},
"description": "Bosch_shc sidumine peab konto uuesti autentima.",
"title": "Taastuvastamine"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Tekan tombol sisi depan Bosch Smart Home Controller hingga LED mulai berkedip.\nSiap melanjutkan penyiapan {model} @ {host} dengan Home Assistant?"
"description": "Smart Home Controller I: Tekan tombol sisi depan hingga LED mulai berkedip.\nSmart Home Controller II: Tekan tombol fungsi sebentar. Lampu cloud dan jaringan mulai berkedip oranye.\nPerangkat sekarang siap untuk dipasangkan.\n\nSiap untuk melanjutkan penyiapan {model} @ {host} dengan Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Host"
},
"description": "Integrasi bosch_shc perlu mengautentikasi ulang akun Anda",
"title": "Autentikasi Ulang Integrasi"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Trykk p\u00e5 Bosch Smart Home Controller-frontknappen til LED-lampen begynner \u00e5 blinke.\n Klar til \u00e5 fortsette \u00e5 konfigurere {model} @ {host} med Home Assistant?"
"description": "Smart Home Controller I: Trykk p\u00e5 knappen p\u00e5 forsiden til LED begynner \u00e5 blinke.\n Smart Home Controller II: Trykk kort p\u00e5 funksjonsknappen. Sky- og nettverkslys begynner \u00e5 blinke oransje.\n Enheten er n\u00e5 klar til \u00e5 bli paret. \n\n Er du klar til \u00e5 fortsette \u00e5 konfigurere {model} @ {host} med Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Vert"
},
"description": "Bosch_shc-integrasjonen m\u00e5 godkjenne kontoen din p\u00e5 nytt",
"title": "Godkjenne integrering p\u00e5 nytt"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Pressione o bot\u00e3o frontal do Bosch Smart Home Controller at\u00e9 que o LED comece a piscar.\n Pronto para continuar a configurar {model} @ {host} com o Home Assistant?"
"description": "Smart Home Controller I: Por favor, pressione o bot\u00e3o frontal at\u00e9 que o LED comece a piscar.\n Smart Home Controller II: Pressione brevemente o bot\u00e3o de fun\u00e7\u00e3o. As luzes da nuvem e da rede come\u00e7am a piscar em laranja.\n O dispositivo agora est\u00e1 pronto para ser emparelhado. \n\n Pronto para continuar a configurar {model} @ {host} com o Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Host"
},
"description": "A integra\u00e7\u00e3o bosch_shc precisa re-autenticar sua conta",
"title": "Reautenticar Integra\u00e7\u00e3o"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "\u0423\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u043d\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043f\u043e\u043a\u0430 \u0441\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434\u043d\u044b\u0435 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043d\u0435 \u043d\u0430\u0447\u043d\u0443\u0442 \u043c\u0438\u0433\u0430\u0442\u044c.\n\u0413\u043e\u0442\u043e\u0432\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 Home Assistant \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 {model} @ {host}?"
"description": "Smart Home Controller I: \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u043f\u043e\u043a\u0430 \u0441\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434 \u043d\u0435 \u043d\u0430\u0447\u043d\u0435\u0442 \u043c\u0438\u0433\u0430\u0442\u044c.\nSmart Home Controller II: \u041a\u0440\u0430\u0442\u043a\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443. \u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043e\u0431\u043b\u0430\u043a\u0430 \u0438 \u0441\u0435\u0442\u0438 \u043d\u0430\u0447\u043d\u0443\u0442 \u043c\u0438\u0433\u0430\u0442\u044c \u043e\u0440\u0430\u043d\u0436\u0435\u0432\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c.\n\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0441\u043e\u043f\u0440\u044f\u0436\u0435\u043d\u0438\u044e.\n\n\u0413\u043e\u0442\u043e\u0432\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 {model} @ {host}?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "\u0425\u043e\u0441\u0442"
},
"description": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 Bosch SHC",
"title": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f"
},

View File

@@ -14,7 +14,7 @@
"flow_title": "Bosch SHC: {name}",
"step": {
"confirm_discovery": {
"description": "Stla\u010dte tla\u010didlo na prednej strane ovl\u00e1da\u010da Bosch Smart Home Controller, k\u00fdm LED neza\u010dne blika\u0165.\n Ste pripraven\u00ed pokra\u010dova\u0165 v nastavovan\u00ed {model} @ {host} pomocou Home Assistant?"
"description": "Smart Home Controller I: Stla\u010dte pros\u00edm tla\u010didlo na prednej strane, k\u00fdm LED neza\u010dne blika\u0165.\n Smart Home Controller II: Kr\u00e1tko stla\u010dte funk\u010dn\u00e9 tla\u010didlo. Kontrolky cloudu a siete za\u010dn\u00fa blika\u0165 na oran\u017eovo.\n Zariadenie je teraz pripraven\u00e9 na sp\u00e1rovanie. \n\n Ste pripraven\u00ed pokra\u010dova\u0165 v nastavovan\u00ed {model} @ {host} pomocou Home Assistant?"
},
"credentials": {
"data": {
@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "Hostite\u013e"
},
"description": "Integr\u00e1cia bosch_shc mus\u00ed znova overi\u0165 v\u00e1\u0161 \u00fa\u010det",
"title": "Znova overi\u0165 integr\u00e1ciu"
},

View File

@@ -22,6 +22,9 @@
}
},
"reauth_confirm": {
"data": {
"host": "\u4e3b\u6a5f\u7aef"
},
"description": "bosch_shc \u6574\u5408\u9700\u8981\u91cd\u65b0\u8a8d\u8b49\u60a8\u7684\u5e33\u865f",
"title": "\u91cd\u65b0\u8a8d\u8b49\u6574\u5408"
},

View File

@@ -60,7 +60,7 @@ class BroadlinkDevice:
@property
def available(self):
"""Return True if the device is available."""
if self.update_manager is None: # pragma: no cover
if self.update_manager is None:
return False
return self.update_manager.available

View File

@@ -2,13 +2,13 @@
"config": {
"abort": {
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e",
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_host": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0438\u043c\u0435 \u043d\u0430 \u0445\u043e\u0441\u0442 \u0438\u043b\u0438 IP \u0430\u0434\u0440\u0435\u0441",
"not_supported": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u043d\u0435 \u0441\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"flow_title": "{name} ({model} at {host})",

View File

@@ -5,7 +5,7 @@
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
},
"flow_title": "{name}",
"step": {

View File

@@ -21,10 +21,11 @@ def get_cert(
"""Get the certificate for the host and port combination."""
ctx = ssl.create_default_context()
address = (host, port)
with socket.create_connection(address, timeout=TIMEOUT) as sock:
with ctx.wrap_socket(sock, server_hostname=address[0]) as ssock:
cert = ssock.getpeercert()
return cert
with socket.create_connection(address, timeout=TIMEOUT) as sock, ctx.wrap_socket(
sock, server_hostname=address[0]
) as ssock:
cert = ssock.getpeercert()
return cert
async def get_cert_expiry_timestamp(

View File

@@ -1,15 +1,23 @@
"""Unify Circuit platform for notify component."""
from __future__ import annotations
import logging
from circuit_webhook import Circuit
from homeassistant.components.notify import BaseNotificationService
from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
def get_service(hass, config, discovery_info=None):
def get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> CircuitNotificationService | None:
"""Get the Unify Circuit notification service."""
if discovery_info is None:
return None

View File

@@ -1,4 +1,6 @@
"""Cisco Webex Teams notify component."""
from __future__ import annotations
import logging
import voluptuous as vol
@@ -10,7 +12,9 @@ from homeassistant.components.notify import (
BaseNotificationService,
)
from homeassistant.const import CONF_TOKEN
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
@@ -21,7 +25,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
)
def get_service(hass, config, discovery_info=None):
def get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> CiscoWebexTeamsNotificationService | None:
"""Get the CiscoWebexTeams notification service."""
client = WebexTeamsAPI(access_token=config[CONF_TOKEN])

View File

@@ -1,4 +1,6 @@
"""clicksend_tts platform for notify component."""
from __future__ import annotations
from http import HTTPStatus
import json
import logging
@@ -14,7 +16,9 @@ from homeassistant.const import (
CONF_USERNAME,
CONTENT_TYPE_JSON,
)
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
@@ -49,7 +53,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
)
def get_service(hass, config, discovery_info=None):
def get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> ClicksendNotificationService | None:
"""Get the ClickSend notification service."""
if not _authenticate(config):
_LOGGER.error("You are not authorized to access ClickSend")

View File

@@ -1,44 +1,128 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "Changer le mode HVAC sur {entity_name}.",
"set_hvac_mode": "D\u00e9finir le mode CVC de {entity_name}",
"set_preset_mode": "Changer les pr\u00e9r\u00e9glages de {entity_name}"
},
"condition_type": {
"is_hvac_mode": "{entity_name} est d\u00e9fini sur un mode HVAC sp\u00e9cifique",
"is_hvac_mode": "{entity_name} est r\u00e9gl\u00e9 sur un mode CVC sp\u00e9cifique",
"is_preset_mode": "{entity_name} est d\u00e9fini sur un mode pr\u00e9d\u00e9fini sp\u00e9cifique"
},
"trigger_type": {
"current_humidity_changed": "Changement d'humidit\u00e9 mesur\u00e9e pour {entity_name}",
"current_temperature_changed": "Changement de temp\u00e9rature mesur\u00e9e pour {entity_name}",
"hvac_mode_changed": "Mode HVAC chang\u00e9 pour {entity_name}"
"hvac_mode_changed": "Modification du mode CVC de {entity_name}"
}
},
"state": {
"_": {
"auto": "Auto",
"cool": "Frais",
"dry": "Sec",
"fan_only": "Ventilateur seul",
"heat": "Chauffe",
"heat_cool": "Chaud/Froid",
"cool": "Rafra\u00eechissement",
"dry": "Ass\u00e9chage",
"fan_only": "Ventilation uniquement",
"heat": "Chauffage",
"heat_cool": "Chauffage / Rafra\u00eechissement",
"off": "D\u00e9sactiv\u00e9"
}
},
"state_attributes": {
"_": {
"hvac_action": {
"aux_heat": {
"name": "Chauffage auxiliaire"
},
"current_humidity": {
"name": "Humidit\u00e9 actuelle"
},
"current_temperature": {
"name": "Temp\u00e9rature actuelle"
},
"fan_mode": {
"name": "Mode de ventilation",
"state": {
"auto": "Auto",
"diffuse": "Diffuse",
"focus": "Focalis\u00e9e",
"high": "\u00c9lev\u00e9e",
"low": "Faible",
"medium": "Moyenne",
"middle": "Milieu",
"off": "D\u00e9sactiv\u00e9e",
"on": "Activ\u00e9e",
"top": "Haute"
}
},
"fan_modes": {
"name": "Modes de ventilation"
},
"humidity": {
"name": "Humidit\u00e9 cible"
},
"hvac_action": {
"name": "Action actuelle",
"state": {
"cooling": "Rafra\u00eechissement",
"drying": "Ass\u00e9chage",
"fan": "Ventilation",
"heating": "Chauffe",
"idle": "Inactif",
"off": "Arr\u00eat"
}
},
"hvac_modes": {
"name": "Modes CVC"
},
"max_humidity": {
"name": "Humidit\u00e9 cible maximale"
},
"max_temp": {
"name": "Temp\u00e9rature cible maximale"
},
"min_humidity": {
"name": "Humidit\u00e9 cible minimale"
},
"min_temp": {
"name": "Temp\u00e9rature cible minimale"
},
"preset_mode": {
"name": "Pr\u00e9r\u00e9glage",
"state": {
"activity": "Activit\u00e9",
"away": "Absent",
"comfort": "Confort"
"boost": "Boost",
"comfort": "Confort",
"eco": "\u00c9co",
"home": "\u00c0 la maison",
"none": "Aucun",
"sleep": "Nuit"
}
},
"preset_modes": {
"name": "Pr\u00e9r\u00e9glages"
},
"swing_mode": {
"name": "Mode d\u2019oscillation",
"state": {
"both": "Les deux",
"horizontal": "Horizontale",
"off": "D\u00e9sactiv\u00e9e",
"on": "Activ\u00e9e",
"vertical": "Verticale"
}
},
"swing_modes": {
"name": "Modes d\u2019oscillation"
},
"target_temp_high": {
"name": "Temp\u00e9rature cible sup\u00e9rieure"
},
"target_temp_low": {
"name": "Temp\u00e9rature cible inf\u00e9rieure"
},
"target_temp_step": {
"name": "Pas de temp\u00e9rature cible"
},
"temperature": {
"name": "Temp\u00e9rature cible"
}
}
},

View File

@@ -40,8 +40,8 @@
"name": "\u98ce\u901f",
"state": {
"auto": "\u81ea\u52a8",
"high": "\u9ad8",
"low": "\u4f4e",
"high": "\u5f3a",
"low": "\u5f31",
"medium": "\u4e2d",
"middle": "\u4e2d\u95f4",
"off": "\u5173",

View File

@@ -38,7 +38,7 @@ async def async_provide_implementation(hass: HomeAssistant, domain: str):
for service in services:
if (
service["service"] == domain
and CURRENT_PLAIN_VERSION >= service["min_version"]
and service["min_version"] <= CURRENT_PLAIN_VERSION
and (
service.get("accepts_new_authorizations", True)
or (

View File

@@ -5,7 +5,7 @@
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"step": {

View File

@@ -11,7 +11,7 @@ import re
from typing import IO, Any
from hassil.intents import Intents, ResponseType, SlotList, TextSlotList
from hassil.recognize import recognize
from hassil.recognize import RecognizeResult, recognize_all
from hassil.util import merge_dict
from home_assistant_intents import get_intents
import yaml
@@ -71,6 +71,8 @@ class DefaultAgent(AbstractConversationAgent):
# intent -> [sentences]
self._config_intents: dict[str, Any] = {}
self._areas_list: TextSlotList | None = None
self._names_list: TextSlotList | None = None
async def async_initialize(self, config_intents):
"""Initialize the default agent."""
@@ -81,6 +83,22 @@ class DefaultAgent(AbstractConversationAgent):
if config_intents:
self._config_intents = config_intents
self.hass.bus.async_listen(
area_registry.EVENT_AREA_REGISTRY_UPDATED,
self._async_handle_area_registry_changed,
run_immediately=True,
)
self.hass.bus.async_listen(
entity_registry.EVENT_ENTITY_REGISTRY_UPDATED,
self._async_handle_entity_registry_changed,
run_immediately=True,
)
self.hass.bus.async_listen(
core.EVENT_STATE_CHANGED,
self._async_handle_state_changed,
run_immediately=True,
)
async def async_process(self, user_input: ConversationInput) -> ConversationResult:
"""Process a sentence."""
language = user_input.language or self.hass.config.language
@@ -109,7 +127,12 @@ class DefaultAgent(AbstractConversationAgent):
"name": self._make_names_list(),
}
result = recognize(user_input.text, lang_intents.intents, slot_lists=slot_lists)
result = await self.hass.async_add_executor_job(
self._recognize,
user_input,
lang_intents,
slot_lists,
)
if result is None:
_LOGGER.debug("No intent was matched for '%s'", user_input.text)
return _make_error_result(
@@ -160,21 +183,43 @@ class DefaultAgent(AbstractConversationAgent):
).get(response_key)
if response_str:
response_template = template.Template(response_str, self.hass)
intent_response.async_set_speech(
response_template.async_render(
{
"slots": {
entity_name: entity_value.text or entity_value.value
for entity_name, entity_value in result.entities.items()
}
speech = response_template.async_render(
{
"slots": {
entity_name: entity_value.text or entity_value.value
for entity_name, entity_value in result.entities.items()
}
)
}
)
# Normalize whitespace
speech = " ".join(speech.strip().split())
intent_response.async_set_speech(speech)
return ConversationResult(
response=intent_response, conversation_id=conversation_id
)
def _recognize(
self,
user_input: ConversationInput,
lang_intents: LanguageIntents,
slot_lists: dict[str, SlotList],
) -> RecognizeResult | None:
"""Search intents for a match to user input."""
# Prioritize matches with entity names above area names
maybe_result: RecognizeResult | None = None
for result in recognize_all(
user_input.text, lang_intents.intents, slot_lists=slot_lists
):
if "name" in result.entities:
return result
# Keep looking in case an entity has the same name
maybe_result = result
return maybe_result
async def async_reload(self, language: str | None = None):
"""Clear cached intents for a language."""
if language is None:
@@ -196,13 +241,15 @@ class DefaultAgent(AbstractConversationAgent):
async def async_get_or_load_intents(self, language: str) -> LanguageIntents | None:
"""Load all intents of a language with lock."""
hass_components = set(self.hass.config.components)
async with self._lang_lock[language]:
return await self.hass.async_add_executor_job(
self._get_or_load_intents,
language,
self._get_or_load_intents, language, hass_components
)
def _get_or_load_intents(self, language: str) -> LanguageIntents | None:
def _get_or_load_intents(
self, language: str, hass_components: set[str]
) -> LanguageIntents | None:
"""Load all intents for language (run inside executor)."""
lang_intents = self._lang_intents.get(language)
@@ -215,7 +262,7 @@ class DefaultAgent(AbstractConversationAgent):
# Check if any new components have been loaded
intents_changed = False
for component in self.hass.config.components:
for component in hass_components:
if component in loaded_components:
continue
@@ -310,8 +357,29 @@ class DefaultAgent(AbstractConversationAgent):
return lang_intents
@core.callback
def _async_handle_area_registry_changed(self, event: core.Event) -> None:
"""Clear area area cache when the area registry has changed."""
self._areas_list = None
@core.callback
def _async_handle_entity_registry_changed(self, event: core.Event) -> None:
"""Clear names list cache when an entity changes aliases."""
if event.data["action"] == "update" and "aliases" not in event.data["changes"]:
return
self._names_list = None
@core.callback
def _async_handle_state_changed(self, event: core.Event) -> None:
"""Clear names list cache when a state is added or removed from the state machine."""
if event.data.get("old_state") and event.data.get("new_state"):
return
self._names_list = None
def _make_areas_list(self) -> TextSlotList:
"""Create slot list mapping area names/aliases to area ids."""
if self._areas_list is not None:
return self._areas_list
registry = area_registry.async_get(self.hass)
areas = []
for entry in registry.async_list_areas():
@@ -320,31 +388,34 @@ class DefaultAgent(AbstractConversationAgent):
for alias in entry.aliases:
areas.append((alias, entry.id))
return TextSlotList.from_tuples(areas)
self._areas_list = TextSlotList.from_tuples(areas, allow_template=False)
return self._areas_list
def _make_names_list(self) -> TextSlotList:
"""Create slot list mapping entity names/aliases to entity ids."""
if self._names_list is not None:
return self._names_list
states = self.hass.states.async_all()
registry = entity_registry.async_get(self.hass)
entities = entity_registry.async_get(self.hass)
names = []
for state in states:
domain = state.entity_id.split(".", maxsplit=1)[0]
context = {"domain": domain}
context = {"domain": state.domain}
entry = registry.async_get(state.entity_id)
if entry is not None:
if entry.entity_category:
entity = entities.async_get(state.entity_id)
if entity is not None:
if entity.entity_category:
# Skip configuration/diagnostic entities
continue
if entry.aliases:
for alias in entry.aliases:
if entity.aliases:
for alias in entity.aliases:
names.append((alias, state.entity_id, context))
# Default name
names.append((state.name, state.entity_id, context))
return TextSlotList.from_tuples(names)
self._names_list = TextSlotList.from_tuples(names, allow_template=False)
return self._names_list
def _get_error_text(
self, response_type: ResponseType, lang_intents: LanguageIntents

View File

@@ -2,9 +2,9 @@
"domain": "conversation",
"name": "Conversation",
"documentation": "https://www.home-assistant.io/integrations/conversation",
"requirements": ["hassil==0.2.5", "home-assistant-intents==2023.1.25"],
"requirements": ["hassil==0.2.6", "home-assistant-intents==2023.1.25"],
"dependencies": ["http"],
"codeowners": ["@home-assistant/core"],
"codeowners": ["@home-assistant/core", "@synesthesiam"],
"quality_scale": "internal",
"iot_class": "local_push",
"integration_type": "system"

View File

@@ -2,7 +2,7 @@
"config": {
"error": {
"cannot_connect": "\u00c9chec de connexion",
"no_units": "Impossible de trouver des unit\u00e9s HVAC dans l'h\u00f4te CoolMasterNet."
"no_units": "Aucune unit\u00e9 CVC n\u2019a \u00e9t\u00e9 trouv\u00e9e dans l\u2019h\u00f4te CoolMasterNet."
},
"step": {
"user": {

View File

@@ -2,7 +2,7 @@
"config": {
"abort": {
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e",
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
},
"error": {
"api_password": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435, \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0439\u0442\u0435 API \u043a\u043b\u044e\u0447 \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0430.",

View File

@@ -88,7 +88,7 @@ class DeconzFlowHandler(ConfigFlow, domain=DOMAIN):
"""
if user_input is not None:
if CONF_MANUAL_INPUT == user_input[CONF_HOST]:
if user_input[CONF_HOST] == CONF_MANUAL_INPUT:
return await self.async_step_manual_input()
for bridge in self.bridges:

View File

@@ -17,6 +17,10 @@ from .device_trigger import (
CONF_BUTTON_2,
CONF_BUTTON_3,
CONF_BUTTON_4,
CONF_BUTTON_5,
CONF_BUTTON_6,
CONF_BUTTON_7,
CONF_BUTTON_8,
CONF_CLOSE,
CONF_DIM_DOWN,
CONF_DIM_UP,
@@ -95,6 +99,10 @@ INTERFACES = {
CONF_BUTTON_2: "Button 2",
CONF_BUTTON_3: "Button 3",
CONF_BUTTON_4: "Button 4",
CONF_BUTTON_5: "Button 5",
CONF_BUTTON_6: "Button 6",
CONF_BUTTON_7: "Button 7",
CONF_BUTTON_8: "Button 8",
CONF_SIDE_1: "Side 1",
CONF_SIDE_2: "Side 2",
CONF_SIDE_3: "Side 3",

View File

@@ -10,7 +10,7 @@
"linking_not_possible": "\u041d\u0435 \u043c\u043e\u0436\u0430 \u0434\u0430 \u0441\u0435 \u0441\u0432\u044a\u0440\u0436\u0435 \u0441 \u0448\u043b\u044e\u0437\u0430",
"no_key": "\u041d\u0435 \u043c\u043e\u0436\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0438 API \u043a\u043b\u044e\u0447"
},
"flow_title": "deCONZ Zigbee \u0448\u043b\u044e\u0437 ({host})",
"flow_title": "{host}",
"step": {
"hassio_confirm": {
"description": "\u0418\u0441\u043a\u0430\u0442\u0435 \u043b\u0438 \u0434\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0442\u0435 Home Assistant \u0434\u0430 \u0441\u0435 \u0441\u0432\u044a\u0440\u0437\u0432\u0430 \u0441 deCONZ \u0431\u0430\u0437\u043e\u0432\u0430 \u0441\u0442\u0430\u043d\u0446\u0438\u044f, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u043e\u0442 \u0434\u043e\u0431\u0430\u0432\u043a\u0430\u0442\u0430 \u0437\u0430 Supervisor {addon}?",

View File

@@ -65,8 +65,8 @@
"trigger_type": {
"remote_awakened": "A k\u00e9sz\u00fcl\u00e9k fel\u00e9bredt",
"remote_button_double_press": "\"{subtype}\" gombra k\u00e9tszer kattintottak",
"remote_button_long_press": "A \"{subtype}\" gomb folyamatosan lenyomva",
"remote_button_long_release": "A \"{subtype}\" gomb hossz\u00fa megnyom\u00e1s ut\u00e1n elengedve",
"remote_button_long_press": "\"{subtype}\" gomb folyamatosan lenyomva",
"remote_button_long_release": "\"{subtype}\" gomb hossz\u00fa megnyom\u00e1s ut\u00e1n elengedve",
"remote_button_quadruple_press": "\"{subtype}\" gombra n\u00e9gyszer kattintottak",
"remote_button_quintuple_press": "\"{subtype}\" gombra \u00f6tsz\u00f6r kattintottak",
"remote_button_rotated": "A gomb elforgatva: \"{subtype}\"",

View File

@@ -99,6 +99,6 @@ class DelugeFlowHandler(ConfigFlow, domain=DOMAIN):
return "cannot_connect"
except Exception as ex: # pylint:disable=broad-except
if type(ex).__name__ == "BadLoginError":
return "invalid_auth" # pragma: no cover
return "invalid_auth"
return "unknown"
return None

View File

@@ -1,5 +1,28 @@
{
"entity": {
"climate": {
"ubercool": {
"state_attributes": {
"fan_mode": {
"state": {
"auto_high": "Auto \u00e9lev\u00e9e",
"auto_low": "Auto faible",
"on_high": "Sur \u00e9lev\u00e9e",
"on_low": "Sur faible"
}
},
"swing_mode": {
"state": {
"1": "1",
"2": "2",
"3": "3",
"auto": "Auto",
"off": "D\u00e9sactiv\u00e9e"
}
}
}
}
},
"sensor": {
"thermostat_mode": {
"state": {

View File

@@ -39,5 +39,14 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"h": "\u038f\u03c1\u03b5\u03c2",
"min": "\u039b\u03b5\u03c0\u03c4\u03ac",
"s": "\u0394\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1"
}
}
},
"title": "\u0391\u03b9\u03c3\u03b8\u03b7\u03c4\u03ae\u03c1\u03b1\u03c2 \u03c0\u03b1\u03c1\u03b1\u03b3\u03ce\u03b3\u03c9\u03bd"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "D\u00edas",
"h": "Horas",
"min": "Minutos",
"s": "Segundos"
}
}
},
"title": "Sensor de derivaci\u00f3n"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "Nap",
"h": "\u00d3ra",
"min": "Perc",
"s": "M\u00e1sodperc"
}
}
},
"title": "Sz\u00e1rmaz\u00e9kos \u00e9rz\u00e9kel\u0151"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "Hari",
"h": "Jam",
"min": "Menit",
"s": "Detik"
}
}
},
"title": "Sensor Turunan"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "Dagen",
"h": "Uren",
"min": "Minuten",
"s": "Seconden"
}
}
},
"title": "Afgeleide"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "Dager",
"h": "Timer",
"min": "Minutter",
"s": "Sekunder"
}
}
},
"title": "Avledet sensor"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "Dias",
"h": "Horas",
"min": "Minutos",
"s": "Segundos"
}
}
},
"title": "Sensor derivativo"
}

View File

@@ -39,5 +39,15 @@
}
}
},
"selector": {
"time_unit": {
"options": {
"d": "Dni",
"h": "Hodiny",
"min": "Min\u00faty",
"s": "Sekundy"
}
}
},
"title": "Deriva\u010dn\u00fd sn\u00edma\u010d"
}

View File

@@ -23,7 +23,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
entry.data[CONF_USERNAME],
entry.data[CONF_USE_LEGACY_PROTOCOL],
)
if not smartplug.authenticated and entry.data[CONF_USE_LEGACY_PROTOCOL]:
if not smartplug.authenticated and smartplug.use_legacy_protocol:
raise ConfigEntryNotReady("Cannot connect/authenticate")
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = SmartPlugData(smartplug)

View File

@@ -131,6 +131,6 @@ class DLinkFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
except Exception as ex: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception: %s", ex)
return "unknown"
if smartplug.authenticated:
return None
return "cannot_connect"
if not smartplug.authenticated and smartplug.use_legacy_protocol:
return "cannot_connect"
return None

View File

@@ -19,9 +19,9 @@ class SmartPlugData:
"""Initialize the data object."""
self.smartplug = smartplug
self.state: str | None = None
self.temperature: str | None = None
self.current_consumption = None
self.total_consumption: str | None = None
self.temperature: str = ""
self.current_consumption: str = ""
self.total_consumption: str = ""
self.available = False
self._n_tried = 0
self._last_tried: datetime | None = None

View File

@@ -94,17 +94,22 @@ class SmartPlugSwitch(DLinkEntity, SwitchEntity):
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes of the device."""
attrs: dict[str, Any] = {}
if self.data.temperature and self.data.temperature.isnumeric():
attrs[ATTR_TEMPERATURE] = self.hass.config.units.temperature(
try:
temperature = self.hass.config.units.temperature(
int(self.data.temperature), UnitOfTemperature.CELSIUS
)
else:
attrs[ATTR_TEMPERATURE] = None
if self.data.total_consumption and self.data.total_consumption.isnumeric():
attrs[ATTR_TOTAL_CONSUMPTION] = float(self.data.total_consumption)
else:
attrs[ATTR_TOTAL_CONSUMPTION] = None
except ValueError:
temperature = None
try:
total_consumption = float(self.data.total_consumption)
except ValueError:
total_consumption = None
attrs = {
ATTR_TOTAL_CONSUMPTION: total_consumption,
ATTR_TEMPERATURE: temperature,
}
return attrs

View File

@@ -12,7 +12,7 @@
"data": {
"password": "Senha (padr\u00e3o: c\u00f3digo PIN no verso)",
"use_legacy_protocol": "Usar protocolo legado",
"username": "Nome de usu\u00e1rio"
"username": "Usu\u00e1rio"
}
},
"user": {

View File

@@ -3,7 +3,7 @@
"name": "DLNA Digital Media Renderer",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
"requirements": ["async-upnp-client==0.33.0", "getmac==0.8.2"],
"requirements": ["async-upnp-client==0.33.1", "getmac==0.8.2"],
"dependencies": ["ssdp"],
"after_dependencies": ["media_source"],
"ssdp": [

View File

@@ -3,7 +3,7 @@
"name": "DLNA Digital Media Server",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/dlna_dms",
"requirements": ["async-upnp-client==0.33.0"],
"requirements": ["async-upnp-client==0.33.1"],
"dependencies": ["ssdp"],
"after_dependencies": ["media_source"],
"ssdp": [

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "El servicio ya est\u00e1 configurado"
},
"error": {
"invalid_resolver": "Direcci\u00f3n IP no v\u00e1lida para resolver"
},

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "A szolg\u00e1ltat\u00e1s m\u00e1r konfigur\u00e1lva van"
},
"error": {
"invalid_resolver": "\u00c9rv\u00e9nytelen IP-c\u00edm a felold\u00f3hoz"
},

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "Layanan sudah dikonfigurasi"
},
"error": {
"invalid_resolver": "Alamat IP tidak valid untuk resolver"
},

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "Dienst is al ingesteld"
},
"error": {
"invalid_resolver": "Ongeldig IP-adres voor resolver"
},

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "Us\u0142uga jest ju\u017c skonfigurowana"
},
"error": {
"invalid_resolver": "Nieprawid\u0142owy adres IP dla resolvera"
},

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "O servi\u00e7o j\u00e1 est\u00e1 configurado"
},
"error": {
"invalid_resolver": "Endere\u00e7o IP inv\u00e1lido para resolver"
},

View File

@@ -14,6 +14,9 @@
}
},
"options": {
"abort": {
"already_configured": "Slu\u017eba u\u017e je nakonfigurovan\u00e1"
},
"error": {
"invalid_resolver": "Neplatn\u00e1 adresa IP pre resolver"
},

View File

@@ -2,7 +2,7 @@
"config": {
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435",
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"flow_title": "{name} ({host})",

View File

@@ -1,14 +1,22 @@
"""Support for SMS notifications from the Dovado router."""
from __future__ import annotations
import logging
from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN as DOVADO_DOMAIN
_LOGGER = logging.getLogger(__name__)
def get_service(hass, config, discovery_info=None):
def get_service(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> DovadoSMSNotificationService:
"""Get the Dovado Router SMS notification service."""
return DovadoSMSNotificationService(hass.data[DOVADO_DOMAIN].client)

View File

@@ -209,7 +209,6 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
DSMRReaderSensorEntityDescription(
key="dsmr/consumption/gas/currently_delivered",
name="Current gas usage",
device_class=SensorDeviceClass.GAS,
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
state_class=SensorStateClass.MEASUREMENT,
),

View File

@@ -69,7 +69,10 @@ class DSMRSensor(SensorEntity):
@callback
def message_received(message):
"""Handle new MQTT messages."""
if self.entity_description.state is not None:
if message.payload == "":
self._attr_native_value = None
elif self.entity_description.state is not None:
# Perform optional additional parsing
self._attr_native_value = self.entity_description.state(message.payload)
else:
self._attr_native_value = message.payload

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