Compare commits

..

282 Commits

Author SHA1 Message Date
Paulus Schoutsen
349e7b8cd1 Bumped version to 0.102.0b0 2019-11-13 13:55:02 +01:00
Paulus Schoutsen
8f390d099a Merge remote-tracking branch 'origin/master' into dev 2019-11-13 13:54:31 +01:00
Thomas
fe942c40a0 Correct openalpr_local config option name (#28746)
Previously was "alp_bin" now "alpr_bin" like it is outlined in the documentation (https://www.home-assistant.io/integrations/openalpr_local/)
2019-11-13 12:11:09 +01:00
Ville Skyttä
a48d426f18 Travis and tox config improvements (#28667)
* Use travis_wait only with pylint

pylint is the only job that is expected to be silent for extended time.
For others such a silence is a sign of a problem and using travis_wait
just lengthens the wait, and makes things harder to follow and debug,
because it also suppresses output in the web UI.

* Use pytest-xdist in tox

Similarly as in Azure.
2019-11-13 08:50:35 +01:00
Fabian Affolter
b4cec23add Upgrade psutil to 5.6.5 (#28717) 2019-11-13 08:43:14 +01:00
Dave T
4bcc669d19 Add device classes to weather sensors. (#28512) 2019-11-13 08:42:46 +01:00
Steven Looman
d7f45a47f5 Upgrade async_upnp_client==0.14.12 (#28733) 2019-11-13 07:43:38 +01:00
Fredrik Erlandsson
70e8c58254 version bump pypoint (#28737) 2019-11-13 07:42:12 +01:00
HomeAssistant Azure
d2d9f09f13 [ci skip] Translation update 2019-11-13 00:32:12 +00:00
Paulus Schoutsen
5961215e6e Set up Almond Web to connect to HA (#28603)
* Set up Almond Web to connect to HA

* Add missing string

* Add type
2019-11-12 11:01:19 -08:00
Otto Winter
a1f2b6d402 ESPHome fix missing state in certain circumstances (#28729)
* Fix ESPHome having missing state in certain situations

Fixes https://github.com/esphome/issues/issues/828

* Update requirements_all

* Also fix climate preset mode
2019-11-12 09:26:46 -08:00
Paulus Schoutsen
fc04b3e31c Remove choice word when Almond has choices (#28725) 2019-11-12 09:22:28 -08:00
jjlawren
5f177fa42e Use library method for season number (#28708) 2019-11-12 10:05:30 -06:00
Kevin Eifinger
48fd95c7db Fix Here Travel Time unable to find entity on startup (#27237)
* add support for entity_id as state of entity

* add circular reference detection

* voluptuous instead of regex

* wait for EVENT_HOMEASSISTANT_START

* move delayed_sensor_update to async_added_to_hass

* add @callback decorator

* remove nested entity resolving
2019-11-12 15:04:17 +01:00
Fabian Affolter
1208ab4c76 Upgrade discogs_client to 2.2.2 (#28723) 2019-11-12 12:28:34 +01:00
SukramJ
e8348221d4 Allow preset boost for Homematic IP Cloud power switches (#28713)
* Allow preset boost for Homematic IP Cloud  power switches

* Sort Imports

* Add test

* align test data
2019-11-12 11:32:32 +01:00
Federico Leoni
4f11eec1a1 Update binary_sensor.py (#28707)
* Update binary_sensor.py

* Fix style issues
2019-11-12 09:53:08 +01:00
jjlawren
87606bc12b Bump plexapi to 3.3.0 (#28709)
* Bump plexapi to 3.2.0

* Bump to 3.3.0
2019-11-11 19:30:07 -08:00
Aaron Bach
a89b4011ee Ensure SimpliSafe alarm control panels can return from being offline (#28710) 2019-11-11 18:55:31 -07:00
Alexei Chetroi
cfa689c3a6 Bump up ZHA dependencies. (#28711) 2019-11-11 20:53:23 -05:00
HomeAssistant Azure
25b0631264 [ci skip] Translation update 2019-11-12 00:32:11 +00:00
GaryOkie
a9a1c2b91d Update Homekit climate.py to remap current mode (#28625)
* Update Homekit climate.py to remap current mode

This update changes the mapping of Homekit's Current Mode Heating/Cooling State  to show the HASS Hvac_action attribute as "idle" instead of "off" when the returned value is 0.

* Update climate.py

removed imported constant no longer being used  (CURRENT_HVAC_OFF)

* corrected update to climate.py

trying again to remove unused constant.

* Update test_climate.py

* removed "change" comment

The added comment describing the change was not needed and should not be included, as it will already be described via "git annotate"  (per @jc2k)
2019-11-12 00:35:09 +01:00
Quentame
decab3e15b Add config flow tests for OwnTracks (#28644)
* Add config flow tests for OwnTracks

* Fix pylint

* Woops, uncomment test

* Woops again, logs removed

* Review from @MartinHjelmare + fix pylint
2019-11-11 21:30:00 +01:00
jjlawren
cfcacc2827 Bump plexwebsocket to 0.0.5 (#28703) 2019-11-11 19:26:56 +01:00
Bas Nijholt
3ce850234f fix typo in comments (#28694)
The global is called `PARALLEL_UPDATES` not `PARALLEL_UPDATE`.
2019-11-11 13:51:26 +01:00
Bram Kragten
90e723e25e Allow icons to be masked (#28692) 2019-11-11 02:53:57 -08:00
Kevin Lee
7bfde2dd33 Add Lutron hybrid keypad raise/lower buttons (#28674)
* Lutron: Add support for hybrid keypad raise/lower buttons

* Add MasterRaiseLower
2019-11-11 08:07:48 +01:00
Teemu R
b6c7976477 Add xiaomi_miio chuangmi.plug.hmi206 (#28688)
Related: https://github.com/rytilahti/python-miio/issues/574
2019-11-11 07:59:07 +01:00
Jon Gilmore
aea7c1c0ce Add codeowner for lutron integration (#28682)
* add codeowner for lutron integration

* ran hassfest
2019-11-11 01:51:24 +01:00
HomeAssistant Azure
0ac8b297cd [ci skip] Translation update 2019-11-11 00:32:13 +00:00
Rohan Kapoor
65dd7d998b #28645: Bump up zm-py to 0.4.0 (#28681) 2019-11-10 13:51:00 -08:00
Bram Kragten
66a574eca4 Hue: store current sensor entities by bridge (#28679) 2019-11-10 11:37:34 -08:00
jjlawren
206547a5d8 Skip updating idle Plex clients (#28664)
* Skip updating idle clients

* Different operators
2019-11-10 11:35:12 +01:00
Per Sandström
a9536e4ed1 verisure autolock service (#27366) 2019-11-10 08:25:10 +01:00
HomeAssistant Azure
65bf0a30f0 [ci skip] Translation update 2019-11-10 00:32:12 +00:00
jjlawren
ef687a36ff Add Plex debug logging (#28665) 2019-11-09 17:02:56 -06:00
Gerard
25f0b70966 Upgrade bimmer_connected to 0.6.2 (#28651)
* Upgrade bimmer_connected to 0.6.1

* Remove time.sleep from library
2019-11-09 23:43:04 +01:00
Aaron Bach
179a2eb187 Create base entity for SimpliSafe 2019-11-09 23:41:02 +01:00
Franck Nijhof
a39cac765e Add sensor platform to WLED integration (#28632)
* Add sensor platform to WLED integration

* Process review comments
2019-11-09 20:18:41 +01:00
Martin Hjelmare
fc95a3d088 Fix xiaomi vacuum tests (#28658)
* Fix xiaomi exceptions test

* Fix xiaomi_specific_services test

* Fix remaining xiaomi miio vacuum tests

* Clean up
2019-11-09 14:07:01 +01:00
bluestripe
0954f7d3be Add bluesound speaker group attribute (#28142)
* Added bluesound speaker group attribute.

* Changed code to fix failing tests.

* Changed condition checking for empty group list.

* Investigating CI pipeline error

* Changed back to the code that passed CI earlier

* Changed condition on existence of list and sorting of bluesound_group

* Re-introduced guard on group_name None
2019-11-09 08:16:53 +01:00
Shulyaka
58eeea903f Add pcal9535a integration (#26563)
* Support for PCAL9535A chip

Signed-off-by: Denis Shulyaka <Shulyaka@gmail.com>

* Code review changes

* Code review changes

* Fix import order

* Fix import order

* Apply suggestions from code review
2019-11-09 08:14:46 +01:00
shred86
97224df4fd Fix Abode capture_image and trigger_quick_action services (#28546)
* Fix Abode services

* Bump abodepy version

* Updated using dispatcher helper

* Code review fixes

* Removed init method from AbodeQuickActionBinary Sensor
2019-11-09 07:35:45 +01:00
HomeAssistant Azure
45b53c8e82 [ci skip] Translation update 2019-11-09 00:32:20 +00:00
LeoCal
bc53e9d0c8 Fix unhandled exception when Swisscom Internet Box is not responsive (#28618)
* Update device_tracker.py

From time to time, Swisscom Internet Box fails to respond and this causes an exception, which is currently not handled by the code:

Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.7/site-packages/homeassistant/components/device_tracker/setup.py", line 164, in async_device_tracker_scan
    found_devices = await scanner.async_scan_devices()
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/srv/homeassistant/lib/python3.7/site-packages/homeassistant/components/swisscom/device_tracker.py", line 46, in scan_devices
    self._update_info()
  File "/srv/homeassistant/lib/python3.7/site-packages/homeassistant/components/swisscom/device_tracker.py", line 67, in _update_info
    data = self.get_swisscom_data()
  File "/srv/homeassistant/lib/python3.7/site-packages/homeassistant/components/swisscom/device_tracker.py", line 83, in get_swisscom_data
    request = requests.post(url, headers=headers, data=data, timeout=10)
  File "/srv/homeassistant/lib/python3.7/site-packages/requests/api.py", line 116, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/srv/homeassistant/lib/python3.7/site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/srv/homeassistant/lib/python3.7/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/srv/homeassistant/lib/python3.7/site-packages/requests/sessions.py", line 686, in send
    r.content
  File "/srv/homeassistant/lib/python3.7/site-packages/requests/models.py", line 828, in content
    self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b''
  File "/srv/homeassistant/lib/python3.7/site-packages/requests/models.py", line 757, in generate
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='192.168.1.1', port=80): Read timed out.

I've just added a try-except around the post.

* Update device_tracker.py

Addressed blank line issue reported by flake8

* Update device_tracker.py

Fixed alignment to be Black compliant.

* Update device_tracker.py

Fixed one more alignment issue
2019-11-08 11:01:35 -08:00
Ari
504ad6488c Add support for Heat Mode detection for ecobee Heat Pumps (#28273)
* Add support for Heat Mode detection for Heat Pumps - Fixes #26547

Since the ecobee component started to dynamically set the supported HVAC modes based on querying the device a few releases ago, users with Heat Pumps noticed that the Heat mode was no longer offered as an option by HA. Some of us did not actually notice until the summer was over :). This commit fixes that.

For heatpumps, ecobee returns:
'coolStages': 1, 
'heatStages': 0,
'hasHeatPump': True,

Fix tested on HA 100.1 and 100.3

Fixes bug https://github.com/home-assistant/home-assistant/issues/26547

* changed line formatted with black
2019-11-08 19:08:50 +01:00
fredericvl
caedc14b00 Added support for multiple SAJ solar inverters (#28612)
Changes after review
2019-11-08 10:48:28 -07:00
Tomasz
f8d3ea20b6 Move imports in xiaomi_miio (#27773)
* move imports in xiaomi_miio

* reorder imports with isort

* fix pylint error

* Rename imports
2019-11-08 18:32:44 +01:00
David F. Mulcahey
f2c56cff43 Bump ZHA quirks version (#28636) 2019-11-08 09:12:50 -08:00
Bram Kragten
d0f1e9fc01 Updated frontend to 20191108.0 (#28638) 2019-11-08 09:12:20 -08:00
Bram Kragten
28c6837f00 Add attribution and onboarding commands to conversation and Almond (#28621)
* Add attribution and onboarding commands to conversation and Almond

* False -> None

* Comments

* Update __init__.py

* Comments + websocket for convert

* Lint
2019-11-08 09:06:23 -08:00
cgtobi
4435b3a5c9 Fix issue with multiple Netatmo home coach devices (#28407)
* Retrieve more detailed module infos

* Switch to using IDs

* Bump pyatmo version to 2.3.3

* Update requirements

* Undo the change of the unique id

* Rename variable
2019-11-08 17:12:41 +01:00
Fredrik Erlandsson
cffadf919a Add turn_on/off to tfiac (#27712)
* Add turn_on/off to tfiac

* fix ws issue
2019-11-08 17:02:44 +01:00
Paulus Schoutsen
bd54ff3c02 Add TT WS API (#28599)
* Add TT WS API

* Add a test

* Correctly convert TT errrors
2019-11-08 10:06:16 +01:00
Franck Nijhof
b2071b81c1 Add switch platform to WLED integration (#28606)
* Add switch platform to WLED integration

* Use async_schedule_update_ha_state in async context

* Process review comments
2019-11-08 09:48:46 +01:00
akasma74
e96b5ef2b0 Fix generic_thermostat too_hot/too_cold (#27860)
* fix for too_hot/too_cold

Closes #27802

* too_hot correction
2019-11-08 09:25:37 +01:00
Ville Skyttä
4f56f4e7e9 Add Huawei LTE device registry support (#28594) 2019-11-08 09:19:59 +01:00
HomeAssistant Azure
64166583b3 [ci skip] Translation update 2019-11-08 00:32:12 +00:00
Jeff Irion
a71d852f16 Use friendly app names for Fire TV sources (#28417)
* Use friendly app names for Fire TV sources

* Remove debugging statement

* Tests pass

* Use 'blocking=True' to patch service calls

* Remove parentheses
2019-11-07 15:04:59 -07:00
Brett T. Warden
1012215709 Match ALARM in NUT UPS status message (#28591)
If ups.status contains "ALARM", add "Alarm" to virtual sensor ups.status.display.

Fixes #28580
2019-11-07 15:03:32 -07:00
jjlawren
2bdfa9928b Allow to skip SSL validation on Plex websocket (#28615) 2019-11-07 21:54:48 +01:00
Paulus Schoutsen
fadb6a3979 Add support for conversation ID (#28620) 2019-11-07 12:21:12 -08:00
Paulus Schoutsen
9b5fa2e67c Add device conditions to climate (#28553)
* Add device conditions to climate

* Update strings.json
2019-11-07 17:03:06 +01:00
SukramJ
9d3d35ad79 Add cool mode to HomematicIP climate (#28525)
* Add cool mode to HomematicIP climate

* Update test

* remove preset_party

* Fix profile_names check
2019-11-07 16:41:33 +01:00
Paulus Schoutsen
899306c8ec Add vacuum device conditions (#28551) 2019-11-07 16:29:39 +01:00
Paulus Schoutsen
a80baf2e5f Add fan device condition (#28549) 2019-11-07 16:29:10 +01:00
Paulus Schoutsen
48660585f1 Add climate device triggers (#28544)
* Add climate device triggers

* Test capabilities
2019-11-07 16:28:45 +01:00
Heine Furubotten
af73e54aee Add azure servicebus notify service (#27566)
* Add azure servicebus notify service

* files added to .coveragerc

* fix: import content type from const

* Moved imports to top level

* Code review fixes
+ added code owner
+ fixed config validation with has at least one
+ seperate attributes for dto to asb
* fixed doc link
* async setup instead of sync

* rename all the things
- removed too many ifs
* changed setup back to sync
+ comment about sync IO in lib

* More informative logging

* logging exception -> error
2019-11-07 14:47:44 +01:00
Pascal Vizeli
abb78a0d13 Fix fan strings 2019-11-07 13:48:23 +01:00
Pascal Vizeli
50f1b6c689 Fix vacuum strings 2019-11-07 13:47:26 +01:00
Paulus Schoutsen
d34caf50f1 Add climate device actions (#28552) 2019-11-07 13:44:59 +01:00
Bram Kragten
76aae0c23e Fix demo TTS (#28608) 2019-11-07 13:43:43 +01:00
Paulus Schoutsen
6999a712ef Add device triggers to vacuum (#28548)
* Add device triggers to vacuum

* Update strings
2019-11-07 13:39:35 +01:00
Tim Gates
c3f07347a1 Fix simple typo: unhasable -> unhashable (#28605) 2019-11-07 12:39:16 +01:00
Paulus Schoutsen
5032c5a04c Add fan device trigger (#28545) 2019-11-07 12:38:58 +01:00
Paulus Schoutsen
78657bfbaf Add lock device triggers (#28547)
* Add lock device triggers

* Lint
2019-11-07 12:26:59 +01:00
Paulus Schoutsen
2c607c836f Add device action to fan (#28550) 2019-11-07 12:26:10 +01:00
Paulus Schoutsen
11cdce3758 Add device actions to vacuum (#28554) 2019-11-07 12:24:58 +01:00
Jonathan Keljo
68fd39e321 Upgrade greeneye_monitor to 1.0.1 (#28600)
This release has a fix for a crash we were seeing occasionally, and a totally
revamped packet handler which should be more robust and CPU-efficient.

Fixes #25887
2019-11-07 10:42:42 +01:00
Malte Franken
b5587348f5 update to latest integration library version (#28597) 2019-11-06 21:37:29 -08:00
HomeAssistant Azure
265c390b65 [ci skip] Translation update 2019-11-07 00:32:16 +00:00
Franck Nijhof
78b83c653a Add WLED integration (#28542)
* Add WLED integration

* Use f-string for uniq id in sensor platform

* Typing improvements

* Removes sensor & light platform

* Remove PARALLEL_UPDATES from integration level

* Correct type in code comment 'themselves'

* Use async_track_time_interval in async context

* Remove stale code

* Remove decorator from Flow handler

* Remove unused __init__ from config flow

* Move show form methods to sync

* Only wrap lines that can raise in try except block

* Remove domain and platform from uniq id

* Wrap light state in bool object in is_on method

* Use async_schedule_update_ha_state in async context

* Return empty dict in device state attributes instead of None

* Remove unneeded setdefault call in setup entry

* Cancel update timer on entry unload

* Restructure config flow code

* Adjust tests for new uniq id

* Correct typo AdGuard Home -> WLED in config flow file comment

* Convert internal package imports to be relative

* Reformat JSON files with Prettier

* Improve tests based on review comments

* Add test for zeroconf when no data is provided

* Cleanup and extended tests
2019-11-06 23:55:39 +01:00
Hans Oischinger
3d2ff841d3 Handle exceptions from PyViCare library (#28536)
* ViCare: Handle exceptions from PyViCare library (#28072)

Sometimes Viessmann server failures or other connection problems may
lead to exceptions thrown when updating data.

This commit handles those exceptions with some error logging and
makes sure that the component does not break completely in that case.

* Remove unneeded returns

* Remove unneeded returns
2019-11-06 22:46:18 +01:00
Ville Skyttä
bb37bc32e3 Always run flake8 through pre-commit, and with doctests (#28490)
* Enable flake8 doctests everywhere

* Always run flake8 through pre-commit
2019-11-06 21:38:00 +02:00
Paulus Schoutsen
d9edd42532 Update to latest Somfy changes (#28207)
* Update to latest Somfy changes

* Update api.py

* Update api.py
2019-11-06 10:55:56 -08:00
Paulus Schoutsen
9a0a889492 Fix token sent to Almond Web (#28584) 2019-11-06 08:32:33 -08:00
ssenart
9ba3abd1b7 Add Netatmo camera services (#27970)
* Netatmo camera : Implement turn_on and turn_off methods.

* Netatmo camera : Implement turn_on and turn_off methods.

* Netatmo camera : Implement turn_on and turn_off methods.

* Netatmo camera : Implement turn_on and turn_off methods.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Netatmo camera : Implement enable_motion_detection(), disable_motion_detection() operations.

* Add Presence Netatmo Camera services (set_light_auto, set_light_on, set_light_off) to control its internal flood light status.

* Add Presence Netatmo Camera services (set_light_auto, set_light_on, set_light_off) to control its internal flood light status.

* Netatmo camera : Use new style string formatting.

* Make the file compliant with flake8 linter.

* Make the file compliant with flake8 linter.

* Make it compliant with black formatter.

* Make it compliant with black formatter.

* Bug fix : Flood light control was not working with VPN url.
2019-11-06 07:52:59 -05:00
Kevin Köck
b7153ca207 Add mqtt temp_low/high_template in SCHEMA_BASE (#28257)
* fix missing temp_low/high_template in SCHEMA_BASE

* temperature_high/low_state_template test

* Update test_climate.py

* paste error

* Update test_climate.py

* Update test_climate.py

* Update test_climate.py

* Update test_climate.py
2019-11-06 07:50:54 -05:00
temeteke
2e1d05560f Reset states when connection to MPC-HC is lost (#27541)
* Reset states when connection to MPC-HC is lost

* Add the available property of mpchc
2019-11-06 07:47:34 -05:00
Josef Schlehofer
ac4d8ee07f Upgrade youtube_dl to 2019.11.05 (#28578) 2019-11-06 09:51:20 +01:00
Zach
e99bb8f75e Fix Doods error when detection labels are specified in list form (#28574) 2019-11-06 08:45:16 +01:00
Jeff Irion
438ee99175 Bump adb-shell to 0.0.8 (#28582)
* Bump 'adb-shell' to 0.0.8

* Update requirements_test_all.txt

* Update manifest.json
2019-11-06 08:02:07 +01:00
Grodesh
f8712b4d7f Update nextbus stop tag to accept strings (#27765) 2019-11-06 07:24:11 +01:00
Paulus Schoutsen
a63e976496 Fix invalid JSON in deconz strings.json 2019-11-05 20:33:37 -08:00
HomeAssistant Azure
8ab04d5fc7 [ci skip] Translation update 2019-11-06 00:31:46 +00:00
Aaron Bach
e69cd271dd Bump pytile and re-order imports (#28570) 2019-11-05 22:40:12 +01:00
Pascal Vizeli
005a1b2713 Add additional support over NC (#28527)
* Add voice support over NC

* Add disocery support for TTS / STT

* fix cloud TTS discovery

* Fix dev config

* Fix discovery

* Bump hass-nabucasa 0.25

* Add channel support

* Fix lint

* Update homeassistant/components/cloud/__init__.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

* Update homeassistant/components/cloud/tts.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

* Update homeassistant/components/cloud/tts.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

* Update homeassistant/components/cloud/tts.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

* bump hass-nabucasa

* Update tts.py

* fix lint
2019-11-05 22:39:15 +01:00
Pascal Vizeli
925e26b061 Update azure-pipelines-ci.yml 2019-11-05 21:58:35 +01:00
Pascal Vizeli
10247f6799 Fix dev dockerfile 2019-11-05 21:38:30 +01:00
Pascal Vizeli
1e398a8966 Try fix tests (#28470) 2019-11-05 21:12:29 +01:00
Santobert
7b86f0f926 Add deprecated attributes to light.reproduce_state (#28557)
* Add deprecated attributes to light.reproduce_state

* Add blank line

* fix minor bug

* Typo
2019-11-05 06:43:50 -08:00
Quentame
136f1f7fe9 Move imports in samsungtv component (#27775)
* Move imports in samsungtv component

* Fix tests

* Fix review 1

* Fix review 2

* wakeonlan is a module
2019-11-05 15:04:19 +01:00
Jesse Hills
a43095b2b5 Add override switch for juicenet (#28049)
* Add override switch for juicenet

* Update generated files

* Update indentation

* Fix indentation

* Remove unnecessary else statement

* Update homeassistant/components/juicenet/switch.py

Co-Authored-By: Fabian Affolter <mail@fabian-affolter.ch>

* Update homeassistant/components/juicenet/switch.py

Co-Authored-By: Fabian Affolter <mail@fabian-affolter.ch>

* Remove state property

* Change string formatting

* Bump juicenet package version again
2019-11-05 14:24:20 +01:00
Zach
11efb2c2eb Avoid drawing image_processing font text inside the bow line (#27796)
* Adjust font text such that it won't be drawn inside the bow line in image_processing.draw_box

* Adjust font_height after actually counting the pixels

* Thinned out line_width and adjusted font size
2019-11-05 11:43:36 +01:00
Ville Skyttä
804b6bbc0e Reduce test requirements duplication, sync flake8 and related (#28538)
* Generate pre-commit test dependencies instead of duplicating

* Upgrade/sync to flake8 3.7.9, flake8-docstrings 1.5.0, and pydocstyle 4.0.1

https://flake8.readthedocs.io/en/latest/release-notes/3.7.9.html
https://gitlab.com/pycqa/flake8-docstrings/blob/1.4.0/HISTORY.rst
https://gitlab.com/pycqa/flake8-docstrings/blob/1.5.0/HISTORY.rst
http://www.pydocstyle.org/en/4.0.1/release_notes.html

* Include requirements_test.txt from *_all.txt instead of copying
2019-11-04 21:21:52 -08:00
Santobert
ef20f0985a Improve scene.create service (#28533)
* Improve scene.create service

* Typo

* Improve coverage

* Add from_yaml attribute

* from_service instead of from_yaml
2019-11-04 21:15:58 -08:00
Bouwe Westerdijk
fb0e20543e Update Plugwise (#28237)
* Plugwise update

* Fix DEFAULT_NAME

* Fix pylint errors

* Remove showing of DHW-status

* Remove `if not None` where possible

* Forgot to remove dhw-related code

* Updated w.r.t. comments from MartinHjelmare

* Remove the illuminance attribute - move to sensor

* Update homeassistant/components/plugwise/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@kth.se>

* Breaking lines

* Remove thermostat_temperature

* Try fix lint errors.

* Remove spaces

* Remove more spaces
2019-11-05 02:58:17 +01:00
HomeAssistant Azure
ade60742d4 [ci skip] Translation update 2019-11-05 00:31:48 +00:00
Paulus Schoutsen
16a80beb43 Fix scaffold 2019-11-04 14:14:57 -08:00
Paulus Schoutsen
83a9f4ddb8 rate is a separate word (#28535) 2019-11-04 14:01:10 -08:00
Marius Flage
f5fb9fc580 Checking state before actually sending a new state change. Some projectors return ERR if you try to turn off a projector that's already off. (#28529) 2019-11-04 21:54:36 +01:00
Thom Troy
6e58a0c996 Update ephember library version (#28507)
* update ephember library version

* update requirements_all.txt for new pyephember version

* update imports to top of module
2019-11-04 21:49:53 +01:00
shred86
fe749fc0f8 Fix sensor device in the Abode component (#28516)
* Fix for occupancy sensor unique_id

* Add check for sensor attributes before adding entity

* Fixes temperature key issue

* Clean up code with better use of keys

* Code clean up
2019-11-04 21:49:11 +01:00
Bram Kragten
e419689229 Add config endpoint for scene (#28429)
* Add config endpoint for scene

* Add scenes to default config

* Fix test and add context to websocket service call

* Update scene.py

* Add tests
2019-11-04 12:38:18 -08:00
kennedyshead
bbe0cf3a0c Bump version for asuswrt to 1.1.22 (#28322)
* Bumping version

* Fix requirements

* Fix requirements
2019-11-04 20:52:55 +01:00
Martin
06c26f3ffc Add heating_type for ViCare integration (#27296)
* Add heating_type for ViCare

* Add additional gas heating properties

* Update requirements_all

* Add hvac action

* Remove measurements

* Remove unused property
2019-11-04 20:12:43 +01:00
chriscla
aaad8eac0a Fire an event when nzbget download completes (#27763)
* Fire an event when download completes

* Rename event and use a set

* Use a set comprehension

* Renaming method
2019-11-04 19:39:03 +01:00
Ville Skyttä
6a7b5657ac Support Huawei LTE SSDP discovery (#28214)
* Support Huawei LTE SSDP discovery

* Avoid KeyError on simultaneous user initiated flow

Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io>

* Format code

* Add already configured check

* Initialize context in test flows

* Move deviceType match to manifest

* Update generated.ssdp

* Add SSDP config flow test case

* Remove stale debug print from tests
2019-11-04 19:56:49 +02:00
Charles Garwood
f3ea44cd92 Cleanup Device Registry on Z-Wave Node Removal (#28240)
* Remove device from device registry on node removal

* Make async_get_registry from entity registry more concise

* Lower log level to debug
2019-11-04 10:17:32 -05:00
Jess
5b85456759 Add switches (on/off zones) to geniushub (#28182)
* New switch platform for geniushub
* Update to new geniushub-client with support for on/off zones
2019-11-04 13:32:33 +00:00
Pascal Vizeli
99c0559a0c Speech to Text component (#28434)
* Initial commit for STT

* Fix code review
2019-11-04 13:10:42 +01:00
SukramJ
33c8cba30d Enable transition time for HmIP-BSL - HomematicIP Cloud (#28201)
* Enable transition time for HmIP-BSL - HomematicIP Cloud

harden ACP
fix hao device name

* update test, initalize instance var
2019-11-04 12:22:28 +01:00
SukramJ
b7296c61bc Align attribute naming between light and switch for HomematicIP Cloud (#28271) 2019-11-04 12:05:39 +01:00
Paulus Schoutsen
552fbda58b Remove legacy reproduce state (#28458)
* Remove legacy reproduce state

* Fix imports
2019-11-04 11:12:04 +01:00
Luca Zimmermann
9b72a55d60 Add compatibility for other STBY Codes (#28478)
Added PWR2 as valid standby code
2019-11-04 11:11:10 +01:00
Oscar Tin Lai
6004ef3279 Expose set auto mode for all Dyson fans (#28488)
Set auto mode should be exposed to all dyson fans (e.g. *Pure Cool Link* and *Pure Hot+Cool Link*) instead of only *Pure Cool*, as it is support in all of the models (i.e. similar to the set night mode).
2019-11-04 11:10:59 +01:00
Jonas Janz
fadb9bdfb3 Add information to IFTTT services.yaml (#28385)
* docs(ifttt): add information to services.yaml

* docs(ifttt): start examples lowercase

* docs(ifttt): start examples with capital letter

* docs(ifttt): end description on period
2019-11-04 10:58:39 +01:00
Tobias Efinger
40b676c06f Add services description for ness alarm (#28250) 2019-11-04 10:29:29 +01:00
Florent Thoumie
de1799d486 iaqualink: better handling of failures (#28514) 2019-11-04 09:58:27 +01:00
Fabian Affolter
60d7f730c3 Upgrade jinja2 to >=2.10.3 (#28422) 2019-11-04 09:57:20 +01:00
Fabian Affolter
cb19827932 Upgrade paho-mqtt to 1.5.0 (#28423) 2019-11-04 09:56:58 +01:00
Fabian Affolter
fe00f3558e Imports twitch (#28517)
* Move imports

* Add unique_id
2019-11-04 09:56:46 +01:00
Tom Robinson
e91bb1ab08 Replace Netatmo CO2 sensor icon (#28520) 2019-11-04 09:56:36 +01:00
Fabian Affolter
381bf987d2 Upgrade TwitterAPI to 2.5.10 (#28401) 2019-11-04 09:56:27 +01:00
SukramJ
7cbd55a817 Add dump config service to HomematicIP Cloud (#28231)
* Add dump config service to HomematicIP Cloud

* Mock builin.open

* Fix test

* reduce SGTIN if anonymize

* apply review feedback
2019-11-04 09:55:12 +01:00
Fabian Affolter
c01b7bbf28 Upgrade pillow to 6.2.1 (#28442) 2019-11-04 09:03:58 +01:00
Ville Skyttä
7e6bcb85b7 Don't fail tox pylint if PYLINT_ARGS is not set (#28403)
Closes https://github.com/home-assistant/home-assistant/issues/28342
2019-11-04 08:12:15 +01:00
Kevin McCormack
cb2f42b336 Update Vivotek component stream source (#27941)
* Update Vivotek component

Fix building stream URL

* Update Vivotek component

Make stream path optionally configurable.

* Update Vivotek camera integration

Use f-string to build stream source URL.
This improve readability and I hear it runs faster.
2019-11-04 04:11:14 +01:00
HomeAssistant Azure
0973f1961d [ci skip] Translation update 2019-11-04 00:32:38 +00:00
Maciej Bieniek
4e40394972 Fix Airly if more than one config entry (#28498) 2019-11-04 00:58:35 +01:00
Ville Skyttä
9b038bd10d Don't use deprecated encoding to json.loads (#28509)
Will be removed in 3.9, ignored in earlier supported versions.
2019-11-04 00:24:24 +01:00
Ville Skyttä
734e982822 Import CancelledError from asyncio, not .futures (#28511)
It's no longer in .futures in Python 3.8.0.
2019-11-04 00:05:01 +01:00
escoand
0768ae2dc8 Fix flaky YesssSMS tests on debug messages (#28506) 2019-11-03 23:56:08 +01:00
Joakim Plate
5fd9b474dc Always provide brightness value (#28228)
HA will remove attribute when light is off, but google expect all trait data all the time.
2019-11-03 11:36:02 -08:00
escoand
ecf2e9c0ab Fix flaky Samsung TV tests (#28503) 2019-11-03 18:32:01 +01:00
Ville Skyttä
b904a2c5ad Handle Huawei LTE timeouts (#28465) 2019-11-02 21:28:38 -07:00
Fabian Affolter
314c3d0965 Use integration name in docstring (#28445) 2019-11-02 21:28:07 -07:00
Tim McCormick
5cbb6607a6 Fix missing import (#28460) 2019-11-02 21:25:24 -07:00
András Rutkai
31752d5736 Fixing #27722 Watson TTS platform (sdk upgrade) (#28468) 2019-11-02 21:24:02 -07:00
michaeldavie
0d432f60e2 Bump env_canada to 0.0.30 (#28487) 2019-11-02 21:21:46 -07:00
Paulus Schoutsen
67eeb8f258 Fix flaky test 2019-11-02 21:21:13 -07:00
HomeAssistant Azure
f71527d5db [ci skip] Translation update 2019-11-03 00:31:44 +00:00
Ville Skyttä
1679ec3245 SSDP matching improvements (#28285)
* SSDP matching improvements

- support multiple match groups per domain
- require matches on all, not any item in a group
- support matching on all UPnP device description data

* Manifest structure fixes
2019-11-02 12:30:09 -07:00
Ville Skyttä
a8dff2f2d0 pre-commit: ship default and full configs (#28463)
For now, the only difference between the two is mypy.
2019-11-02 12:21:09 -07:00
Nash Kaminski
b8fa5367db Fix inability to transition between specific presets in Venstar component (#28238)
This change addresses a bug where one is unable to change directly between the away and temperature hold presets, as temperature hold cannot be enabled on a Venstar thermostat if away mode is active.
Furthermore, this change removes redundant state checks as the set_away and set_schedule calls are idempotent in the venstarcolortouch library. See https://github.com/hpeyerl/venstar_colortouch/blob/master/src/venstarcolortouch/venstarcolortouch.py#L275.
2019-11-02 10:51:30 +01:00
ktnrg45
512ef2fce4 Change ps4 state off to state standby (#28261)
* Change state off to state standby

* update docstring
2019-11-02 10:32:37 +01:00
HomeAssistant Azure
4863face69 [ci skip] Translation update 2019-11-02 00:31:48 +00:00
Fabian Affolter
15900094a1 Update MQTT sensor test (#28449) 2019-11-01 17:30:37 -07:00
Mister Wil
ad4a960ed2 Change Abode cache file path, add cache path to config flow (#28389)
* Changed cache file path

* Cache file naming scheme matches original

* Restart tests

* Adding cache path to config_flow.py

* Moved DEFAULT_CACHEDB to consts file

* Use correct cache path

* Linting issues
2019-11-01 17:28:50 -07:00
Paulus Schoutsen
50affdf953 Also install after_deps (#28453) 2019-11-01 17:21:50 -07:00
Santobert
6655b7db2c Add scene.create service (#28300)
* Initial commit

* Fix scene.create
2019-11-01 15:53:42 -07:00
Robert Svensson
c0e1b97119 deCONZ - Improve discovery logging (#28452) 2019-11-01 23:36:23 +01:00
Robert Svensson
6cc947abbf deCONZ - Add Hue dimmer gen1 (rwl020) support to device triggers(#28450) 2019-11-01 23:06:29 +01:00
jjlawren
21d48218aa Use server-specific unique_ids for Plex media_players (#28447) 2019-11-01 22:41:26 +01:00
Robert Svensson
557e585e56 deCONZ - Support creating battery sensor when reported (#27538) 2019-11-01 22:31:22 +01:00
Robert Svensson
62b09580c4 deCONZ - Add Xiaomi Aqara Cube device trigger support (#27548)
* Add Xiaomi Aqara Cube device trigger support
2019-11-01 22:29:34 +01:00
Santobert
07b7d514ac Add improved scene support to the water_heater integration (#28277) 2019-11-01 13:37:34 -07:00
Santobert
12f1a8f551 Add improved scene support to the alarm_control_panel integration (#28269)
* Add improved scene support to the alarm_control_panel integration

* Add service description for alarm_arm_custom_bypass
2019-11-01 13:36:18 -07:00
SukramJ
1fb377e61e Use defined device class constants for Homematic (#28438)
* Use defined device classes for Homematic

* Remove not required default None

* Missed on None
2019-11-01 21:25:33 +01:00
phispi
f8d779e840 Prevent TypeError when KNX RGB(W) light value contains None (#28358)
* Prevent TypeError when KNX RGB(W) light value contains None.

* Pylint doesn't like 'w' as variable name, therefore using 'white' instead.

* Simplified code as suggested by pvizeli.
2019-11-01 21:23:23 +01:00
John Mihalic
44879b323e Bump pyEight library to 0.1.2 to update API URL (#28413) 2019-11-01 18:40:35 +01:00
Robin Pronk
c7d72f55e9 SNMP switch fix integer support (#28425) 2019-11-01 15:38:13 +01:00
Fabian Affolter
07337badcd Upgrade pysnmp to 4.4.12 (#28428) 2019-11-01 14:28:38 +01:00
Michael Schoonmaker
6f24d2bb3b Add a Services YAML for the Dominos integration (#27289) (#28339) 2019-11-01 14:27:26 +01:00
Fabian Affolter
083d34cdd9 Upgrade attrs to 19.3.0 (#28421) 2019-11-01 13:10:53 +01:00
Fabian Affolter
72a17d4c67 Upgrade thingspeak to 1.0.0 (#28424) 2019-11-01 13:09:45 +01:00
HomeAssistant Azure
bb6a617a6f [ci skip] Translation update 2019-11-01 00:32:13 +00:00
Daniyar Yeralin
54361342ba Introduce SUPPORT_COLOR_TEMP for flux_led component (#26692)
* Introduce SUPPORT_COLOR_TEMP for flux_led component

* Make black linter happy

* Remove duplicate SUPPORT_COLOR_TEMP

* Make linter happy
2019-11-01 00:15:20 +01:00
Paulus Schoutsen
5c9f7484c2 Merge remote-tracking branch 'origin/master' into dev 2019-10-31 14:18:03 -07:00
Malte Franken
d200c2dca2 fix feedreader handling unrecognized published date (#28225) 2019-10-31 21:05:42 +01:00
escoand
82729bef70 Show all UPNP/IGD sensors in one device (#27517)
* show all UPNP/IGD sensors in one device

* use device name correctly

* Use id of device
2019-10-31 20:51:35 +01:00
thoscut
ec373d90c1 Add file list to attributes of folder sensor (#28338) 2019-10-31 20:49:33 +01:00
gngj
b74711793e Fill services.yaml for squeezebox (#28247)
* fill services.yaml for squeezebox

* Minor fix
2019-10-31 20:32:05 +01:00
Nikolay Vasilchuk
abbf6595bb Fix (#28369) 2019-10-31 12:07:07 -07:00
Paulus Schoutsen
631a819bd1 Fix check config (#28393) 2019-10-31 11:39:26 -07:00
Paulus Schoutsen
70c4b4a4f0 Check for import errors before validating config (#28395) 2019-10-31 11:38:06 -07:00
Tsvi Mostovicz
674860e00e Fix hdate spamming homeassistant log (#28392)
* Fix hdate spamming homeassistant log

* Lower verbosity of another spammy message
2019-10-31 11:16:27 -07:00
ZiroNL
5854eef47b Add services.yaml to onvif component (#28349) 2019-10-31 18:57:00 +01:00
Robert Van Gorkom
226b2bc3d0 Update withings-api to avoid data parsing bugs. (#28382) 2019-10-31 18:29:10 +01:00
Alexei Chetroi
89213a4ce8 Don't set entity_id in ZHA entities (#28362)
* Don't set entity_id on ZHA entities.
* Update tests.
* Use comma as separator for multiple channel names.
* Address PR comments.
2019-10-31 12:31:06 -04:00
Maciej Bieniek
d133501735 Fix Airly asyncio timeout error (#28387)
* Raise ConfigEntryNotReady

* Better asyncio.TimeoutError handling

* Sort imports

* Increase asyncio timeout
2019-10-31 09:29:27 -07:00
ochlocracy
ff5b070f4b Implement Alexa.SeekController Interface for media_player in Alexa (#28299)
* Implement Alexa.SeekController Interface for Alexa

* Added error handling and duration checks.

* Split out media_player SeekController tests and added error test.
2019-10-31 10:38:44 +01:00
gngj
bfe4a85e9d Fill services.yaml for duckdns (#28248)
* Fill services.yaml for duckdns

* Apply suggestions from code review

Co-Authored-By: Fabian Affolter <mail@fabian-affolter.ch>
2019-10-31 09:51:15 +01:00
Mark Coombes
e11c9d710c Add modelnumber for ecobee4 (#28278) 2019-10-31 09:49:38 +01:00
Santobert
89df821113 Flux log with debug instead of info (#28352) 2019-10-31 09:41:44 +01:00
fredericvl
ef92c5672d Bump pysaj to v0.0.13 (fix for sensor date) (#28351) 2019-10-31 09:39:27 +01:00
Steve M
d3750401c1 Bump env_canada to fixed 0.0.29 version (#28360)
* Bump env_canada to fixed 0.0.29 version

* bump env_canada to 0.29
2019-10-31 09:38:53 +01:00
HomeAssistant Azure
ee24710524 [ci skip] Translation update 2019-10-31 00:32:14 +00:00
Erik Montnemery
8ae43d2de3 Add device triggers to cover (#28063)
* Add device triggers to cover

* Use numeric_state trigger instead of template trigger

* Tweak translations
2019-10-30 20:49:01 +01:00
Aaron Bach
bda3aadbcf Bump pymyq to 2.0.1 (#28348) 2019-10-30 09:05:13 -06:00
ZiroNL
4350467a00 Add services.yaml to local_file component. (#28330) 2019-10-30 08:36:53 +01:00
springstan
f8efc2adc6 Fix KeyError in decora setup (#28279)
* Imported homeassistant.util and slugified address if no name is specified

* Added a custom validator function in case name is not set in config

* Removed logger.debug line only used for testing
2019-10-30 07:57:40 +01:00
Paulus Schoutsen
24c29f9227 Add OAuth2 config flow scaffold (#28220)
* Add OAuth2 scaffold

* Generate integration if non-existing domain specified

* Update URL
2019-10-29 20:34:03 -07:00
HomeAssistant Azure
e700384cce [ci skip] Translation update 2019-10-30 00:32:11 +00:00
David Bonnes
e1eab214ad allow multiple heaters per incomfort gateway (#28324)
* add multiple heaters per gateway
* bump client to handle the above
2019-10-29 21:29:39 +00:00
Sebastian Muszynski
6d734a714e Clean up Xiaomi Air Quality Monitor support (cgllc.airmonitor.b1) (#28301)
* Clean up Xiaomi Air Quality Monitor support (cgllc.airmonitor.b1)

* Remove unused variable

* Provide a proper unique_id

* Incorporate review

* Wrap the method that cause the exception

* Undo mistakenly changed file. Fixed in the separate PR.
2019-10-29 22:17:09 +01:00
Renaud Martinet
3a9e3ce857 Add services description for sabnzbd component (#28252) 2019-10-29 15:17:49 -04:00
cgtobi
1dfb67f0c5 Bump pytest to 5.2.2 (#28230) 2019-10-29 15:16:05 -04:00
Bram Kragten
5592eb7709 Updated frontend to 20191025.1 (#28327) 2019-10-29 16:30:33 +01:00
Pascal Vizeli
c00b058e53 Cleanup not needed websocket flags for ingress (#28295) 2019-10-29 12:05:05 +01:00
Jonas Janz
502f59977a Add description for arlo.update service (#28270) 2019-10-29 11:02:25 +01:00
Franck Nijhof
756c36171d Bump youtube_dl to 2019.10.29 (#28312) 2019-10-29 09:37:51 +01:00
Franck Nijhof
4dc6d36224 Bump pre-commit to 1.20.0 (#28313) 2019-10-29 09:37:18 +01:00
Paulus Schoutsen
79ac77a93d Almond integration (#28282)
* Initial Almond integration

* Hassfest

* Update library

* Address comments

* Fix inheritance issue py36

* Remove no longer needed check

* Fix time
2019-10-28 23:47:31 -07:00
Franck Nijhof
a4ec4d5a18 Add source constants for all config entry discovery sources (#28311) 2019-10-28 23:32:57 -07:00
Franck Nijhof
04ab20846a Bump black to 19.10b0 (#28310) 2019-10-28 23:32:34 -07:00
Sebastian Muszynski
5b96704c4a Use dict[key] for required config keys (#28304)
* Use dict[key] for required config keys

* Change CONF_NAME too because it has a default
2019-10-29 01:45:22 +01:00
Sebastian Muszynski
a0f764cf6d Remove blocking I/O from the event loop (#28305) 2019-10-29 01:44:26 +01:00
HomeAssistant Azure
0e4331e922 [ci skip] Translation update 2019-10-29 00:32:16 +00:00
Josh Bendavid
1e27a1f2b9 Add keyboard_remote trigger on multiple event types and emulate key hold events (#27761)
* convert keyboard_remote to async and add possibility to trigger on multiple event types, as well as emulate key hold events

* update requirements

* cleanup shutdown handling and config handling as well as address other minor comments

* cleanup unused return values and debug message formatting

* move start and stop event listen to separate coroutine plus minor cleanup

* make setup coroutine a function

* fix import order and attribute defined outside of init

* add to codeowners

* update codeowners
2019-10-29 00:59:13 +01:00
Florent Thoumie
0ef99934b7 Add more iaqualink entity properties, fix timeout issues (#28236)
* iaqualink: implement some more entity properties

* Style fixes
2019-10-29 00:42:06 +01:00
Ville Skyttä
f88ead597a Type hint improvements (#28260)
* Add and improve core and config_entries type hints

* Complete and improve config_entries type hints

* More entity registry type hints

* Complete helpers.event type hints
2019-10-28 13:36:26 -07:00
Yann Jajkiewicz
f7a64019b6 Add support for Somfy Garage door Rollixo IO DiscreteGarageOpenerIOComponent in Tahoma component (#28291) 2019-10-28 11:22:15 -07:00
jjlawren
31dd69196c Bump library to 0.0.3 (#28294) 2019-10-28 10:39:37 -07:00
Pascal Vizeli
335872b54d Revert "More header cleanup for websocket proxy (#28288)" (#28293)
This reverts commit 7887850505.
2019-10-28 16:54:15 +01:00
Bram Kragten
549e8cf2c5 Hue: Create new config flow when auth is lost (#28204)
* Hue: Create new config flow when auth is lost

* Fix tests

* Fix tests

* Comments

* Lint
2019-10-28 08:45:08 -07:00
Eliseo Martelli
30f4ee121a Remove GTT component (#28286)
* removed GTT component

* Removed gtt.py from coveragerc
2019-10-28 14:54:42 +01:00
Sören
c1d88dd7a4 Bump avea to 1.4 (#28287)
* Bump avea to 1.4

* Bump avea to 1.4 #2
2019-10-28 14:47:04 +01:00
Pascal Vizeli
7887850505 More header cleanup for websocket proxy (#28288) 2019-10-28 14:34:13 +01:00
J.P. Hutchins
54342d2a4e Add transmission info about torrents that is accessible with templating (#27111)
* Add information about current downloads.

* Cleanup: add "Torrent Info" state attribute

* Add username to codeowners

* Rename state_attributes - device_state_attributes.

* Fix snakecase keys, use f-strings, remove redundant method.

* Access started_torrent_dict directly

* Add return None condition

* Remove redundancy.

* Add missing comma in codeowners list.

* Add missing @ to username.

* Update CODEOWNERS with script.hassfest.

* Remove transmission_downloading, give started_torrents the info.

* Confirm changes.

* Actually approve changes.

* Resolve conflicts.

* Remove leftovers from old torrent_info sensor.

* Remove get_started_torrent_info method.

Old method to display boolean for the removed torrent_info sensor.
2019-10-28 10:20:59 +01:00
fwestenberg
edcf476408 Add support for Xiaomi Air Quality Monitor (cgllc.airmonitor.b1) (#27735) 2019-10-28 07:43:01 +01:00
HomeAssistant Azure
72dee7dd21 [ci skip] Translation update 2019-10-28 00:32:16 +00:00
SukramJ
75f94b9147 Reorg and test attributes for HomematicIP Cloud (#28234)
* Reorg and test attribute for HomematicIP Cloud

* Add dutyCycle check to security_group

* Edit test to improve coverage

* Add missing flow test

* apply suggestion

Co-Authored-By: Martin Hjelmare <marhje52@kth.se>

* fix assert condition
2019-10-28 01:03:26 +01:00
ZiroNL
6ac7796fb7 Add charset to imap component. (#28258) 2019-10-27 13:07:44 +01:00
Fabian Affolter
a9db2ead33 Suppress traceback (fixes #28243) (#28262) 2019-10-27 12:39:36 +01:00
Fabian Affolter
7e862e4d92 Update praw to 6.4.0 (#27324)
* Update praw to 6.4.0

* Update requirements_test_all.txt

* Fix docstrings

* Update tests
2019-10-27 10:04:43 +01:00
Floris Van der krieken
2747f08385 Add available state to unifiled integration (#28189)
* Added Unifi Led

* fixed manifest

* fixed style issue

* removed unused setting

* added sugested changes.

* fixed order

* fixed settings that are required

* Fix review issues

* fix variable name that was too short

* Testing something

* Reverted to a previous version for testing

* Reverted testing changes.

* Add available status and increase version of unifiled package version.

* No io in init function.
2019-10-27 05:18:23 +01:00
HomeAssistant Azure
868f88a4e0 [ci skip] Translation update 2019-10-27 00:32:10 +00:00
Fabian Affolter
bb8f139716 Upgrade speedtest-cli to 2.1.2 (#28216) 2019-10-26 13:45:42 +02:00
Ville Skyttä
2baee4ac3e Add Huawei LTE mobile data switch support (#28188)
* Add Huawei LTE mobile data switch support

* Remove stale comment

* Do HA state updates in base entity
2019-10-26 13:29:36 +03:00
HomeAssistant Azure
7096826d1d [ci skip] Translation update 2019-10-26 00:32:20 +00:00
Paulus Schoutsen
08cc9fd375 Add cloud account linking support (#28210)
* Add cloud account linking support

* Update account_link.py
2019-10-25 16:04:24 -07:00
Erik Montnemery
475b43500a Add above and below to sensor condition extra_fields (#27364)
* Add above and below to sensor condition extra_fields

* Change unit_of_measurement to suffix in extra_fields

* Check if sensor has unit when getting capabilities

* Improve tests
2019-10-26 06:55:42 +08:00
ochlocracy
d6654eaecb Implement Alexa.PlaybackStateReporter Interface for alexa (#28215) 2019-10-25 14:53:33 -07:00
Erik Montnemery
7fee44b8c5 Add additional device conditions to cover (#27830)
* Add additional device conditions to cover

* Add default value

* Add test

* Use numeric_state condition instead of template condition
2019-10-25 13:50:46 -07:00
ochlocracy
d44bfa8e88 Improved Alexa ThermostatController thermostatMode handling (#28176)
* Update ThermostatController to map directives to supported modes and add support for CUSTOM mode.

* Removed erroneous config value from test.

* Removed unnecessary use of a comprehension by dumbing down comment so pylint could comprehend.

* Removed erroneous import variable caused by removing erroneous config value from test.

* Removed unnecessary use of a comprehension.

* Reverted Removal or erroneous import variable and erroneous config value from test.
Apparently need for additional tests outside this component. Whoops.
2019-10-25 13:42:21 -07:00
Erik Montnemery
f4341c1546 Fix broken deconz trigger (#28211) 2019-10-25 13:40:05 -07:00
ochlocracy
da8a476142 Add support for supportedOperations to Alexa.PlaybackController (#28212)
* Added support for supportedOperations to Alexa.PlaybackController

* Added support for supportedOperations to Alexa.PlaybackController
2019-10-25 13:34:51 -07:00
Markus Pöschl
f2d6cc7329 Increased python-eq3bt version to latest (0.1.11) (#28175) 2019-10-25 21:25:27 +02:00
Hayley McIldoon
7ddce1d52b Add device condition support for device_tracker (#28190) 2019-10-25 10:51:35 -07:00
gngj
d28f7ab120 Fix microsoft tts (#28199)
* Update pycsspeechtts

From 1.0.2 to 1.0.3 as the old one is using an api that doesn't work

* Give a option to choose region

Api is now region dependent, so gave it a config
2019-10-25 10:42:23 -07:00
Hayley McIldoon
2c914e0c59 Add device condition support for media_player (#28161)
* Add device condition for media_player

* Fix typo in strings
2019-10-25 10:22:39 -07:00
ochlocracy
38428308fc Change Alexa default display category based on media_player device_class (#28191)
* Support default display category based one media_player device_class.

* Support default display category based one media_player device_class.
2019-10-25 10:21:22 -07:00
Bram Kragten
5c8a9c2815 Updated frontend to 20191025.0 (#28208) 2019-10-25 10:20:42 -07:00
Ville Skyttä
3c4caaaefc Add presentation URL to SSDP discovery info (#28196) 2019-10-25 20:09:18 +03:00
On Freund
0656f0c62b Address post-merge coolmaster config flow code review (#28163)
* Address post-merge code review comments

* Use component path for 3rd party lib
2019-10-25 18:39:16 +02:00
jjlawren
43c7b57d1e Update Plex via websockets (#28158)
* Save client identifier from auth for future use

* Use websocket events to update Plex

* Handle websocket disconnections

* Use aiohttp, shut down socket cleanly

* Bad rebase fix

* Don't connect websocket during config_flow validation, fix tests

* Move websocket handling to external library

* Close websocket session on HA stop

* Use external library, revert unnecessary test change

* Async & lint fixes

* Clean up websocket stopper on entry unload

* Setup websocket in component, pass actual needed object to library
2019-10-25 18:37:50 +02:00
gngj
9153729b21 move hass-frontend import back down (#28203) 2019-10-25 09:02:40 -07:00
guillempages
98cf3f4aa3 [homematic]Add support for HmIP-BSL LEDs (#27307)
With this commit, 3 entities are created for the HmIP-BSL device:
2 lights for the two independent LEDs and 1 switch for the relais
2019-10-25 16:08:11 +02:00
guillempages
6bfb2460f2 [homematic]Pass channel to light color functions (#27306)
The device HmIP-BSL has two independent LEDs on two different channels,
so the channel needs to be explictly specified when setting the color.
2019-10-25 16:06:52 +02:00
escoand
9661efc312 Add Samsung TV automatic protocol detection (#27492)
* added automatic protocol detection

* fix logger tests

* fix async tests

* add missin const.py

* fix log formatting

* wait for first update call

* migrate first tests

* migrated all test functions

* started to use state machine

* updated all tests to use async_setup_component

* slove hints

* update tests

* get state at correct position

* remove impossible tests

* fix autodetect tests

* use caplog fixture

* add test for duplicate

* catch concrete exceptions

* don't mock samsungctl exceptions

* add test for discovery

* get state when possible

* add test for autodetect without connection
2019-10-25 14:32:12 +02:00
HomeAssistant Azure
95295791bd [ci skip] Translation update 2019-10-25 00:32:15 +00:00
Ville Skyttä
643b3a98ee Huawei LTE sensor metadata update (#28187) 2019-10-24 16:42:54 -07:00
SukramJ
32a024c641 Partially revert tensorflow import move (#28184)
* Revert "Refactor imports for tensorflow (#27617)"

This reverts commit 5a83a92390.

* move only some imports to top

* fix lint

* add comments
2019-10-24 16:41:13 -07:00
Joakim Sørensen
67cf7c26da Removes unwanted tradfri battery sensor (#28181) 2019-10-24 23:25:47 +02:00
Josef Schlehofer
63deec3275 Bump python-slugify to 4.0.0 (#28186) 2019-10-24 23:12:41 +02:00
kennedyshead
98ac8a217d Adding device_class to samsungtv (#28168)
* Adding device_id to samsungtv

* Lint

* Adding test
2019-10-24 13:41:07 -07:00
Diefferson Koderer Môro
c96d4c978d Fix tzinfo type for onvif component (#28178) 2019-10-24 13:39:10 -07:00
Joakim Sørensen
ec478ab848 Add stop feature to tradfri covers (#28180)
* Tradfri cover enhancements

* tradfri dependency update

* Revert addition of battery attrubite

* Remove the supported_features property

* Remove unwanted file
2019-10-24 13:38:24 -07:00
Otto Winter
322d8c2dd5 Fix ESPHome stacktraces when removing entity and shutting down (#28185) 2019-10-24 13:36:47 -07:00
Joakim Sørensen
b61218f90e Tradfri config flow enhancements (#28179) 2019-10-24 21:31:58 +02:00
Otto Winter
8791a48328 Bump aioesphomeapi to 2.4.1 (#28170)
* Bump aioesphomeapi to 2.4.1

* Update requirements

* Bump to 2.4.2
2019-10-24 20:24:46 +02:00
Robert Van Gorkom
15bedd8f27 Use latest withings_api module (#27817)
* Using latest winthings_api module.
Drastically reduced complexity of tests.

* Removing import source.

* Fixing test requirements.

* Using requests_mock instead of responses module.

* Updating file formatting.

* Removing unused method.

* Adding support for new OAuth2 config flow.

* Addressing PR feedback.
Removing unecessary base_url from config, this is a potential breaking change.

* Addressing PR feedback.
2019-10-24 09:41:04 -07:00
Ville Skyttä
fc09702cc3 Modernize Huawei LTE (#26675)
* Modernization rework

- config entry support, with override support from huawei_lte platform in YAML
- device tracker entity registry support
- refactor for easier addition of more features
- internal code cleanups

* Remove log level dependent subscription/data debug hack

No longer needed, because pretty much all keys from supported
categories are exposed as sensors.

Closes https://github.com/home-assistant/home-assistant/issues/23819

* Upgrade huawei-lte-api to 1.4.1

https://github.com/Salamek/huawei-lte-api/releases

* Add support for access without username and password

* Use subclass init instead of config_entries.HANDLERS

* Update huawei-lte-api to 1.4.3 (#27269)

* Convert device state attributes to snake_case

* Simplify scanner entity initialization

* Remove not needed hass reference from Router

* Return explicit None from unsupported old device tracker setup

* Mark unknown connection errors during config as such

* Drop some dead config flow code

* Run config flow sync I/O in executor

* Parametrize config flow login error tests

* Forward entry unload to platforms

* Async/sync fixups

* Improve data subscription debug logging

* Implement on the fly add of new and tracking of seen device tracker entities

* Handle device tracker entry unload cleanup in component

* Remove unnecessary _async_setup_lte, just have code in async_setup_entry

* Remove time tracker on unload

* Fix to not use same mutable default subscription set for all routers

* Pylint fixes

* Remove some redundant defensive device tracker code

* Add back explicit get_scanner None return, hush pylint

* Adjust approach to set system_options on entry create

* Enable some sensors on first add instead of disabling everything

* Fix SMS notification recipients default value

* Add option to skip new device tracker entities

* Fix SMS notification recipient option default

* Work around https://github.com/PyCQA/pylint/issues/3202

* Remove unrelated type hint additions

* Change async_add_new_entities to a regular function

* Remove option to disable polling for new device tracker entries
2019-10-24 19:31:49 +03:00
Alexei Chetroi
969322e14a Fixes/zha ieee tail (#28160)
* Fix ZHA entity_id assignment.

* Update tests.
2019-10-24 12:23:02 -04:00
Floris Van der krieken
b1fcecd526 Add Unifi Led (#27475)
* Added Unifi Led

* fixed manifest

* fixed style issue

* removed unused setting

* added sugested changes.

* fixed order

* fixed settings that are required

* Fix review issues

* fix variable name that was too short

* Testing something

* Reverted to a previous version for testing

* Reverted testing changes.
2019-10-24 17:59:25 +02:00
kennedyshead
d44de6dd2b Fix Venstar formatting to restore clean CI (#28171) 2019-10-24 16:03:29 +02:00
Diefferson Koderer Môro
dd9ca70e96 Add onvif local datetime support (#26656)
* Update camera.py

* Add onvif local datetime support

* Correct capture TimeZone

* Replace one line if-statement by if-block
2019-10-23 21:03:24 -07:00
HomeAssistant Azure
8c31afc31e [ci skip] Translation update 2019-10-24 00:32:18 +00:00
Tyler Page
6a1501b59c Cover all possible values for venstar operation_mode (#27949)
* cover all possible values for operation_mode

* Update climate.py

* Update climate.py

* Update climate.py

mapped homeassistant constants to client ones so we don't have to check for both

* black + pylint

* move mode_map to __init__()

* Update climate.py

* Update climate.py
2019-10-24 02:10:57 +02:00
Teemu R
160c201be1 Bump songpal to fix a regression (#28115)
The new release fixes a single regression from requests to aiohttp conversion.
Some devices do not respond with the correct mimetype which was not enforced
by requests but is enforced by aiohttp.

Related PR https://github.com/rytilahti/python-songpal/pull/59
2019-10-23 23:13:56 +02:00
Paulus Schoutsen
1b21685651 Version bump to 102.0.dev0" 2019-10-23 13:38:35 -07:00
805 changed files with 22755 additions and 4991 deletions

View File

@@ -69,6 +69,7 @@ omit =
homeassistant/components/avea/light.py
homeassistant/components/avion/light.py
homeassistant/components/azure_event_hub/*
homeassistant/components/azure_service_bus/*
homeassistant/components/baidu/tts.py
homeassistant/components/beewi_smartclim/sensor.py
homeassistant/components/bbb_gpio/*
@@ -274,7 +275,6 @@ omit =
homeassistant/components/growatt_server/sensor.py
homeassistant/components/gstreamer/media_player.py
homeassistant/components/gtfs/sensor.py
homeassistant/components/gtt/sensor.py
homeassistant/components/habitica/*
homeassistant/components/hangouts/*
homeassistant/components/hangouts/__init__.py
@@ -499,6 +499,7 @@ omit =
homeassistant/components/panasonic_bluray/media_player.py
homeassistant/components/panasonic_viera/media_player.py
homeassistant/components/pandora/media_player.py
homeassistant/components/pcal9535a/*
homeassistant/components/pencom/switch.py
homeassistant/components/philips_js/media_player.py
homeassistant/components/pi_hole/sensor.py
@@ -720,6 +721,7 @@ omit =
homeassistant/components/uber/sensor.py
homeassistant/components/ubus/device_tracker.py
homeassistant/components/ue_smart_radio/media_player.py
homeassistant/components/unifiled/*
homeassistant/components/upcloud/*
homeassistant/components/upnp/*
homeassistant/components/upc_connect/*

View File

@@ -0,0 +1,42 @@
# This configuration includes the full set of hooks we use. In
# addition to the defaults (see .pre-commit-config.yaml), this
# includes hooks that require our development and test dependencies
# installed and the virtualenv containing them active by the time
# pre-commit runs to produce correct results.
#
# If this is not a problem for your workflow, using this config is
# recommended, install it with
# pre-commit install --config .pre-commit-config-all.yaml
# Otherwise, see the default .pre-commit-config.yaml for a lighter one.
repos:
- repo: https://github.com/psf/black
rev: 19.10b0
hooks:
- id: black
args:
- --safe
- --quiet
files: ^((homeassistant|script|tests)/.+)?[^/]+\.py$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.9
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.5.0
- pydocstyle==4.0.1
files: ^(homeassistant|script|tests)/.+\.py$
# Using a local "system" mypy instead of the mypy hook, because its
# results depend on what is installed. And the mypy hook runs in a
# virtualenv of its own, meaning we'd need to install and maintain
# another set of our dependencies there... no. Use the "system" one
# and reuse the environment that is set up anyway already instead.
- repo: local
hooks:
- id: mypy
name: mypy
entry: mypy
language: system
types: [python]
require_serial: true
files: ^homeassistant/.+\.py$

View File

@@ -1,6 +1,13 @@
# This configuration includes the default, minimal set of hooks to be
# run on all commits. It requires no specific setup and one can just
# start using pre-commit with it.
#
# See .pre-commit-config-all.yaml for a more complete one that comes
# with a better coverage at the cost of some specific setup needed.
repos:
- repo: https://github.com/psf/black
rev: 19.3b0
rev: 19.10b0
hooks:
- id: black
args:
@@ -8,24 +15,10 @@ repos:
- --quiet
files: ^((homeassistant|script|tests)/.+)?[^/]+\.py$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.8
rev: 3.7.9
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.3.1
- pydocstyle==4.0.0
- flake8-docstrings==1.5.0
- pydocstyle==4.0.1
files: ^(homeassistant|script|tests)/.+\.py$
# Using a local "system" mypy instead of the mypy hook, because its
# results depend on what is installed. And the mypy hook runs in a
# virtualenv of its own, meaning we'd need to install and maintain
# another set of our dependencies there... no. Use the "system" one
# and reuse the environment that is set up anyway already instead.
- repo: local
hooks:
- id: mypy
name: mypy
entry: mypy
language: system
types: [python]
require_serial: true
files: ^homeassistant/.+\.py$

View File

@@ -19,7 +19,7 @@ matrix:
- python: "3.6.1"
env: TOXENV=lint
- python: "3.6.1"
env: TOXENV=pylint PYLINT_ARGS=--jobs=0
env: TOXENV=pylint PYLINT_ARGS=--jobs=0 TRAVIS_WAIT=30
- python: "3.6.1"
env: TOXENV=typing
- python: "3.6.1"
@@ -33,4 +33,4 @@ cache:
- $HOME/.cache/pre-commit
install: pip install -U tox
language: python
script: travis_wait 50 tox --develop
script: ${TRAVIS_WAIT:+travis_wait $TRAVIS_WAIT} tox --develop

2
.vscode/tasks.json vendored
View File

@@ -33,7 +33,7 @@
{
"label": "Flake8",
"type": "shell",
"command": "flake8 homeassistant tests",
"command": "pre-commit run flake8 --all-files",
"group": {
"kind": "test",
"isDefault": true

View File

@@ -19,6 +19,7 @@ homeassistant/components/airly/* @bieniu
homeassistant/components/airvisual/* @bachya
homeassistant/components/alarm_control_panel/* @colinodell
homeassistant/components/alexa/* @home-assistant/cloud @ochlocracy
homeassistant/components/almond/* @gcampax @balloob
homeassistant/components/alpha_vantage/* @fabaff
homeassistant/components/amazon_polly/* @robbiet480
homeassistant/components/ambiclimate/* @danielhiversen
@@ -42,6 +43,7 @@ homeassistant/components/awair/* @danielsjf
homeassistant/components/aws/* @awarecan @robbiet480
homeassistant/components/axis/* @kane610
homeassistant/components/azure_event_hub/* @eavanvalkenburg
homeassistant/components/azure_service_bus/* @hfurubotten
homeassistant/components/beewi_smartclim/* @alemuro
homeassistant/components/bitcoin/* @fabaff
homeassistant/components/bizkaibus/* @UgaitzEtxebarria
@@ -155,9 +157,11 @@ homeassistant/components/iqvia/* @bachya
homeassistant/components/irish_rail_transport/* @ttroy50
homeassistant/components/izone/* @Swamp-Ig
homeassistant/components/jewish_calendar/* @tsvi
homeassistant/components/juicenet/* @jesserockz
homeassistant/components/kaiterra/* @Michsior14
homeassistant/components/keba/* @dannerph
homeassistant/components/keenetic_ndms2/* @foxel
homeassistant/components/keyboard_remote/* @bendavid
homeassistant/components/knx/* @Julius2342
homeassistant/components/kodi/* @armills
homeassistant/components/konnected/* @heythisisnate
@@ -173,6 +177,7 @@ homeassistant/components/logi_circle/* @evanjd
homeassistant/components/lovelace/* @home-assistant/frontend
homeassistant/components/luci/* @fbradyirl @mzdrale
homeassistant/components/luftdaten/* @fabaff
homeassistant/components/lutron/* @JonGilmore
homeassistant/components/mastodon/* @fabaff
homeassistant/components/matrix/* @tinloaf
homeassistant/components/mcp23017/* @jardiamj
@@ -221,13 +226,14 @@ homeassistant/components/oru/* @bvlaicu
homeassistant/components/owlet/* @oblogic7
homeassistant/components/panel_custom/* @home-assistant/frontend
homeassistant/components/panel_iframe/* @home-assistant/frontend
homeassistant/components/pcal9535a/* @Shulyaka
homeassistant/components/persistent_notification/* @home-assistant/core
homeassistant/components/philips_js/* @elupus
homeassistant/components/pi_hole/* @fabaff @johnluetke
homeassistant/components/plaato/* @JohNan
homeassistant/components/plant/* @ChristianKuehnel
homeassistant/components/plex/* @jjlawren
homeassistant/components/plugwise/* @laetificat @CoMPaTech
homeassistant/components/plugwise/* @laetificat @CoMPaTech @bouwew
homeassistant/components/point/* @fredrike
homeassistant/components/ps4/* @ktnrg45
homeassistant/components/ptvsd/* @swamp-ig
@@ -247,6 +253,7 @@ homeassistant/components/rfxtrx/* @danielhiversen
homeassistant/components/rmvtransport/* @cgtobi
homeassistant/components/roomba/* @pschmitt
homeassistant/components/saj/* @fredericvl
homeassistant/components/samsungtv/* @escoand
homeassistant/components/scene/* @home-assistant/core
homeassistant/components/scrape/* @fabaff
homeassistant/components/script/* @home-assistant/core
@@ -277,6 +284,7 @@ homeassistant/components/sql/* @dgomes
homeassistant/components/statistics/* @fabaff
homeassistant/components/stiebel_eltron/* @fucm
homeassistant/components/stream/* @hunterjm
homeassistant/components/stt/* @pvizeli
homeassistant/components/suez_water/* @ooii
homeassistant/components/sun/* @Swamp-Ig
homeassistant/components/supla/* @mwegrzynek
@@ -305,12 +313,13 @@ homeassistant/components/tplink/* @rytilahti
homeassistant/components/traccar/* @ludeeus
homeassistant/components/tradfri/* @ggravlingen
homeassistant/components/trafikverket_train/* @endor-force
homeassistant/components/transmission/* @engrbm87
homeassistant/components/transmission/* @engrbm87 @JPHutchins
homeassistant/components/tts/* @robbiet480
homeassistant/components/twentemilieu/* @frenck
homeassistant/components/twilio_call/* @robbiet480
homeassistant/components/twilio_sms/* @robbiet480
homeassistant/components/unifi/* @kane610
homeassistant/components/unifiled/* @florisvdk
homeassistant/components/upc_connect/* @pvizeli
homeassistant/components/upcloud/* @scop
homeassistant/components/updater/* @home-assistant/core
@@ -333,6 +342,7 @@ homeassistant/components/weblink/* @home-assistant/core
homeassistant/components/websocket_api/* @home-assistant/core
homeassistant/components/wemo/* @sqldiablo
homeassistant/components/withings/* @vangorra
homeassistant/components/wled/* @frenck
homeassistant/components/worldclock/* @fabaff
homeassistant/components/wwlln/* @bachya
homeassistant/components/xbox_live/* @MartinHjelmare

View File

@@ -24,9 +24,9 @@ RUN git clone --depth 1 https://github.com/home-assistant/hass-release \
WORKDIR /workspaces
# Install Python dependencies from requirements
COPY requirements_test.txt homeassistant/package_constraints.txt ./
COPY requirements_test.txt requirements_test_pre_commit.txt homeassistant/package_constraints.txt ./
RUN pip3 install -r requirements_test.txt -c package_constraints.txt \
&& rm -f requirements_test.txt package_constraints.txt
&& rm -f requirements_test.txt package_constraints.txt requirements_test_pre_commit.txt
# Set the default shell to bash instead of sh
ENV SHELL /bin/bash

View File

@@ -45,7 +45,7 @@ stages:
. venv/bin/activate
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
pre-commit install-hooks
pre-commit install-hooks --config .pre-commit-config-all.yaml
- script: |
. venv/bin/activate
pre-commit run flake8 --all-files
@@ -84,7 +84,7 @@ stages:
. venv/bin/activate
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
pre-commit install-hooks
pre-commit install-hooks --config .pre-commit-config-all.yaml
- script: |
. venv/bin/activate
pre-commit run black --all-files
@@ -127,7 +127,7 @@ stages:
set -e
. venv/bin/activate
pytest --timeout=9 --durations=10 -n 2 --dist loadfile -qq -o console_output_style=count -p no:sugar tests
pytest --timeout=9 --durations=10 -n auto --dist=loadfile -qq -o console_output_style=count -p no:sugar tests
script/check_dirty
displayName: 'Run pytest for python $(python.container)'
condition: and(succeeded(), ne(variables['python.container'], variables['PythonMain']))
@@ -135,7 +135,7 @@ stages:
set -e
. venv/bin/activate
pytest --timeout=9 --durations=10 -n 2 --dist loadfile --cov homeassistant --cov-report html -qq -o console_output_style=count -p no:sugar tests
pytest --timeout=9 --durations=10 -n auto --dist=loadfile --cov homeassistant --cov-report html -qq -o console_output_style=count -p no:sugar tests
codecov --token $(codecovToken)
script/check_dirty
displayName: 'Run pytest for python $(python.container) / coverage'
@@ -182,8 +182,8 @@ stages:
. venv/bin/activate
pip install -e . -r requirements_test.txt -c homeassistant/package_constraints.txt
pre-commit install-hooks
pre-commit install-hooks --config .pre-commit-config-all.yaml
- script: |
. venv/bin/activate
pre-commit run mypy --all-files
pre-commit run --config .pre-commit-config-all.yaml mypy --all-files
displayName: 'Run mypy'

View File

@@ -261,7 +261,7 @@ class AuthManager:
"""Enable a multi-factor auth module for user."""
if user.system_generated:
raise ValueError(
"System generated users cannot enable " "multi-factor auth module."
"System generated users cannot enable multi-factor auth module."
)
module = self.get_auth_mfa_module(mfa_module_id)
@@ -276,7 +276,7 @@ class AuthManager:
"""Disable a multi-factor auth module for user."""
if user.system_generated:
raise ValueError(
"System generated users cannot disable " "multi-factor auth module."
"System generated users cannot disable multi-factor auth module."
)
module = self.get_auth_mfa_module(mfa_module_id)
@@ -320,7 +320,7 @@ class AuthManager:
if user.system_generated != (token_type == models.TOKEN_TYPE_SYSTEM):
raise ValueError(
"System generated users can only have system type " "refresh tokens"
"System generated users can only have system type refresh tokens"
)
if token_type == models.TOKEN_TYPE_NORMAL and client_id is None:
@@ -330,7 +330,7 @@ class AuthManager:
token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
and client_name is None
):
raise ValueError("Client_name is required for long-lived access " "token")
raise ValueError("Client_name is required for long-lived access token")
if token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN:
for token in user.refresh_tokens.values():

View File

@@ -215,7 +215,11 @@ class TotpSetupFlow(SetupFlow):
else:
hass = self._auth_module.hass
self._ota_secret, self._url, self._image = await hass.async_add_executor_job(
(
self._ota_secret,
self._url,
self._image,
) = await hass.async_add_executor_job(
_generate_secret_and_qr_code, # type: ignore
str(self._user.name),
)

View File

@@ -33,6 +33,8 @@ STAGE_1_INTEGRATIONS = {
"recorder",
# To make sure we forward data to other instances
"mqtt_eventstream",
# To provide account link implementations
"cloud",
}

View File

@@ -0,0 +1,22 @@
{
"config": {
"abort": {
"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."
},
"error": {
"connection_error": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u0441 Abode.",
"identifier_exists": "\u041f\u0440\u043e\u0444\u0438\u043b\u044a\u0442 \u0435 \u0432\u0435\u0447\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0430\u043d.",
"invalid_credentials": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0438 \u0434\u0430\u043d\u043d\u0438."
},
"step": {
"user": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u0430",
"username": "E-mail \u0430\u0434\u0440\u0435\u0441"
},
"title": "\u041f\u043e\u043f\u044a\u043b\u043d\u0435\u0442\u0435 \u0412\u0430\u0448\u0430\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0432\u0445\u043e\u0434 \u0432 Abode"
}
},
"title": "Abode"
}
}

View File

@@ -0,0 +1,22 @@
{
"config": {
"abort": {
"single_instance_allowed": "Je povolena pouze jedna konfigurace Abode."
},
"error": {
"connection_error": "Nelze se p\u0159ipojit k Abode.",
"identifier_exists": "\u00da\u010det je ji\u017e zaregistrov\u00e1n.",
"invalid_credentials": "Neplatn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje."
},
"step": {
"user": {
"data": {
"password": "Heslo",
"username": "E-mailov\u00e1 adresa"
},
"title": "Vypl\u0148te p\u0159ihla\u0161ovac\u00ed \u00fadaje Abode"
}
},
"title": "Abode"
}
}

View File

@@ -1,8 +1,17 @@
{
"config": {
"abort": {
"single_instance_allowed": "Somente uma \u00fanica configura\u00e7\u00e3o de Abode \u00e9 permitida."
},
"error": {
"connection_error": "N\u00e3o foi poss\u00edvel conectar ao Abode.",
"identifier_exists": "Conta j\u00e1 cadastrada.",
"invalid_credentials": "Credenciais inv\u00e1lidas."
},
"step": {
"user": {
"data": {
"password": "Senha",
"username": "Endere\u00e7o de e-mail"
}
}

View File

@@ -20,10 +20,17 @@ from homeassistant.const import (
CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP,
)
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity
from .const import ATTRIBUTION, DOMAIN, DEFAULT_CACHEDB
from .const import (
ATTRIBUTION,
DOMAIN,
DEFAULT_CACHEDB,
SIGNAL_CAPTURE_IMAGE,
SIGNAL_TRIGGER_QUICK_ACTION,
)
_LOGGER = logging.getLogger(__name__)
@@ -89,7 +96,7 @@ class AbodeSystem:
self.abode = abode
self.polling = polling
self.devices = []
self.entity_ids = set()
self.logout_listener = None
@@ -179,27 +186,29 @@ def setup_hass_services(hass):
"""Capture a new image."""
entity_ids = call.data.get(ATTR_ENTITY_ID)
target_devices = [
device
for device in hass.data[DOMAIN].devices
if device.entity_id in entity_ids
target_entities = [
entity_id
for entity_id in hass.data[DOMAIN].entity_ids
if entity_id in entity_ids
]
for device in target_devices:
device.capture()
for entity_id in target_entities:
signal = SIGNAL_CAPTURE_IMAGE.format(entity_id)
dispatcher_send(hass, signal)
def trigger_quick_action(call):
"""Trigger a quick action."""
entity_ids = call.data.get(ATTR_ENTITY_ID, None)
target_devices = [
device
for device in hass.data[DOMAIN].devices
if device.entity_id in entity_ids
target_entities = [
entity_id
for entity_id in hass.data[DOMAIN].entity_ids
if entity_id in entity_ids
]
for device in target_devices:
device.trigger()
for entity_id in target_entities:
signal = SIGNAL_TRIGGER_QUICK_ACTION.format(entity_id)
dispatcher_send(hass, signal)
hass.services.register(
DOMAIN, SERVICE_SETTINGS, change_setting, schema=CHANGE_SETTING_SCHEMA
@@ -290,6 +299,7 @@ class AbodeDevice(Entity):
self._device.device_id,
self._update_callback,
)
self.hass.data[DOMAIN].entity_ids.add(self.entity_id)
async def async_will_remove_from_hass(self):
"""Unsubscribe from device events."""
@@ -352,13 +362,14 @@ class AbodeAutomation(Entity):
self._event = event
async def async_added_to_hass(self):
"""Subscribe Abode events."""
"""Subscribe to a group of Abode timeline events."""
if self._event:
self.hass.async_add_job(
self._data.abode.events.add_event_callback,
self._event,
self._update_callback,
)
self.hass.data[DOMAIN].entity_ids.add(self.entity_id)
@property
def should_poll(self):

View File

@@ -23,9 +23,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up an alarm control panel for an Abode device."""
"""Set up Abode alarm control panel device."""
data = hass.data[DOMAIN]
async_add_entities(
[AbodeAlarm(data, await hass.async_add_executor_job(data.abode.get_alarm))]
)

View File

@@ -5,9 +5,10 @@ import abodepy.helpers.constants as CONST
import abodepy.helpers.timeline as TIMELINE
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import AbodeAutomation, AbodeDevice
from .const import DOMAIN
from .const import DOMAIN, SIGNAL_TRIGGER_QUICK_ACTION
_LOGGER = logging.getLogger(__name__)
@@ -18,7 +19,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a sensor for an Abode device."""
"""Set up Abode binary sensor devices."""
data = hass.data[DOMAIN]
device_types = [
@@ -29,19 +30,19 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
CONST.TYPE_OPENING,
]
devices = []
entities = []
for device in data.abode.get_devices(generic_type=device_types):
devices.append(AbodeBinarySensor(data, device))
entities.append(AbodeBinarySensor(data, device))
for automation in data.abode.get_automations(generic_type=CONST.TYPE_QUICK_ACTION):
devices.append(
entities.append(
AbodeQuickActionBinarySensor(
data, automation, TIMELINE.AUTOMATION_EDIT_GROUP
)
)
async_add_entities(devices)
async_add_entities(entities)
class AbodeBinarySensor(AbodeDevice, BinarySensorDevice):
@@ -61,6 +62,12 @@ class AbodeBinarySensor(AbodeDevice, BinarySensorDevice):
class AbodeQuickActionBinarySensor(AbodeAutomation, BinarySensorDevice):
"""A binary sensor implementation for Abode quick action automations."""
async def async_added_to_hass(self):
"""Subscribe Abode events."""
await super().async_added_to_hass()
signal = SIGNAL_TRIGGER_QUICK_ACTION.format(self.entity_id)
async_dispatcher_connect(self.hass, signal, self.trigger)
def trigger(self):
"""Trigger a quick automation."""
self._automation.trigger()

View File

@@ -7,10 +7,11 @@ import abodepy.helpers.timeline as TIMELINE
import requests
from homeassistant.components.camera import Camera
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.util import Throttle
from . import AbodeDevice
from .const import DOMAIN
from .const import DOMAIN, SIGNAL_CAPTURE_IMAGE
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90)
@@ -23,15 +24,15 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a camera for an Abode device."""
"""Set up Abode camera devices."""
data = hass.data[DOMAIN]
devices = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_CAMERA):
devices.append(AbodeCamera(data, device, TIMELINE.CAPTURE_IMAGE))
entities = []
async_add_entities(devices)
for device in data.abode.get_devices(generic_type=CONST.TYPE_CAMERA):
entities.append(AbodeCamera(data, device, TIMELINE.CAPTURE_IMAGE))
async_add_entities(entities)
class AbodeCamera(AbodeDevice, Camera):
@@ -54,6 +55,9 @@ class AbodeCamera(AbodeDevice, Camera):
self._capture_callback,
)
signal = SIGNAL_CAPTURE_IMAGE.format(self.entity_id)
async_dispatcher_connect(self.hass, signal, self.capture)
def capture(self):
"""Request a new image capture."""
return self._device.capture()

View File

@@ -3,3 +3,6 @@ DOMAIN = "abode"
ATTRIBUTION = "Data provided by goabode.com"
DEFAULT_CACHEDB = "abodepy_cache.pickle"
SIGNAL_CAPTURE_IMAGE = "abode_camera_capture_{}"
SIGNAL_TRIGGER_QUICK_ACTION = "abode_trigger_quick_action_{}"

View File

@@ -18,14 +18,14 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Abode cover devices."""
data = hass.data[DOMAIN]
devices = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_COVER):
devices.append(AbodeCover(data, device))
entities = []
async_add_entities(devices)
for device in data.abode.get_devices(generic_type=CONST.TYPE_COVER):
entities.append(AbodeCover(data, device))
async_add_entities(entities)
class AbodeCover(AbodeDevice, CoverDevice):

View File

@@ -33,12 +33,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Abode light devices."""
data = hass.data[DOMAIN]
devices = []
entities = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_LIGHT):
devices.append(AbodeLight(data, device))
entities.append(AbodeLight(data, device))
async_add_entities(devices)
async_add_entities(entities)
class AbodeLight(AbodeDevice, Light):

View File

@@ -18,14 +18,14 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Abode lock devices."""
data = hass.data[DOMAIN]
devices = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_LOCK):
devices.append(AbodeLock(data, device))
entities = []
async_add_entities(devices)
for device in data.abode.get_devices(generic_type=CONST.TYPE_LOCK):
entities.append(AbodeLock(data, device))
async_add_entities(entities)
class AbodeLock(AbodeDevice, LockDevice):

View File

@@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/abode",
"requirements": [
"abodepy==0.16.6"
"abodepy==0.16.7"
],
"dependencies": [],
"codeowners": [

View File

@@ -16,9 +16,9 @@ _LOGGER = logging.getLogger(__name__)
# Sensor types: Name, icon
SENSOR_TYPES = {
"temp": ["Temperature", DEVICE_CLASS_TEMPERATURE],
"humidity": ["Humidity", DEVICE_CLASS_HUMIDITY],
"lux": ["Lux", DEVICE_CLASS_ILLUMINANCE],
CONST.TEMP_STATUS_KEY: ["Temperature", DEVICE_CLASS_TEMPERATURE],
CONST.HUMI_STATUS_KEY: ["Humidity", DEVICE_CLASS_HUMIDITY],
CONST.LUX_STATUS_KEY: ["Lux", DEVICE_CLASS_ILLUMINANCE],
}
@@ -28,16 +28,18 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a sensor for an Abode device."""
"""Set up Abode sensor devices."""
data = hass.data[DOMAIN]
devices = []
entities = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_SENSOR):
for sensor_type in SENSOR_TYPES:
devices.append(AbodeSensor(data, device, sensor_type))
if sensor_type not in device.get_value(CONST.STATUSES_KEY):
continue
entities.append(AbodeSensor(data, device, sensor_type))
async_add_entities(devices)
async_add_entities(entities)
class AbodeSensor(AbodeDevice):
@@ -62,6 +64,11 @@ class AbodeSensor(AbodeDevice):
"""Return the device class."""
return self._device_class
@property
def unique_id(self):
"""Return a unique ID to use for this device."""
return f"{self._device.device_uuid}-{self._sensor_type}"
@property
def state(self):
"""Return the state of the sensor."""

View File

@@ -21,17 +21,17 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Abode switch devices."""
data = hass.data[DOMAIN]
devices = []
entities = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_SWITCH):
devices.append(AbodeSwitch(data, device))
entities.append(AbodeSwitch(data, device))
for automation in data.abode.get_automations(generic_type=CONST.TYPE_AUTOMATION):
devices.append(
entities.append(
AbodeAutomationSwitch(data, automation, TIMELINE.AUTOMATION_EDIT_GROUP)
)
async_add_entities(devices)
async_add_entities(entities)
class AbodeSwitch(AbodeDevice, SwitchDevice):

View File

@@ -1,6 +1,8 @@
{
"config": {
"abort": {
"adguard_home_addon_outdated": "\u0422\u0430\u0437\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u0438\u0441\u043a\u0432\u0430 AdGuard Home {minimal_version} \u0438\u043b\u0438 \u043f\u043e-\u043d\u043e\u0432\u0430 {minimal_version}, \u0438\u043c\u0430\u0442\u0435 {current_version}. \u041c\u043e\u043b\u044f, \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u0439\u0442\u0435 \u0432\u0430\u0448\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 \u0437\u0430 Hass.io AdGuard Home.",
"adguard_home_outdated": "\u0422\u0430\u0437\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u0438\u0441\u043a\u0432\u0430 AdGuard Home {minimal_version} \u0438\u043b\u0438 \u043f\u043e-\u043d\u043e\u0432\u0430 {minimal_version}, \u0438\u043c\u0430\u0442\u0435 {current_version}.",
"existing_instance_updated": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0430\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f.",
"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 AdGuard Home."
},

View File

@@ -1,6 +1,8 @@
{
"config": {
"abort": {
"adguard_home_addon_outdated": "Questa integrazione richiede AdGuard Home {minimal_version} o versione successiva, si dispone di {current_version}. Aggiorna il componente aggiuntivo Hass.io AdGuard Home.",
"adguard_home_outdated": "Questa integrazione richiede AdGuard Home {minimal_version} o versione successiva, si dispone di {current_version}.",
"existing_instance_updated": "Configurazione esistente aggiornata.",
"single_instance_allowed": "\u00c8 consentita solo una singola configurazione di AdGuard Home."
},

View File

@@ -0,0 +1,22 @@
{
"config": {
"error": {
"auth": "API \u043a\u043b\u044e\u0447\u044a\u0442 \u043d\u0435 \u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0435\u043d.",
"name_exists": "\u0418\u043c\u0435\u0442\u043e \u0432\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430.",
"wrong_location": "\u0412 \u0442\u0430\u0437\u0438 \u043e\u0431\u043b\u0430\u0441\u0442 \u043d\u044f\u043c\u0430 \u0438\u0437\u043c\u0435\u0440\u0432\u0430\u0442\u0435\u043b\u043d\u0438 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u043d\u0430 Airly."
},
"step": {
"user": {
"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"
},
"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",
"title": "Airly"
}
},
"title": "Airly"
}
}

View File

@@ -0,0 +1,11 @@
{
"device_automation": {
"action_type": {
"arm_away": "\u0421\u043b\u043e\u0436\u0438 {entity_name} \u043f\u043e\u0434 \u043e\u0445\u0440\u0430\u043d\u0430 \u0432 \u0440\u0435\u0436\u0438\u043c \u043e\u0442\u0441\u044a\u0441\u0442\u0432\u0438\u0435",
"arm_home": "\u0421\u043b\u043e\u0436\u0438 {entity_name} \u043f\u043e\u0434 \u043e\u0445\u0440\u0430\u043d\u0430 \u0432 \u0440\u0435\u0436\u0438\u043c \u0432\u043a\u044a\u0449\u0438",
"arm_night": "\u0421\u043b\u043e\u0436\u0438 {entity_name} \u043f\u043e\u0434 \u043e\u0445\u0440\u0430\u043d\u0430 \u0432 \u043d\u043e\u0449\u0435\u043d \u0440\u0435\u0436\u0438\u043c",
"disarm": "\u0414\u0435\u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0439 {entity_name}",
"trigger": "\u0417\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0430\u043d\u0435 {entity_name}"
}
}
}

View File

@@ -0,0 +1,11 @@
{
"device_automation": {
"action_type": {
"arm_away": "Aktivovat {entity_name} v re\u017eimu mimo domov",
"arm_home": "Aktivovat {entity_name} v re\u017eimu doma",
"arm_night": "Aktivovat {entity_name} v re\u017eimu noc",
"disarm": "Deaktivovat {entity_name}",
"trigger": "Spustit {entity_name}"
}
}
}

View File

@@ -1,6 +1,9 @@
{
"device_automation": {
"action_type": {
"arm_away": "Inschakelen {entity_name} afwezig",
"arm_home": "Inschakelen {entity_name} thuis",
"arm_night": "Inschakelen {entity_name} nacht",
"disarm": "Uitschakelen {entity_name}",
"trigger": "Trigger {entity_name}"
}

View File

@@ -1,6 +1,10 @@
{
"device_automation": {
"action_type": {
"arm_away": "Armar {entity_name} longe",
"arm_home": "Armar {entity_name} casa",
"arm_night": "Armar {entity_name} noite",
"disarm": "Desarmar {entity_name}",
"trigger": "Disparar {entidade_nome}"
}
}

View File

@@ -1,6 +1,10 @@
{
"device_automation": {
"action_type": {
"arm_away": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u043e\u0445\u0440\u0430\u043d\u044b \"\u041d\u0435 \u0434\u043e\u043c\u0430\" \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 {entity_name}",
"arm_home": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u043e\u0445\u0440\u0430\u043d\u044b \"\u0414\u043e\u043c\u0430\" \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 {entity_name}",
"arm_night": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u043e\u0445\u0440\u0430\u043d\u044b \"\u041d\u043e\u0447\u044c\" \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 {entity_name}",
"disarm": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0445\u0440\u0430\u043d\u0443 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 {entity_name}",
"trigger": "{entity_name} \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442"
}
}

View File

@@ -0,0 +1,84 @@
"""Reproduce an Alarm control panel state."""
import asyncio
import logging
from typing import Iterable, Optional
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
SERVICE_ALARM_ARM_HOME,
SERVICE_ALARM_ARM_NIGHT,
SERVICE_ALARM_DISARM,
SERVICE_ALARM_TRIGGER,
STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_CUSTOM_BYPASS,
STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED,
)
from homeassistant.core import Context, State
from homeassistant.helpers.typing import HomeAssistantType
from . import DOMAIN
_LOGGER = logging.getLogger(__name__)
VALID_STATES = {
STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_CUSTOM_BYPASS,
STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED,
}
async def _async_reproduce_state(
hass: HomeAssistantType, state: State, context: Optional[Context] = None
) -> None:
"""Reproduce a single state."""
cur_state = hass.states.get(state.entity_id)
if cur_state is None:
_LOGGER.warning("Unable to find entity %s", state.entity_id)
return
if state.state not in VALID_STATES:
_LOGGER.warning(
"Invalid state specified for %s: %s", state.entity_id, state.state
)
return
# Return if we are already at the right state.
if cur_state.state == state.state:
return
service_data = {ATTR_ENTITY_ID: state.entity_id}
if state.state == STATE_ALARM_ARMED_AWAY:
service = SERVICE_ALARM_ARM_AWAY
elif state.state == STATE_ALARM_ARMED_CUSTOM_BYPASS:
service = SERVICE_ALARM_ARM_CUSTOM_BYPASS
elif state.state == STATE_ALARM_ARMED_HOME:
service = SERVICE_ALARM_ARM_HOME
elif state.state == STATE_ALARM_ARMED_NIGHT:
service = SERVICE_ALARM_ARM_NIGHT
elif state.state == STATE_ALARM_DISARMED:
service = SERVICE_ALARM_DISARM
elif state.state == STATE_ALARM_TRIGGERED:
service = SERVICE_ALARM_TRIGGER
await hass.services.async_call(
DOMAIN, service, service_data, context=context, blocking=True
)
async def async_reproduce_states(
hass: HomeAssistantType, states: Iterable[State], context: Optional[Context] = None
) -> None:
"""Reproduce Alarm control panel states."""
await asyncio.gather(
*(_async_reproduce_state(hass, state, context) for state in states)
)

View File

@@ -10,6 +10,16 @@ alarm_disarm:
description: An optional code to disarm the alarm control panel with.
example: 1234
alarm_arm_custom_bypass:
description: Send arm custom bypass command.
fields:
entity_id:
description: Name of alarm control panel to arm custom bypass.
example: 'alarm_control_panel.downstairs'
code:
description: An optional code to arm custom bypass the alarm control panel with.
example: 1234
alarm_arm_home:
description: Send the alarm the command for arm home.
fields:

View File

@@ -12,11 +12,14 @@ from homeassistant.const import (
STATE_LOCKED,
STATE_OFF,
STATE_ON,
STATE_PAUSED,
STATE_PLAYING,
STATE_UNAVAILABLE,
STATE_UNLOCKED,
STATE_UNKNOWN,
STATE_UNLOCKED,
)
import homeassistant.components.climate.const as climate
import homeassistant.components.media_player.const as media_player
from homeassistant.components.alarm_control_panel import ATTR_CODE_FORMAT, FORMAT_NUMBER
from homeassistant.components import light, fan, cover
import homeassistant.util.color as color_util
@@ -110,6 +113,11 @@ class AlexaCapability:
"""Return the Configuration object."""
return []
@staticmethod
def supported_operations():
"""Return the supportedOperations object."""
return []
def serialize_discovery(self):
"""Serialize according to the Discovery API."""
result = {"type": "AlexaInterface", "interface": self.name(), "version": "3"}
@@ -150,6 +158,10 @@ class AlexaCapability:
if instance is not None:
result["instance"] = instance
supported_operations = self.supported_operations()
if supported_operations:
result["supportedOperations"] = supported_operations
return result
def serialize_properties(self):
@@ -484,6 +496,28 @@ class AlexaPlaybackController(AlexaCapability):
"""Return the Alexa API name of this interface."""
return "Alexa.PlaybackController"
def supported_operations(self):
"""Return the supportedOperations object.
Supported Operations: FastForward, Next, Pause, Play, Previous, Rewind, StartOver, Stop
"""
supported_features = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
operations = {
media_player.SUPPORT_NEXT_TRACK: "Next",
media_player.SUPPORT_PAUSE: "Pause",
media_player.SUPPORT_PLAY: "Play",
media_player.SUPPORT_PREVIOUS_TRACK: "Previous",
media_player.SUPPORT_STOP: "Stop",
}
supported_operations = []
for operation in operations:
if operation & supported_features:
supported_operations.append(operations[operation])
return supported_operations
class AlexaInputController(AlexaCapability):
"""Implements Alexa.InputController.
@@ -704,6 +738,33 @@ class AlexaThermostatController(AlexaCapability):
return {"value": temp, "scale": API_TEMP_UNITS[unit]}
def configuration(self):
"""Return configuration object.
Translates climate HVAC_MODES and PRESETS to supported Alexa ThermostatMode Values.
ThermostatMode Value must be AUTO, COOL, HEAT, ECO, OFF, or CUSTOM.
"""
supported_modes = []
hvac_modes = self.entity.attributes.get(climate.ATTR_HVAC_MODES)
for mode in hvac_modes:
thermostat_mode = API_THERMOSTAT_MODES.get(mode)
if thermostat_mode:
supported_modes.append(thermostat_mode)
preset_modes = self.entity.attributes.get(climate.ATTR_PRESET_MODES)
for mode in preset_modes:
thermostat_mode = API_THERMOSTAT_PRESETS.get(mode)
if thermostat_mode:
supported_modes.append(thermostat_mode)
# Return False for supportsScheduling until supported with event listener in handler.
configuration = {"supportsScheduling": False}
if supported_modes:
configuration["supportedModes"] = supported_modes
return configuration
class AlexaPowerLevelController(AlexaCapability):
"""Implements Alexa.PowerLevelController.
@@ -1078,3 +1139,50 @@ class AlexaDoorbellEventSource(AlexaCapability):
def capability_proactively_reported(self):
"""Return True for proactively reported capability."""
return True
class AlexaPlaybackStateReporter(AlexaCapability):
"""Implements Alexa.PlaybackStateReporter.
https://developer.amazon.com/docs/device-apis/alexa-playbackstatereporter.html
"""
def name(self):
"""Return the Alexa API name of this interface."""
return "Alexa.PlaybackStateReporter"
def properties_supported(self):
"""Return what properties this entity supports."""
return [{"name": "playbackState"}]
def properties_proactively_reported(self):
"""Return True if properties asynchronously reported."""
return True
def properties_retrievable(self):
"""Return True if properties can be retrieved."""
return True
def get_property(self, name):
"""Read and return a property."""
if name != "playbackState":
raise UnsupportedProperty(name)
playback_state = self.entity.state
if playback_state == STATE_PLAYING:
return {"state": "PLAYING"}
if playback_state == STATE_PAUSED:
return {"state": "PAUSED"}
return {"state": "STOPPED"}
class AlexaSeekController(AlexaCapability):
"""Implements Alexa.SeekController.
https://developer.amazon.com/docs/device-apis/alexa-seekcontroller.html
"""
def name(self):
"""Return the Alexa API name of this interface."""
return "Alexa.SeekController"

View File

@@ -56,9 +56,10 @@ API_THERMOSTAT_MODES = OrderedDict(
(climate.HVAC_MODE_AUTO, "AUTO"),
(climate.HVAC_MODE_OFF, "OFF"),
(climate.HVAC_MODE_FAN_ONLY, "OFF"),
(climate.HVAC_MODE_DRY, "OFF"),
(climate.HVAC_MODE_DRY, "CUSTOM"),
]
)
API_THERMOSTAT_MODES_CUSTOM = {climate.HVAC_MODE_DRY: "DEHUMIDIFY"}
API_THERMOSTAT_PRESETS = {climate.PRESET_ECO: "ECO"}
PERCENTAGE_FAN_MAP = {

View File

@@ -46,11 +46,13 @@ from .capabilities import (
AlexaMotionSensor,
AlexaPercentageController,
AlexaPlaybackController,
AlexaPlaybackStateReporter,
AlexaPowerController,
AlexaPowerLevelController,
AlexaRangeController,
AlexaSceneController,
AlexaSecurityPanelController,
AlexaSeekController,
AlexaSpeaker,
AlexaStepSpeaker,
AlexaTemperatureSensor,
@@ -391,6 +393,10 @@ class MediaPlayerCapabilities(AlexaEntity):
def default_display_categories(self):
"""Return the display categories for this entity."""
device_class = self.entity.attributes.get(ATTR_DEVICE_CLASS)
if device_class == media_player.DEVICE_CLASS_SPEAKER:
return [DisplayCategory.SPEAKER]
return [DisplayCategory.TV]
def interfaces(self):
@@ -418,6 +424,10 @@ class MediaPlayerCapabilities(AlexaEntity):
)
if supported & playback_features:
yield AlexaPlaybackController(self.entity)
yield AlexaPlaybackStateReporter(self.entity)
if supported & media_player.const.SUPPORT_SEEK:
yield AlexaSeekController(self.entity)
if supported & media_player.SUPPORT_SELECT_SOURCE:
yield AlexaInputController(self.entity)

View File

@@ -111,3 +111,10 @@ class AlexaInvalidDirectiveError(AlexaError):
namespace = "Alexa"
error_type = "INVALID_DIRECTIVE"
class AlexaVideoActionNotPermittedForContentError(AlexaError):
"""Class to represent action not permitted for content errors."""
namespace = "Alexa.Video"
error_type = "ACTION_NOT_PERMITTED_FOR_CONTENT"

View File

@@ -38,6 +38,7 @@ from homeassistant.util.temperature import convert as convert_temperature
from .const import (
API_TEMP_UNITS,
API_THERMOSTAT_MODES_CUSTOM,
API_THERMOSTAT_MODES,
API_THERMOSTAT_PRESETS,
Cause,
@@ -53,6 +54,7 @@ from .errors import (
AlexaSecurityPanelUnauthorizedError,
AlexaTempRangeError,
AlexaUnsupportedThermostatModeError,
AlexaVideoActionNotPermittedForContentError,
)
from .state_report import async_enable_proactive_mode
@@ -767,11 +769,28 @@ async def async_api_set_thermostat_mode(hass, config, directive, context):
raise AlexaUnsupportedThermostatModeError(msg)
service = climate.SERVICE_SET_PRESET_MODE
data[climate.ATTR_PRESET_MODE] = climate.PRESET_ECO
data[climate.ATTR_PRESET_MODE] = ha_preset
elif mode == "CUSTOM":
operation_list = entity.attributes.get(climate.ATTR_HVAC_MODES)
custom_mode = directive.payload["thermostatMode"]["customName"]
custom_mode = next(
(k for k, v in API_THERMOSTAT_MODES_CUSTOM.items() if v == custom_mode),
None,
)
if custom_mode not in operation_list:
msg = (
f"The requested thermostat mode {mode}: {custom_mode} is not supported"
)
raise AlexaUnsupportedThermostatModeError(msg)
service = climate.SERVICE_SET_HVAC_MODE
data[climate.ATTR_HVAC_MODE] = custom_mode
else:
operation_list = entity.attributes.get(climate.ATTR_HVAC_MODES)
ha_mode = next((k for k, v in API_THERMOSTAT_MODES.items() if v == mode), None)
ha_modes = {k: v for k, v in API_THERMOSTAT_MODES.items() if v == mode}
ha_mode = next(iter(set(ha_modes).intersection(operation_list)), None)
if ha_mode not in operation_list:
msg = f"The requested thermostat mode {mode} is not supported"
raise AlexaUnsupportedThermostatModeError(msg)
@@ -1168,3 +1187,45 @@ async def async_api_skipchannel(hass, config, directive, context):
)
return response
@HANDLERS.register(("Alexa.SeekController", "AdjustSeekPosition"))
async def async_api_seek(hass, config, directive, context):
"""Process a seek request."""
entity = directive.entity
position_delta = int(directive.payload["deltaPositionMilliseconds"])
current_position = entity.attributes.get(media_player.ATTR_MEDIA_POSITION)
if not current_position:
msg = f"{entity} did not return the current media position."
raise AlexaVideoActionNotPermittedForContentError(msg)
seek_position = int(current_position) + int(position_delta / 1000)
if seek_position < 0:
seek_position = 0
media_duration = entity.attributes.get(media_player.ATTR_MEDIA_DURATION)
if media_duration and 0 < int(media_duration) < seek_position:
seek_position = media_duration
data = {
ATTR_ENTITY_ID: entity.entity_id,
media_player.ATTR_MEDIA_SEEK_POSITION: seek_position,
}
await hass.services.async_call(
media_player.DOMAIN,
media_player.SERVICE_MEDIA_SEEK,
data,
blocking=False,
context=context,
)
# convert seconds to milliseconds for StateReport.
seek_position = int(seek_position * 1000)
payload = {"properties": [{"name": "positionMilliseconds", "value": seek_position}]}
return directive.response(
name="StateReport", namespace="Alexa.SeekController", payload=payload
)

View File

@@ -0,0 +1,9 @@
{
"config": {
"abort": {
"already_setup": "\u041c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0442\u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u0438\u043d Almond \u0430\u043a\u0430\u0443\u043d\u0442.",
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u0441 Almond \u0441\u044a\u0440\u0432\u044a\u0440\u0430."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,9 @@
{
"config": {
"abort": {
"already_setup": "Nom\u00e9s pots configurar un \u00fanic compte amb Almond.",
"cannot_connect": "No es pot connectar amb el servidor d'Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,9 @@
{
"config": {
"abort": {
"already_setup": "Sie k\u00f6nnen nur ein Almond-Konto konfigurieren.",
"cannot_connect": "Verbindung zum Almond-Server nicht m\u00f6glich."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,15 @@
{
"config": {
"abort": {
"already_setup": "You can only configure one Almond account.",
"cannot_connect": "Unable to connect to the Almond server.",
"missing_configuration": "Please check the documentation on how to set up Almond."
},
"step": {
"pick_implementation": {
"title": "Pick Authentication Method"
}
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,15 @@
{
"config": {
"abort": {
"already_setup": "S\u00f3lo puede configurar una cuenta de Almond.",
"cannot_connect": "No se puede conectar al servidor Almond.",
"missing_configuration": "Consulte la documentaci\u00f3n sobre c\u00f3mo configurar Almond."
},
"step": {
"pick_implementation": {
"title": "Seleccione el m\u00e9todo de autenticaci\u00f3n"
}
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "Vous ne pouvez configurer qu'un seul compte Almond",
"cannot_connect": "Impossible de se connecter au serveur Almond",
"missing_configuration": "Veuillez consulter la documentation pour savoir comment configurer Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "\u00c8 possibile configurare un solo account Almond.",
"cannot_connect": "Impossibile connettersi al server Almond.",
"missing_configuration": "Si prega di controllare la documentazione su come impostare Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,9 @@
{
"config": {
"abort": {
"already_setup": "\ud558\ub098\uc758 Almond \uacc4\uc815\ub9cc \uad6c\uc131 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.",
"cannot_connect": "Almond \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "Dir k\u00ebnnt n\u00ebmmen een eenzegen Almond Kont konfigur\u00e9ieren.",
"cannot_connect": "Kann sech net mam Almond Server verbannen.",
"missing_configuration": "Kuckt w.e.g. Dokumentatioun iwwert d'ariichten vun Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "U kunt slechts \u00e9\u00e9n Almond-account configureren.",
"cannot_connect": "Kan geen verbinding maken met de Almond-server.",
"missing_configuration": "Raadpleeg de documentatie over het instellen van Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "Du kan bare konfigurere en Almond konto.",
"cannot_connect": "Kan ikke koble til Almond-serveren.",
"missing_configuration": "Vennligst sjekk dokumentasjonen om hvordan du setter opp Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,9 @@
{
"config": {
"abort": {
"already_setup": "Mo\u017cesz skonfigurowa\u0107 tylko jedno konto Almond.",
"cannot_connect": "Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z serwerem Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430.",
"cannot_connect": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 Almond.",
"missing_configuration": "\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "Konfigurirate lahko samo en ra\u010dun Almond.",
"cannot_connect": "Ni mogo\u010de vzpostaviti povezave s stre\u017enikom Almond.",
"missing_configuration": "Prosimo, preverite dokumentacijo o tem, kako nastaviti Almond."
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,10 @@
{
"config": {
"abort": {
"already_setup": "\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44 Almond \u5e33\u865f\u3002",
"cannot_connect": "\u7121\u6cd5\u9023\u7dda\u81f3 Almond \u4f3a\u670d\u5668\u3002",
"missing_configuration": "\u8acb\u53c3\u8003\u76f8\u95dc\u6587\u4ef6\u4ee5\u4e86\u89e3\u5982\u4f55\u8a2d\u5b9a Almond\u3002"
},
"title": "Almond"
}
}

View File

@@ -0,0 +1,310 @@
"""Support for Almond."""
import asyncio
from datetime import timedelta
import logging
import time
from typing import Optional
import async_timeout
from aiohttp import ClientSession, ClientError
from pyalmond import AlmondLocalAuth, AbstractAlmondWebAuth, WebAlmondAPI
import voluptuous as vol
from homeassistant.core import HomeAssistant, CoreState
from homeassistant.const import CONF_TYPE, CONF_HOST, EVENT_HOMEASSISTANT_START
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.helpers import (
config_validation as cv,
config_entry_oauth2_flow,
event,
intent,
aiohttp_client,
storage,
network,
)
from homeassistant import config_entries
from homeassistant.components import conversation
from . import config_flow
from .const import DOMAIN, TYPE_LOCAL, TYPE_OAUTH2
CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"
STORAGE_VERSION = 1
STORAGE_KEY = DOMAIN
ALMOND_SETUP_DELAY = 30
DEFAULT_OAUTH2_HOST = "https://almond.stanford.edu"
DEFAULT_LOCAL_HOST = "http://localhost:3000"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Any(
vol.Schema(
{
vol.Required(CONF_TYPE): TYPE_OAUTH2,
vol.Required(CONF_CLIENT_ID): cv.string,
vol.Required(CONF_CLIENT_SECRET): cv.string,
vol.Optional(CONF_HOST, default=DEFAULT_OAUTH2_HOST): cv.url,
}
),
vol.Schema(
{vol.Required(CONF_TYPE): TYPE_LOCAL, vol.Required(CONF_HOST): cv.url}
),
)
},
extra=vol.ALLOW_EXTRA,
)
_LOGGER = logging.getLogger(__name__)
async def async_setup(hass, config):
"""Set up the Almond component."""
hass.data[DOMAIN] = {}
if DOMAIN not in config:
return True
conf = config[DOMAIN]
host = conf[CONF_HOST]
if conf[CONF_TYPE] == TYPE_OAUTH2:
config_flow.AlmondFlowHandler.async_register_implementation(
hass,
config_entry_oauth2_flow.LocalOAuth2Implementation(
hass,
DOMAIN,
conf[CONF_CLIENT_ID],
conf[CONF_CLIENT_SECRET],
f"{host}/me/api/oauth2/authorize",
f"{host}/me/api/oauth2/token",
),
)
return True
if not hass.config_entries.async_entries(DOMAIN):
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={"type": TYPE_LOCAL, "host": conf[CONF_HOST]},
)
)
return True
async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEntry):
"""Set up Almond config entry."""
websession = aiohttp_client.async_get_clientsession(hass)
if entry.data["type"] == TYPE_LOCAL:
auth = AlmondLocalAuth(entry.data["host"], websession)
else:
# OAuth2
implementation = await config_entry_oauth2_flow.async_get_config_entry_implementation(
hass, entry
)
oauth_session = config_entry_oauth2_flow.OAuth2Session(
hass, entry, implementation
)
auth = AlmondOAuth(entry.data["host"], websession, oauth_session)
api = WebAlmondAPI(auth)
agent = AlmondAgent(hass, api, entry)
# Hass.io does its own configuration.
if not entry.data.get("is_hassio"):
# If we're not starting or local, set up Almond right away
if hass.state != CoreState.not_running or entry.data["type"] == TYPE_LOCAL:
await _configure_almond_for_ha(hass, entry, api)
else:
# OAuth2 implementations can potentially rely on the HA Cloud url.
# This url is not be available until 30 seconds after boot.
async def configure_almond(_now):
try:
await _configure_almond_for_ha(hass, entry, api)
except ConfigEntryNotReady:
_LOGGER.warning(
"Unable to configure Almond to connect to Home Assistant"
)
async def almond_hass_start(_event):
event.async_call_later(hass, ALMOND_SETUP_DELAY, configure_almond)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, almond_hass_start)
conversation.async_set_agent(hass, agent)
return True
async def _configure_almond_for_ha(
hass: HomeAssistant, entry: config_entries.ConfigEntry, api: WebAlmondAPI
):
"""Configure Almond to connect to HA."""
if entry.data["type"] == TYPE_OAUTH2:
# If we're connecting over OAuth2, we will only set up connection
# with Home Assistant if we're remotely accessible.
hass_url = network.async_get_external_url(hass)
else:
hass_url = hass.config.api.base_url
# If hass_url is None, we're not going to configure Almond to connect to HA.
if hass_url is None:
return
_LOGGER.debug("Configuring Almond to connect to Home Assistant at %s", hass_url)
store = storage.Store(hass, STORAGE_VERSION, STORAGE_KEY)
data = await store.async_load()
if data is None:
data = {}
user = None
if "almond_user" in data:
user = await hass.auth.async_get_user(data["almond_user"])
if user is None:
user = await hass.auth.async_create_system_user("Almond", [GROUP_ID_ADMIN])
data["almond_user"] = user.id
await store.async_save(data)
refresh_token = await hass.auth.async_create_refresh_token(
user,
# Almond will be fine as long as we restart once every 5 years
access_token_expiration=timedelta(days=365 * 5),
)
# Create long lived access token
access_token = hass.auth.async_create_access_token(refresh_token)
# Store token in Almond
try:
with async_timeout.timeout(30):
await api.async_create_device(
{
"kind": "io.home-assistant",
"hassUrl": hass_url,
"accessToken": access_token,
"refreshToken": "",
# 5 years from now in ms.
"accessTokenExpires": (time.time() + 60 * 60 * 24 * 365 * 5) * 1000,
}
)
except (asyncio.TimeoutError, ClientError) as err:
if isinstance(err, asyncio.TimeoutError):
msg = "Request timeout"
else:
msg = err
_LOGGER.warning("Unable to configure Almond: %s", msg)
await hass.auth.async_remove_refresh_token(refresh_token)
raise ConfigEntryNotReady
# Clear all other refresh tokens
for token in list(user.refresh_tokens.values()):
if token.id != refresh_token.id:
await hass.auth.async_remove_refresh_token(token)
async def async_unload_entry(hass, entry):
"""Unload Almond."""
conversation.async_set_agent(hass, None)
return True
class AlmondOAuth(AbstractAlmondWebAuth):
"""Almond Authentication using OAuth2."""
def __init__(
self,
host: str,
websession: ClientSession,
oauth_session: config_entry_oauth2_flow.OAuth2Session,
):
"""Initialize Almond auth."""
super().__init__(host, websession)
self._oauth_session = oauth_session
async def async_get_access_token(self):
"""Return a valid access token."""
if not self._oauth_session.valid_token:
await self._oauth_session.async_ensure_token_valid()
return self._oauth_session.token["access_token"]
class AlmondAgent(conversation.AbstractConversationAgent):
"""Almond conversation agent."""
def __init__(
self, hass: HomeAssistant, api: WebAlmondAPI, entry: config_entries.ConfigEntry
):
"""Initialize the agent."""
self.hass = hass
self.api = api
self.entry = entry
@property
def attribution(self):
"""Return the attribution."""
return {"name": "Powered by Almond", "url": "https://almond.stanford.edu/"}
async def async_get_onboarding(self):
"""Get onboard url if not onboarded."""
if self.entry.data.get("onboarded"):
return None
host = self.entry.data["host"]
if self.entry.data.get("is_hassio"):
host = "/core_almond"
elif self.entry.data["type"] != TYPE_LOCAL:
host = f"{host}/me"
return {
"text": "Would you like to opt-in to share your anonymized commands with Stanford to improve Almond's responses?",
"url": f"{host}/conversation",
}
async def async_set_onboarding(self, shown):
"""Set onboarding status."""
self.hass.config_entries.async_update_entry(
self.entry, data={**self.entry.data, "onboarded": shown}
)
return True
async def async_process(
self, text: str, conversation_id: Optional[str] = None
) -> intent.IntentResponse:
"""Process a sentence."""
response = await self.api.async_converse_text(text, conversation_id)
first_choice = True
buffer = ""
for message in response["messages"]:
if message["type"] == "text":
buffer += "\n" + message["text"]
elif message["type"] == "picture":
buffer += "\n Picture: " + message["url"]
elif message["type"] == "rdl":
buffer += (
"\n Link: "
+ message["rdl"]["displayTitle"]
+ " "
+ message["rdl"]["webCallback"]
)
elif message["type"] == "choice":
if first_choice:
first_choice = False
else:
buffer += ","
buffer += f" {message['title']}"
intent_result = intent.IntentResponse()
intent_result.async_set_speech(buffer.strip())
return intent_result

View File

@@ -0,0 +1,125 @@
"""Config flow to connect with Home Assistant."""
import asyncio
import logging
import async_timeout
from aiohttp import ClientError
from yarl import URL
import voluptuous as vol
from pyalmond import AlmondLocalAuth, WebAlmondAPI
from homeassistant import data_entry_flow, config_entries, core
from homeassistant.helpers import config_entry_oauth2_flow, aiohttp_client
from .const import DOMAIN, TYPE_LOCAL, TYPE_OAUTH2
async def async_verify_local_connection(hass: core.HomeAssistant, host: str):
"""Verify that a local connection works."""
websession = aiohttp_client.async_get_clientsession(hass)
api = WebAlmondAPI(AlmondLocalAuth(host, websession))
try:
with async_timeout.timeout(10):
await api.async_list_apps()
return True
except (asyncio.TimeoutError, ClientError):
return False
@config_entries.HANDLERS.register(DOMAIN)
class AlmondFlowHandler(config_entry_oauth2_flow.AbstractOAuth2FlowHandler):
"""Implementation of the Almond OAuth2 config flow."""
DOMAIN = DOMAIN
host = None
hassio_discovery = None
@property
def logger(self) -> logging.Logger:
"""Return logger."""
return logging.getLogger(__name__)
@property
def extra_authorize_data(self) -> dict:
"""Extra data that needs to be appended to the authorize url."""
return {"scope": "profile user-read user-read-results user-exec-command"}
async def async_step_user(self, user_input=None):
"""Handle a flow start."""
# Only allow 1 instance.
if self._async_current_entries():
return self.async_abort(reason="already_setup")
return await super().async_step_user(user_input)
async def async_step_auth(self, user_input=None):
"""Handle authorize step."""
result = await super().async_step_auth(user_input)
if result["type"] == data_entry_flow.RESULT_TYPE_EXTERNAL_STEP:
self.host = str(URL(result["url"]).with_path("me"))
return result
async def async_oauth_create_entry(self, data: dict) -> dict:
"""Create an entry for the flow.
Ok to override if you want to fetch extra info or even add another step.
"""
# pylint: disable=invalid-name
self.CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
data["type"] = TYPE_OAUTH2
data["host"] = self.host
return self.async_create_entry(title=self.flow_impl.name, data=data)
async def async_step_import(self, user_input: dict = None) -> dict:
"""Import data."""
# Only allow 1 instance.
if self._async_current_entries():
return self.async_abort(reason="already_setup")
if not await async_verify_local_connection(self.hass, user_input["host"]):
self.logger.warning(
"Aborting import of Almond because we're unable to connect"
)
return self.async_abort(reason="cannot_connect")
# pylint: disable=invalid-name
self.CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
return self.async_create_entry(
title="Configuration.yaml",
data={"type": TYPE_LOCAL, "host": user_input["host"]},
)
async def async_step_hassio(self, user_input=None):
"""Receive a Hass.io discovery."""
if self._async_current_entries():
return self.async_abort(reason="already_setup")
self.hassio_discovery = user_input
return await self.async_step_hassio_confirm()
async def async_step_hassio_confirm(self, user_input=None):
"""Confirm a Hass.io discovery."""
data = self.hassio_discovery
if user_input is not None:
return self.async_create_entry(
title=data["addon"],
data={
"is_hassio": True,
"type": TYPE_LOCAL,
"host": f"http://{data['host']}:{data['port']}",
},
)
return self.async_show_form(
step_id="hassio_confirm",
description_placeholders={"addon": data["addon"]},
data_schema=vol.Schema({}),
)

View File

@@ -0,0 +1,4 @@
"""Constants for the Almond integration."""
DOMAIN = "almond"
TYPE_OAUTH2 = "oauth2"
TYPE_LOCAL = "local"

View File

@@ -0,0 +1,9 @@
{
"domain": "almond",
"name": "Almond",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/almond",
"dependencies": ["http", "conversation"],
"codeowners": ["@gcampax", "@balloob"],
"requirements": ["pyalmond==0.0.2"]
}

View File

@@ -0,0 +1,15 @@
{
"config": {
"step": {
"pick_implementation": {
"title": "Pick Authentication Method"
}
},
"abort": {
"already_setup": "You can only configure one Almond account.",
"cannot_connect": "Unable to connect to the Almond server.",
"missing_configuration": "Please check the documentation on how to set up Almond."
},
"title": "Almond"
}
}

View File

@@ -145,7 +145,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
)
def get_engine(hass, config):
def get_engine(hass, config, discovery_info=None):
"""Set up Amazon Polly speech component."""
output_format = config.get(CONF_OUTPUT_FORMAT)
sample_rate = config.get(CONF_SAMPLE_RATE, DEFAULT_SAMPLE_RATES[output_format])

View File

@@ -3,7 +3,7 @@
"name": "Androidtv",
"documentation": "https://www.home-assistant.io/integrations/androidtv",
"requirements": [
"adb-shell==0.0.7",
"adb-shell==0.0.8",
"androidtv==0.0.32"
],
"dependencies": [],

View File

@@ -287,8 +287,11 @@ class ADBDevice(MediaPlayerDevice):
"""Initialize the Android TV / Fire TV device."""
self.aftv = aftv
self._name = name
self._apps = APPS.copy()
self._apps.update(apps)
self._app_id_to_name = APPS.copy()
self._app_id_to_name.update(apps)
self._app_name_to_id = {
value: key for key, value in self._app_id_to_name.items()
}
self._keys = KEYS
self._device_properties = self.aftv.device_properties
@@ -328,7 +331,7 @@ class ADBDevice(MediaPlayerDevice):
@property
def app_name(self):
"""Return the friendly name of the current app."""
return self._apps.get(self._current_app, self._current_app)
return self._app_id_to_name.get(self._current_app, self._current_app)
@property
def available(self):
@@ -455,9 +458,13 @@ class AndroidTVDevice(ADBDevice):
return
# Get the updated state and attributes.
state, self._current_app, self._device, self._is_volume_muted, self._volume_level = (
self.aftv.update()
)
(
state,
self._current_app,
self._device,
self._is_volume_muted,
self._volume_level,
) = self.aftv.update()
self._state = ANDROIDTV_STATES.get(state)
if self._state is None:
@@ -514,7 +521,7 @@ class FireTVDevice(ADBDevice):
super().__init__(aftv, name, apps, turn_on_command, turn_off_command)
self._get_sources = get_sources
self._running_apps = None
self._sources = None
@adb_decorator(override_available=True)
def update(self):
@@ -534,23 +541,28 @@ class FireTVDevice(ADBDevice):
return
# Get the `state`, `current_app`, and `running_apps`.
state, self._current_app, self._running_apps = self.aftv.update(
self._get_sources
)
state, self._current_app, running_apps = self.aftv.update(self._get_sources)
self._state = ANDROIDTV_STATES.get(state)
if self._state is None:
self._available = False
if running_apps:
self._sources = [
self._app_id_to_name.get(app_id, app_id) for app_id in running_apps
]
else:
self._sources = None
@property
def source(self):
"""Return the current app."""
return self._current_app
return self._app_id_to_name.get(self._current_app, self._current_app)
@property
def source_list(self):
"""Return a list of running apps."""
return self._running_apps
return self._sources
@property
def supported_features(self):
@@ -571,6 +583,7 @@ class FireTVDevice(ADBDevice):
"""
if isinstance(source, str):
if not source.startswith("!"):
self.aftv.launch_app(source)
self.aftv.launch_app(self._app_name_to_id.get(source, source))
else:
self.aftv.stop_app(source[1:].lstrip())
source_ = source[1:].lstrip()
self.aftv.stop_app(self._app_name_to_id.get(source_, source_))

View File

@@ -0,0 +1,4 @@
# Describes the format for available arlo services
update:
description: Update the state for all cameras and the base station.

View File

@@ -3,7 +3,7 @@
"name": "Asuswrt",
"documentation": "https://www.home-assistant.io/integrations/asuswrt",
"requirements": [
"aioasuswrt==1.1.21"
"aioasuswrt==1.1.22"
],
"dependencies": [],
"codeowners": [

View File

@@ -25,7 +25,7 @@
},
"step": {
"init": {
"description": "\uc2dc\uac04 \uae30\ubc18\uc758 \uc77c\ud68c\uc6a9 \ube44\ubc00\ubc88\ud638\ub97c \uc0ac\uc6a9\ud558\ub294 2\ub2e8\uacc4 \uc778\uc99d\uc744 \ud558\ub824\uba74 \uc778\uc99d\uc6a9 \uc571\uc744 \uc774\uc6a9\ud574\uc11c QR \ucf54\ub4dc\ub97c \uc2a4\uce94\ud574\uc8fc\uc138\uc694. \uc778\uc99d\uc6a9 \uc571\uc740 [Google OTP](https://support.google.com/accounts/answer/1066447) \ub610\ub294 [Authy](https://authy.com/) \ub97c \ucd94\ucc9c\ub4dc\ub9bd\ub2c8\ub2e4.\n\n{qr_code}\n\n\uc2a4\uce94 \ud6c4\uc5d0 \uc0dd\uc131\ub41c 6\uc790\ub9ac \ucf54\ub4dc\ub97c \uc785\ub825\ud574\uc11c \uc124\uc815\uc744 \ud655\uc778\ud558\uc138\uc694. QR \ucf54\ub4dc \uc2a4\uce94\uc5d0 \ubb38\uc81c\uac00 \uc788\ub2e4\uba74, **`{code}`** \ucf54\ub4dc\ub85c \uc9c1\uc811 \uc124\uc815\ud574\ubcf4\uc138\uc694.",
"description": "\uc2dc\uac04 \uae30\ubc18\uc758 \uc77c\ud68c\uc6a9 \ube44\ubc00\ubc88\ud638\ub97c \uc0ac\uc6a9\ud558\ub294 2\ub2e8\uacc4 \uc778\uc99d\uc744 \uad6c\uc131\ud558\ub824\uba74 \uc778\uc99d\uc6a9 \uc571\uc744 \uc774\uc6a9\ud574\uc11c QR \ucf54\ub4dc\ub97c \uc2a4\uce94\ud574\uc8fc\uc138\uc694. \uc778\uc99d\uc6a9 \uc571\uc740 [Google OTP](https://support.google.com/accounts/answer/1066447) \ub610\ub294 [Authy](https://authy.com/) \ub97c \ucd94\ucc9c\ub4dc\ub9bd\ub2c8\ub2e4.\n\n{qr_code}\n\n\uc2a4\uce94 \ud6c4\uc5d0 \uc0dd\uc131\ub41c 6\uc790\ub9ac \ucf54\ub4dc\ub97c \uc785\ub825\ud574\uc11c \uc124\uc815\uc744 \ud655\uc778\ud558\uc138\uc694. QR \ucf54\ub4dc \uc2a4\uce94\uc5d0 \ubb38\uc81c\uac00 \uc788\ub2e4\uba74, **`{code}`** \ucf54\ub4dc\ub85c \uc9c1\uc811 \uc124\uc815\ud574\ubcf4\uc138\uc694.",
"title": "TOTP 2\ub2e8\uacc4 \uc778\uc99d \uad6c\uc131"
}
},

View File

@@ -4,7 +4,7 @@ import logging
import voluptuous as vol
from homeassistant import exceptions
from homeassistant.core import callback
from homeassistant.core import CALLBACK_TYPE, callback
from homeassistant.const import (
CONF_VALUE_TEMPLATE,
CONF_PLATFORM,
@@ -17,7 +17,8 @@ from homeassistant.helpers.event import async_track_state_change, async_track_sa
from homeassistant.helpers import condition, config_validation as cv, template
# mypy: allow-untyped-defs, no-check-untyped-defs
# mypy: allow-incomplete-defs, allow-untyped-calls, allow-untyped-defs
# mypy: no-check-untyped-defs
TRIGGER_SCHEMA = vol.All(
vol.Schema(
@@ -42,7 +43,7 @@ _LOGGER = logging.getLogger(__name__)
async def async_attach_trigger(
hass, config, action, automation_info, *, platform_type="numeric_state"
):
) -> CALLBACK_TYPE:
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
below = config.get(CONF_BELOW)
@@ -52,7 +53,7 @@ async def async_attach_trigger(
value_template = config.get(CONF_VALUE_TEMPLATE)
unsub_track_same = {}
entities_triggered = set()
period = {}
period: dict = {}
if value_template is not None:
value_template.hass = hass

View File

@@ -27,8 +27,8 @@ TRIGGER_SCHEMA = vol.All(
vol.Required(CONF_PLATFORM): "state",
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
# These are str on purpose. Want to catch YAML conversions
vol.Optional(CONF_FROM): str,
vol.Optional(CONF_TO): str,
vol.Optional(CONF_FROM): vol.Any(str, [str]),
vol.Optional(CONF_TO): vol.Any(str, [str]),
vol.Optional(CONF_FOR): vol.Any(
vol.All(cv.time_period, cv.positive_timedelta),
cv.template,

View File

@@ -28,7 +28,9 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema(
)
async def async_attach_trigger(hass, config, action, automation_info):
async def async_attach_trigger(
hass, config, action, automation_info, *, platform_type="numeric_state"
):
"""Listen for state changes based on configuration."""
value_template = config.get(CONF_VALUE_TEMPLATE)
value_template.hass = hass
@@ -65,7 +67,7 @@ async def async_attach_trigger(hass, config, action, automation_info):
variables = {
"trigger": {
"platform": "template",
"platform": platform_type,
"entity_id": entity_id,
"from_state": from_s,
"to_state": to_s,

View File

@@ -4,5 +4,5 @@
"documentation": "https://www.home-assistant.io/integrations/avea",
"dependencies": [],
"codeowners": ["@pattyland"],
"requirements": ["avea==1.2.8"]
}
"requirements": ["avea==1.4"]
}

View File

@@ -12,6 +12,7 @@
"device_unavailable": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u043d\u0435 \u0435 \u043d\u0430\u043b\u0438\u0447\u043d\u043e",
"faulty_credentials": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0438 \u0434\u0430\u043d\u043d\u0438"
},
"flow_title": "Axis \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e: {name} ({host})",
"step": {
"user": {
"data": {

View File

@@ -0,0 +1,5 @@
{
"config": {
"flow_title": "Za\u0159\u00edzen\u00ed Axis: {name} ({host})"
}
}

View File

@@ -12,6 +12,7 @@
"device_unavailable": "O dispositivo n\u00e3o est\u00e1 dispon\u00edvel",
"faulty_credentials": "Credenciais do usu\u00e1rio inv\u00e1lidas"
},
"flow_title": "Eixos do dispositivo: {name} ({host})",
"step": {
"user": {
"data": {

View File

@@ -0,0 +1 @@
"""The Azure Service Bus integration."""

View File

@@ -0,0 +1,12 @@
{
"domain": "azure_service_bus",
"name": "Azure Service Bus",
"documentation": "https://www.home-assistant.io/integrations/azure_service_bus",
"requirements": [
"azure-servicebus==0.50.1"
],
"dependencies": [],
"codeowners": [
"@hfurubotten"
]
}

View File

@@ -0,0 +1,106 @@
"""Support for azure service bus notification."""
import json
import logging
from azure.servicebus.aio import Message, ServiceBusClient
from azure.servicebus.common.errors import (
MessageSendFailed,
ServiceBusConnectionError,
ServiceBusResourceNotFound,
)
import voluptuous as vol
from homeassistant.components.notify import (
ATTR_DATA,
ATTR_TARGET,
ATTR_TITLE,
PLATFORM_SCHEMA,
BaseNotificationService,
)
from homeassistant.const import CONTENT_TYPE_JSON
import homeassistant.helpers.config_validation as cv
CONF_CONNECTION_STRING = "connection_string"
CONF_QUEUE_NAME = "queue"
CONF_TOPIC_NAME = "topic"
ATTR_ASB_MESSAGE = "message"
ATTR_ASB_TITLE = "title"
ATTR_ASB_TARGET = "target"
PLATFORM_SCHEMA = vol.All(
cv.has_at_least_one_key(CONF_QUEUE_NAME, CONF_TOPIC_NAME),
PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_CONNECTION_STRING): cv.string,
vol.Exclusive(
CONF_QUEUE_NAME, "output", "Can only send to a queue or a topic."
): cv.string,
vol.Exclusive(
CONF_TOPIC_NAME, "output", "Can only send to a queue or a topic."
): cv.string,
}
),
)
_LOGGER = logging.getLogger(__name__)
def get_service(hass, config, discovery_info=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)
# Library can do synchronous IO when creating the clients.
# Passes in loop here, but can't run setup on the event loop.
servicebus = ServiceBusClient.from_connection_string(
connection_string, loop=hass.loop
)
try:
if queue_name:
client = servicebus.get_queue(queue_name)
else:
client = servicebus.get_topic(topic_name)
except (ServiceBusConnectionError, ServiceBusResourceNotFound) as err:
_LOGGER.error(
"Connection error while creating client for queue/topic '%s'. %s",
queue_name or topic_name,
err,
)
return None
return ServiceBusNotificationService(client)
class ServiceBusNotificationService(BaseNotificationService):
"""Implement the notification service for the service bus service."""
def __init__(self, client):
"""Initialize the service."""
self._client = client
async def async_send_message(self, message, **kwargs):
"""Send a message."""
dto = {ATTR_ASB_MESSAGE: message}
if ATTR_TITLE in kwargs:
dto[ATTR_ASB_TITLE] = kwargs[ATTR_TITLE]
if ATTR_TARGET in kwargs:
dto[ATTR_ASB_TARGET] = kwargs[ATTR_TARGET]
data = kwargs.get(ATTR_DATA)
if data:
dto.update(data)
queue_message = Message(json.dumps(dto))
queue_message.properties.content_type = CONTENT_TYPE_JSON
try:
await self._client.send(queue_message)
except MessageSendFailed as err:
_LOGGER.error(
"Could not send service bus notification to %s. %s",
self._client.name,
err,
)

View File

@@ -52,7 +52,7 @@ _OPTIONS = {
SUPPORTED_OPTIONS = [CONF_PERSON, CONF_PITCH, CONF_SPEED, CONF_VOLUME]
def get_engine(hass, config):
def get_engine(hass, config, discovery_info=None):
"""Set up Baidu TTS component."""
return BaiduTTSProvider(hass, config)

View File

@@ -53,6 +53,7 @@
"hot": "{entity_name} \u0441\u0435 \u0441\u0442\u043e\u043f\u043b\u0438",
"light": "{entity_name} \u0437\u0430\u043f\u043e\u0447\u043d\u0430 \u0434\u0430 \u043e\u0442\u043a\u0440\u0438\u0432\u0430 \u0441\u0432\u0435\u0442\u043b\u0438\u043d\u0430",
"locked": "{entity_name} \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d",
"moist": "{entity_name} \u0441\u0442\u0430\u043d\u0430 \u0432\u043b\u0430\u0436\u0435\u043d",
"moist\u00a7": "{entity_name} \u0441\u0442\u0430\u0432\u0430 \u0432\u043b\u0430\u0436\u0435\u043d",
"motion": "{entity_name} \u0437\u0430\u043f\u043e\u0447\u043d\u0430 \u043e\u0442\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435",
"moving": "{entity_name} \u0437\u0430\u043f\u043e\u0447\u043d\u0430 \u043e\u0442\u043a\u0440\u0438\u0432\u0430 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435",
@@ -71,6 +72,7 @@
"not_moist": "{entity_name} \u0441\u0442\u0430\u0432\u0430 \u0441\u0443\u0445",
"not_moving": "{entity_name} \u0441\u043f\u0440\u044f \u0434\u0430 \u0441\u0435 \u0434\u0432\u0438\u0436\u0438",
"not_occupied": "{entity_name} \u0432\u0435\u0447\u0435 \u043d\u0435 \u0435 \u0437\u0430\u0435\u0442",
"not_opened": "{entity_name} \u0437\u0430\u0442\u0432\u043e\u0440\u0435\u043d",
"not_plugged_in": "{entity_name} \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d",
"not_powered": "{entity_name} \u043d\u0435 \u0441\u0435 \u0437\u0430\u0445\u0440\u0430\u043d\u0432\u0430",
"not_present": "{entity_name} \u043d\u0435 \u043f\u0440\u0438\u0441\u044a\u0441\u0442\u0432\u0430",

View File

@@ -0,0 +1,8 @@
{
"device_automation": {
"trigger_type": {
"moist": "{entity_name} se navlh\u010dil",
"not_opened": "{entity_name} uzav\u0159eno"
}
}
}

View File

@@ -86,7 +86,7 @@
"smoke": "{entity_name} commenc\u00e9 \u00e0 d\u00e9tecter la fum\u00e9e",
"sound": "{entity_name} commenc\u00e9 \u00e0 d\u00e9tecter le son",
"turned_off": "{entity_name} est d\u00e9sactiv\u00e9",
"turned_on": "{entity_name} activ\u00e9",
"turned_on": "{entity_name} est activ\u00e9",
"unsafe": "{entity_name} est devenu dangereux",
"vibration": "{entity_name} a commenc\u00e9 \u00e0 d\u00e9tecter les vibrations"
}

View File

@@ -46,13 +46,14 @@
},
"trigger_type": {
"bat_low": "{entity_name} akkufesz\u00fclts\u00e9g alacsony",
"closed": "{entity_name} be lett z\u00e1rva",
"closed": "{entity_name} be lett csukva",
"cold": "{entity_name} hideg lett",
"connected": "{entity_name} csatlakozott",
"connected": "{entity_name} csatlakozik",
"gas": "{entity_name} g\u00e1zt \u00e9rz\u00e9kel",
"hot": "{entity_name} felforr\u00f3sodott",
"hot": "{entity_name} felforr\u00f3sodik",
"light": "{entity_name} f\u00e9nyt \u00e9rz\u00e9kel",
"locked": "{entity_name} be lett z\u00e1rva",
"moist": "{entity_name} nedves lett",
"moist\u00a7": "{entity_name} nedves lett",
"motion": "{entity_name} mozg\u00e1st \u00e9rz\u00e9kel",
"moving": "{entity_name} mozog",
@@ -65,12 +66,13 @@
"no_vibration": "{entity_name} m\u00e1r nem \u00e9rz\u00e9kel rezg\u00e9st",
"not_bat_low": "{entity_name} akkufesz\u00fclts\u00e9g megfelel\u0151",
"not_cold": "{entity_name} m\u00e1r nem hideg",
"not_connected": "{entity_name} lecsatlakozott",
"not_connected": "{entity_name} lecsatlakozik",
"not_hot": "{entity_name} m\u00e1r nem forr\u00f3",
"not_locked": "{entity_name} ki lett nyitva",
"not_moist": "{entity_name} sz\u00e1raz lett",
"not_moving": "{entity_name} m\u00e1r nem mozog",
"not_occupied": "{entity_name} m\u00e1r nem foglalt",
"not_opened": "{entity_name} be lett csukva",
"not_plugged_in": "{entity_name} m\u00e1r nincs csatlakoztatva",
"not_powered": "{entity_name} m\u00e1r nincs fesz\u00fcts\u00e9g alatt",
"not_present": "{entity_name} m\u00e1r nincs jelen",

View File

@@ -28,7 +28,7 @@
"is_not_occupied": "{entity_name} \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435",
"is_not_open": "{entity_name} \u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438",
"is_not_plugged_in": "{entity_name} \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435",
"is_not_powered": "{entity_name} \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043d\u0435\u0440\u0433\u0438\u044e",
"is_not_powered": "{entity_name} \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0438\u0442\u0430\u043d\u0438\u0435",
"is_not_present": "{entity_name} \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435",
"is_not_unsafe": "{entity_name} \u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438",
"is_occupied": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435",
@@ -36,7 +36,7 @@
"is_on": "{entity_name} \u0432\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438",
"is_open": "{entity_name} \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438",
"is_plugged_in": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435",
"is_powered": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043d\u0435\u0440\u0433\u0438\u044e",
"is_powered": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0438\u0442\u0430\u043d\u0438\u0435",
"is_present": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435",
"is_problem": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443",
"is_smoke": "{entity_name} \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u044b\u043c",

View File

@@ -1,6 +1,6 @@
"""Support for Bluesound devices."""
import asyncio
from asyncio.futures import CancelledError
from asyncio import CancelledError
from datetime import timedelta
import logging
from urllib import parse
@@ -53,6 +53,7 @@ import homeassistant.util.dt as dt_util
_LOGGER = logging.getLogger(__name__)
ATTR_BLUESOUND_GROUP = "bluesound_group"
ATTR_MASTER = "master"
DATA_BLUESOUND = "bluesound"
@@ -219,6 +220,8 @@ class BluesoundPlayer(MediaPlayerDevice):
self._master = None
self._is_master = False
self._group_name = None
self._group_list = []
self._bluesound_device_name = None
self._init_callback = init_callback
if self.port is None:
@@ -247,6 +250,8 @@ class BluesoundPlayer(MediaPlayerDevice):
if not self._name:
self._name = self._sync_status.get("@name", self.host)
if not self._bluesound_device_name:
self._bluesound_device_name = self._sync_status.get("@name", self.host)
if not self._icon:
self._icon = self._sync_status.get("@icon", self.host)
@@ -331,7 +336,6 @@ class BluesoundPlayer(MediaPlayerDevice):
self, method, raise_timeout=False, allow_offline=False
):
"""Send command to the player."""
if not self._is_online and not allow_offline:
return
@@ -371,7 +375,6 @@ class BluesoundPlayer(MediaPlayerDevice):
async def async_update_status(self):
"""Use the poll session to always get the status of the player."""
response = None
url = "Status"
@@ -402,6 +405,10 @@ class BluesoundPlayer(MediaPlayerDevice):
if group_name != self._group_name:
_LOGGER.debug("Group name change detected on device: %s", self.host)
self._group_name = group_name
# rebuild ordered list of entity_ids that are in the group, master is first
self._group_list = self.rebuild_bluesound_group()
# the sleep is needed to make sure that the
# devices is synced
await asyncio.sleep(1)
@@ -659,6 +666,11 @@ class BluesoundPlayer(MediaPlayerDevice):
"""Return the name of the device."""
return self._name
@property
def bluesound_device_name(self):
"""Return the device name as returned by the device."""
return self._bluesound_device_name
@property
def icon(self):
"""Return the icon of the device."""
@@ -690,7 +702,6 @@ class BluesoundPlayer(MediaPlayerDevice):
@property
def source(self):
"""Name of the current input source."""
if self._status is None or (self.is_grouped and not self.is_master):
return None
@@ -831,6 +842,39 @@ class BluesoundPlayer(MediaPlayerDevice):
else:
_LOGGER.error("Master not found %s", master_device)
@property
def device_state_attributes(self):
"""List members in group."""
attributes = {}
if self._group_list:
attributes = {ATTR_BLUESOUND_GROUP: self._group_list}
attributes[ATTR_MASTER] = self._is_master
return attributes
def rebuild_bluesound_group(self):
"""Rebuild the list of entities in speaker group."""
if self._group_name is None:
return None
bluesound_group = []
device_group = self._group_name.split("+")
sorted_entities = sorted(
self._hass.data[DATA_BLUESOUND],
key=lambda entity: entity.is_master,
reverse=True,
)
bluesound_group = [
entity.name
for entity in sorted_entities
if entity.bluesound_device_name in device_group
]
return bluesound_group
async def async_unjoin(self):
"""Unjoin the player from a group."""
if self._master is None:

View File

@@ -3,7 +3,7 @@
"name": "BMW Connected Drive",
"documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
"requirements": [
"bimmer_connected==0.6.0"
"bimmer_connected==0.6.2"
],
"dependencies": [],
"codeowners": [

View File

@@ -4,10 +4,12 @@
"host_port_exists": "\u0422\u0430\u0437\u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u043e\u0442 \u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442 \u0435 \u0432\u0435\u0447\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0430"
},
"error": {
"certificate_error": "\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044a\u0442 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0430\u043d",
"certificate_fetch_failed": "\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043c\u0438\u0437\u0432\u043b\u0435\u0447\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043e\u0442 \u0442\u0430\u0437\u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u043e\u0442 \u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442",
"connection_timeout": "\u041d\u0435\u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442 \u0437\u0430 \u0441\u0432\u043e\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u0441 \u0442\u043e\u0437\u0438 \u0430\u0434\u0440\u0435\u0441",
"host_port_exists": "\u0422\u0430\u0437\u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u043e\u0442 \u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442 \u0435 \u0432\u0435\u0447\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0430",
"resolve_failed": "\u0422\u043e\u0437\u0438 \u0430\u0434\u0440\u0435\u0441 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d"
"resolve_failed": "\u0422\u043e\u0437\u0438 \u0430\u0434\u0440\u0435\u0441 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d",
"wrong_host": "\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044a\u0442 \u043d\u0435 \u0441\u044a\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0430 \u043d\u0430 \u0438\u043c\u0435\u0442\u043e \u043d\u0430 \u0445\u043e\u0441\u0442\u0430"
},
"step": {
"user": {

View File

@@ -0,0 +1,8 @@
{
"config": {
"error": {
"certificate_error": "Certifik\u00e1t nelze ov\u011b\u0159it",
"wrong_host": "Certifik\u00e1t neodpov\u00edd\u00e1 n\u00e1zvu hostitele"
}
}
}

View File

@@ -4,10 +4,12 @@
"host_port_exists": "Esta combinaci\u00f3n de host y puerto ya est\u00e1 configurada"
},
"error": {
"certificate_error": "El certificado no pudo ser validado",
"certificate_fetch_failed": "No se puede obtener el certificado de esta combinaci\u00f3n de host y puerto",
"connection_timeout": "Tiempo de espera agotado al conectar a este host",
"host_port_exists": "Esta combinaci\u00f3n de host y puerto ya est\u00e1 configurada",
"resolve_failed": "Este host no se puede resolver"
"resolve_failed": "Este host no se puede resolver",
"wrong_host": "El certificado no coincide con el nombre de host"
},
"step": {
"user": {

View File

@@ -4,10 +4,12 @@
"host_port_exists": "Questa combinazione di host e porta \u00e8 gi\u00e0 configurata"
},
"error": {
"certificate_error": "Il certificato non pu\u00f2 essere convalidato",
"certificate_fetch_failed": "Non \u00e8 possibile recuperare il certificato da questa combinazione di host e porta",
"connection_timeout": "Tempo scaduto collegandosi a questo host",
"host_port_exists": "Questa combinazione di host e porta \u00e8 gi\u00e0 configurata",
"resolve_failed": "Questo host non pu\u00f2 essere risolto"
"resolve_failed": "Questo host non pu\u00f2 essere risolto",
"wrong_host": "Il certificato non corrisponde al nome host"
},
"step": {
"user": {

View File

@@ -4,10 +4,12 @@
"host_port_exists": "\ud638\uc2a4\ud2b8\uc640 \ud3ec\ud2b8\uac00 \uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4"
},
"error": {
"certificate_error": "\uc778\uc99d\uc11c\ub97c \ud655\uc778\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4",
"certificate_fetch_failed": "\ud574\ub2f9 \ud638\uc2a4\ud2b8\uc640 \ud3ec\ud2b8\uc5d0\uc11c \uc778\uc99d\uc11c\ub97c \uac00\uc838 \uc62c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4",
"connection_timeout": "\ud638\uc2a4\ud2b8 \uc5f0\uacb0 \uc2dc\uac04\uc774 \ucd08\uacfc\ud588\uc2b5\ub2c8\ub2e4",
"host_port_exists": "\ud638\uc2a4\ud2b8\uc640 \ud3ec\ud2b8\uac00 \uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4",
"resolve_failed": "\ud638\uc2a4\ud2b8\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4"
"resolve_failed": "\ud638\uc2a4\ud2b8\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4",
"wrong_host": "\uc778\uc99d\uc11c\uac00 \ud638\uc2a4\ud2b8 \uc774\ub984\uacfc \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4"
},
"step": {
"user": {

View File

@@ -4,10 +4,12 @@
"host_port_exists": "D\u00ebsen Host an Port sinn scho konfigur\u00e9iert"
},
"error": {
"certificate_error": "Zertifikat konnt net valid\u00e9iert ginn",
"certificate_fetch_failed": "Kann keen Zertifikat vun d\u00ebsen Host a Port recuper\u00e9ieren",
"connection_timeout": "Z\u00e4it Iwwerschreidung beim verbannen.",
"host_port_exists": "D\u00ebsen Host an Port sinn scho konfigur\u00e9iert",
"resolve_failed": "D\u00ebsen Host kann net opgel\u00e9ist ginn"
"resolve_failed": "D\u00ebsen Host kann net opgel\u00e9ist ginn",
"wrong_host": "Zertifikat entspr\u00e9cht net den Numm vum Apparat"
},
"step": {
"user": {

View File

@@ -4,10 +4,12 @@
"host_port_exists": "Ta kombinacja hosta i portu jest ju\u017c skonfigurowana"
},
"error": {
"certificate_error": "Nie mo\u017cna zweryfikowa\u0107 certyfikatu",
"certificate_fetch_failed": "Nie mo\u017cna pobra\u0107 certyfikatu z tej kombinacji hosta i portu",
"connection_timeout": "Przekroczono limit czasu po\u0142\u0105czenia z tym hostem",
"connection_timeout": "Przekroczono limit czasu po\u0142\u0105czenia z hostem.",
"host_port_exists": "Ta kombinacja hosta i portu jest ju\u017c skonfigurowana",
"resolve_failed": "Tego hosta nie mo\u017cna rozwi\u0105za\u0107"
"resolve_failed": "Tego hosta nie mo\u017cna rozwi\u0105za\u0107",
"wrong_host": "Certyfikat nie pasuje do nazwy hosta"
},
"step": {
"user": {

View File

@@ -4,10 +4,12 @@
"host_port_exists": "Ta kombinacija gostitelja in vrat je \u017ee konfigurirana"
},
"error": {
"certificate_error": "Certifikata ni bilo mogo\u010de preveriti",
"certificate_fetch_failed": "Iz te kombinacije gostitelja in vrat ni mogo\u010de pridobiti potrdila",
"connection_timeout": "\u010casovna omejitev za povezavo s tem gostiteljem je potekla",
"host_port_exists": "Ta kombinacija gostitelja in vrat je \u017ee konfigurirana",
"resolve_failed": "Tega gostitelja ni mogo\u010de razre\u0161iti"
"resolve_failed": "Tega gostitelja ni mogo\u010de razre\u0161iti",
"wrong_host": "Potrdilo se ne ujema z imenom gostitelja"
},
"step": {
"user": {

View File

@@ -4,10 +4,12 @@
"host_port_exists": "\u6b64\u4e3b\u6a5f\u7aef\u8207\u901a\u8a0a\u57e0\u7d44\u5408\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210"
},
"error": {
"certificate_error": "\u8a8d\u8b49\u7121\u6cd5\u78ba\u8a8d",
"certificate_fetch_failed": "\u7121\u6cd5\u81ea\u6b64\u4e3b\u6a5f\u7aef\u8207\u901a\u8a0a\u57e0\u7d44\u5408\u7372\u5f97\u8a8d\u8b49",
"connection_timeout": "\u9023\u7dda\u81f3\u4e3b\u6a5f\u7aef\u903e\u6642",
"host_port_exists": "\u6b64\u4e3b\u6a5f\u7aef\u8207\u901a\u8a0a\u57e0\u7d44\u5408\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210",
"resolve_failed": "\u4e3b\u6a5f\u7aef\u7121\u6cd5\u89e3\u6790"
"resolve_failed": "\u4e3b\u6a5f\u7aef\u7121\u6cd5\u89e3\u6790",
"wrong_host": "\u8a8d\u8b49\u8207\u4e3b\u6a5f\u540d\u7a31\u4e0d\u7b26\u5408"
},
"step": {
"user": {

View File

@@ -0,0 +1,16 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "Canvia el mode HVAC de {entity_name}"
},
"condtion_type": {
"is_hvac_mode": "{entity_name} est\u00e0 configurat/ada en un mode HVAC espec\u00edfic",
"is_preset_mode": "{entity_name} est\u00e0 configurat/ada en un mode preestablert espec\u00edfic"
},
"trigger_type": {
"current_humidity_changed": "Ha canviat la humitat mesurada per {entity_name}",
"current_temperature_changed": "Ha canviat la temperatura mesurada per {entity_name}",
"hvac_mode_changed": "El mode HVAC de {entity_name} ha canviat"
}
}
}

View File

@@ -0,0 +1,17 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "Change HVAC mode on {entity_name}",
"set_preset_mode": "Change preset on {entity_name}"
},
"condtion_type": {
"is_hvac_mode": "{entity_name} is set to a specific HVAC mode",
"is_preset_mode": "{entity_name} is set to a specific preset mode"
},
"trigger_type": {
"current_humidity_changed": "{entity_name} measured humidity changed",
"current_temperature_changed": "{entity_name} measured temperature changed",
"hvac_mode_changed": "{entity_name} HVAC mode changed"
}
}
}

View File

@@ -0,0 +1,17 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "Cambiar el modo HVAC de {entity_name}.",
"set_preset_mode": "Cambiar la configuraci\u00f3n prefijada de {entity_name}"
},
"condtion_type": {
"is_hvac_mode": "{entity_name} est\u00e1 configurado en un modo HVAC espec\u00edfico",
"is_preset_mode": "{entity_name} se establece en un modo predeterminado espec\u00edfico"
},
"trigger_type": {
"current_humidity_changed": "{entity_name} humedad medida cambi\u00f3",
"current_temperature_changed": "{entity_name} temperatura medida cambi\u00f3",
"hvac_mode_changed": "{entity_name} Modo HVAC cambiado"
}
}
}

View File

@@ -0,0 +1,12 @@
{
"device_automation": {
"action_type": {
"set_preset_mode": "Changer les pr\u00e9r\u00e9glages de {entity_name}"
},
"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}"
}
}
}

View File

@@ -0,0 +1,17 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "Cambia modalit\u00e0 HVAC su {entity_name}",
"set_preset_mode": "Modifica preimpostazione su {entity_name}"
},
"condtion_type": {
"is_hvac_mode": "{entity_name} \u00e8 impostato su una modalit\u00e0 HVAC specifica",
"is_preset_mode": "{entity_name} \u00e8 impostato su una modalit\u00e0 preimpostata specifica"
},
"trigger_type": {
"current_humidity_changed": "{entity_name} umidit\u00e0 misurata modificata",
"current_temperature_changed": "{entity_name} temperatura misurata cambiata",
"hvac_mode_changed": "{entity_name} modalit\u00e0 HVAC modificata"
}
}
}

View File

@@ -0,0 +1,17 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "HVAC Modus \u00e4nnere fir {entity_name}",
"set_preset_mode": "Preset \u00e4nnere fir {entity_name}"
},
"condtion_type": {
"is_hvac_mode": "\n{entity_name} ass op e spezifesche HVAC Modus gesat",
"is_preset_mode": "{entity_name} ass op e spezifesche preset Modus gesat"
},
"trigger_type": {
"current_humidity_changed": "{entity_name} gemoosse Fiichtegkeet ge\u00e4nnert",
"current_temperature_changed": "{entity_name} gemoossen Temperatur ge\u00e4nnert",
"hvac_mode_changed": "{entity_name} HVAC Modus ge\u00e4nnert"
}
}
}

View File

@@ -0,0 +1,17 @@
{
"device_automation": {
"action_type": {
"set_hvac_mode": "Endre HVAC-modus p\u00e5 {entity_name}",
"set_preset_mode": "Endre forh\u00e5ndsinnstilling p\u00e5 {entity_name}"
},
"condtion_type": {
"is_hvac_mode": "{entity_name} er satt til en spesifikk HVAC-modus",
"is_preset_mode": "{entity_name} er satt til en spesifikk forh\u00e5ndsinnstilt modus"
},
"trigger_type": {
"current_humidity_changed": "{entity_name} m\u00e5lt fuktighet er endret",
"current_temperature_changed": "{entity_name} m\u00e5lt temperatur er endret",
"hvac_mode_changed": "{entity_name} HVAC-modus er endret"
}
}
}

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