Compare commits

...

454 Commits

Author SHA1 Message Date
Paulus Schoutsen
4d3d51635d Bumped version to 0.80.0b3 2018-10-08 16:16:01 +02:00
Malte Franken
a372053eac updated georss-client library to 0.3 (#17239) 2018-10-08 16:15:40 +02:00
Paulus Schoutsen
2e120061b4 Guard for bad device info (#17238) 2018-10-08 16:15:40 +02:00
Paulus Schoutsen
3a6eac216c Fix SPC (#17236) 2018-10-08 16:15:39 +02:00
Otto Winter
6671cbb96d Fix potential MQTT discovery race condition (#17208)
* Fix potential MQTT discovery race condition

* Rename data key
2018-10-08 16:15:39 +02:00
Matt Schmitt
9e386938bb MyQ cover return unknown state if not available (#17207)
* Add additional supported states

* Use get method for lookup

* Return None if unable to get status
2018-10-08 16:15:38 +02:00
Paulus Schoutsen
6be52208fc Prevent accidental device reg override (#17136) 2018-10-08 16:15:38 +02:00
Paulus Schoutsen
bd4ff6fc21 Bumped version to 0.80.0b2 2018-10-07 23:33:46 +02:00
Martin Berg
5fcea074c4 Init sub-components using global var. (#17220) 2018-10-07 23:33:40 +02:00
Per Sandström
7369af0639 Verisure standard config for scan interval (#17192)
* verisure configurable polling

* fix indentation
2018-10-07 23:33:40 +02:00
Anders Melchiorsen
b872cb95c7 Upgrade aiolifx_effects to 0.2.1 (#17188) 2018-10-07 23:33:39 +02:00
cdce8p
3338ebd4c1 Bugfix switch flux - light service call (#17187)
* Bugfix switch flux - light service call

* Change x_val and y_val test
2018-10-07 23:33:38 +02:00
cdce8p
7b176aa7c9 Fix device_tracker service call & cleanup (#17173)
* Bugfix group service - device_tracker

* Cleanup
2018-10-07 23:33:38 +02:00
Paulus Schoutsen
c722091967 Fix data used for logbook (#17172)
* Fix data used for logbook

* Lint
2018-10-07 23:33:38 +02:00
Paulus Schoutsen
4cffef7f2b Update translations 2018-10-07 23:27:57 +02:00
Paulus Schoutsen
31b1b0c044 Update frontend to 20181007.0 2018-10-07 23:27:57 +02:00
Paulus Schoutsen
7a22fbe961 Bumped version to 0.80.0b1 2018-10-05 20:21:27 +02:00
Paulus Schoutsen
738089c57c Fix incorrect yaml in hangouts (#17169) 2018-10-05 20:21:23 +02:00
Paulus Schoutsen
88c0a92857 Bumped version to 0.80.0b0 2018-10-05 17:56:30 +02:00
Paulus Schoutsen
0c770520ed Update translations 2018-10-05 17:50:00 +02:00
Paulus Schoutsen
92e28067d8 Update frontend to 20181005.0 2018-10-05 17:49:27 +02:00
prophit987
d1636dab31 @danielhiversen as codeowner for Tibber (#17154) 2018-10-05 14:55:16 +02:00
prophit987
13aa935147 Discover Danfoss/devolo RS Room Sensor thermostat (#17153)
Allows the Danfoss/Devolo RS Room Sensor thermostat to be discovered as climate device in homeassistant.
This device is defined as GENERIC_TYPE_MULTILEVEL_SENSOR, and not GENERIC_TYPE_THERMOSTAT.
Ref: https://community.home-assistant.io/t/devolo-zwave-thermostat/58739
2018-10-05 14:39:10 +02:00
Paul Annekov
29c3f1618f Fix miflora connection errors during platform setup (#16798)
* possible fix for startup delay

* fixed reported issues

* moved update code into setup

* reverted to previous solution
2018-10-05 13:33:28 +02:00
cdce8p
37a47b5a59 Add faucet, shower, sprinkler, valve to HomeKit (#17145) 2018-10-05 12:43:50 +02:00
Julius Mittenzwei
2e62afabdc Added warning to HomeKit component (#16807)
* added warning if more then 100 devices are added to HomeKit
2018-10-05 12:32:26 +02:00
Rohan Kapoor
a8f5e8699a Fix zoneminder zms_url construction (#17150) 2018-10-05 10:30:08 +02:00
Lewis Juggins
4218efddcd Cleanly stop tradfri on shutdown (#17114)
* Tradfri shutdown fix

* Bump version

* Bump version

* Fix

* Derp

* Remove unnecessary shutdown event
2018-10-05 09:59:34 +02:00
Gerard
aec320dc19 Fix a typo (#17147) 2018-10-05 07:48:40 +02:00
Aaron Bach
acf684de05 Added OpenUV CODEOWNERS info (#17149) 2018-10-04 19:57:52 -06:00
Florian Klien
ce1e8f8ace YesssSMS handling more errors, upgrade to version 0.2.3 (#17052)
* YesssSMS handling more errors, upgrade to version 0.2.1

 - handling missing internet connection nicely
 - disabling login with non-working credentials (website locked account for 1 hour)
 - upgrade to new upstream version of YesssSMS

* notify.yessssms tests

* test requirements

* flake8 fix

* fixing tests, new upstream version 0.2.3

fixing tests based on requested changes, coverage

* removing unmotivated print

* passing exception to ConnectionError and SMSSendingError logger
2018-10-04 17:34:04 -04:00
Per Sandström
b55c7a5ba2 verisure configurable polling (#17144) 2018-10-04 21:41:02 +02:00
cdce8p
52ff232797 Bugfix invalid entity_config parameter HomeKit (#17143) 2018-10-04 20:37:04 +02:00
Paulus Schoutsen
769dda735d Remove discovery (#17070) 2018-10-04 16:04:44 +02:00
Ana Paula Gomes
02bf07d9df Add timeout and fix oscillations on Samsung TV component (#17102)
* Add timeout and fix oscillations

* Adjust code to py3.5.3

* Clean code
2018-10-04 16:02:14 +02:00
Georgi Kirichkov
b92b24e8a4 Webhook component - pass headers to webhook handler (#17091)
* Pass headers to webhook handler

* Refactors webhook component to post Request object instead of data

* Update webhook tests

* Cleanup webhook test and fix a bug in ifttt

* Address code review comments
2018-10-04 15:54:51 +02:00
Paulus Schoutsen
0cfbb9ce91 Allow config entry setup to raise not ready (#17135) 2018-10-04 15:53:50 +02:00
Tsvi Mostovicz
c9976718d4 Take timezone into consideration when calulating Zmanim. Partial fix for #16946 (#17131) 2018-10-04 15:51:56 +02:00
Jason Hu
b61a250321 Fix upnp component l10n error (#17132) 2018-10-04 15:50:42 +02:00
Alok Saboo
ae0dd33e2e Add update service to Google Travel Sensor (#17092)
* Add update service

* Update service name

* Register service only once

* Make hound happy
2018-10-04 14:02:30 +02:00
Daniel Høyer Iversen
0d93bf9a45 Update xiaomi lib (#17129) 2018-10-04 13:24:54 +02:00
Heiko Thiery
178bf736f6 Add new component fritzbox binary_sensor (#17057)
* Add new component fritzbox binary_sensor

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* fix failed flake8 test

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* add new file to .coveragerc

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* use wildcard to cover all platforms

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* remove polling because polling is true by default

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* add blank line to keep imports ordered

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* Minor changes
2018-10-04 12:16:27 +02:00
Paulus Schoutsen
a559c06d6b Make it easier for auth to consume newer formats (#17127) 2018-10-04 10:41:13 +02:00
Jerad Meisner
cc1891ef2b Add time created to persistent notifications. (#17121)
* Add time created to persistent notifications.

* UTC
2018-10-04 10:24:14 +02:00
Daniel Høyer Iversen
05d8c57212 Tibber component and notify (#17062)
* Refactor tibber, and Tibber notify

* update Tibber lib.

* tibber

* Tibber coveragerc

* Tibber upgrade lib

* style

* comments

* use async_get_service

* event
2018-10-04 09:29:49 +02:00
Adam Mills
3abdf217bb Homekit controller reconnect (#17060)
* Add threaded call_later helper

* Reconnect to device when connection fails

* Consolidate connection logs and warn on first
2018-10-04 09:25:05 +02:00
Martin Hjelmare
6a0c9a718e Fix sonos async use (#17099)
* Entry setup wasn't using the async api. Fix this by using correct
  async api.s
* Also use new async executor scheduler in async_added_to_hass.
2018-10-04 09:20:20 +02:00
Ville Skyttä
abd329d707 Upgrade pytest to 3.8.2 (#17125) 2018-10-04 09:03:31 +02:00
Aaron Bach
04fdde0e86 Bumps simplisafe-python to 3.1.2 (#16931)
* Bumps simplisafe-python to 3.0.4

* Updated requirements

* Refresh token logic added

* Member-requested changes

* Removed unused import

* Updated CODEOWNERS

* Bump library to 3.1.2
2018-10-03 21:03:29 -06:00
Michael Wei
2b3019bdf4 Support multiple accounts in Tile, use device identifiers (#17108)
*  Update tile to support multiple accounts

* 🎨 fix indent

* 🐛 fix format string

* 🎨 use .format

* 🎨 fix line indent
2018-10-03 17:22:21 -06:00
Diogo Gomes
cf0147098a Merge pull request #16300 from StevenLooman/igd
Adds discovery and config flow
Breaking change: no longer possible to map ports other than the port used by Home Assistant
2018-10-03 22:55:01 +01:00
mvn23
aeb21596a0 Fix counter restore. (#17101)
Add config option to disable restore (always use initial value on restart).
Add unit tests for restore config option.
2018-10-03 23:12:21 +02:00
Tsvi Mostovicz
cf5f02b347 Fix jewish calendar sensor with language set to english (#17104)
* Add failing testcase for issue #16830

* Fix for #16830
2018-10-03 18:43:25 +02:00
Michael Wei
467a59a6ed Change Tile icon to view-grid (#17098) 2018-10-03 09:59:11 -06:00
Kevin Fronczak
da622abb79 Adding myself as blink codeowner (#17096) 2018-10-03 17:04:31 +02:00
David Bilay
16cbc2d07f Add weather condition code to OpenWeatherMap sensor (#17093) 2018-10-03 16:15:45 +02:00
Anders Melchiorsen
952a1b3513 Smaller steps for Sonos volume up/down (#17080) 2018-10-03 15:09:05 +02:00
Anders Melchiorsen
a5402739b7 Keep the repeat mode when setting Sonos shuffle mode (#17083)
* Keep the repeat mode when setting Sonos shuffle mode

* Fix test
2018-10-03 14:50:13 +02:00
Pascal Vizeli
704c9d8582 Add support for Hass.io discovery feature for Add-ons (#17035)
* Update handler.py

* Update __init__.py

* Update handler.py

* Update __init__.py

* Create discovery.py

* Update handler.py

* Update discovery.py

* Update __init__.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update struct

* Update handler.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update __init__.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update __init__.py

* Update discovery.py

* fix lint

* Update discovery.py

* cleanup old discovery

* Update discovery.py

* Update discovery.py

* Fix lint

* Fix tests

* Write more tests with new functions

* Update test_handler.py

* Create test_discovery.py

* Update conftest.py

* Update test_discovery.py

* Update conftest.py

* Update test_discovery.py

* Update conftest.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Fix test

* Add test

* fix lint

* Update handler.py

* Update discovery.py

* Update test_discovery.py

* fix lint

* Lint
2018-10-03 13:10:38 +02:00
David Peterson
2e5eb4d9dc Add optional headers configuration for scrape (#17085) 2018-10-03 12:47:38 +02:00
Steven Looman
5d693277f0 Fix stale docstrings 2018-10-03 11:27:38 +02:00
Steven Looman
3cb20c7b4d Changes after review by @MartinHjelmare 2018-10-03 11:08:32 +02:00
Paulus Schoutsen
4210835dcd Async response all the things (#17073)
* Use async_response

* Update device_registry.py
2018-10-03 07:53:54 +02:00
Dan Cinnamon
15a160a630 Bump pyenvisalink (#17086) 2018-10-03 06:28:08 +02:00
Kevin Fronczak
c78850a983 Overhaul of Blink platform (#16942)
* Using new methods for blink camera

- Refactored blink platform (breaking change)
- Camera needs to be uniquely enabled in config from now on
- Added motion detection enable/disable to camera platform

* Fix motion detection

- bumped blinkpy to 0.8.1
- Added wifi strength sensor

* Added platform schema to sensor

- Added global variables for brand and attribution to main platform

* Removed blink binary sensor

* Add alarm control panel

* Fixed dependency, added alarm_home

* Update requirements

* Fix lint errors

* Updated throttle times

* Add trigger_camera service (replaced snap_picture)

* Add refresh after camera trigger

* Update blinkpy version

* Wait for valid camera response before returning image

- Motion detection now working!

* Updated for new blinkpy 0.9.0

* Add refresh control and other fixes for new blinkpy release

* Add save video service

* Pushing to force bot to update

* Changed based on first review

- Pass blink as BLINK_DATA instead of DOMAIN
- Remove alarm_arm_home from alarm_control_panel
- Re-add discovery with schema for sensors/binar_sensors
- Change motion_detected to a binary_sensor
- Added camera_armed binary sensor
- Update camera device_state_attributes rather than state_attributes

* Moved blink.py to own folder. Added service hints.

* Updated coveragerc to reflect previous change

* Register services with DOMAIN

- Change device add for loop order in binary_sensor

* Fix lint error

* services.async_register -> services.register
2018-10-03 04:17:14 +02:00
Fabian Affolter
8e3a70e568 Upgrade youtube_dl to 2018.09.26 (#17079) 2018-10-02 22:31:59 +02:00
Thomas Lovén
06340c9875 Allow no movement in vamera.onvif_ptz service (#17065) 2018-10-02 14:36:28 +02:00
Paulus Schoutsen
31dd327c59 Catch possible errors from tradfri (#17068)
* Catch possible errors from tradfri

* Update config_flow.py
2018-10-02 14:35:43 +02:00
Paulus Schoutsen
38e2926a48 Update translations 2018-10-02 14:33:47 +02:00
Paulus Schoutsen
19722a0ef8 bump frontend to 20181002.0 2018-10-02 14:33:30 +02:00
Paulus Schoutsen
a6f8c3f662 Add logging to light updates (#17069) 2018-10-02 13:33:16 +02:00
Thomas Lovén
11d5671ee0 De-syncing binary_sensor.ping (#17056)
* Quick and dirty asyncing of binary_sensor.ping

* Minor changes
2018-10-02 11:43:34 +02:00
Paulus Schoutsen
20601cfc2d Merge branch 'master' into dev 2018-10-02 11:19:25 +02:00
Paulus Schoutsen
07972c84a1 Merge pull request #17067 from home-assistant/rc
0.79.3
2018-10-02 11:17:14 +02:00
cdce8p
7f0a50ce31 async_create_task (#17059)
* async_create_task

* Update google.py
2018-10-02 11:03:09 +02:00
Paulus Schoutsen
03845ef490 Lint 2018-10-02 10:35:15 +02:00
Paulus Schoutsen
37706c2731 Lint 2018-10-02 10:35:00 +02:00
Aaron Bach
71e3047f5c OpenUV: Fixed issue with missing protection window data (#17051) 2018-10-02 10:34:12 +02:00
Charles Garwood
0954eefa9f MJPEG Camera Log Filter Fixes (#17050)
* Move filter to setup platform

* pylint
2018-10-02 10:24:44 +02:00
cdce8p
90f71261c5 Remove service helper (8) (#17055)
* Updated keyboard

* Updated microsoft_face

* Updated ffmpeg

* Updated logger

* Updated components/__init__.py
2018-10-02 10:23:37 +02:00
Malte Franken
13af61e103 GeoRSS events sensor refactored (#16939)
* refactored geo_rss_events sensor to make use of new georss-client library that handles the communication with the rss feed

* fixed lint error
2018-10-02 10:20:51 +02:00
Nicko van Someren
b0b3620b2b Added working support for private storage (#16903)
* Fixed file corruption bugs in private storage code.

* Restoring fixed test case.

* Implemented test suite for utils/json.py

* Added new unit test cases for util/json.py

* Dixed formatting nags

* Fixed more nags from the Hound

* Added doc strings to some very short functions

* Fixing lint's complains about my choice of parts of speach. Sigh.

* Moved atomic save operations down into util/json.py so that all benefit.

Added extra clean-up code to ensure that temporary files are removed in
case of errors.
Updated emulated_hue unit tests to avoid errors.

* Apparently 'e' is not allows as a variable name for an exception...
2018-10-02 10:16:43 +02:00
Paulus Schoutsen
e07b6dfe0b Bumped version to 0.79.3 2018-10-02 09:57:01 +02:00
Paulus Schoutsen
3f5018459f Proactor policy fix (#17066)
* Proactor policy fix

* Backport Proactor policy for <py37
2018-10-02 09:56:54 +02:00
Jason Hu
2feab82396 Use Protractor loop in Windows (#17061)
* Use Protractor loop in Windows

* Add import sys
2018-10-02 09:56:53 +02:00
Paulus Schoutsen
1decba0052 Proactor policy fix (#17066)
* Proactor policy fix

* Backport Proactor policy for <py37
2018-10-02 09:55:37 +02:00
Jason Hu
1667481342 Use Protractor loop in Windows (#17061)
* Use Protractor loop in Windows

* Add import sys
2018-10-02 09:21:02 +02:00
Mathieu Velten
8e276295eb Update pynetgear to 0.4.2 (fix #14752) (#17064) 2018-10-02 09:14:07 +02:00
Sean Wilson
284d4d49c7 Add AquaLogic component (#16763)
* Add missing ups.status states.

* Add missing DISCHRG state.

* AquaLogic work-in-progress

* - Fix dependencies
- Switch updates

* Add support for aqualogic 0.8 features.

* Remove debugging.

* Switch to async updates rather than using polling.

* Rebase

* Fix lint errors

* Fix lint errors

* Fix lint errors

* Fix lint errors

* Fix lint errors.

* Bump aqualogic version to 0.11

* Update .coveragerc

* Remove integration-specific I/O

* Resolve code review issues.

* Fixed init() call.
2018-10-02 07:32:03 +02:00
cdce8p
c3eff5773b Remove alert service helper (#17038) 2018-10-02 00:33:45 +02:00
Daniel Perna
4d471622f6 Update pyhomematic to 0.1.50 (#17048) 2018-10-02 00:02:59 +02:00
SNoof85
90f2990b9e Support code 7 (#17047) 2018-10-01 22:18:56 +02:00
Charles Garwood
b197b8bab3 Suppress urllib3 header parsing error (#17042) 2018-10-01 20:39:40 +02:00
Fabian Affolter
a148f3e2a9 Mind the unit system (fixes #16819) (#16823) 2018-10-01 20:38:41 +02:00
Steven Looman
d732f8eca2 Changes after review by @MartinHjelmare 2018-10-01 19:26:43 +02:00
Nikolay Vasilchuk
b0c1c37cd5 Fix long update 'load_power' and 'in_use' for Xiaomi Zegbee Plug (#16915) 2018-10-01 18:00:48 +02:00
Anders Melchiorsen
4c36ffd0ef Remove error logging when Sonos shuffle_set is not available (#16921)
Error on set_shuffle with UPnP Error 712 received: Play mode not supported from 10.23.2.16
2018-10-01 17:58:04 +02:00
Paulus Schoutsen
fbc1c41673 Logbook context (#16937)
* Convert logbook to use attr

* Add context to events

* Enhance logbook

* Lint

* Fix logbook entry

* Don't use intermediary classes for logbook entries
2018-10-01 16:12:25 +02:00
Paulus Schoutsen
2e6346ca43 Break up websocket 2 (#17028)
* Break up websocket 2

* Lint+Test

* Lintttt

* Rename
2018-10-01 16:09:31 +02:00
Paulus Schoutsen
122e21a3c4 Merge pull request #17041 from home-assistant/rc
0.79.2
2018-10-01 15:50:25 +02:00
Paulus Schoutsen
33a54043e9 Bumped version to 0.79.2 2018-10-01 15:08:56 +02:00
Rohan Kapoor
d09ee8ac82 Fix switch.zoneminder name (#17026) 2018-10-01 15:08:50 +02:00
Paulus Schoutsen
1ca2e5226b Fix MQTT certificates (#16999) 2018-10-01 15:08:50 +02:00
cdce8p
b5e3d8c337 Async syntax (#17033)
* async-syntax-mqtt_room

* async-syntax-alert

* Additional fixes
2018-10-01 14:44:11 +02:00
Josh Anderson
f0fbdd6a26 Send headers with REST switch GET request (#17036) 2018-10-01 14:43:54 +02:00
cdce8p
e5c0e4336d Update coverage to exclude not tested file (#17039) 2018-10-01 14:41:35 +02:00
Paulus Schoutsen
c69a790ede Add Hass.io discovery to MQTT (#16962)
* Add Hass.io discovery to MQTT

* Update en.json

* Update __init__.py

* Update config_flow.py

* Update strings.json

* Update test_config_flow.py

* Lint

* Ensure we don't send bad data in config entry
2018-10-01 14:11:21 +02:00
David De Sloovere
5bc2e78ab4 Bump Enphase_Envoy dependency for older models (#17032) 2018-10-01 14:10:32 +02:00
Heiko Thiery
68bda1c732 Add new device attributes to fritzbox climate (#17027)
* Add new device attributes to fritzbox climate

With Fitz!OS 7 new parameters are introduced.

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>

* update requirements

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
2018-10-01 12:53:25 +02:00
Timmo
3137099348 🔨 update errors (#17029) 2018-10-01 12:51:39 +02:00
Paulus Schoutsen
22a80cf733 Break up websocket component (#17003)
* Break up websocket component

* Lint
2018-10-01 11:21:00 +02:00
Fabian Affolter
9edf1e5151 Upgrade locationsharinglib to 3.0.3 (#17010)
* Upgrade locationsharinglib to 3.0.3

* Revert change from #16969
2018-10-01 10:55:16 +02:00
Rohan Kapoor
6159f8b0ce Fix switch.zoneminder name (#17026) 2018-10-01 10:53:20 +02:00
Ville Skyttä
d4cde2bfbf Upgrade huawei-lte-api to 1.0.16 (#16972) 2018-10-01 10:52:49 +02:00
Otto Winter
760f822dce Fix MQTT discovery (#17004) 2018-10-01 09:01:40 +02:00
cdce8p
b24f9f5dfa Async syntax 3/8 (#17017)
* Async syntax 3, device_tracker & fan & hassio & image_processing & input

* Pylint fixes
2018-10-01 08:59:45 +02:00
cdce8p
134eeecd65 Async syntax 4/8 (#17018)
* Async syntax 4, media_player & notify

* Pylint fixes
2018-10-01 08:58:21 +02:00
cdce8p
3b5e5cbcd6 Async syntax 5, light & lock & remote & scene & telegram & helpers (#17019) 2018-10-01 08:56:50 +02:00
cdce8p
9e4c8f45d6 Async syntax 6, sensor (#17020) 2018-10-01 08:55:43 +02:00
cdce8p
121dba659c Async syntax 7, switch & tts & vacuum (#17021) 2018-10-01 08:55:00 +02:00
cdce8p
9aaf11de8c Async syntax 8/8 (#17022)
* Async syntax 8

* Pylint fixes
2018-10-01 08:52:42 +02:00
Charles Garwood
ea7b1e4573 Update Z-Wave service descriptions to point to proper log file (#17024) 2018-10-01 08:50:32 +02:00
cdce8p
8444b9ba03 Async syntax 2, camera & climate & config (#17016) 2018-10-01 08:50:05 +02:00
cdce8p
38e371c5d9 Async syntax 1, alarm_control_panel & automation & binary_sensor (#17015) 2018-10-01 08:49:19 +02:00
sander76
750c96709e Homematic cloud device update fix (#17001) 2018-09-30 22:39:25 +02:00
Patrik
940d5fb2ee Add basic support for Tradfri switches (#17007)
* Initial commit

* Sockets have been moved to separate component

* Sockets have been moved to separate component

* Fix const PLATFORM_SCHEMA

* Fix unique id

* Fix async_create_task

* Fix PLATFORM_SCHEMA

* Fix typo

* Remove pylint disable
2018-09-30 22:22:07 +02:00
Paulus Schoutsen
0a2b266742 Fix MQTT certificates (#16999) 2018-09-30 21:36:27 +02:00
Steven Looman
f511920a04 Merge remote-tracking branch 'upstream/dev' into igd 2018-09-30 20:22:10 +02:00
Totoo
1b7bfec247 Google Maps supports battery level and charging. (#16969)
* Google Maps supports battery level and charging.

With 3.0.2 locationsharinglib now the battery level and the charging attributes are available.

* Update google_maps.py

fix too long line error

* Update google_maps.py

Fix multi line import, and line length limit

* Update gen_requirements_all.py

Add locationsharinglib to gen_requirements_all

* update requirements_all

* Last try to fix requirements_all...
2018-09-30 15:17:39 +02:00
Paulus Schoutsen
f5632a5da5 Add webhook + IFTTT example (#16817)
* Add webhook + IFTTT example

* Abort if not externally accessible

* Abort on local url

* Add description to create entry

* Make body optional

* Allow ifttt setup without config

* Add tests

* Lint

* Fix Lint + Tests

* Fix typing
2018-09-30 14:45:48 +02:00
Paulus Schoutsen
1e28c752e1 Merge pull request #16988 from home-assistant/rc
0.79.1
2018-09-30 13:31:29 +02:00
Paulus Schoutsen
677714ecab Bumped version to 0.79.1 2018-09-30 10:22:49 +02:00
Rohan Kapoor
e2aadc3227 Bump zm-py to 0.0.4 (#16979) 2018-09-30 10:22:42 +02:00
Greg Laabs
c45b240026 Fix ISY blocking bug (#16978)
This fix results in `is_on` returning False if the state is unknown (which was a bug in 0.79).
2018-09-30 10:22:42 +02:00
Jason Hu
32d652884b Override unique_id of NestActivityZoneSensor (#16961) 2018-09-30 10:22:41 +02:00
Anders Melchiorsen
3528f8e647 Fix exception during history_stats startup (#16932)
* Fix exception during history_stats startup

* Do not track changes during startup

* Ignore args
2018-09-30 10:22:41 +02:00
Jason Hu
3e6cf8f59f Optimize Ring Sensors platform setup (#16886) 2018-09-30 10:22:41 +02:00
Ville Skyttä
06d959ed43 Upgrade pytest to 3.8.1 (#16980) 2018-09-30 10:20:10 +02:00
Greg Laabs
7f47d601f1 Fix ISY blocking bug (#16978)
This fix results in `is_on` returning False if the state is unknown (which was a bug in 0.79).
2018-09-30 09:21:27 +02:00
Rohan Kapoor
8b1bdda0fa Bump zm-py to 0.0.4 (#16979) 2018-09-30 09:21:07 +02:00
Otto Winter
70ce9bb7bc Add pressure sensor device class (#16965)
* Add pressure sensor device class

* Undo github desktop line exclude
2018-09-29 22:01:04 +02:00
Otto Winter
45fdda3f5d Add unique_id to MQTT fan (#16949) 2018-09-29 21:22:57 +02:00
Anders Melchiorsen
caaf4f5694 Fix exception during history_stats startup (#16932)
* Fix exception during history_stats startup

* Do not track changes during startup

* Ignore args
2018-09-29 21:22:24 +02:00
Otto Winter
3ddad83a84 Add unique_id to MQTT cover (#16950)
* Add unique_id to MQTT cover

* Fix tests
2018-09-29 20:54:57 +02:00
Otto Winter
35b6064581 Convert fan component to config entry (#16951)
* Conver fan component to config entry

* Lint
2018-09-29 20:53:48 +02:00
Jason Hu
c600d28b6a Override unique_id of NestActivityZoneSensor (#16961) 2018-09-29 20:53:02 +02:00
Diogo Gomes
909c3bdd63 Merge pull request #16954 from abmantis/patch-2
Adds @abmantis to CODEOWNERS
2018-09-28 23:05:59 +01:00
Abílio Costa
4b8c38819e Add myself to CODEOWNERS 2018-09-28 22:47:29 +01:00
Jan van Helvoort
7d1960baba Add zwave.network_complete_some_dead event (#16894)
* Add zwave.network_complete_some_dead event

* add missing comma

* typo

* Add SIGNAL_AWAKE_NODES_QUERIED_SOME_DEAD Test

* Add blank lines

* fix linter warnings

Line too long

* remove trailing whitespace

* Change test signal

* Listen to other event
2018-09-28 19:14:57 +02:00
Otto Winter
af89e7c50f Move more MQTT platforms to config entries (#16918)
* Move more MQTT platforms to config entries

* Address comments
2018-09-28 16:57:17 +02:00
Paulus Schoutsen
c93879074b Merge pull request #16940 from home-assistant/rc
0.79.0
2018-09-28 16:51:25 +02:00
Paulus Schoutsen
f476d781ec Version bump to 0.79.0 2018-09-28 15:28:24 +02:00
Anders Melchiorsen
720b05c301 Fix race between script delay and turn_off (#16923) 2018-09-27 22:08:09 -06:00
Otto Winter
c9b6567265 Remove discovered mqtt_json light entity when discovery is cleared (#16906)
* Remove discovered mqtt_json entity device when discovery topic is cleared

* Keep imports ordered
2018-09-28 00:25:51 +02:00
Greg Laabs
9abdbf3db6 Rachio component modernization (#16911)
Add `unique_id` to all rachio entities
Add platform discovery to rachio component
Move config options from switch.rachio platform to the rachio component
2018-09-27 23:17:15 +02:00
cdce8p
f879ac0993 Remove service helper (6) (#16920)
* Update automation

* Update group

* Async_create_task
2018-09-27 23:14:09 +02:00
cdce8p
70b901017f Remove service helper (5) (#16917)
* Update switch

* Update script

* Update light

* Fix tests

* Fix config/script hook

* Async_create_task

* Fix flux switch
2018-09-27 23:13:11 +02:00
Paulus Schoutsen
7bfe0e1c00 Bumped version to 0.79.0b3 2018-09-27 23:10:42 +02:00
Paulus Schoutsen
fb39641eef Handle exception handling websocket command (#16927)
* Handle exception handling websocket command

* lint

* Lint2
2018-09-27 23:10:36 +02:00
Paulus Schoutsen
b7e03f6973 Prevent discovered Tradfri while already configured (#16891)
* Prevent discovered Tradfri while already configured

* Lint
2018-09-27 23:10:35 +02:00
Charles Garwood
7597e30efb Add unique_id to Nest Sensors (#16869)
* Add unique_id

* Add device_info

* Fix typo

* Update __init__.py
2018-09-27 23:10:35 +02:00
Paulus Schoutsen
a7248d4574 Handle exception handling websocket command (#16927)
* Handle exception handling websocket command

* lint

* Lint2
2018-09-27 23:10:07 +02:00
Paulus Schoutsen
51dbc988f9 Update translations 2018-09-27 23:08:04 +02:00
Paulus Schoutsen
71333a15f7 Bump frontend to 20180927.0 2018-09-27 23:08:04 +02:00
Paulus Schoutsen
bac71d3d22 Update translations 2018-09-27 23:04:28 +02:00
Paulus Schoutsen
d77e88645e Bump frontend to 20180927.0 2018-09-27 23:04:03 +02:00
Otto Winter
2d104f95d7 Fix MQTT Config Entry Discovery (#16919) 2018-09-27 22:56:04 +02:00
Paulus Schoutsen
81e21b90c9 Fix auth redirect (#16914)
* Fix auth redirect

* Remove old test
2018-09-27 09:02:50 -07:00
Otto Winter
d1ad2cc225 Make MQTT platforms config entries (#16904)
* Make MQTT platforms config entries

* Fix tests

* Address Comment

* Rework tests

* Undo style auto-reformat style changes
2018-09-27 16:07:56 +02:00
zxdavb
8d65230a36 Add (EU-based) Honeywell evohome CH/DHW controller (#16427)
* Add support for Honeywell evohome CH/DHW systems

More flake8 corrections

Passes Flake8 tests

Almost passed flake8.pylint!

Passed all tox tests

Now it needs serious testing!

Almost ready to submit

BUGFIX: DHW state now functional

More improvements to available()

Solved the DHW temp units problem!

Last minute bug squash

to improve dicts merge

Trying to rebase

fixing more rbase errors

revert to creating HTTP_error_code internally for now

ready to submit PR

Added support for Honeywell evohome CH/DHW systems

* Updated requirements_test_all.txt

* Fix: D401 First line should be in imperative mood

* Remove _LOGGER.info (replace with _LOGGER.debug)

* raise PlatformNotReady when RequestException during setup()

* Revert some LOGGER.debug to LOGGER.warning

* Improved logging levels, and removed some unwanted comments

* Improvments to logging - additional self._status info

* BUGFIX: DHW wrongly showing available = False (and some other tweaks)

* Fix trailing whitespace

* Remove state_attributes override and API_VER code

* Removed heating zones, DHW and heuristics to reduce # lines of code

* Removed some more lines of code

* Removed unused configuration parameters

* Remove some more un-needed lines

* Removed more (uneeded) lines of code & fixed two minor typos

* Improvements to debug logging of available() = False

* Improvements to code, and code clean-up

* Corrected a minor typo

* A small tidy up

* reduces precision of emulated temps floats to 0.1

* Some code improvements as suggested by JeardM

* Rewrite of exception handler

* Removed another unwanted logging in properties

* Remove async_ version of various methods

* moved available heuristics to update()

* Cleanup of code, and re-work linter hints

* fixed a minor documentation typo

* scan_interval is now no longer a configurable option

* Change from Master/Slave to Parent/Child

* Removed the last of the slaves

* Removed the last of the masters

* Move -PARALLEL_UPDATES to .\climate\evohome.py'

* main code moved to climate/evohome.py

* merge EvoEntity into EvoController class

* remove should_poll (for now)

* woops! left a hint in

* removed icon

* only log a WARNING the first time available = False

* cleanup dodgy exception handling

* Tidy up exception handling

* Many changes as suggested by @MartinHjelmare, thanks

* remove hass from init, part 1

* use async_added_to_hass instead of dispatcher_connect

* remove hass from init, part 2 (done)

* add 1-2 arrays, and tidied up some comments

* from dispatcher to async_added_to_hass

* cleaned up some logging, and removed others

* Many changes as request by @MartinHjelmare

* Homage to the lint

* Changed to the HA of doing operating_mode

* Now using update_before_add=True

* reduced logging further still...

* fixed minor lint

* fix a small logic error

* Add device_state_attributes to track actual operating mode

* Clean up doc quotes caused by  previous changes

* Woops! removed some debug lines that shoudln't have stayed in

* Add a complete set of device_state_attributes

* Cleanup some constants

* Remove more legacy code

* domain_data to evo_data & this else should be a finally

* minor change for readability

* Minor change for readability #2

* removed unused code

* small tidy up - no code changes

* fix minor lint

* Correct URLs & descriptions in docstring

* whoops - fixed a typo in docstrings

* remove an unused line of cide & a small tidy-up
2018-09-27 13:29:44 +02:00
Blake Blackshear
2cc6263092 Add new services for set/refresh Z-Wave device values (#16638)
* Add services for getting and setting indicator values for Z-Wave

* Add service to manually refresh Z-Wave node value by value_id

* Remove refresh_indicator service

* Coerce to int

* Add generic set_node_value service

* Remove set_indicator service
2018-09-27 12:34:42 +02:00
emontnemery
ad79dc673d MQTT Light - Do not throw if property is missing from templated MQTT message (#16720)
* Do not throw if property is missing

* Render template once, add debug prints
2018-09-27 11:48:52 +02:00
Paulus Schoutsen
da3342f1aa Update new values coming in for dev registry (#16852)
* Update new values coming in for dev registry

* fix Lint+Test;2C
2018-09-27 11:26:58 +02:00
Anders Melchiorsen
29db43edb2 Ignore Xiaomi hub callbacks during setup (#16910) 2018-09-27 09:44:19 +02:00
Anders Melchiorsen
24e9c62fe7 Upgrade pysonos to 0.0.3 (#16901)
This version has downgraded/removed some logging that we then no
longer have to hide.
2018-09-27 01:09:30 +02:00
Anders Melchiorsen
81d4338b93 Upgrade aiolifx_effects to 0.2.0 (#16900) 2018-09-27 01:08:20 +02:00
Jason Hu
96e5acda1a Optimize Ring Sensors platform setup (#16886) 2018-09-26 15:38:13 -07:00
Anders Melchiorsen
726cf9b1c4 Remove unused import (#16909)
* Remove unused import

* Revert test usage
2018-09-27 00:21:29 +02:00
Paulus Schoutsen
631ecf578e Lint 2018-09-26 23:48:55 +02:00
Paulus Schoutsen
273a7af330 Prevent discovered Tradfri while already configured (#16891)
* Prevent discovered Tradfri while already configured

* Lint
2018-09-26 18:03:25 +02:00
cdce8p
4b674b1d16 Remove unused legacy test helper methods (#16893) 2018-09-26 18:03:13 +02:00
cdce8p
dd45e99302 Remove service helper (4) (#16892)
* Update media_player

* Update lock

* Update notify

* Update remote

* Update scene

* Update vacuum

* Remove timer helpers

* Removed unused legacy helpers
2018-09-26 18:02:05 +02:00
Paulus Schoutsen
d0ddc28f96 Revert file mode write_json (#16897) 2018-09-26 17:58:44 +02:00
Paulus Schoutsen
9ab8f78b19 Don't pass use_env=True (#16896) 2018-09-26 17:20:34 +02:00
Paulus Schoutsen
732009c668 Update translations 2018-09-26 15:39:20 +02:00
Paulus Schoutsen
d20e0f5c95 Update frontend to 20180926.0 2018-09-26 15:39:20 +02:00
cgtobi
98a4b1e9ac Update language strings (#16884) 2018-09-26 13:07:43 +02:00
Nikolay Vasilchuk
917df1af00 Telegram_bot polling support proxy_url and proxy_params (Fix #15746) (#16740)
* Telegram bot polling proxy support

* CI fix

* houndci-bot review fix

* houndci-bot review fix

* CI fix

* Review

* Update polling.py
2018-09-26 11:59:37 +02:00
Blake Blackshear
f13f723a04 Add bitwise operations as template helpers (#16833) 2018-09-26 11:57:16 +02:00
Paulus Schoutsen
7b68f344e3 Bumped version to 0.79.0b2 2018-09-26 11:21:22 +02:00
Paulus Schoutsen
824e59499f Make ring sync again (#16866) 2018-09-26 11:21:10 +02:00
Paulus Schoutsen
ff9377d1d9 Fix MQTT discovery (#16864)
* Fix MQTT discovery

* Update __init__.py
2018-09-26 11:21:09 +02:00
Charles Garwood
cf0d0fb33e Device Registry Support for iOS Sensors (#16862)
* Add device_info property to iOS sensors for device registry

* Remove unused logger import

* Fix spacing

* lint

* Lint
2018-09-26 11:21:09 +02:00
Jason Hu
75c372021d Fix example for long-lived access token WS API (#16882) 2018-09-26 11:20:48 +02:00
Paulus Schoutsen
3aaf619fc3 Update translations 2018-09-26 11:20:07 +02:00
Paulus Schoutsen
e375b63902 Update frontend to 20180926.0 2018-09-26 11:20:00 +02:00
Nicko van Someren
e5861241c7 Added support for private storage. (#16878)
* Addded support for private storage.

Include 'private' flag parameters to the Store class and save_json function.
Updated various authentication and onboarding classes to use private stores.
Fixed unit test for emulated_hue which used a mock patch on save_json().

* Fixed Hound formatting issues not detected by local linting.
2018-09-26 10:24:32 +02:00
Paulus Schoutsen
e205092693 Revert incorrect check (#16883) 2018-09-26 10:15:49 +02:00
cdce8p
fa98a27df7 Remove service helper (2) (#16863)
* alarm_control_panel

* automation

* camera

* climate

* counter

* fan

* Add legacy notes

* Fix tests
2018-09-26 09:49:55 +02:00
Paulus Schoutsen
c899875abb Fix MQTT discovery (#16864)
* Fix MQTT discovery

* Update __init__.py
2018-09-26 09:38:50 +02:00
Charles Garwood
bab079f649 Add unique_id to Nest Sensors (#16869)
* Add unique_id

* Add device_info

* Fix typo

* Update __init__.py
2018-09-26 09:19:47 +02:00
Jason Hu
92a5068977 Use HA native OAuth2 flow for google assistant components (#16848)
* Use HA native OAuth2 flow for google assistant components

* Lint

* Force breaking changes

* Fix CONFIG_SCHEMA
2018-09-26 08:57:55 +02:00
Charles Garwood
3cba2e695c Device Registry Support for iOS Sensors (#16862)
* Add device_info property to iOS sensors for device registry

* Remove unused logger import

* Fix spacing

* lint

* Lint
2018-09-26 08:56:23 +02:00
cdce8p
bfa1c55803 Fix fan_init test (#16865)
* Fix fan_init test

* Readd __init__.py
2018-09-26 08:53:24 +02:00
Paulus Schoutsen
ba2b8512c5 Make ring sync again (#16866) 2018-09-26 08:52:22 +02:00
cdce8p
e2a56721d3 Remove service helper (3) (#16879)
* Update duckdns

* Update google_assistant

* Update group

* Update homematic

* Update image_processing

* Update input_boolean

* Update input_number

* Update input_select

* Update input_text
2018-09-26 08:50:05 +02:00
Martin Mois
672fc61bb2 aiohttp.ClientSession gets proxy information from HTTP_PROXY/HTTPS_PROXY (#16874) 2018-09-26 08:43:09 +02:00
Gerard
6490ec87f3 Upgrade to bimmer_connected 0.5.3 (#16877) 2018-09-26 08:24:59 +02:00
Daniel Høyer Iversen
dc102a96a9 Tibber realtime consumption, Tibber pulse (#16870)
* tibber real time data

* Tibber Pulse, realtime consumption

* update lib
2018-09-26 07:49:09 +02:00
cdce8p
b91a061cef Add missing __init__ test files (#16871) 2018-09-25 23:08:37 +02:00
cdce8p
7eaf8640d0 Update cover tests (#16832)
* Update test_group
* Update test_command_line
* Update test_demo
* Update test_mqtt
* Update test_template
* Remove cover service call helpers
2018-09-25 22:32:05 +02:00
Jedmeng
8e311686d0 Add support for Opple light (#16765)
* Add support for Opple light

* Update docstring

* review fix

* review fix

* review fix
2018-09-25 20:49:37 +02:00
Paulus Schoutsen
5a22e7d211 Fail if dirty (#16839)
* Fail if dirty

* Update check_dirty

* Update text

* Fix comment

* Add -e

* Update dirty script
2018-09-25 20:47:51 +02:00
Paulus Schoutsen
7de0e1e39a Add executor job (#16853) 2018-09-25 20:47:22 +02:00
emontnemery
4501bdb4a0 Remove discovered MQTT cover device when discovery topic is cleared (#16857) 2018-09-25 19:32:42 +02:00
emontnemery
4a265f37e0 Remove discovered MQTT fan device when discovery topic is cleared (#16858) 2018-09-25 19:32:31 +02:00
emontnemery
c3f58b8c74 Remove discovered MQTT lock device when discovery topic is cleared (#16859) 2018-09-25 19:32:25 +02:00
emontnemery
422ccc1a28 Remove discovered MQTT sensor device when discovery topic is cleared (#16860) 2018-09-25 19:32:16 +02:00
emontnemery
eb59f2dd3c Move MQTT discovery removal tests to platform test files (#16861) 2018-09-25 19:32:04 +02:00
Paulus Schoutsen
399040de46 Fix files left behind (#16855)
* Light demo test to not write entity registry

* Fix Manual MQTT alarm control panel
2018-09-25 17:19:46 +02:00
emontnemery
0dbfd77402 Remove discovered MQTT climate device when discovery topic is cleared (#16856) 2018-09-25 17:15:39 +02:00
Paulus Schoutsen
61a2d09342 Bumped version to 0.79.0b1 2018-09-25 15:39:42 +02:00
Paulus Schoutsen
345c886dec Add unique ID and device info to Nest camera (#16846)
* Add unique ID and device info to Nest camera

* Remove sw version
2018-09-25 15:39:36 +02:00
Paulus Schoutsen
b9043ef7a7 Allow MQTT discovery (#16842) 2018-09-25 15:39:36 +02:00
Paulus Schoutsen
356040d506 Support old tradfri config format (#16841) 2018-09-25 15:39:35 +02:00
Rohan Kapoor
0431e38aa2 Bump zm-py to 0.0.3 (#16835) 2018-09-25 15:39:34 +02:00
Paulus Schoutsen
4c32ad3b48 Don't warn but info when on dev mode (#16831) 2018-09-25 15:39:33 +02:00
Tommy Jonsson
bc8d323bdd Add image support to hangouts notifications (#16560)
* add image to services.yaml

* add image support

Add image support to hangouts notification.

* fix indents

* fix line length

* Add data schema

forgot schema

* fix linelength

* use is_allowed_path and better file error handling

* elif not else if

* fix logger error

* fixes

* fix travis errors/warnings

* remove trailing whitespace

* fix travis pylint naming

* new async style

* removed unused async_timeout

* change to image_file/url (#3)

* change to image_file/url

* removed whitespace

* forgot to remove unused urlparse import

* image_file/url in service help
2018-09-25 15:04:43 +02:00
Paulus Schoutsen
a1c914dfeb On removal, only unload config entry if loaded (#16844)
* On removal, only unload config entry if loaded

* Fix test
2018-09-25 14:29:13 +02:00
emontnemery
093285f92f Remove discovered MQTT binary_sensor device when discovery topic is cleared (#16826) 2018-09-25 14:25:03 +02:00
Paulus Schoutsen
9ea5afd109 Add unique ID and device info to Nest camera (#16846)
* Add unique ID and device info to Nest camera

* Remove sw version
2018-09-25 13:47:12 +02:00
Daniel Høyer Iversen
01925fdfff change unknown to None in Netatmo public (#16845) 2018-09-25 13:41:29 +02:00
Paulus Schoutsen
7840b1e387 Fix MQTT leaving files behind (#16840) 2018-09-25 12:22:27 +02:00
Paulus Schoutsen
e4898bb05c Allow MQTT discovery (#16842) 2018-09-25 12:22:14 +02:00
Paulus Schoutsen
f4974f58fe Config entry update data (#16843)
* WIP

* Allow updating data of a config entry
2018-09-25 12:21:11 +02:00
Paulus Schoutsen
2b2502c91c Support old tradfri config format (#16841) 2018-09-25 11:57:32 +02:00
Daniel Winks
4a4c07ac1b GitLab-CI sensor integration addition. (#16561)
* Updates to GitLab Sensor

* Updates to GitLab_CI sensor.

* Added GitLab_CI sensor.

* Updated interval to a more appropriate 300 seconds.

* Added GitLab_CI.py to ommitted files.

* Initial refactor to use python-gitlab PyPI module.

* Fixes to dict parsing.

* Updated required packages for GitLab_CI requirements.

* Updates and refactoring to more closely align with Home-Assistant standards.

* Moved import to init, removed unreachable requests exception.

* Removed references to STATE_UNKNOWN and replaced with None

* Removed extra whitespace

* Changed PLATFORM_SCHEMA and renamed add_devices.

Changed PLATFORM_SCHEMA to use SCAN_INTERVAL and add_devices to add_entities

* Added configurable name, changed logger and removed cruft.

* Removed _status to use _state instead, as both held same value.

* Fixed ATTR_BUILD_BRANCH, removed more extraneous cruft.

* Changed required config keys to dict[key] format.

* Removed extraneous CONF_SCAN_INTERVAL as it's already defined.
2018-09-25 11:18:23 +02:00
GP8x
03bce84c32 Add additional Netatmo public data sensors (#16671)
Update deps
2018-09-25 11:14:42 +02:00
Paulus Schoutsen
4f9fc9b39f Don't create entity registry in tests (#16838) 2018-09-25 10:16:30 +02:00
sander76
069b819679 Add unique_id to homematic_cloud (#16828)
* add unique_id

* add docstring and trigger travis
2018-09-25 10:15:03 +02:00
emontnemery
90197b6ec9 Remove discovered MQTT light device when discovery topic is cleared (#16824) 2018-09-25 09:19:04 +02:00
emontnemery
42790d3e97 Remove discovered MQTT alarm_control_panel device when discovery topic is cleared (#16825) 2018-09-25 08:44:14 +02:00
Paulus Schoutsen
e78f4d1b65 Extract lovelace to it's own component (#16816)
* Extract lovelace to it's own component

* Lint

* Update comment

* Lint

* Lint
2018-09-25 08:39:35 +02:00
Rohan Kapoor
354c8f3409 Bump zm-py to 0.0.3 (#16835) 2018-09-25 07:53:35 +02:00
Paulus Schoutsen
579b77ba4c Don't warn but info when on dev mode (#16831) 2018-09-25 07:52:10 +02:00
randellhodges
b52e8525ac Add mode (daily/hourly) to darksky (#16719)
* added daily mode to darksky and wind_bearing, ozone, and visibility

* Removed dew point and pressure until the standard is updated
2018-09-24 18:09:15 +02:00
Paulus Schoutsen
dc75db6376 Bumped version to 0.80.0.dev0 2018-09-24 12:15:47 +02:00
Paulus Schoutsen
7d68ec1110 Merge branch 'dev' into rc 2018-09-24 12:14:43 +02:00
Paulus Schoutsen
c352b6fa59 Version bump to 0.79.0b0 2018-09-24 12:13:52 +02:00
Paulus Schoutsen
0bd94d8b56 Remove unused translation key 2018-09-24 12:02:26 +02:00
Paulus Schoutsen
3e2a9afff0 Another update translations 2018-09-24 12:01:34 +02:00
Paulus Schoutsen
d4b239d1d4 Update translations 2018-09-24 12:01:01 +02:00
Paulus Schoutsen
b2a9e203f2 Update frontend to 20180924.0 2018-09-24 11:58:03 +02:00
Greg Laabs
dc1534c6d1 Fix some unhandled exceptions due to missing null checks (#16812)
Fixed a couple cases that would produce errors when the ISY node status was None or `-inf`.
2018-09-24 11:43:00 +02:00
Robin Clarke
589554ad16 Allow soundtouch to play https content too (#16713) 2018-09-24 11:16:28 +02:00
Ville Skyttä
33d6c99f19 Add Python 3.7 classifier (#16645) 2018-09-24 11:11:24 +02:00
Daniel Høyer Iversen
1f74adae2a Broadlink service name (#16345)
* Broadlink. slugify service name

* style
2018-09-24 11:10:33 +02:00
Jason Hu
7a77951bb4 Add Notify MFA module (#16314)
* Add Notify MFA

* Fix unit test

* Address review comment, change storage implementation

* Add retry limit to mfa module

* Fix loading

* Fix invalaid login log processing

* Typing

* Change default message template

* Change one-time password to 8 digit

* Refactoring to not save secret

* Bug fixing

* Change async_initialize method name to aysnc_initialize_login_mfa_step

* Address some simple fix code review comment
2018-09-24 11:06:50 +02:00
Thomas Lovén
ad47ece5c6 Allow split component definitions in packages (#16177)
* Allow split component definitions in packages

Two different configuration styles are described in
https://www.home-assistant.io/docs/configuration/devices/#style-2-list-each-device-separately

But only one is allowed in packages according to
https://www.home-assistant.io/docs/configuration/packages/

This change allows "Style 2" configuration in packages.

* Added test for split component definition in packages
2018-09-24 10:17:24 +02:00
emontnemery
5ee4718e24 Remove discovered MQTT Switch device when discovery topic is cleared (#16605)
* Remove discovered device when discovery topic is cleared

* Move entity removal away from mqtt discovery

* Move discovery update to mixin class

* Add testcase

* Review comments
2018-09-24 10:11:49 +02:00
Martin Berg
a5cb4e6c2b Use pyspcwebgw for SPC component (#16214)
* Use pyspcwebgw library.

* Support alarm triggering.

* Update requirements.

* Add pyspcwebgw to test reqs.

* Also update script.

* Use dispatcher.

* Address review feedback.
2018-09-24 10:10:10 +02:00
Baptiste Lecocq
4fd2f773ad Add linky sensor (#16468)
* Add linky component

* Update requirements_all.txt

* Add timeout to pylinky requests

* Make linky platform fail fast
2018-09-24 08:09:34 +02:00
Jason Hu
564ad7e22a Rework chromecast fix (#16804)
* Revert changes of #16471, and fix the platform setup issue

* Fix unit test

* Fix

* Fix comment

* Fix test

* Address review comment

* Address review comment
2018-09-23 23:35:07 +02:00
mvn23
329d9dfc06 Improve opentherm_gw state detection (#16809)
Only show the platform in STATE_HEAT when the boiler is actually heating.
2018-09-23 22:16:24 +02:00
Anders Melchiorsen
2258c56d34 Handle netgear_lte connection errors (#16806) 2018-09-23 18:58:09 +02:00
Daniel Shokouhi
e90abf1007 Set botvac state when offline (#16805) 2018-09-23 12:35:18 +02:00
Paul Biester
eaee55175b Add configurable host for bbox routers (#16778)
* Add configurable host for bbox routers

Add configurable host for bbox router running on non-default IP addresses.

* Fix unused import

Fix unused import which also resolves "line too long"

* Fix wrong import order

* Update validation
2018-09-23 10:37:53 +02:00
huangyupeng
539b86e079 Add Tuya cover state (#16709)
* add cover open and close state

* add tuya cover state

* fix pylint

* fix pylint problem
2018-09-23 10:36:33 +02:00
tadly
127395ae8d Upgrade zeroconf to 0.21.3 (#16789) 2018-09-23 09:50:59 +02:00
Greg Laabs
eca1f050cd Bump sucks (Ecovacs) lib to 0.9.3 (#16803)
* Bump sucks (Ecovacs) lib to 0.9.3

Changed code that was in place as a workaround pre-0.9.2. This version bump fixes a few issues.

* Update requirements_all
2018-09-23 09:43:01 +02:00
Rohan Kapoor
0d681b0ba6 Bump zm-py up to 0.0.2 (#16800) 2018-09-23 09:42:11 +02:00
Daniel Shokouhi
94d38a1c6b Bump pybotvac to 0.0.10 (#16799) 2018-09-23 09:41:45 +02:00
Daniel Høyer Iversen
cfd1aec741 Update Tibber lib (#16795) 2018-09-22 18:25:17 +02:00
Daniel Shokouhi
eec6722cf4 Fix return to base logic for neato (#16776) 2018-09-22 11:34:46 +02:00
Paulus Schoutsen
fce275d29c Merge pull request #16787 from home-assistant/rc
0.78.3
2018-09-22 11:20:29 +02:00
Paulus Schoutsen
5eda5f2f7b Bumped version to 0.78.3 2018-09-22 11:18:54 +02:00
edif30
5ab580ab34 Bump gtts-token to 1.1.2 (#16775)
* bump gtts-token to 1.1.2

* bump gtts-token to 1.1.2

* bump gtts-token to 1.1.2
2018-09-22 11:18:47 +02:00
Paulus Schoutsen
5613816476 Fix Windows loop (#16737)
* Fix Windows loop

* Fix windows Ctrl+C

* Move windows restart handler out of setup_and_run_hass
2018-09-22 09:54:37 +02:00
Gerard
e9c7fe184d Upgrade bimmer_connected to 0.5.2 (#16780) 2018-09-22 08:52:57 +02:00
Fabian Affolter
41bb4760f7 Upgrade restrictedpython to 4.0b5 (#16779) 2018-09-21 23:21:00 +02:00
edif30
ee3f17d5c7 Bump gtts-token to 1.1.2 (#16775)
* bump gtts-token to 1.1.2

* bump gtts-token to 1.1.2

* bump gtts-token to 1.1.2
2018-09-21 21:22:27 +02:00
Malte Franken
18d37ff0fd GeoJSON platform (#16610)
* initial version of geojson platform

* unit tests for geo json platform added; smaller bugfixes and code cleanups

* fixing pylint issues

* moved all code accessing the external feed into separate library; refactored platform and tests to work with that new library

* fixing lint

* small refactorings
2018-09-21 21:15:57 +02:00
Robert Svensson
7fe0d8b2f4 deCONZ cover support (#16759)
deCONZ cover platform for Keen vents
2018-09-21 19:59:20 +02:00
Paulus Schoutsen
8b42d0c471 Add confirmation to Cast/Sonos/iOS config entries (#16769)
* Add confirmation to Cast/Sonos/iOS config entries

* Remove redundant code
2018-09-21 16:34:37 +02:00
Giuseppe
213171769d Refactored units and icons for the Dyson sensors (#14550)
* Refactored units and icons for the Dyson sensors

* Adapted unit tests to the new device names and unit of measurements

* Use None as empty unit of measurement

* Unrelated overall improvements following code review

* Adapted tests to new constructors as per previous commit

* Make sure the sensors have their `hass` attribute set in the test environment
2018-09-21 15:55:07 +02:00
Malte Franken
d5813cf167 Make rest sensor and binary sensor more efficient (#14484)
* create binary sensor even if initial update fails

* fixed broken test assertion

* fixed broken test assertion

* avoid fetching resource twice - manually in the setup_platform and then through add_devices

* raising PlatformNotReady instead of creating the sensor if the initial rest call fails; throttling the update to avoid fetching the same resource again immediately after setting up sensor

* rolled back throttling of the rest update call; can still avoid updating the binary sensor's rest resoure twice; fixed tests

* typo
2018-09-21 15:54:50 +02:00
Paulus Schoutsen
3e59ffb33a Add tradfri device info (#16768) 2018-09-21 14:47:52 +02:00
Maciej Bieniek
a0a54dfd5b Add unique_id to mqtt camera (#16569)
* Add unique_id to mqtt camera

* Remove whitespaces

* Add test for unique_id

* Add blank line
2018-09-21 13:09:54 +02:00
cdce8p
3bfe9e757e Add Carbon Monoxide HomeKit Sensor (#16664) 2018-09-21 12:51:02 +02:00
Alexei Chetroi
9fdf123a2f Zha switch schedule update state (#16621)
* switch.zha: Schedule state update.

if turning switch On or Off operation was successful, then schedule
state update

* switch.zha: Update debug logging.
2018-09-21 12:11:23 +02:00
Evan Bruhn
aeaf694552 Add Logi Circle component, camera and sensor platform (#16540)
* Added Logi Circle platform, camera and sensor

* Integrated with Logo Circle API’s feature detection to exclude sensors not supported by device. Added services for recording livestream and taking a snapshot from the livestream.

* Migrated livestream snapshot and recording functionality out of home assistant components and into the logi circle API wrapper. Added services.yaml entries for logi services.

* Added new Logi sensor types, updated to latest version of `logi_circle` and tidy up in preparation for pull request.

- Renamed `logi_set_mode` to `logi_set_config`.
- Live stream recording and snapshot methods now respect whitelisted path configuration.
- Added `streaming_mode` and `speaker_volume` sensors.
- Moved model-specific turn on/off logic to `logi_circle` library.

* Renamed `logi` component domain to `logi_circle`.

* Updates based on PR feedback

* Added timeout of 15s to logi_circle initial setup requests (login and grabbing cameras).
* Added unique ID (uses MAC address for camera platform, MAC address + sensor type for sensor platform).
* Added battery level and battery charging attributes to camera.
* Removed static attributes from device_state_attributes.
* Replaced STATE_UNKNOWN with None, replaced ‘on’ & ‘off’ with STATE_ON and STATE_OFF.
* Removed redundant SCAN_INTERVAL in sensor, removed redundant hass param from async_setup_platform in camera and sensor.
* Style tweaks.

* Replaced `asyncio.wait_for` with `async_timeout` to be consistent with other components.
2018-09-21 12:00:15 +02:00
Rohan Kapoor
3d1c8ee467 Implement support for complex templates in script delays (#16442)
* Implement support for complex templates in script delays

* Swap out dict instead of collections.Mapping
2018-09-21 11:57:01 +02:00
PhracturedBlue
98b92c78c0 Add Call Data Log platform. Mailboxes no longer require media (#16579)
* Add multiple mailbox support

* Fix extraneous debugging

* Add cdr support

* liniting errors

* Mailbox log messages should mostly be debug.  Fix race condition with initializing CDR

* async decorators to async

* Lint fixes

* Typo

* remove unneeded parameter

* Fix variable names

* Fix async calls from worker thread.  Other minor cleanups

* more variable renames
2018-09-21 11:55:12 +02:00
Paulus Schoutsen
2ac16b12c1 Merge pull request #16770 from home-assistant/rc
0.78.2
2018-09-21 11:40:04 +02:00
Paulus Schoutsen
df67093441 Fix faulty color temp crashing google (#16758)
* Fix faulty color temp crashing google

* Rename

* Print warning for incorrect color temp
2018-09-21 10:51:46 +02:00
Anders Melchiorsen
c475a876ce Upgrade pysonos to 0.0.2 (#16761) 2018-09-21 09:21:56 +02:00
Robert Svensson
90c18d1c15 deCONZ add via_hub attribute for device registry (#16760)
* deCONZ add via_hub attribute for device registry

* A shorter way to get bridgeid
2018-09-21 09:21:44 +02:00
Anders Melchiorsen
78b6439ee6 Use pysonos for Sonos media player (#16753) 2018-09-20 23:50:11 +02:00
Paulus Schoutsen
092c146eae Add option to disable specific integrations (#16757)
* Add option to disable specific integrations

* Lint
2018-09-20 23:46:51 +02:00
Paulus Schoutsen
44a98fb77a Bumped version to 0.78.2 2018-09-20 20:26:25 +02:00
Fabian Affolter
03d93bea34 Upgrade zeroconf to 0.21.2 (#16730) 2018-09-20 20:25:39 +02:00
Fabian Affolter
9dbac9b033 Upgrade zeroconf to 0.21.1 (#16687) 2018-09-20 20:25:38 +02:00
tadly
9e86f0498b Upgrade zeroconf to 0.21.0 (#16647) 2018-09-20 20:25:38 +02:00
Zoé Bőle
03de658d4d Changed save_on_change to default to False (#16744) 2018-09-20 20:24:01 +02:00
Alexei Chetroi
3ea8c25e1f light.zha: Catch exceptions for all commands. (#16752)
Catch exceptions for all operations which may fail because of device
reachibility
More verbose debug logging on operations
2018-09-20 20:23:09 +02:00
Steven Looman
6e01ea5929 Preserve compatibility with original upnp 2018-09-20 18:15:04 +02:00
Pascal Vizeli
c6ccbed828 Small cleanup for slack (#16743) 2018-09-20 15:14:43 +02:00
Paulus Schoutsen
e58836f99f Add subscription info endpoint (#16727)
* Add subscription info endpoint

* Lint

* Lint

* Make decorator

* Lint
2018-09-20 14:53:13 +02:00
Paulus Schoutsen
874225dd67 Merge branch 'master' into dev 2018-09-20 13:57:35 +02:00
Paulus Schoutsen
0d0d5c8c2c Merge pull request #16742 from home-assistant/rc
0.78.1
2018-09-20 13:55:09 +02:00
Paulus Schoutsen
fc6cc22b6d Bump frontend to 20180920.0 2018-09-20 13:09:43 +02:00
Fabian Affolter
39ea9a8c90 Upgrade shodan to 1.10.2 (#16736) 2018-09-20 11:34:37 +02:00
Paulus Schoutsen
c7d5f7698e Bumped version to 0.78.1 2018-09-20 11:32:26 +02:00
Jason Hu
9bbd61cbe4 Upgrade netdisco to 2.1.0 (#16735) 2018-09-20 11:32:16 +02:00
Jason Hu
7a7a164cb8 Handle chromecast CONNECTION_STATUS_DISCONNECTED event (#16732) 2018-09-20 11:32:15 +02:00
Andreas Oberritter
8379567636 SnmpSensor: Fix async_update (#16679) (#16716)
Bugfix provided by awarecan.
2018-09-20 11:32:14 +02:00
Daniel Høyer Iversen
93af3c57ff Avoid calling yr update every second for a minute ones every hour (#16731)
* Avoid calling yr update every second for a minute one every hour

* style
2018-09-20 11:31:05 +02:00
Jason Hu
d1acb0326c Upgrade netdisco to 2.1.0 (#16735) 2018-09-20 11:11:39 +02:00
Fabian Affolter
35005474f8 Upgrade keyring to 15.1.0 (#16734) 2018-09-20 11:11:08 +02:00
Jason Hu
3a45481b5b Handle chromecast CONNECTION_STATUS_DISCONNECTED event (#16732) 2018-09-20 10:48:45 +02:00
Daniel Høyer Iversen
aa7635398a Met.no weather platform (#16582)
* Add met.no weather component

* requirements .coveragerx

* use lib

* style

* style

* renam function to _fetch_data

* Only update once per hour

* style
2018-09-20 10:32:14 +02:00
Fabian Affolter
d3658c4af9 Upgrade zeroconf to 0.21.2 (#16730) 2018-09-20 09:38:35 +02:00
Fabian Affolter
dfe38b4d5a Upgrade youtube_dl to 2018.09.18 (#16729) 2018-09-20 09:37:44 +02:00
Vikram Gorla
fcb84d951e On-demand update of swiss public transport sensor (#16723)
* Sensor values to be updated only when required (only after the train has crossed).
Looking at the documentation on https://transport.opendata.ch/docs.html, delay information is available only on stationboard, so no need to query often if there is no "real"time info.

* Bumping up version of python_opendata_transport to 0.1.4 in order to catch client errors like throttling rejection (HTTP 429)

* pleasing the hound

* bumping python_opendata_transport to 0.1.4
2018-09-20 08:45:16 +02:00
Nikolay Kasyanov
27eede724c Add unique_id to mqtt_json light (#16721)
Applies changes from #16303 to mqtt_json component.
Fixes #16600.
2018-09-20 08:15:17 +02:00
kunago
258beb9cd3 Upgrading librouteros version (#16718) 2018-09-20 07:52:06 +02:00
Charles Garwood
da882672bd Save disabled_by in entity registry (#16699)
* Save disabled_by in entity registry

* Add trailing comma
2018-09-20 00:52:10 +02:00
geekofweek
60dfd68083 MyQ Open State Fix (#16681)
* MyQ Open State Fix

Fixes issues with MyQ reporting an open state

* Update myq.py

* MyQ STATE_OPEN Fix

remove un-needed code
2018-09-19 22:03:47 +02:00
Andreas Oberritter
6e4a6cc069 SnmpSensor: Fix async_update (#16679) (#16716)
Bugfix provided by awarecan.
2018-09-19 22:01:54 +02:00
Paulus Schoutsen
a1c524d372 Config flow tradfri (#16665)
* Fix comments

* Add config flow tests

* Fix Tradfri light tests

* Lint

* Remove import group from config flow

* fix stale comments
2018-09-19 21:21:43 +02:00
Ville Skyttä
3160fa5de8 Make pylint report non-LF linefeeds per the style guidelines (#16601) 2018-09-19 15:51:57 +02:00
Ville Skyttä
d4b7057a3d Use posargs in tox lint env (#16646)
Allows linting specified files or dirs only.
2018-09-19 15:48:04 +02:00
Ville Skyttä
227a1b919b More isort preparations (#16633)
* Adjust config closer to currently established style conventions

* Adjust some imports for better outcome with their comments
2018-09-19 15:40:36 +02:00
Matthias Urlichs
0121e3cb04 Remove usage of "run_until_complete" (#16617)
* De-run_forever()-ization

* Use asyncio.run (or our own implementation on Python <3.7)
* hass.start is only used by tests
* setup_and_run_hass() is now async
* Add "main" async hass.run method
* move SIGINT handling to helpers/signal.py
  * add flag to .run to disable hass's signal handlers
* Teach async_start and async_stop to not step on each other
  (more than necessary)

* shorten over-long lines

* restore missing "import asyncio"

* move run_asyncio to homeassistant.util.async_

* LOGGER: warn => warning

* Add "force" flag to async_stop

only useful for testing

* Add 'attrs==18.2.0' to requirements_all.txt

Required for keeping requirements_test_all.txt in sync, where it is in
turn required to prevent auto-downgrading "attrs" during "pip install"

* Fixes for mypy

* Fix "mock_signal" fixture

* Revert mistaken edit

* Flake8 fixes

* mypy fixes

* pylint fix

* Revert adding attrs== to requirements_test*.txt

solved by using "pip -c"

* Rename "run" to "async_run", as per calling conventions
2018-09-19 15:40:02 +02:00
Paulus Schoutsen
da108f1999 bump frontend to 20180919.0 2018-09-19 15:17:05 +02:00
Pascal Vizeli
d376049a3f Use one regex for Hass.io URL check (#16710) 2018-09-19 12:57:55 +02:00
Ville Skyttä
7f462ba0ec Upgrade mypy to 0.630 (#16674) 2018-09-19 08:58:58 +02:00
Fabien Piuzzi
b7ef4dddb4 Netdata configuration change: Allows multiple elements per group (#16656)
Allows multiple Netdata elements per group
2018-09-19 00:42:09 +02:00
Steven Looman
b72499a949 Fixes after rename 2018-09-18 20:22:33 +02:00
Steven Looman
b770acd9a7 Update requirements_all.txt 2018-09-18 20:21:52 +02:00
Adam Dullage
56b0d2e99f Added support for Starling Bank (#16522)
* Added support for Starling Bank

* Fixing Lint Issues

* Resolving Change Requests

* HTTP Error Handling & Sandbox URL Option

* Update starlingbank Requirement to v1.2

* Minor changes
2018-09-18 15:55:10 +02:00
Maikel Punie
8e7f783da8 Added velbus counter sensors, updated to py-velbus 2.0.20 (#16683) 2018-09-18 15:51:22 +02:00
Fabian Affolter
1913d07c39 Upgrade zeroconf to 0.21.1 (#16687) 2018-09-18 15:49:54 +02:00
Glenn Waters
2a85ed7236 Streamline log messages (#16243) 2018-09-18 15:06:52 +02:00
Fabian Affolter
cba3a5b055 Upgrade paho-mqtt to 1.4.0 (#16688) 2018-09-18 14:59:39 +02:00
Fabian Affolter
d2246d5a4f Fix test 2018-09-18 12:15:55 +02:00
Greg Laabs
72419a1afe Fix Ecovacs vacuums showing "None" for name (#16654)
Was previously checking for a missing key, when should have been checking for the value being None
2018-09-18 08:30:20 +02:00
Fabian Affolter
a7325ebe1f Suppress traceback and log error (#16669) 2018-09-18 07:55:13 +02:00
Aaron Bach
27d50d388f Fixes an AirVisual bug where response data is missing (#16673) 2018-09-17 14:44:18 -06:00
Tsvi Mostovicz
25712f16b3 Jewish calendar sensor (#16393)
* Initial commit for  jewish calendar sensor

* Make check for logging errors into it's own function

* Can't use f-strings as we need to support python3.5

* Implement basic functionality: printing of date

* Update requirements_all.txt

* Allow user to specify date for sensor

* Add hdate to test requirements

* Update to match pull request

* Support date output in hebrew

* Limit languages to english and hebrew

* Add name back to sensor

* Change icon to be calendar-today

* Add multiple sensors

* Fix tests

* Make Hound happy, remove unused imported class

* hdate expects datetime.date not datetime.datetime

* Return sensor name

* Times should be returned as time object, not datetime

* Add myself to codeowners for jewish calendar component

* Return actual reading, not index

* Add more tests. Currently failing.

Will need to update hdate API and version before continuing.

* Fix weekly portion test

* Make all tests pass

* Make travis happy and add a test so it doesnt happen again

* Remove defaults in __init__ method

* Change sensor state variable to local variable in update() method

* Minor changes
2018-09-17 22:43:31 +02:00
Steven Looman
5cb0c92e78 Fix discovery/config entry handlers 2018-09-17 22:25:32 +02:00
Steven Looman
a7a16e4317 Fix tracebacks 2018-09-17 22:15:44 +02:00
Steven Looman
c19665fed4 Rename igd to upnp 2018-09-17 22:10:18 +02:00
Steven Looman
6588dceadd Fix uppercase
Fix translation
2018-09-17 22:09:51 +02:00
Paulus Schoutsen
9e59fc5d05 Merge pull request #16666 from home-assistant/rc
0.78.0
2018-09-17 19:03:37 +02:00
Paulus Schoutsen
366e270e94 Bump frontend to 20180916.0 2018-09-17 18:33:41 +02:00
Paulus Schoutsen
4b30cbbf3b Update translations 2018-09-17 14:18:20 +02:00
Paulus Schoutsen
41ac2a3c73 Bump frontend to 20180917.0 2018-09-17 14:18:04 +02:00
Paulus Schoutsen
b8257866f5 Clean up device update, add via-hub (#16659)
* Clean up device update, add via-hub

* Test loading/saving data

* Lint

* Add to Hue"

* Lint + tests
2018-09-17 13:39:30 +02:00
Paulus Schoutsen
849a93e0a6 Update translations 2018-09-17 10:48:22 +02:00
Paulus Schoutsen
f918d62571 version bump to 0.78.0 2018-09-17 10:48:09 +02:00
damarco
1c251009fe Add zha device entity (#14579)
* Add endpoint entity

* Fix lint error

* Add nwk address as device state attribute

* Change to ZhaDeviceEntity

* Show last_seen only if offline

* Remove obsolete _discover_endpoint_info()
2018-09-17 10:42:21 +02:00
Paulus Schoutsen
201fd4afee Add config entries to connection class (#16618) 2018-09-17 10:12:46 +02:00
Anders Melchiorsen
3e0c6c176a Rework timer delays (#16650)
* Calibrate timer for each tick

* Return of timer out of sync detection
2018-09-17 10:10:50 +02:00
Alexei Chetroi
44fdfdf695 Log raw result of configure_reporting() command. (#16655) 2018-09-17 07:45:44 +02:00
Fabian Affolter
fea1c921fc Fix link to docs (#16652) 2018-09-17 07:45:01 +02:00
Fabian Affolter
5e3e441aa0 Upgrade holidays to 0.9.7 (#16651) 2018-09-17 07:44:23 +02:00
Daniel Perna
a1e6e04a5e Update pyhomematic to 0.1.49 (#16649) 2018-09-16 22:56:01 +02:00
tadly
2002497d09 Upgrade zeroconf to 0.21.0 (#16647) 2018-09-16 22:53:25 +02:00
Daniel Høyer Iversen
baeb791d84 Upgrade Switchmate lib (#16637)
* new version switchmate lib, fix bug, and enable more logging in lib

* new version switchmate lib, fix bug, and enable more logging in lib
2018-09-16 13:58:26 +02:00
Abílio Costa
9c9df793b4 New EDP re:dy component (#16426)
* add new EDP re:dy platform

* lint

* move api code to pypi module; fix lint

* fix lint; remove unused import

* pass aiohttp client session and hass loop to platform

* update requirements_all.txt

* fix docstring lint

* normalize quotes

* use async setup_platform

* improve entities update mechanism

* doc lint

* send update topic only after loading platforms

* lint whitespaces

* mute used-before-assignment pylint false error
2018-09-16 01:17:47 +02:00
Mattias Welponer
05922ac56a Add new devices to HomematicIP Cloud (#16636)
* Add support for outdoor temperature sensor and cleanup

* Add support for rotary handle and water sensor

* Fix comment
2018-09-15 21:28:49 +02:00
Jason Hu
34deaf8849 Add valid_window=1 to TOTP verify (#16625) 2018-09-15 13:28:25 +02:00
Ville Skyttä
cc38981a38 Update developer doc links to developers.home-assistant.io (#16622) 2018-09-15 13:27:37 +02:00
Paulus Schoutsen
18ce5092b4 Bumped version to 0.78.0b3 2018-09-15 12:46:02 +02:00
Paulus Schoutsen
7f7372198a Update translations 2018-09-15 12:45:54 +02:00
Pascal Vizeli
abe61c5529 Rewrite bluetooth le (#16592)
* Rewrite bluetooth le

* Update requirements_all.txt

* Update gen_requirements_all.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py
2018-09-15 12:45:23 +02:00
Jason Hu
b231fa2616 Fix broken bluetooth tracker (#16589) 2018-09-15 12:45:23 +02:00
Jason Hu
336289d7e7 Add retry limit for chromecast connection (#16471) 2018-09-15 12:45:22 +02:00
Rohan Kapoor
19514ea500 Clean up MjpegCamera by removing unnused hass object in __init__ (#16628) 2018-09-15 11:26:29 +02:00
Sören Oldag
00918af94d Upgrade pwmled to 1.3.0 (#16624) 2018-09-15 10:08:52 +02:00
Ville Skyttä
e054e4da1b Small huawei_lte improvements (#16626)
* Add bunch of RouterData tests

* Avoid raising AttributeError from RouterData.__getitem__

* Use new style string formatting

* Use {key: value} instead of dict(key=value)
2018-09-15 10:42:36 +03:00
Rohan Kapoor
0c945d81c8 Add @rohankapoorcom to CODEOWNERS for the zoneminder platform (#16627) 2018-09-15 09:25:21 +02:00
Rohan Kapoor
1ca09ea36f Extracting zoneminder to a new library (#16527)
* Migrating out the zoneminder platform (and camera.zoneminder) to a new library

* Clean up the global variable ZM usage

* Modify camera.zoneminder to use the new Monitor class implementation

* Refactor camera.zoneminder after latest refactor in zm-py

* Implementing changes to switch.zoneminder to use zm-py native methods

* Complete migrating over sensor.zoneminder to the zm-py library

* Tweaking ZoneMinder components from code review

* Linting fixes for the zoneminder components

* Directly assign value when turning on/off in switch.zoneminder
2018-09-15 08:44:48 +02:00
Nate Clark
8ce2d701c2 fix bug where momentary switch with activation low does not reset (#16603) 2018-09-14 13:31:41 -06:00
christopheBfr
9c1a539f90 Adding support for RTDSContactSensor and RTDSMotionSensor in Tahoma … (RTS Alarms sensors and contacts for Somfy Protexiom alarms) (#16609)
* Adding support for RTDSContactSensor and RTDSContactSensor in Tahoma component

* Removing extra blank lines
2018-09-14 13:31:08 -06:00
Steven Looman
ca7911ec47 Set ports (hass -> hass) when no ports have been specified 2018-09-14 21:30:08 +02:00
Alexei Chetroi
0d0bda9658 Switch components.sensor.zha to await syntax. (#16619) 2018-09-14 13:29:10 -06:00
Pascal Vizeli
7705666061 Rewrite bluetooth le (#16592)
* Rewrite bluetooth le

* Update requirements_all.txt

* Update gen_requirements_all.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py

* Update bluetooth_le_tracker.py
2018-09-14 13:49:20 +02:00
Anders Melchiorsen
e82e75baf3 Improve precision of timer ticks (#16598) 2018-09-14 12:28:09 +02:00
Fabian Affolter
481f6e09fa Upgrade python-twitch-client to 0.6.0 (#16602) 2018-09-14 12:08:33 +02:00
Paulus Schoutsen
72e746d240 MQTT config entry (#16594)
* MQTT config entry

* Solely rely on config entry

* Improve wawrning

* Lint

* Lint2
2018-09-14 11:57:31 +02:00
Paulus Schoutsen
05c0717167 Add websocket list APIs for the registries (#16597)
* Add websocket list APIs for the registries

* Remove identifiers

* Fix tests

* Use ordered dict
2018-09-14 11:57:18 +02:00
Ville Skyttä
67b5b5bc85 Add myself to CODEOWNERS for upcloud (#16599) 2018-09-14 08:42:23 +02:00
Harvtronix
d076251b18 Changing z-wave brightness calculation to respect 0x01 and 0x02 byte values (#16420)
* Changing z-wave brightness calculation to respect 0x01 and 0x02 byte
values

* adding additional line breaks to satisfy houndci

* - Update comment style for linter
- Add additional unit test to increase code coverage

* Update zwave.py
2018-09-13 10:38:07 -04:00
Ville Skyttä
e59ba28fe6 Add Huawei LTE router platform, device tracker, and sensor (#16498)
* Add Huawei LTE router platform, device tracker, and sensor

* Add myself to CODEOWNERS for huawei_lte
2018-09-13 10:01:28 +02:00
Sergiy Maysak
f63dba5521 Multiple tag managers for Wireless Sensor Tags. (#16353)
* Added support for multiple tag managers. Fixed typo for signal strength.

* Corrected broken merge.

* Fixed flake8/pylint error.

* Improved docstring.
2018-09-13 09:48:17 +02:00
William Scanlon
f43d9ba680 Support for the Quirky Nimbus (#16520)
* Support for quriky nimbu

* Fixed lint

* fixed some typos
2018-09-13 09:35:40 +02:00
Daniel Høyer Iversen
aec134c47a xiaomi lib 0.10.0 (#16591) 2018-09-13 09:26:46 +02:00
Daniel Høyer Iversen
901dd9acca Update tibber lib version (#16590) 2018-09-13 09:23:33 +02:00
Alexei Chetroi
7a52bbdf24 Allow only_cache parameter in zha.safe_read() (#16553)
* Allow only_cache parameter in zha.safe_read()

* Use cache_only for binary_sensor.zha initial update.

* Use cache_only for fan.zha initial update.

* Use cache_only for sensor.zha initial update.

* Use cache_only for switch.zha initial update.

* Use cache_only for light.zha initial update.

* Refactor cached only read in zha platform.
2018-09-13 09:22:50 +02:00
Alexei Chetroi
f2203e52ef Add configure_reporting() method to zha component (#16487)
* Add zha.configure_reporting() method.

Binds a cluster and configures reporting for the specified attribute.

* git add homeassistant/components/binary_sensor/zha.py

* Refactor sensor.zha to use new 'configure_reporting() method.

* Zha configure reporting - switch (#1)

* use configure_reporting for zha switch

* lint fixes

* Rename variables/classes to properly reflect the content
2018-09-13 09:11:47 +02:00
Jason Hu
1586d3000c Fix broken bluetooth tracker (#16589) 2018-09-13 07:52:31 +02:00
Daniel Perna
d0aeb90c22 Update pyhomematic to 0.1.48 (#16588) 2018-09-13 01:04:15 +02:00
Daniel Høyer Iversen
cb542a90eb Switchmate (#16395)
* Switchmate

* switchmate

* swithcmate

* switchmate

* switchmate

* switchmate

* Make switchmate a bit more robust

* style

* style

* style

* Use external lib for switchmate

* add_entities

* Update requirements_all.txt

* unnecessary string format
2018-09-12 21:10:04 +02:00
Paulus Schoutsen
3824582e68 Add config entry to iOS (#16580)
* Add config entry to iOS

* Add translation
2018-09-12 20:17:52 +02:00
Nate Clark
2682d26f79 Konnected component feature updates (#16479)
* add  config option to invert state of binary_sensor

* Add API endpoint to get state of a Konnected switch
2018-09-12 13:54:38 +02:00
Jason Hu
308b7fb385 Add retry limit for chromecast connection (#16471) 2018-09-12 13:42:54 +02:00
Marcel Hoppe
4efe86327d Hangouts help "page" and little bugfix (#16464)
* add 'default_conversations' parameter

* remove the empty message segment at the end of every message

* add 'HangoutsHelp' intent

* add hangouts/intents.py
2018-09-12 13:27:21 +02:00
Jason Hu
ff78a5b04b Track refresh token last usage information (#16408)
* Extend refresh_token to support last_used_at and last_used_by

* Address code review comment

* Remove unused code

* Add it to websocket response

* Fix typing
2018-09-12 13:24:16 +02:00
Paulus Schoutsen
453cbb7c60 Update frontend to 20180912.0 2018-09-12 13:23:50 +02:00
Zoé Bőle
77026a2242 Increasing python-websockets' version number (#16578)
* increasing python-websockets' version number so now it works with python 3.7

* required version for websockets increased to work with Python 3.7

* script/gen_requirements_all.py is done
2018-09-12 12:44:14 +02:00
Alexei Chetroi
501f2b0a93 Update fan.zha platform. (#16551)
* Update fan.zha platform.

switch from asyncio to async def()
catch DeliveryError exceptions
keep previous state, if reading 'fan_mode' attribute fails

* fan.zha: Use None for unknown state.

if we fail to read 'fan_mode' attribute, use None for state
2018-09-12 12:43:06 +02:00
Alexei Chetroi
117ea9e553 Refactor zha/async_device_initialized(). (#16485)
Leverage endpoint.model and endpoint.manufacturer properties
2018-09-12 11:39:23 +02:00
Ville Skyttä
beed82ab12 Upgrade pytest to 3.8.0 and pytest-timeout to 1.3.2 (#16489) 2018-09-12 11:33:26 +02:00
Daniel Perna
601f2df5a7 Notifications for Android TV: Add fontsize and sending images (#16565)
* Add fontsize and image functionality

* woof
2018-09-12 11:22:21 +02:00
Jason Hu
34d369ba26 Return if refresh token is current used one in WS API (#16575) 2018-09-12 09:49:44 +02:00
Daniel Høyer Iversen
e2465da7c2 yr: use async syntax (#16563) 2018-09-12 04:52:01 +02:00
William Scanlon
6bd120ff1d Bump pyeconet (#16571)
* Updated pyeconet to the newest version to deal with econet API change
2018-09-11 21:45:51 -04:00
Aaron Bach
188f5de5ae Fixes an OpenUV bug with the scan interval (#16570) 2018-09-11 17:13:16 -06:00
Paulus Schoutsen
06af76404f Fix invalid state (#16558)
* Fix invalid state

* Make slightly more efficient in unsubscribing

* Use uuid4"
2018-09-11 21:40:35 +02:00
Paulus Schoutsen
629c4a0bf5 Update frontend to 20180911.0 2018-09-11 21:37:38 +02:00
Paulus Schoutsen
3f06b4eb9b Update translations 2018-09-11 21:36:54 +02:00
Paulus Schoutsen
0db13a99aa Add websocket commands for refresh tokens (#16559)
* Add websocket commands for refresh tokens

* Comment
2018-09-11 09:08:03 -07:00
Paulus Schoutsen
4e3faf6108 Fix typo (#16556) 2018-09-11 12:55:05 +02:00
Jason Hu
9583947012 Long-lived access token (#16453)
* Allow create refresh_token with specific access_token_expiration

* Add token_type, client_name and client_icon

* Add unit test

* Add websocket API to create long-lived access token

* Allow URL use as client_id for long-lived access token

* Remove mutate_refresh_token method

* Use client name as id for long_lived_access_token type refresh token

* Minor change

* Do not allow duplicate client name

* Update docstring

* Remove unnecessary `list`
2018-09-11 12:05:15 +02:00
Jerad Meisner
50fb59477a Store notifications in component. Add ws endpoint for fetching. (#16503)
* Store notifications in component. Add ws endpoint for fetching.

* Comments
2018-09-11 11:39:30 +02:00
Diogo Gomes
20f6cb7cc7 Replace api_password in Camera.Push (#16339)
* Use access_token and user provided token instead of api_password

* address comments by @awarecan

* new tests

* add extra checks and test

* lint

* add comment
2018-09-11 11:30:20 +02:00
Zellux Wang
6b08e6e769 Fix arlo intilization when no base station available (#16529)
* Fix arlo intilization when no base station

* Fix pylint for empty camera check

* Fix typo

* Minor change to trigger CI again
2018-09-11 11:25:38 +02:00
Ville Skyttä
ee696643cd Isort preparations (#16555)
* Don't treat typing as an "in-between" module for import order

That was a < 3.5 era thing.

* Tighten scope of some pylint unused-import disables

To avoid isort moving a top level one around, undesirably broadening its
scope.
2018-09-11 11:21:48 +02:00
cgtobi
a059cc860a Update PyRMVtransport version (#16547)
* Update PyRMVtransport version

* Update requirements.
2018-09-11 05:55:02 +02:00
Paulus Schoutsen
cfe5db4350 Fail fetch auth providers if onboarding required (#16454) 2018-09-10 23:51:40 +02:00
Tom Harris
dcd7b9a529 Fix insteon Hub v1 support (#16472)
* Fix support for Hub version 1 (i.e. pre-2014 Hub model 2242)

* Bump insteonplm to 0.14.1

* Code review changes

* Clean up and better document set_default_port

* Simplify set_default_port based on code review

* Remove Callable type import

* Simplify port setup
2018-09-10 16:54:17 +02:00
mrosseel
f858938ada Make the Qnap sensor more resilient if server is not reachable (#16445)
* add CONF_ALLOW_UNREACHABLE option, retry connection if allowed

* fix linting errors

* Removing the config option, just using PlatformNotReady
2018-09-10 16:19:17 +02:00
vikramgorla
e96635b5c1 bugfix - incorrect camera type and missing sensors when multiple netatmo cameras (#16490)
fixed get_camera_type as it was originally not consuming any input, was looping with all cameras and the first camera type was retutned, modified to call cameraType using provided camera name.
2018-09-10 16:13:05 +02:00
Fabian Affolter
d2d715faa8 Upgrade wakeonlan to 1.1.6 (#16512) 2018-09-10 16:07:31 +02:00
Franck Nijhof
7a5e828f6b Updates documentation repo URL in PR template (#16537) 2018-09-10 14:28:21 +02:00
Paulus Schoutsen
99f7b7f42d Version bump to 0.79.0dev0 2018-09-10 13:46:07 +02:00
Steven Looman
6433f2e2e3 Working on igd 2018-09-08 00:24:47 +02:00
Steven Looman
f4a54e2483 Changes after review 2018-09-03 21:16:45 +02:00
Steven Looman
85c40d29ee Linting 2018-09-02 17:03:31 +02:00
Steven Looman
a4a175440b Move ensure_domain_data 2018-09-02 16:40:39 +02:00
Steven Looman
8bec4a55d1 Working on igd 2018-09-01 21:20:15 +02:00
Steven Looman
50f63ed4c5 Fix not being able to re-add IGD when removed 2018-09-01 18:13:45 +02:00
Steven Looman
c9e34e236d Prevent error message when component is actually ok 2018-09-01 10:14:21 +02:00
Steven Looman
38318ed15f Ensure config_flow is imported 2018-09-01 10:09:22 +02:00
Steven Looman
553d3c0179 Merge remote-tracking branch 'upstream/dev' into igd 2018-09-01 10:01:12 +02:00
Steven Looman
20879726b0 Working on IGD 2018-08-30 17:41:11 +02:00
Steven Looman
3db766e2ec Merge remote-tracking branch 'upstream/dev' into igd 2018-08-29 21:19:27 +02:00
Steven Looman
1eac6408f5 Working on IGD 2018-08-29 21:19:04 +02:00
Steven Looman
e73f31d829 Merge remote-tracking branch 'upstream/dev' into igd 2018-08-24 15:25:07 +02:00
Steven Looman
839b58c600 Working on IGD 2018-08-17 21:28:29 +02:00
Steven Looman
71d00062e5 Upgrade to async_upnp_client 0.12.4 2018-08-17 21:25:08 +02:00
Steven Looman
80f98b9ea2 Fix message "Updating dlna_dmr media_player took longer than ..." 2018-08-16 22:14:13 +02:00
988 changed files with 24704 additions and 11734 deletions

View File

@@ -28,6 +28,9 @@ omit =
homeassistant/components/apple_tv.py
homeassistant/components/*/apple_tv.py
homeassistant/components/aqualogic.py
homeassistant/components/*/aqualogic.py
homeassistant/components/arduino.py
homeassistant/components/*/arduino.py
@@ -42,6 +45,7 @@ omit =
homeassistant/components/asterisk_mbox.py
homeassistant/components/*/asterisk_mbox.py
homeassistant/components/*/asterisk_cdr.py
homeassistant/components/august.py
homeassistant/components/*/august.py
@@ -52,7 +56,7 @@ omit =
homeassistant/components/bbb_gpio.py
homeassistant/components/*/bbb_gpio.py
homeassistant/components/blink.py
homeassistant/components/blink/*
homeassistant/components/*/blink.py
homeassistant/components/bloomsky.py
@@ -92,6 +96,9 @@ omit =
homeassistant/components/ecobee.py
homeassistant/components/*/ecobee.py
homeassistant/components/edp_redy.py
homeassistant/components/*/edp_redy.py
homeassistant/components/egardia.py
homeassistant/components/*/egardia.py
@@ -101,8 +108,11 @@ omit =
homeassistant/components/envisalink.py
homeassistant/components/*/envisalink.py
homeassistant/components/evohome.py
homeassistant/components/*/evohome.py
homeassistant/components/fritzbox.py
homeassistant/components/switch/fritzbox.py
homeassistant/components/*/fritzbox.py
homeassistant/components/ecovacs.py
homeassistant/components/*/ecovacs.py
@@ -123,6 +133,7 @@ omit =
homeassistant/components/hangouts/const.py
homeassistant/components/hangouts/hangouts_bot.py
homeassistant/components/hangouts/hangups_utils.py
homeassistant/components/hangouts/intents.py
homeassistant/components/*/hangouts.py
homeassistant/components/hdmi_cec.py
@@ -140,6 +151,9 @@ omit =
homeassistant/components/homematicip_cloud.py
homeassistant/components/*/homematicip_cloud.py
homeassistant/components/huawei_lte.py
homeassistant/components/*/huawei_lte.py
homeassistant/components/hydrawise.py
homeassistant/components/*/hydrawise.py
@@ -183,6 +197,9 @@ omit =
homeassistant/components/linode.py
homeassistant/components/*/linode.py
homeassistant/components/logi_circle.py
homeassistant/components/*/logi_circle.py
homeassistant/components/lutron.py
homeassistant/components/*/lutron.py
@@ -299,6 +316,9 @@ omit =
homeassistant/components/*/thinkingcleaner.py
homeassistant/components/tibber/*
homeassistant/components/*/tibber.py
homeassistant/components/toon.py
homeassistant/components/*/toon.py
@@ -499,6 +519,7 @@ omit =
homeassistant/components/light/lw12wifi.py
homeassistant/components/light/mystrom.py
homeassistant/components/light/nanoleaf_aurora.py
homeassistant/components/light/opple.py
homeassistant/components/light/osramlightify.py
homeassistant/components/light/piglow.py
homeassistant/components/light/rpi_gpio_pwm.py
@@ -609,7 +630,6 @@ omit =
homeassistant/components/notify/telstra.py
homeassistant/components/notify/twitter.py
homeassistant/components/notify/xmpp.py
homeassistant/components/notify/yessssms.py
homeassistant/components/nuimo_controller.py
homeassistant/components/prometheus.py
homeassistant/components/rainbird.py
@@ -668,6 +688,7 @@ omit =
homeassistant/components/sensor/fritzbox_netmonitor.py
homeassistant/components/sensor/gearbest.py
homeassistant/components/sensor/geizhals.py
homeassistant/components/sensor/gitlab_ci.py
homeassistant/components/sensor/gitter.py
homeassistant/components/sensor/glances.py
homeassistant/components/sensor/google_travel_time.py
@@ -676,6 +697,7 @@ omit =
homeassistant/components/sensor/haveibeenpwned.py
homeassistant/components/sensor/hp_ilo.py
homeassistant/components/sensor/htu21d.py
homeassistant/components/sensor/upnp.py
homeassistant/components/sensor/imap_email_content.py
homeassistant/components/sensor/imap.py
homeassistant/components/sensor/influxdb.py
@@ -684,6 +706,7 @@ omit =
homeassistant/components/sensor/kwb.py
homeassistant/components/sensor/lacrosse.py
homeassistant/components/sensor/lastfm.py
homeassistant/components/sensor/linky.py
homeassistant/components/sensor/linux_battery.py
homeassistant/components/sensor/loopenergy.py
homeassistant/components/sensor/luftdaten.py
@@ -697,6 +720,7 @@ omit =
homeassistant/components/sensor/mqtt_room.py
homeassistant/components/sensor/mvglive.py
homeassistant/components/sensor/nederlandse_spoorwegen.py
homeassistant/components/sensor/netatmo_public.py
homeassistant/components/sensor/netdata.py
homeassistant/components/sensor/netdata_public.py
homeassistant/components/sensor/neurio_energy.py
@@ -740,6 +764,7 @@ omit =
homeassistant/components/sensor/sonarr.py
homeassistant/components/sensor/speedtest.py
homeassistant/components/sensor/spotcrime.py
homeassistant/components/sensor/starlingbank.py
homeassistant/components/sensor/steam_online.py
homeassistant/components/sensor/supervisord.py
homeassistant/components/sensor/swiss_hydrological_data.py
@@ -751,7 +776,6 @@ omit =
homeassistant/components/sensor/tank_utility.py
homeassistant/components/sensor/ted5000.py
homeassistant/components/sensor/temper.py
homeassistant/components/sensor/tibber.py
homeassistant/components/sensor/time_date.py
homeassistant/components/sensor/torque.py
homeassistant/components/sensor/trafikverket_weatherstation.py
@@ -759,7 +783,6 @@ omit =
homeassistant/components/sensor/travisci.py
homeassistant/components/sensor/twitch.py
homeassistant/components/sensor/uber.py
homeassistant/components/sensor/upnp.py
homeassistant/components/sensor/ups.py
homeassistant/components/sensor/uscis.py
homeassistant/components/sensor/vasttrafik.py
@@ -813,6 +836,7 @@ omit =
homeassistant/components/weather/bom.py
homeassistant/components/weather/buienradar.py
homeassistant/components/weather/darksky.py
homeassistant/components/weather/met.py
homeassistant/components/weather/metoffice.py
homeassistant/components/weather/openweathermap.py
homeassistant/components/weather/zamg.py

View File

@@ -3,7 +3,7 @@
**Related issue (if applicable):** fixes #<home-assistant issue number goes here>
**Pull request in [home-assistant.github.io](https://github.com/home-assistant/home-assistant.github.io) with documentation (if applicable):** home-assistant/home-assistant.github.io#<home-assistant.github.io PR number goes here>
**Pull request in [home-assistant.io](https://github.com/home-assistant/home-assistant.io) with documentation (if applicable):** home-assistant/home-assistant.io#<home-assistant.io PR number goes here>
## Example entry for `configuration.yaml` (if applicable):
```yaml
@@ -15,7 +15,7 @@
- [ ] Local tests pass with `tox`. **Your PR cannot be merged unless tests pass**
If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [home-assistant.github.io](https://github.com/home-assistant/home-assistant.github.io)
- [ ] Documentation added/updated in [home-assistant.io](https://github.com/home-assistant/home-assistant.io)
If the code communicates with devices, web services, or third-party tools:
- [ ] New dependencies have been added to the `REQUIREMENTS` variable ([example][ex-requir]).

View File

@@ -41,6 +41,7 @@ homeassistant/components/hassio.py @home-assistant/hassio
# Individual components
homeassistant/components/alarm_control_panel/egardia.py @jeroenterheerdt
homeassistant/components/alarm_control_panel/manual_mqtt.py @colinodell
homeassistant/components/alarm_control_panel/simplisafe.py @bachya
homeassistant/components/binary_sensor/hikvision.py @mezz64
homeassistant/components/bmw_connected_drive.py @ChristianKuehnel
homeassistant/components/camera/yi.py @bachya
@@ -50,6 +51,7 @@ homeassistant/components/climate/sensibo.py @andrey-git
homeassistant/components/cover/group.py @cdce8p
homeassistant/components/cover/template.py @PhracturedBlue
homeassistant/components/device_tracker/automatic.py @armills
homeassistant/components/device_tracker/huawei_router.py @abmantis
homeassistant/components/device_tracker/tile.py @bachya
homeassistant/components/history_graph.py @andrey-git
homeassistant/components/light/lifx.py @amelchio
@@ -72,6 +74,7 @@ homeassistant/components/sensor/airvisual.py @bachya
homeassistant/components/sensor/filter.py @dgomes
homeassistant/components/sensor/gearbest.py @HerrHofrat
homeassistant/components/sensor/irish_rail_transport.py @ttroy50
homeassistant/components/sensor/jewish_calendar.py @tsvi
homeassistant/components/sensor/miflora.py @danielhiversen @ChristianKuehnel
homeassistant/components/sensor/nsw_fuel_station.py @nickw444
homeassistant/components/sensor/pollen.py @bachya
@@ -79,31 +82,35 @@ homeassistant/components/sensor/qnap.py @colinodell
homeassistant/components/sensor/sma.py @kellerza
homeassistant/components/sensor/sql.py @dgomes
homeassistant/components/sensor/sytadin.py @gautric
homeassistant/components/sensor/tibber.py @danielhiversen
homeassistant/components/sensor/upnp.py @dgomes
homeassistant/components/sensor/waqi.py @andrey-git
homeassistant/components/switch/tplink.py @rytilahti
homeassistant/components/vacuum/roomba.py @pschmitt
homeassistant/components/xiaomi_aqara.py @danielhiversen @syssi
homeassistant/components/*/axis.py @kane610
homeassistant/components/blink/* @fronzbot
homeassistant/components/*/blink.py @fronzbot
homeassistant/components/*/bmw_connected_drive.py @ChristianKuehnel
homeassistant/components/*/broadlink.py @danielhiversen
homeassistant/components/*/deconz.py @kane610
homeassistant/components/ecovacs.py @OverloadUT
homeassistant/components/*/ecovacs.py @OverloadUT
homeassistant/components/edp_redy.py @abmantis
homeassistant/components/*/edp_redy.py @abmantis
homeassistant/components/eight_sleep.py @mezz64
homeassistant/components/*/eight_sleep.py @mezz64
homeassistant/components/hive.py @Rendili @KJonline
homeassistant/components/*/hive.py @Rendili @KJonline
homeassistant/components/homekit/* @cdce8p
homeassistant/components/huawei_lte.py @scop
homeassistant/components/*/huawei_lte.py @scop
homeassistant/components/knx.py @Julius2342
homeassistant/components/*/knx.py @Julius2342
homeassistant/components/konnected.py @heythisisnate
homeassistant/components/*/konnected.py @heythisisnate
homeassistant/components/matrix.py @tinloaf
homeassistant/components/*/matrix.py @tinloaf
homeassistant/components/openuv.py @bachya
homeassistant/components/openuv/* @bachya
homeassistant/components/*/openuv.py @bachya
homeassistant/components/qwikswitch.py @kellerza
homeassistant/components/*/qwikswitch.py @kellerza
@@ -116,10 +123,16 @@ homeassistant/components/tesla.py @zabuldon
homeassistant/components/*/tesla.py @zabuldon
homeassistant/components/tellduslive.py @molobrakos @fredrike
homeassistant/components/*/tellduslive.py @molobrakos @fredrike
homeassistant/components/tibber/* @danielhiversen
homeassistant/components/*/tibber.py @danielhiversen
homeassistant/components/*/tradfri.py @ggravlingen
homeassistant/components/upcloud.py @scop
homeassistant/components/*/upcloud.py @scop
homeassistant/components/velux.py @Julius2342
homeassistant/components/*/velux.py @Julius2342
homeassistant/components/*/xiaomi_aqara.py @danielhiversen @syssi
homeassistant/components/*/xiaomi_miio.py @rytilahti @syssi
homeassistant/components/zoneminder.py @rohankapoorcom
homeassistant/components/*/zoneminder.py @rohankapoorcom
homeassistant/scripts/check_config.py @kellerza

View File

@@ -10,5 +10,5 @@ The process is straight-forward.
- Ensure tests work.
- Create a Pull Request against the [**dev**](https://github.com/home-assistant/home-assistant/tree/dev) branch of Home Assistant.
Still interested? Then you should take a peek at the [developer documentation](https://home-assistant.io/developers/) to get more details.
Still interested? Then you should take a peek at the [developer documentation](https://developers.home-assistant.io/) to get more details.

View File

@@ -21,8 +21,8 @@ Featured integrations
|screenshot-components|
The system is built using a modular approach so support for other devices or actions can be implemented easily. See also the `section on architecture <https://home-assistant.io/developers/architecture/>`__ and the `section on creating your own
components <https://home-assistant.io/developers/creating_components/>`__.
The system is built using a modular approach so support for other devices or actions can be implemented easily. See also the `section on architecture <https://developers.home-assistant.io/docs/en/architecture_index.html>`__ and the `section on creating your own
components <https://developers.home-assistant.io/docs/en/creating_component_index.html>`__.
If you run into issues while using Home Assistant or during development
of a component, check the `Home Assistant help section <https://home-assistant.io/help/>`__ of our website for further help and information.

View File

@@ -19,4 +19,4 @@ Indices and tables
* :ref:`modindex`
* :ref:`search`
.. _Home Assistant developers: https://home-assistant.io/developers/
.. _Home Assistant developers: https://developers.home-assistant.io/

View File

@@ -7,7 +7,6 @@ import platform
import subprocess
import sys
import threading
from typing import List, Dict, Any # noqa pylint: disable=unused-import
@@ -20,15 +19,34 @@ from homeassistant.const import (
)
def attempt_use_uvloop() -> None:
def set_loop() -> None:
"""Attempt to use uvloop."""
import asyncio
from asyncio.events import BaseDefaultEventLoopPolicy
try:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError:
pass
policy = None
if sys.platform == 'win32':
if hasattr(asyncio, 'WindowsProactorEventLoopPolicy'):
# pylint: disable=no-member
policy = asyncio.WindowsProactorEventLoopPolicy()
else:
class ProactorPolicy(BaseDefaultEventLoopPolicy):
"""Event loop policy to create proactor loops."""
_loop_factory = asyncio.ProactorEventLoop
policy = ProactorPolicy()
else:
try:
import uvloop
except ImportError:
pass
else:
policy = uvloop.EventLoopPolicy()
if policy is not None:
asyncio.set_event_loop_policy(policy)
def validate_python() -> None:
@@ -240,51 +258,39 @@ def cmdline() -> List[str]:
return [arg for arg in sys.argv if arg != '--daemon']
def setup_and_run_hass(config_dir: str,
args: argparse.Namespace) -> int:
async def setup_and_run_hass(config_dir: str,
args: argparse.Namespace) -> int:
"""Set up HASS and run."""
from homeassistant import bootstrap
from homeassistant import bootstrap, core
# Run a simple daemon runner process on Windows to handle restarts
if os.name == 'nt' and '--runner' not in sys.argv:
nt_args = cmdline() + ['--runner']
while True:
try:
subprocess.check_call(nt_args)
sys.exit(0)
except subprocess.CalledProcessError as exc:
if exc.returncode != RESTART_EXIT_CODE:
sys.exit(exc.returncode)
hass = core.HomeAssistant()
if args.demo_mode:
config = {
'frontend': {},
'demo': {}
} # type: Dict[str, Any]
hass = bootstrap.from_config_dict(
config, config_dir=config_dir, verbose=args.verbose,
bootstrap.async_from_config_dict(
config, hass, config_dir=config_dir, verbose=args.verbose,
skip_pip=args.skip_pip, log_rotate_days=args.log_rotate_days,
log_file=args.log_file, log_no_color=args.log_no_color)
else:
config_file = ensure_config_file(config_dir)
print('Config directory:', config_dir)
hass = bootstrap.from_config_file(
config_file, verbose=args.verbose, skip_pip=args.skip_pip,
await bootstrap.async_from_config_file(
config_file, hass, verbose=args.verbose, skip_pip=args.skip_pip,
log_rotate_days=args.log_rotate_days, log_file=args.log_file,
log_no_color=args.log_no_color)
if hass is None:
return -1
if args.open_ui:
# Imported here to avoid importing asyncio before monkey patch
from homeassistant.util.async_ import run_callback_threadsafe
def open_browser(_: Any) -> None:
"""Open the web interface in a browser."""
if hass.config.api is not None: # type: ignore
if hass.config.api is not None:
import webbrowser
webbrowser.open(hass.config.api.base_url) # type: ignore
webbrowser.open(hass.config.api.base_url)
run_callback_threadsafe(
hass.loop,
@@ -292,7 +298,7 @@ def setup_and_run_hass(config_dir: str,
EVENT_HOMEASSISTANT_START, open_browser
)
return hass.start()
return await hass.async_run()
def try_to_restart() -> None:
@@ -347,7 +353,20 @@ def main() -> int:
monkey_patch.disable_c_asyncio()
monkey_patch.patch_weakref_tasks()
attempt_use_uvloop()
set_loop()
# Run a simple daemon runner process on Windows to handle restarts
if os.name == 'nt' and '--runner' not in sys.argv:
nt_args = cmdline() + ['--runner']
while True:
try:
subprocess.check_call(nt_args)
sys.exit(0)
except KeyboardInterrupt:
sys.exit(0)
except subprocess.CalledProcessError as exc:
if exc.returncode != RESTART_EXIT_CODE:
sys.exit(exc.returncode)
args = get_arguments()
@@ -366,11 +385,12 @@ def main() -> int:
if args.pid_file:
write_pid(args.pid_file)
exit_code = setup_and_run_hass(config_dir, args)
from homeassistant.util.async_ import asyncio_run
exit_code = asyncio_run(setup_and_run_hass(config_dir, args))
if exit_code == RESTART_EXIT_CODE and not args.runner:
try_to_restart()
return exit_code
return exit_code # type: ignore # mypy cannot yet infer it
if __name__ == "__main__":

View File

@@ -1,9 +1,9 @@
"""Storage for auth models."""
from collections import OrderedDict
from datetime import timedelta
import hmac
from logging import getLogger
from typing import Any, Dict, List, Optional # noqa: F401
import hmac
from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION
from homeassistant.core import HomeAssistant, callback
@@ -28,7 +28,8 @@ class AuthStore:
"""Initialize the auth store."""
self.hass = hass
self._users = None # type: Optional[Dict[str, models.User]]
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY,
private=True)
async def async_get_users(self) -> List[models.User]:
"""Retrieve all users."""
@@ -213,14 +214,24 @@ class AuthStore:
if self._users is not None:
return
users = OrderedDict() # type: Dict[str, models.User]
if data is None:
self._users = users
self._set_defaults()
return
users = OrderedDict() # type: Dict[str, models.User]
# When creating objects we mention each attribute explicetely. This
# prevents crashing if user rolls back HA version after a new property
# was added.
for user_dict in data['users']:
users[user_dict['id']] = models.User(**user_dict)
users[user_dict['id']] = models.User(
name=user_dict['name'],
id=user_dict['id'],
is_owner=user_dict['is_owner'],
is_active=user_dict['is_active'],
system_generated=user_dict['system_generated'],
)
for cred_dict in data['credentials']:
users[cred_dict['user_id']].credentials.append(models.Credentials(
@@ -340,3 +351,7 @@ class AuthStore:
'credentials': credentials,
'refresh_tokens': refresh_tokens,
}
def _set_defaults(self) -> None:
"""Set default values for auth store."""
self._users = OrderedDict() # type: Dict[str, models.User]

View File

@@ -2,3 +2,4 @@
from datetime import timedelta
ACCESS_TOKEN_EXPIRATION = timedelta(minutes=30)
MFA_SESSION_EXPIRATION = timedelta(minutes=5)

View File

@@ -1,5 +1,4 @@
"""Plugable auth modules for Home Assistant."""
from datetime import timedelta
import importlib
import logging
import types
@@ -23,8 +22,6 @@ MULTI_FACTOR_AUTH_MODULE_SCHEMA = vol.Schema({
vol.Optional(CONF_ID): str,
}, extra=vol.ALLOW_EXTRA)
SESSION_EXPIRATION = timedelta(minutes=5)
DATA_REQS = 'mfa_auth_module_reqs_processed'
_LOGGER = logging.getLogger(__name__)
@@ -34,6 +31,7 @@ class MultiFactorAuthModule:
"""Multi-factor Auth Module of validation function."""
DEFAULT_TITLE = 'Unnamed auth module'
MAX_RETRY_TIME = 3
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
"""Initialize an auth module."""
@@ -84,7 +82,7 @@ class MultiFactorAuthModule:
"""Return whether user is setup."""
raise NotImplementedError
async def async_validation(
async def async_validate(
self, user_id: str, user_input: Dict[str, Any]) -> bool:
"""Return True if validation passed."""
raise NotImplementedError

View File

@@ -77,7 +77,7 @@ class InsecureExampleModule(MultiFactorAuthModule):
return True
return False
async def async_validation(
async def async_validate(
self, user_id: str, user_input: Dict[str, Any]) -> bool:
"""Return True if validation passed."""
for data in self._data:

View File

@@ -0,0 +1,325 @@
"""HMAC-based One-time Password auth module.
Sending HOTP through notify service
"""
import logging
from collections import OrderedDict
from typing import Any, Dict, Optional, Tuple, List # noqa: F401
import attr
import voluptuous as vol
from homeassistant.const import CONF_EXCLUDE, CONF_INCLUDE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from . import MultiFactorAuthModule, MULTI_FACTOR_AUTH_MODULES, \
MULTI_FACTOR_AUTH_MODULE_SCHEMA, SetupFlow
REQUIREMENTS = ['pyotp==2.2.6']
CONF_MESSAGE = 'message'
CONFIG_SCHEMA = MULTI_FACTOR_AUTH_MODULE_SCHEMA.extend({
vol.Optional(CONF_INCLUDE): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_EXCLUDE): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_MESSAGE,
default='{} is your Home Assistant login code'): str
}, extra=vol.PREVENT_EXTRA)
STORAGE_VERSION = 1
STORAGE_KEY = 'auth_module.notify'
STORAGE_USERS = 'users'
STORAGE_USER_ID = 'user_id'
INPUT_FIELD_CODE = 'code'
_LOGGER = logging.getLogger(__name__)
def _generate_secret() -> str:
"""Generate a secret."""
import pyotp
return str(pyotp.random_base32())
def _generate_random() -> int:
"""Generate a 8 digit number."""
import pyotp
return int(pyotp.random_base32(length=8, chars=list('1234567890')))
def _generate_otp(secret: str, count: int) -> str:
"""Generate one time password."""
import pyotp
return str(pyotp.HOTP(secret).at(count))
def _verify_otp(secret: str, otp: str, count: int) -> bool:
"""Verify one time password."""
import pyotp
return bool(pyotp.HOTP(secret).verify(otp, count))
@attr.s(slots=True)
class NotifySetting:
"""Store notify setting for one user."""
secret = attr.ib(type=str, factory=_generate_secret) # not persistent
counter = attr.ib(type=int, factory=_generate_random) # not persistent
notify_service = attr.ib(type=Optional[str], default=None)
target = attr.ib(type=Optional[str], default=None)
_UsersDict = Dict[str, NotifySetting]
@MULTI_FACTOR_AUTH_MODULES.register('notify')
class NotifyAuthModule(MultiFactorAuthModule):
"""Auth module send hmac-based one time password by notify service."""
DEFAULT_TITLE = 'Notify One-Time Password'
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
"""Initialize the user data store."""
super().__init__(hass, config)
self._user_settings = None # type: Optional[_UsersDict]
self._user_store = hass.helpers.storage.Store(
STORAGE_VERSION, STORAGE_KEY, private=True)
self._include = config.get(CONF_INCLUDE, [])
self._exclude = config.get(CONF_EXCLUDE, [])
self._message_template = config[CONF_MESSAGE]
@property
def input_schema(self) -> vol.Schema:
"""Validate login flow input data."""
return vol.Schema({INPUT_FIELD_CODE: str})
async def _async_load(self) -> None:
"""Load stored data."""
data = await self._user_store.async_load()
if data is None:
data = {STORAGE_USERS: {}}
self._user_settings = {
user_id: NotifySetting(**setting)
for user_id, setting in data.get(STORAGE_USERS, {}).items()
}
async def _async_save(self) -> None:
"""Save data."""
if self._user_settings is None:
return
await self._user_store.async_save({STORAGE_USERS: {
user_id: attr.asdict(
notify_setting, filter=attr.filters.exclude(
attr.fields(NotifySetting).secret,
attr.fields(NotifySetting).counter,
))
for user_id, notify_setting
in self._user_settings.items()
}})
@callback
def aync_get_available_notify_services(self) -> List[str]:
"""Return list of notify services."""
unordered_services = set()
for service in self.hass.services.async_services().get('notify', {}):
if service not in self._exclude:
unordered_services.add(service)
if self._include:
unordered_services &= set(self._include)
return sorted(unordered_services)
async def async_setup_flow(self, user_id: str) -> SetupFlow:
"""Return a data entry flow handler for setup module.
Mfa module should extend SetupFlow
"""
return NotifySetupFlow(
self, self.input_schema, user_id,
self.aync_get_available_notify_services())
async def async_setup_user(self, user_id: str, setup_data: Any) -> Any:
"""Set up auth module for user."""
if self._user_settings is None:
await self._async_load()
assert self._user_settings is not None
self._user_settings[user_id] = NotifySetting(
notify_service=setup_data.get('notify_service'),
target=setup_data.get('target'),
)
await self._async_save()
async def async_depose_user(self, user_id: str) -> None:
"""Depose auth module for user."""
if self._user_settings is None:
await self._async_load()
assert self._user_settings is not None
if self._user_settings.pop(user_id, None):
await self._async_save()
async def async_is_user_setup(self, user_id: str) -> bool:
"""Return whether user is setup."""
if self._user_settings is None:
await self._async_load()
assert self._user_settings is not None
return user_id in self._user_settings
async def async_validate(
self, user_id: str, user_input: Dict[str, Any]) -> bool:
"""Return True if validation passed."""
if self._user_settings is None:
await self._async_load()
assert self._user_settings is not None
notify_setting = self._user_settings.get(user_id, None)
if notify_setting is None:
return False
# user_input has been validate in caller
return await self.hass.async_add_executor_job(
_verify_otp, notify_setting.secret,
user_input.get(INPUT_FIELD_CODE, ''),
notify_setting.counter)
async def async_initialize_login_mfa_step(self, user_id: str) -> None:
"""Generate code and notify user."""
if self._user_settings is None:
await self._async_load()
assert self._user_settings is not None
notify_setting = self._user_settings.get(user_id, None)
if notify_setting is None:
raise ValueError('Cannot find user_id')
def generate_secret_and_one_time_password() -> str:
"""Generate and send one time password."""
assert notify_setting
# secret and counter are not persistent
notify_setting.secret = _generate_secret()
notify_setting.counter = _generate_random()
return _generate_otp(
notify_setting.secret, notify_setting.counter)
code = await self.hass.async_add_executor_job(
generate_secret_and_one_time_password)
await self.async_notify_user(user_id, code)
async def async_notify_user(self, user_id: str, code: str) -> None:
"""Send code by user's notify service."""
if self._user_settings is None:
await self._async_load()
assert self._user_settings is not None
notify_setting = self._user_settings.get(user_id, None)
if notify_setting is None:
_LOGGER.error('Cannot find user %s', user_id)
return
await self.async_notify( # type: ignore
code, notify_setting.notify_service, notify_setting.target)
async def async_notify(self, code: str, notify_service: str,
target: Optional[str] = None) -> None:
"""Send code by notify service."""
data = {'message': self._message_template.format(code)}
if target:
data['target'] = [target]
await self.hass.services.async_call('notify', notify_service, data)
class NotifySetupFlow(SetupFlow):
"""Handler for the setup flow."""
def __init__(self, auth_module: NotifyAuthModule,
setup_schema: vol.Schema,
user_id: str,
available_notify_services: List[str]) -> None:
"""Initialize the setup flow."""
super().__init__(auth_module, setup_schema, user_id)
# to fix typing complaint
self._auth_module = auth_module # type: NotifyAuthModule
self._available_notify_services = available_notify_services
self._secret = None # type: Optional[str]
self._count = None # type: Optional[int]
self._notify_service = None # type: Optional[str]
self._target = None # type: Optional[str]
async def async_step_init(
self, user_input: Optional[Dict[str, str]] = None) \
-> Dict[str, Any]:
"""Let user select available notify services."""
errors = {} # type: Dict[str, str]
hass = self._auth_module.hass
if user_input:
self._notify_service = user_input['notify_service']
self._target = user_input.get('target')
self._secret = await hass.async_add_executor_job(_generate_secret)
self._count = await hass.async_add_executor_job(_generate_random)
return await self.async_step_setup()
if not self._available_notify_services:
return self.async_abort(reason='no_available_service')
schema = OrderedDict() # type: Dict[str, Any]
schema['notify_service'] = vol.In(self._available_notify_services)
schema['target'] = vol.Optional(str)
return self.async_show_form(
step_id='init',
data_schema=vol.Schema(schema),
errors=errors
)
async def async_step_setup(
self, user_input: Optional[Dict[str, str]] = None) \
-> Dict[str, Any]:
"""Verify user can recevie one-time password."""
errors = {} # type: Dict[str, str]
hass = self._auth_module.hass
if user_input:
verified = await hass.async_add_executor_job(
_verify_otp, self._secret, user_input['code'], self._count)
if verified:
await self._auth_module.async_setup_user(
self._user_id, {
'notify_service': self._notify_service,
'target': self._target,
})
return self.async_create_entry(
title=self._auth_module.name,
data={}
)
errors['base'] = 'invalid_code'
# generate code every time, no retry logic
assert self._secret and self._count
code = await hass.async_add_executor_job(
_generate_otp, self._secret, self._count)
assert self._notify_service
await self._auth_module.async_notify(
code, self._notify_service, self._target)
return self.async_show_form(
step_id='setup',
data_schema=self._setup_schema,
description_placeholders={'notify_service': self._notify_service},
errors=errors,
)

View File

@@ -60,13 +60,14 @@ class TotpAuthModule(MultiFactorAuthModule):
"""Auth module validate time-based one time password."""
DEFAULT_TITLE = 'Time-based One Time Password'
MAX_RETRY_TIME = 5
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
"""Initialize the user data store."""
super().__init__(hass, config)
self._users = None # type: Optional[Dict[str, str]]
self._user_store = hass.helpers.storage.Store(
STORAGE_VERSION, STORAGE_KEY)
STORAGE_VERSION, STORAGE_KEY, private=True)
@property
def input_schema(self) -> vol.Schema:
@@ -130,7 +131,7 @@ class TotpAuthModule(MultiFactorAuthModule):
return user_id in self._users # type: ignore
async def async_validation(
async def async_validate(
self, user_id: str, user_input: Dict[str, Any]) -> bool:
"""Return True if validation passed."""
if self._users is None:
@@ -149,10 +150,10 @@ class TotpAuthModule(MultiFactorAuthModule):
if ota_secret is None:
# even we cannot find user, we still do verify
# to make timing the same as if user was found.
pyotp.TOTP(DUMMY_SECRET).verify(code)
pyotp.TOTP(DUMMY_SECRET).verify(code, valid_window=1)
return False
return bool(pyotp.TOTP(ota_secret).verify(code))
return bool(pyotp.TOTP(ota_secret).verify(code, valid_window=1))
class TotpSetupFlow(SetupFlow):

View File

@@ -19,19 +19,19 @@ class User:
"""A user."""
name = attr.ib(type=str) # type: Optional[str]
id = attr.ib(type=str, default=attr.Factory(lambda: uuid.uuid4().hex))
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
is_owner = attr.ib(type=bool, default=False)
is_active = attr.ib(type=bool, default=False)
system_generated = attr.ib(type=bool, default=False)
# List of credentials of a user.
credentials = attr.ib(
type=list, default=attr.Factory(list), cmp=False
type=list, factory=list, cmp=False
) # type: List[Credentials]
# Tokens associated with a user.
refresh_tokens = attr.ib(
type=dict, default=attr.Factory(dict), cmp=False
type=dict, factory=dict, cmp=False
) # type: Dict[str, RefreshToken]
@@ -48,12 +48,10 @@ class RefreshToken:
validator=attr.validators.in_((
TOKEN_TYPE_NORMAL, TOKEN_TYPE_SYSTEM,
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN)))
id = attr.ib(type=str, default=attr.Factory(lambda: uuid.uuid4().hex))
created_at = attr.ib(type=datetime, default=attr.Factory(dt_util.utcnow))
token = attr.ib(type=str,
default=attr.Factory(lambda: generate_secret(64)))
jwt_key = attr.ib(type=str,
default=attr.Factory(lambda: generate_secret(64)))
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
created_at = attr.ib(type=datetime, factory=dt_util.utcnow)
token = attr.ib(type=str, factory=lambda: generate_secret(64))
jwt_key = attr.ib(type=str, factory=lambda: generate_secret(64))
last_used_at = attr.ib(type=Optional[datetime], default=None)
last_used_ip = attr.ib(type=Optional[str], default=None)
@@ -69,7 +67,7 @@ class Credentials:
# Allow the auth provider to store data to represent their auth.
data = attr.ib(type=dict)
id = attr.ib(type=str, default=attr.Factory(lambda: uuid.uuid4().hex))
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
is_new = attr.ib(type=bool, default=True)

View File

@@ -15,8 +15,8 @@ from homeassistant.util import dt as dt_util
from homeassistant.util.decorator import Registry
from ..auth_store import AuthStore
from ..const import MFA_SESSION_EXPIRATION
from ..models import Credentials, User, UserMeta # noqa: F401
from ..mfa_modules import SESSION_EXPIRATION
_LOGGER = logging.getLogger(__name__)
DATA_REQS = 'auth_prov_reqs_processed'
@@ -171,6 +171,7 @@ class LoginFlow(data_entry_flow.FlowHandler):
self._auth_manager = auth_provider.hass.auth # type: ignore
self.available_mfa_modules = {} # type: Dict[str, str]
self.created_at = dt_util.utcnow()
self.invalid_mfa_times = 0
self.user = None # type: Optional[User]
async def async_step_init(
@@ -212,6 +213,8 @@ class LoginFlow(data_entry_flow.FlowHandler):
self, user_input: Optional[Dict[str, str]] = None) \
-> Dict[str, Any]:
"""Handle the step of mfa validation."""
assert self.user
errors = {}
auth_module = self._auth_manager.get_auth_mfa_module(
@@ -221,25 +224,34 @@ class LoginFlow(data_entry_flow.FlowHandler):
# will show invalid_auth_module error
return await self.async_step_select_mfa_module(user_input={})
if user_input is None and hasattr(auth_module,
'async_initialize_login_mfa_step'):
await auth_module.async_initialize_login_mfa_step(self.user.id)
if user_input is not None:
expires = self.created_at + SESSION_EXPIRATION
expires = self.created_at + MFA_SESSION_EXPIRATION
if dt_util.utcnow() > expires:
return self.async_abort(
reason='login_expired'
)
result = await auth_module.async_validation(
self.user.id, user_input) # type: ignore
result = await auth_module.async_validate(
self.user.id, user_input)
if not result:
errors['base'] = 'invalid_code'
self.invalid_mfa_times += 1
if self.invalid_mfa_times >= auth_module.MAX_RETRY_TIME > 0:
return self.async_abort(
reason='too_many_retry'
)
if not errors:
return await self.async_finish(self.user)
description_placeholders = {
'mfa_module_name': auth_module.name,
'mfa_module_id': auth_module.id
} # type: Dict[str, str]
'mfa_module_id': auth_module.id,
} # type: Dict[str, Optional[str]]
return self.async_show_form(
step_id='mfa',

View File

@@ -52,7 +52,8 @@ class Data:
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize the user data store."""
self.hass = hass
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY,
private=True)
self._data = None # type: Optional[Dict[str, Any]]
async def async_load(self) -> None:

View File

@@ -5,7 +5,6 @@ import os
import sys
from time import time
from collections import OrderedDict
from typing import Any, Optional, Dict
import voluptuous as vol
@@ -19,7 +18,6 @@ from homeassistant.util.logging import AsyncHandler
from homeassistant.util.package import async_get_user_site, is_virtual_env
from homeassistant.util.yaml import clear_secret_cache
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.signal import async_register_signal_handling
_LOGGER = logging.getLogger(__name__)
@@ -160,7 +158,6 @@ async def async_from_config_dict(config: Dict[str, Any],
stop = time()
_LOGGER.info("Home Assistant initialized in %.2fs", stop-start)
async_register_signal_handling(hass)
return hass

View File

@@ -59,61 +59,9 @@ def is_on(hass, entity_id=None):
return False
def turn_on(hass, entity_id=None, **service_data):
"""Turn specified entity on if possible."""
if entity_id is not None:
service_data[ATTR_ENTITY_ID] = entity_id
hass.services.call(ha.DOMAIN, SERVICE_TURN_ON, service_data)
def turn_off(hass, entity_id=None, **service_data):
"""Turn specified entity off."""
if entity_id is not None:
service_data[ATTR_ENTITY_ID] = entity_id
hass.services.call(ha.DOMAIN, SERVICE_TURN_OFF, service_data)
def toggle(hass, entity_id=None, **service_data):
"""Toggle specified entity."""
if entity_id is not None:
service_data[ATTR_ENTITY_ID] = entity_id
hass.services.call(ha.DOMAIN, SERVICE_TOGGLE, service_data)
def stop(hass):
"""Stop Home Assistant."""
hass.services.call(ha.DOMAIN, SERVICE_HOMEASSISTANT_STOP)
def restart(hass):
"""Stop Home Assistant."""
hass.services.call(ha.DOMAIN, SERVICE_HOMEASSISTANT_RESTART)
def check_config(hass):
"""Check the config files."""
hass.services.call(ha.DOMAIN, SERVICE_CHECK_CONFIG)
def reload_core_config(hass):
"""Reload the core config."""
hass.services.call(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
@asyncio.coroutine
def async_reload_core_config(hass):
"""Reload the core config."""
yield from hass.services.async_call(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
@asyncio.coroutine
def async_setup(hass: ha.HomeAssistant, config: dict) -> Awaitable[bool]:
async def async_setup(hass: ha.HomeAssistant, config: dict) -> Awaitable[bool]:
"""Set up general services related to Home Assistant."""
@asyncio.coroutine
def async_handle_turn_service(service):
async def async_handle_turn_service(service):
"""Handle calls to homeassistant.turn_on/off."""
entity_ids = extract_entity_ids(hass, service)
@@ -148,7 +96,7 @@ def async_setup(hass: ha.HomeAssistant, config: dict) -> Awaitable[bool]:
tasks.append(hass.services.async_call(
domain, service.service, data, blocking))
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)
hass.services.async_register(
ha.DOMAIN, SERVICE_TURN_OFF, async_handle_turn_service)
@@ -164,15 +112,14 @@ def async_setup(hass: ha.HomeAssistant, config: dict) -> Awaitable[bool]:
hass.helpers.intent.async_register(intent.ServiceIntentHandler(
intent.INTENT_TOGGLE, ha.DOMAIN, SERVICE_TOGGLE, "Toggled {}"))
@asyncio.coroutine
def async_handle_core_service(call):
async def async_handle_core_service(call):
"""Service handler for handling core services."""
if call.service == SERVICE_HOMEASSISTANT_STOP:
hass.async_create_task(hass.async_stop())
return
try:
errors = yield from conf_util.async_check_ha_config_file(hass)
errors = await conf_util.async_check_ha_config_file(hass)
except HomeAssistantError:
return
@@ -193,16 +140,15 @@ def async_setup(hass: ha.HomeAssistant, config: dict) -> Awaitable[bool]:
hass.services.async_register(
ha.DOMAIN, SERVICE_CHECK_CONFIG, async_handle_core_service)
@asyncio.coroutine
def async_handle_reload_config(call):
async def async_handle_reload_config(call):
"""Service handler for reloading core config."""
try:
conf = yield from conf_util.async_hass_config_yaml(hass)
conf = await conf_util.async_hass_config_yaml(hass)
except HomeAssistantError as err:
_LOGGER.error(err)
return
yield from conf_util.async_process_ha_core_config(
await conf_util.async_process_ha_core_config(
hass, conf.get(ha.DOMAIN) or {})
hass.services.async_register(

View File

@@ -4,7 +4,6 @@ This component provides basic support for Abode Home Security system.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/abode/
"""
import asyncio
import logging
from functools import partial
from requests.exceptions import HTTPError, ConnectTimeout
@@ -261,8 +260,7 @@ class AbodeDevice(Entity):
self._data = data
self._device = device
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Subscribe Abode events."""
self.hass.async_add_job(
self._data.abode.events.add_device_callback,
@@ -308,8 +306,7 @@ class AbodeAutomation(Entity):
self._automation = automation
self._event = event
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Subscribe Abode events."""
if self._event:
self.hass.async_add_job(

View File

@@ -4,7 +4,6 @@ Component to interface with an alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel/
"""
import asyncio
from datetime import timedelta
import logging
@@ -14,7 +13,6 @@ from homeassistant.const import (
ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER,
SERVICE_ALARM_DISARM, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_NIGHT, SERVICE_ALARM_ARM_CUSTOM_BYPASS)
from homeassistant.loader import bind_hass
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
@@ -32,85 +30,12 @@ ALARM_SERVICE_SCHEMA = vol.Schema({
})
@bind_hass
def alarm_disarm(hass, code=None, entity_id=None):
"""Send the alarm the command for disarm."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_DISARM, data)
@bind_hass
def alarm_arm_home(hass, code=None, entity_id=None):
"""Send the alarm the command for arm home."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_HOME, data)
@bind_hass
def alarm_arm_away(hass, code=None, entity_id=None):
"""Send the alarm the command for arm away."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_AWAY, data)
@bind_hass
def alarm_arm_night(hass, code=None, entity_id=None):
"""Send the alarm the command for arm night."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_NIGHT, data)
@bind_hass
def alarm_trigger(hass, code=None, entity_id=None):
"""Send the alarm the command for trigger."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_TRIGGER, data)
@bind_hass
def alarm_arm_custom_bypass(hass, code=None, entity_id=None):
"""Send the alarm the command for arm custom bypass."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_CUSTOM_BYPASS, data)
@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Track states and offer events for sensors."""
component = hass.data[DOMAIN] = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
yield from component.async_setup(config)
await component.async_setup(config)
component.async_register_entity_service(
SERVICE_ALARM_DISARM, ALARM_SERVICE_SCHEMA,

View File

@@ -4,7 +4,6 @@ Support for AlarmDecoder-based alarm control panels (Honeywell/DSC).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.alarmdecoder/
"""
import asyncio
import logging
import voluptuous as vol
@@ -59,8 +58,7 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
self._ready = None
self._zone_bypassed = None
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
self.hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_PANEL_MESSAGE, self._message_callback)

View File

@@ -4,7 +4,6 @@ Interfaces with Alarm.com alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.alarmdotcom/
"""
import asyncio
import logging
import re
@@ -32,9 +31,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up a Alarm.com control panel."""
name = config.get(CONF_NAME)
code = config.get(CONF_CODE)
@@ -42,7 +40,7 @@ def async_setup_platform(hass, config, async_add_entities,
password = config.get(CONF_PASSWORD)
alarmdotcom = AlarmDotCom(hass, name, code, username, password)
yield from alarmdotcom.async_login()
await alarmdotcom.async_login()
async_add_entities([alarmdotcom])
@@ -63,15 +61,13 @@ class AlarmDotCom(alarm.AlarmControlPanel):
self._alarm = Alarmdotcom(
username, password, self._websession, hass.loop)
@asyncio.coroutine
def async_login(self):
async def async_login(self):
"""Login to Alarm.com."""
yield from self._alarm.async_login()
await self._alarm.async_login()
@asyncio.coroutine
def async_update(self):
async def async_update(self):
"""Fetch the latest state."""
yield from self._alarm.async_update()
await self._alarm.async_update()
return self._alarm.state
@property
@@ -106,23 +102,20 @@ class AlarmDotCom(alarm.AlarmControlPanel):
'sensor_status': self._alarm.sensor_status
}
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if self._validate_code(code):
yield from self._alarm.async_alarm_disarm()
await self._alarm.async_alarm_disarm()
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
async def async_alarm_arm_home(self, code=None):
"""Send arm hom command."""
if self._validate_code(code):
yield from self._alarm.async_alarm_arm_home()
await self._alarm.async_alarm_arm_home()
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
if self._validate_code(code):
yield from self._alarm.async_alarm_arm_away()
await self._alarm.async_alarm_arm_away()
def _validate_code(self, code):
"""Validate given code."""

View File

@@ -0,0 +1,86 @@
"""
Support for Blink Alarm Control Panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.blink/
"""
import logging
from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.blink import (
BLINK_DATA, DEFAULT_ATTRIBUTION)
from homeassistant.const import (
ATTR_ATTRIBUTION, STATE_ALARM_DISARMED, STATE_ALARM_ARMED_AWAY)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['blink']
ICON = 'mdi:security'
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Arlo Alarm Control Panels."""
if discovery_info is None:
return
data = hass.data[BLINK_DATA]
# Current version of blinkpy API only supports one sync module. When
# support for additional models is added, the sync module name should
# come from the API.
sync_modules = []
sync_modules.append(BlinkSyncModule(data, 'sync'))
add_entities(sync_modules, True)
class BlinkSyncModule(AlarmControlPanel):
"""Representation of a Blink Alarm Control Panel."""
def __init__(self, data, name):
"""Initialize the alarm control panel."""
self.data = data
self.sync = data.sync
self._name = name
self._state = None
@property
def icon(self):
"""Return icon."""
return ICON
@property
def state(self):
"""Return the state of the device."""
return self._state
@property
def name(self):
"""Return the name of the panel."""
return "{} {}".format(BLINK_DATA, self._name)
@property
def device_state_attributes(self):
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION,
}
def update(self):
"""Update the state of the device."""
_LOGGER.debug("Updating Blink Alarm Control Panel %s", self._name)
self.data.refresh()
mode = self.sync.arm
if mode:
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = STATE_ALARM_DISARMED
def alarm_disarm(self, code=None):
"""Send disarm command."""
self.sync.arm = False
self.sync.refresh()
def alarm_arm_away(self, code=None):
"""Send arm command."""
self.sync.arm = True
self.sync.refresh()

View File

@@ -4,7 +4,6 @@ Interfaces with Egardia/Woonveilig alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.egardia/
"""
import asyncio
import logging
import requests
@@ -61,8 +60,7 @@ class EgardiaAlarm(alarm.AlarmControlPanel):
self._rs_codes = rs_codes
self._rs_port = rs_port
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Add Egardiaserver callback if enabled."""
if self._rs_enabled:
_LOGGER.debug("Registering callback to Egardiaserver")

View File

@@ -4,7 +4,6 @@ Support for Envisalink-based alarm control panels (Honeywell/DSC).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.envisalink/
"""
import asyncio
import logging
import voluptuous as vol
@@ -32,9 +31,8 @@ ALARM_KEYPRESS_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Perform the setup for Envisalink alarm panels."""
configured_partitions = discovery_info['partitions']
code = discovery_info[CONF_CODE]
@@ -88,8 +86,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
_LOGGER.debug("Setting up alarm: %s", alarm_name)
super().__init__(alarm_name, info, controller)
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_KEYPAD_UPDATE, self._update_callback)
@@ -128,8 +125,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
state = STATE_ALARM_DISARMED
return state
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if code:
self.hass.data[DATA_EVL].disarm_partition(
@@ -138,8 +134,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
self.hass.data[DATA_EVL].disarm_partition(
str(self._code), self._partition_number)
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
async def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
if code:
self.hass.data[DATA_EVL].arm_stay_partition(
@@ -148,8 +143,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
self.hass.data[DATA_EVL].arm_stay_partition(
str(self._code), self._partition_number)
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
if code:
self.hass.data[DATA_EVL].arm_away_partition(
@@ -158,8 +152,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
self.hass.data[DATA_EVL].arm_away_partition(
str(self._code), self._partition_number)
@asyncio.coroutine
def async_alarm_trigger(self, code=None):
async def async_alarm_trigger(self, code=None):
"""Alarm trigger command. Will be used to trigger a panic alarm."""
self.hass.data[DATA_EVL].panic_alarm(self._panic_type)

View File

@@ -4,7 +4,6 @@ Support for manual alarms controllable via MQTT.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.manual_mqtt/
"""
import asyncio
import copy
import datetime
import logging
@@ -363,8 +362,8 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
return mqtt.async_subscribe(
self.hass, self._command_topic, message_received, self._qos)
@asyncio.coroutine
def _async_state_changed_listener(self, entity_id, old_state, new_state):
async def _async_state_changed_listener(self, entity_id, old_state,
new_state):
"""Publish state change to MQTT."""
mqtt.async_publish(
self.hass, self._state_topic, new_state.state, self._qos, True)

View File

@@ -4,7 +4,6 @@ This platform enables the possibility to control a MQTT alarm.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.mqtt/
"""
import asyncio
import logging
import re
@@ -18,10 +17,13 @@ from homeassistant.const import (
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN,
CONF_NAME, CONF_CODE)
from homeassistant.components.mqtt import (
CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC, CONF_COMMAND_TOPIC,
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS,
CONF_RETAIN, MqttAvailability)
ATTR_DISCOVERY_HASH, CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC,
CONF_COMMAND_TOPIC, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE,
CONF_QOS, CONF_RETAIN, MqttAvailability, MqttDiscoveryUpdate)
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
_LOGGER = logging.getLogger(__name__)
@@ -46,13 +48,28 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the MQTT Alarm Control Panel platform."""
if discovery_info is not None:
config = PLATFORM_SCHEMA(discovery_info)
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
async_add_entities, discovery_info=None):
"""Set up MQTT alarm control panel through configuration.yaml."""
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up MQTT alarm control panel dynamically through MQTT discovery."""
async def async_discover(discovery_payload):
"""Discover and add an MQTT alarm control panel."""
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(hass, config, async_add_entities,
discovery_payload[ATTR_DISCOVERY_HASH])
async_dispatcher_connect(
hass, MQTT_DISCOVERY_NEW.format(alarm.DOMAIN, 'mqtt'),
async_discover)
async def _async_setup_entity(hass, config, async_add_entities,
discovery_hash=None):
"""Set up the MQTT Alarm Control Panel platform."""
async_add_entities([MqttAlarm(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
@@ -65,18 +82,22 @@ def async_setup_platform(hass, config, async_add_entities,
config.get(CONF_CODE),
config.get(CONF_AVAILABILITY_TOPIC),
config.get(CONF_PAYLOAD_AVAILABLE),
config.get(CONF_PAYLOAD_NOT_AVAILABLE))])
config.get(CONF_PAYLOAD_NOT_AVAILABLE),
discovery_hash,)])
class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
class MqttAlarm(MqttAvailability, MqttDiscoveryUpdate,
alarm.AlarmControlPanel):
"""Representation of a MQTT alarm status."""
def __init__(self, name, state_topic, command_topic, qos, retain,
payload_disarm, payload_arm_home, payload_arm_away, code,
availability_topic, payload_available, payload_not_available):
availability_topic, payload_available, payload_not_available,
discovery_hash):
"""Init the MQTT Alarm Control Panel."""
super().__init__(availability_topic, qos, payload_available,
payload_not_available)
MqttAvailability.__init__(self, availability_topic, qos,
payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash)
self._state = STATE_UNKNOWN
self._name = name
self._state_topic = state_topic
@@ -87,11 +108,12 @@ class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
self._payload_arm_home = payload_arm_home
self._payload_arm_away = payload_arm_away
self._code = code
self._discovery_hash = discovery_hash
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Subscribe mqtt events."""
yield from super().async_added_to_hass()
await MqttAvailability.async_added_to_hass(self)
await MqttDiscoveryUpdate.async_added_to_hass(self)
@callback
def message_received(topic, payload, qos):
@@ -104,7 +126,7 @@ class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
self._state = payload
self.async_schedule_update_ha_state()
yield from mqtt.async_subscribe(
await mqtt.async_subscribe(
self.hass, self._state_topic, message_received, self._qos)
@property
@@ -131,8 +153,7 @@ class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
return 'Number'
return 'Any'
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
async def async_alarm_disarm(self, code=None):
"""Send disarm command.
This method is a coroutine.
@@ -143,8 +164,7 @@ class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
self.hass, self._command_topic, self._payload_disarm, self._qos,
self._retain)
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
async def async_alarm_arm_home(self, code=None):
"""Send arm home command.
This method is a coroutine.
@@ -155,8 +175,7 @@ class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
self.hass, self._command_topic, self._payload_arm_home, self._qos,
self._retain)
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
async def async_alarm_arm_away(self, code=None):
"""Send arm away command.
This method is a coroutine.

View File

@@ -4,7 +4,6 @@ Support for Satel Integra alarm, using ETHM module: https://www.satel.pl/en/ .
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.satel_integra/
"""
import asyncio
import logging
import homeassistant.components.alarm_control_panel as alarm
@@ -18,9 +17,8 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['satel_integra']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up for Satel Integra alarm panels."""
if not discovery_info:
return
@@ -39,8 +37,7 @@ class SatelIntegraAlarmPanel(alarm.AlarmControlPanel):
self._state = None
self._arm_home_mode = arm_home_mode
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_PANEL_MESSAGE, self._message_callback)
@@ -74,21 +71,18 @@ class SatelIntegraAlarmPanel(alarm.AlarmControlPanel):
"""Return the state of the device."""
return self._state
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if code:
yield from self.hass.data[DATA_SATEL].disarm(code)
await self.hass.data[DATA_SATEL].disarm(code)
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
if code:
yield from self.hass.data[DATA_SATEL].arm(code)
await self.hass.data[DATA_SATEL].arm(code)
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
async def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
if code:
yield from self.hass.data[DATA_SATEL].arm(
await self.hass.data[DATA_SATEL].arm(
code, self._arm_home_mode)

View File

@@ -12,75 +12,100 @@ import voluptuous as vol
from homeassistant.components.alarm_control_panel import (
PLATFORM_SCHEMA, AlarmControlPanel)
from homeassistant.const import (
CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_UNKNOWN)
import homeassistant.helpers.config_validation as cv
CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED)
from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = ['simplisafe-python==2.0.2']
REQUIREMENTS = ['simplisafe-python==3.1.2']
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'SimpliSafe'
ATTR_ALARM_ACTIVE = "alarm_active"
ATTR_TEMPERATURE = "temperature"
DATA_FILE = '.simplisafe'
DEFAULT_NAME = 'SimpliSafe'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_CODE): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_CODE): cv.string,
})
def setup_platform(hass, config, add_entities, discovery_info=None):
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
"""Set up the SimpliSafe platform."""
from simplipy.api import SimpliSafeApiInterface, SimpliSafeAPIException
from simplipy import API
from simplipy.errors import SimplipyError
username = config[CONF_USERNAME]
password = config[CONF_PASSWORD]
name = config.get(CONF_NAME)
code = config.get(CONF_CODE)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
websession = aiohttp_client.async_get_clientsession(hass)
config_data = await hass.async_add_executor_job(
load_json, hass.config.path(DATA_FILE))
try:
simplisafe = SimpliSafeApiInterface(username, password)
except SimpliSafeAPIException:
_LOGGER.error("Failed to set up SimpliSafe")
if config_data:
try:
simplisafe = await API.login_via_token(
config_data['refresh_token'], websession)
_LOGGER.debug('Logging in with refresh token')
except SimplipyError:
_LOGGER.info('Refresh token expired; attempting credentials')
simplisafe = await API.login_via_credentials(
username, password, websession)
else:
simplisafe = await API.login_via_credentials(
username, password, websession)
_LOGGER.debug('Logging in with credentials')
except SimplipyError as err:
_LOGGER.error("There was an error during setup: %s", err)
return
systems = []
config_data = {'refresh_token': simplisafe.refresh_token}
await hass.async_add_executor_job(
save_json, hass.config.path(DATA_FILE), config_data)
for system in simplisafe.get_systems():
systems.append(SimpliSafeAlarm(system, name, code))
add_entities(systems)
systems = await simplisafe.get_systems()
async_add_entities(
[SimpliSafeAlarm(system, name, code) for system in systems], True)
class SimpliSafeAlarm(AlarmControlPanel):
"""Representation of a SimpliSafe alarm."""
def __init__(self, simplisafe, name, code):
def __init__(self, system, name, code):
"""Initialize the SimpliSafe alarm."""
self.simplisafe = simplisafe
self._name = name
self._attrs = {}
self._code = str(code) if code else None
self._name = name
self._system = system
self._state = None
@property
def unique_id(self):
"""Return the unique ID."""
return self.simplisafe.location_id
return self._system.system_id
@property
def name(self):
"""Return the name of the device."""
if self._name is not None:
if self._name:
return self._name
return 'Alarm {}'.format(self.simplisafe.location_id)
return 'Alarm {}'.format(self._system.system_id)
@property
def code_format(self):
"""Return one or more digits/characters."""
if self._code is None:
if not self._code:
return None
if isinstance(self._code, str) and re.search('^\\d+$', self._code):
return 'Number'
@@ -89,53 +114,12 @@ class SimpliSafeAlarm(AlarmControlPanel):
@property
def state(self):
"""Return the state of the device."""
status = self.simplisafe.state
if status.lower() == 'off':
state = STATE_ALARM_DISARMED
elif status.lower() == 'home' or status.lower() == 'home_count':
state = STATE_ALARM_ARMED_HOME
elif (status.lower() == 'away' or status.lower() == 'exitDelay' or
status.lower() == 'away_count'):
state = STATE_ALARM_ARMED_AWAY
else:
state = STATE_UNKNOWN
return state
return self._state
@property
def device_state_attributes(self):
"""Return the state attributes."""
attributes = {}
attributes[ATTR_ALARM_ACTIVE] = self.simplisafe.alarm_active
if self.simplisafe.temperature is not None:
attributes[ATTR_TEMPERATURE] = self.simplisafe.temperature
return attributes
def update(self):
"""Update alarm status."""
self.simplisafe.update()
def alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'disarming'):
return
self.simplisafe.set_state('off')
_LOGGER.info("SimpliSafe alarm disarming")
def alarm_arm_home(self, code=None):
"""Send arm home command."""
if not self._validate_code(code, 'arming home'):
return
self.simplisafe.set_state('home')
_LOGGER.info("SimpliSafe alarm arming home")
def alarm_arm_away(self, code=None):
"""Send arm away command."""
if not self._validate_code(code, 'arming away'):
return
self.simplisafe.set_state('away')
_LOGGER.info("SimpliSafe alarm arming away")
return self._attrs
def _validate_code(self, code, state):
"""Validate given code."""
@@ -143,3 +127,46 @@ class SimpliSafeAlarm(AlarmControlPanel):
if not check:
_LOGGER.warning("Wrong code entered for %s", state)
return check
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'disarming'):
return
await self._system.set_off()
async def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
if not self._validate_code(code, 'arming home'):
return
await self._system.set_home()
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
if not self._validate_code(code, 'arming away'):
return
await self._system.set_away()
async def async_update(self):
"""Update alarm status."""
await self._system.update()
if self._system.state == self._system.SystemStates.off:
self._state = STATE_ALARM_DISARMED
elif self._system.state in (
self._system.SystemStates.home,
self._system.SystemStates.home_count):
self._state = STATE_ALARM_ARMED_HOME
elif self._system.state in (
self._system.SystemStates.away,
self._system.SystemStates.away_count,
self._system.SystemStates.exit_delay):
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = None
self._attrs[ATTR_ALARM_ACTIVE] = self._system.alarm_going_off
if self._system.temperature:
self._attrs[ATTR_TEMPERATURE] = self._system.temperature

View File

@@ -4,71 +4,63 @@ Support for Vanderbilt (formerly Siemens) SPC alarm systems.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.spc/
"""
import asyncio
import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.spc import (
ATTR_DISCOVER_AREAS, DATA_API, DATA_REGISTRY, SpcWebGateway)
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.core import callback
from homeassistant.components.spc import (DATA_API, SIGNAL_UPDATE_ALARM)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN)
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED)
_LOGGER = logging.getLogger(__name__)
SPC_AREA_MODE_TO_STATE = {
'0': STATE_ALARM_DISARMED,
'1': STATE_ALARM_ARMED_HOME,
'3': STATE_ALARM_ARMED_AWAY,
}
def _get_alarm_state(spc_mode):
def _get_alarm_state(area):
"""Get the alarm state."""
return SPC_AREA_MODE_TO_STATE.get(spc_mode, STATE_UNKNOWN)
from pyspcwebgw.const import AreaMode
if area.verified_alarm:
return STATE_ALARM_TRIGGERED
mode_to_state = {
AreaMode.UNSET: STATE_ALARM_DISARMED,
AreaMode.PART_SET_A: STATE_ALARM_ARMED_HOME,
AreaMode.PART_SET_B: STATE_ALARM_ARMED_NIGHT,
AreaMode.FULL_SET: STATE_ALARM_ARMED_AWAY,
}
return mode_to_state.get(area.mode)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the SPC alarm control panel platform."""
if (discovery_info is None or
discovery_info[ATTR_DISCOVER_AREAS] is None):
if discovery_info is None:
return
api = hass.data[DATA_API]
devices = [SpcAlarm(api, area)
for area in discovery_info[ATTR_DISCOVER_AREAS]]
async_add_entities(devices)
async_add_entities([SpcAlarm(area=area, api=api)
for area in api.areas.values()])
class SpcAlarm(alarm.AlarmControlPanel):
"""Representation of the SPC alarm panel."""
def __init__(self, api, area):
def __init__(self, area, api):
"""Initialize the SPC alarm panel."""
self._area_id = area['id']
self._name = area['name']
self._state = _get_alarm_state(area['mode'])
if self._state == STATE_ALARM_DISARMED:
self._changed_by = area.get('last_unset_user_name', 'unknown')
else:
self._changed_by = area.get('last_set_user_name', 'unknown')
self._area = area
self._api = api
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Call for adding new entities."""
self.hass.data[DATA_REGISTRY].register_alarm_device(
self._area_id, self)
async_dispatcher_connect(self.hass,
SIGNAL_UPDATE_ALARM.format(self._area.id),
self._update_callback)
@asyncio.coroutine
def async_update_from_spc(self, state, extra):
"""Update the alarm panel with a new state."""
self._state = state
self._changed_by = extra.get('changed_by', 'unknown')
self.async_schedule_update_ha_state()
@callback
def _update_callback(self):
"""Call update method."""
self.async_schedule_update_ha_state(True)
@property
def should_poll(self):
@@ -78,32 +70,34 @@ class SpcAlarm(alarm.AlarmControlPanel):
@property
def name(self):
"""Return the name of the device."""
return self._name
return self._area.name
@property
def changed_by(self):
"""Return the user the last change was triggered by."""
return self._changed_by
return self._area.last_changed_by
@property
def state(self):
"""Return the state of the device."""
return self._state
return _get_alarm_state(self._area)
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
yield from self._api.send_area_command(
self._area_id, SpcWebGateway.AREA_COMMAND_UNSET)
from pyspcwebgw.const import AreaMode
self._api.change_mode(area=self._area, new_mode=AreaMode.UNSET)
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
async def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
yield from self._api.send_area_command(
self._area_id, SpcWebGateway.AREA_COMMAND_PART_SET)
from pyspcwebgw.const import AreaMode
self._api.change_mode(area=self._area, new_mode=AreaMode.PART_SET_A)
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
async def async_alarm_arm_night(self, code=None):
"""Send arm home command."""
from pyspcwebgw.const import AreaMode
self._api.change_mode(area=self._area, new_mode=AreaMode.PART_SET_B)
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
yield from self._api.send_area_command(
self._area_id, SpcWebGateway.AREA_COMMAND_SET)
from pyspcwebgw.const import AreaMode
self._api.change_mode(area=self._area, new_mode=AreaMode.FULL_SET)

View File

@@ -4,7 +4,6 @@ Interfaces with Wink Cameras.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.wink/
"""
import asyncio
import logging
import homeassistant.components.alarm_control_panel as alarm
@@ -38,8 +37,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
class WinkCameraDevice(WinkDevice, alarm.AlarmControlPanel):
"""Representation a Wink camera alarm."""
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Call when entity is added to hass."""
self.hass.data[DOMAIN]['entities']['alarm_control_panel'].append(self)

View File

@@ -10,7 +10,8 @@ import logging
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.components.notify import (
ATTR_MESSAGE, DOMAIN as DOMAIN_NOTIFY)
from homeassistant.const import (
CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE, STATE_ON, STATE_OFF,
SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE, ATTR_ENTITY_ID)
@@ -59,53 +60,12 @@ def is_on(hass, entity_id):
return hass.states.is_state(entity_id, STATE_ON)
def turn_on(hass, entity_id):
"""Reset the alert."""
hass.add_job(async_turn_on, hass, entity_id)
@callback
def async_turn_on(hass, entity_id):
"""Async reset the alert."""
data = {ATTR_ENTITY_ID: entity_id}
hass.async_create_task(
hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data))
def turn_off(hass, entity_id):
"""Acknowledge alert."""
hass.add_job(async_turn_off, hass, entity_id)
@callback
def async_turn_off(hass, entity_id):
"""Async acknowledge the alert."""
data = {ATTR_ENTITY_ID: entity_id}
hass.async_create_task(
hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data))
def toggle(hass, entity_id):
"""Toggle acknowledgement of alert."""
hass.add_job(async_toggle, hass, entity_id)
@callback
def async_toggle(hass, entity_id):
"""Async toggle acknowledgement of alert."""
data = {ATTR_ENTITY_ID: entity_id}
hass.async_create_task(
hass.services.async_call(DOMAIN, SERVICE_TOGGLE, data))
@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Set up the Alert component."""
alerts = config.get(DOMAIN)
all_alerts = {}
@asyncio.coroutine
def async_handle_alert_service(service_call):
async def async_handle_alert_service(service_call):
"""Handle calls to alert services."""
alert_ids = service.extract_entity_ids(hass, service_call)
@@ -113,11 +73,11 @@ def async_setup(hass, config):
alert = all_alerts[alert_id]
alert.async_set_context(service_call.context)
if service_call.service == SERVICE_TURN_ON:
yield from alert.async_turn_on()
await alert.async_turn_on()
elif service_call.service == SERVICE_TOGGLE:
yield from alert.async_toggle()
await alert.async_toggle()
else:
yield from alert.async_turn_off()
await alert.async_turn_off()
# Setup alerts
for entity_id, alert in alerts.items():
@@ -141,7 +101,7 @@ def async_setup(hass, config):
tasks = [alert.async_update_ha_state() for alert in all_alerts.values()]
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)
return True
@@ -196,17 +156,15 @@ class Alert(ToggleEntity):
"""Hide the alert when it is not firing."""
return not self._can_ack or not self._firing
@asyncio.coroutine
def watched_entity_change(self, entity, from_state, to_state):
async def watched_entity_change(self, entity, from_state, to_state):
"""Determine if the alert should start or stop."""
_LOGGER.debug("Watched entity (%s) has changed", entity)
if to_state.state == self._alert_state and not self._firing:
yield from self.begin_alerting()
await self.begin_alerting()
if to_state.state != self._alert_state and self._firing:
yield from self.end_alerting()
await self.end_alerting()
@asyncio.coroutine
def begin_alerting(self):
async def begin_alerting(self):
"""Begin the alert procedures."""
_LOGGER.debug("Beginning Alert: %s", self._name)
self._ack = False
@@ -214,25 +172,23 @@ class Alert(ToggleEntity):
self._next_delay = 0
if not self._skip_first:
yield from self._notify()
await self._notify()
else:
yield from self._schedule_notify()
await self._schedule_notify()
self.async_schedule_update_ha_state()
@asyncio.coroutine
def end_alerting(self):
async def end_alerting(self):
"""End the alert procedures."""
_LOGGER.debug("Ending Alert: %s", self._name)
self._cancel()
self._ack = False
self._firing = False
if self._done_message and self._send_done_message:
yield from self._notify_done_message()
await self._notify_done_message()
self.async_schedule_update_ha_state()
@asyncio.coroutine
def _schedule_notify(self):
async def _schedule_notify(self):
"""Schedule a notification."""
delay = self._delay[self._next_delay]
next_msg = datetime.now() + delay
@@ -240,8 +196,7 @@ class Alert(ToggleEntity):
event.async_track_point_in_time(self.hass, self._notify, next_msg)
self._next_delay = min(self._next_delay + 1, len(self._delay) - 1)
@asyncio.coroutine
def _notify(self, *args):
async def _notify(self, *args):
"""Send the alert notification."""
if not self._firing:
return
@@ -250,36 +205,32 @@ class Alert(ToggleEntity):
_LOGGER.info("Alerting: %s", self._name)
self._send_done_message = True
for target in self._notifiers:
yield from self.hass.services.async_call(
'notify', target, {'message': self._name})
yield from self._schedule_notify()
await self.hass.services.async_call(
DOMAIN_NOTIFY, target, {ATTR_MESSAGE: self._name})
await self._schedule_notify()
@asyncio.coroutine
def _notify_done_message(self, *args):
async def _notify_done_message(self, *args):
"""Send notification of complete alert."""
_LOGGER.info("Alerting: %s", self._done_message)
self._send_done_message = False
for target in self._notifiers:
yield from self.hass.services.async_call(
'notify', target, {'message': self._done_message})
await self.hass.services.async_call(
DOMAIN_NOTIFY, target, {ATTR_MESSAGE: self._done_message})
@asyncio.coroutine
def async_turn_on(self, **kwargs):
async def async_turn_on(self, **kwargs):
"""Async Unacknowledge alert."""
_LOGGER.debug("Reset Alert: %s", self._name)
self._ack = False
yield from self.async_update_ha_state()
await self.async_update_ha_state()
@asyncio.coroutine
def async_turn_off(self, **kwargs):
async def async_turn_off(self, **kwargs):
"""Async Acknowledge alert."""
_LOGGER.debug("Acknowledged Alert: %s", self._name)
self._ack = True
yield from self.async_update_ha_state()
await self.async_update_ha_state()
@asyncio.coroutine
def async_toggle(self, **kwargs):
async def async_toggle(self, **kwargs):
"""Async toggle alert."""
if self._ack:
return self.async_turn_on()
return self.async_turn_off()
return await self.async_turn_on()
return await self.async_turn_off()

View File

@@ -4,7 +4,6 @@ Support for Alexa skill service end point.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/alexa/
"""
import asyncio
import logging
import voluptuous as vol
@@ -53,8 +52,7 @@ CONFIG_SCHEMA = vol.Schema({
}, extra=vol.ALLOW_EXTRA)
@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Activate Alexa component."""
config = config.get(DOMAIN, {})
flash_briefings_config = config.get(CONF_FLASH_BRIEFINGS)

View File

@@ -4,7 +4,6 @@ Support for Alexa skill service end point.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/alexa/
"""
import asyncio
import enum
import logging
@@ -59,16 +58,15 @@ class AlexaIntentsView(http.HomeAssistantView):
url = INTENTS_API_ENDPOINT
name = 'api:alexa'
@asyncio.coroutine
def post(self, request):
async def post(self, request):
"""Handle Alexa."""
hass = request.app['hass']
message = yield from request.json()
message = await request.json()
_LOGGER.debug("Received Alexa request: %s", message)
try:
response = yield from async_handle_message(hass, message)
response = await async_handle_message(hass, message)
return b'' if response is None else self.json(response)
except UnknownRequest as err:
_LOGGER.warning(str(err))
@@ -101,8 +99,7 @@ def intent_error_response(hass, message, error):
return alexa_response.as_dict()
@asyncio.coroutine
def async_handle_message(hass, message):
async def async_handle_message(hass, message):
"""Handle an Alexa intent.
Raises:
@@ -120,20 +117,18 @@ def async_handle_message(hass, message):
if not handler:
raise UnknownRequest('Received unknown request {}'.format(req_type))
return (yield from handler(hass, message))
return await handler(hass, message)
@HANDLERS.register('SessionEndedRequest')
@asyncio.coroutine
def async_handle_session_end(hass, message):
async def async_handle_session_end(hass, message):
"""Handle a session end request."""
return None
@HANDLERS.register('IntentRequest')
@HANDLERS.register('LaunchRequest')
@asyncio.coroutine
def async_handle_intent(hass, message):
async def async_handle_intent(hass, message):
"""Handle an intent request.
Raises:
@@ -153,7 +148,7 @@ def async_handle_intent(hass, message):
else:
intent_name = alexa_intent_info['name']
intent_response = yield from intent.async_handle(
intent_response = await intent.async_handle(
hass, DOMAIN, intent_name,
{key: {'value': value} for key, value
in alexa_response.variables.items()})

View File

@@ -1,5 +1,4 @@
"""Support for alexa Smart Home Skill API."""
import asyncio
import logging
import math
from datetime import datetime
@@ -695,8 +694,7 @@ class SmartHomeView(http.HomeAssistantView):
"""Initialize."""
self.smart_home_config = smart_home_config
@asyncio.coroutine
def post(self, request):
async def post(self, request):
"""Handle Alexa Smart Home requests.
The Smart Home API requires the endpoint to be implemented in AWS
@@ -704,11 +702,11 @@ class SmartHomeView(http.HomeAssistantView):
the response.
"""
hass = request.app['hass']
message = yield from request.json()
message = await request.json()
_LOGGER.debug("Received Alexa Smart Home request: %s", message)
response = yield from async_handle_message(
response = await async_handle_message(
hass, self.smart_home_config, message)
_LOGGER.debug("Sending Alexa Smart Home response: %s", response)
return b'' if response is None else self.json(response)
@@ -1529,3 +1527,8 @@ async def async_api_reportstate(hass, config, request, context, entity):
name='StateReport',
context={'properties': properties}
)
def turned_off_response(message):
"""Return a device turned off response."""
return api_error(message[API_DIRECTIVE], error_type='BRIDGE_UNREACHABLE')

View File

@@ -149,16 +149,14 @@ CONFIG_SCHEMA = vol.Schema({
}, extra=vol.ALLOW_EXTRA)
@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Set up the IP Webcam component."""
from pydroid_ipcam import PyDroidIPCam
webcams = hass.data[DATA_IP_WEBCAM] = {}
websession = async_get_clientsession(hass)
@asyncio.coroutine
def async_setup_ipcamera(cam_config):
async def async_setup_ipcamera(cam_config):
"""Set up an IP camera."""
host = cam_config[CONF_HOST]
username = cam_config.get(CONF_USERNAME)
@@ -188,16 +186,15 @@ def async_setup(hass, config):
if motion is None:
motion = 'motion_active' in cam.enabled_sensors
@asyncio.coroutine
def async_update_data(now):
async def async_update_data(now):
"""Update data from IP camera in SCAN_INTERVAL."""
yield from cam.update()
await cam.update()
async_dispatcher_send(hass, SIGNAL_UPDATE_DATA, host)
async_track_point_in_utc_time(
hass, async_update_data, utcnow() + interval)
yield from async_update_data(None)
await async_update_data(None)
# Load platforms
webcams[host] = cam
@@ -242,7 +239,7 @@ def async_setup(hass, config):
tasks = [async_setup_ipcamera(conf) for conf in config[DOMAIN]]
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)
return True
@@ -255,8 +252,7 @@ class AndroidIPCamEntity(Entity):
self._host = host
self._ipcam = ipcam
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register update dispatcher."""
@callback
def async_ipcam_update(host):

View File

@@ -6,7 +6,6 @@ https://home-assistant.io/components/apple_tv/
"""
import asyncio
import logging
from typing import Sequence, TypeVar, Union
import voluptuous as vol
@@ -78,14 +77,13 @@ def request_configuration(hass, config, atv, credentials):
"""Request configuration steps from the user."""
configurator = hass.components.configurator
@asyncio.coroutine
def configuration_callback(callback_data):
async def configuration_callback(callback_data):
"""Handle the submitted configuration."""
from pyatv import exceptions
pin = callback_data.get('pin')
try:
yield from atv.airplay.finish_authentication(pin)
await atv.airplay.finish_authentication(pin)
hass.components.persistent_notification.async_create(
'Authentication succeeded!<br /><br />Add the following '
'to credentials: in your apple_tv configuration:<br /><br />'
@@ -109,11 +107,10 @@ def request_configuration(hass, config, atv, credentials):
)
@asyncio.coroutine
def scan_for_apple_tvs(hass):
async def scan_for_apple_tvs(hass):
"""Scan for devices and present a notification of the ones found."""
import pyatv
atvs = yield from pyatv.scan_for_apple_tvs(hass.loop, timeout=3)
atvs = await pyatv.scan_for_apple_tvs(hass.loop, timeout=3)
devices = []
for atv in atvs:
@@ -133,14 +130,12 @@ def scan_for_apple_tvs(hass):
notification_id=NOTIFICATION_SCAN_ID)
@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Set up the Apple TV component."""
if DATA_APPLE_TV not in hass.data:
hass.data[DATA_APPLE_TV] = {}
@asyncio.coroutine
def async_service_handler(service):
async def async_service_handler(service):
"""Handle service calls."""
entity_ids = service.data.get(ATTR_ENTITY_ID)
@@ -159,17 +154,16 @@ def async_setup(hass, config):
continue
atv = device.atv
credentials = yield from atv.airplay.generate_credentials()
yield from atv.airplay.load_credentials(credentials)
credentials = await atv.airplay.generate_credentials()
await atv.airplay.load_credentials(credentials)
_LOGGER.debug('Generated new credentials: %s', credentials)
yield from atv.airplay.start_authentication()
await atv.airplay.start_authentication()
hass.async_add_job(request_configuration,
hass, config, atv, credentials)
@asyncio.coroutine
def atv_discovered(service, info):
async def atv_discovered(service, info):
"""Set up an Apple TV that was auto discovered."""
yield from _setup_atv(hass, {
await _setup_atv(hass, {
CONF_NAME: info['name'],
CONF_HOST: info['host'],
CONF_LOGIN_ID: info['properties']['hG'],
@@ -180,7 +174,7 @@ def async_setup(hass, config):
tasks = [_setup_atv(hass, conf) for conf in config.get(DOMAIN, [])]
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SCAN, async_service_handler,
@@ -193,8 +187,7 @@ def async_setup(hass, config):
return True
@asyncio.coroutine
def _setup_atv(hass, atv_config):
async def _setup_atv(hass, atv_config):
"""Set up an Apple TV."""
import pyatv
name = atv_config.get(CONF_NAME)
@@ -210,7 +203,7 @@ def _setup_atv(hass, atv_config):
session = async_get_clientsession(hass)
atv = pyatv.connect_to_apple_tv(details, hass.loop, session=session)
if credentials:
yield from atv.airplay.load_credentials(credentials)
await atv.airplay.load_credentials(credentials)
power = AppleTVPowerManager(hass, atv, start_off)
hass.data[DATA_APPLE_TV][host] = {
@@ -259,4 +252,4 @@ class AppleTVPowerManager:
self.atv.push_updater.start()
for listener in self.listeners:
self.hass.async_add_job(listener.async_update_ha_state())
self.hass.async_create_task(listener.async_update_ha_state())

View File

@@ -0,0 +1,95 @@
"""
Support for AquaLogic component.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/aqualogic/
"""
from datetime import timedelta
import logging
import time
import threading
import voluptuous as vol
from homeassistant.const import (CONF_HOST, CONF_PORT,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers import config_validation as cv
REQUIREMENTS = ["aqualogic==1.0"]
_LOGGER = logging.getLogger(__name__)
DOMAIN = "aqualogic"
UPDATE_TOPIC = DOMAIN + "_update"
CONF_UNIT = "unit"
RECONNECT_INTERVAL = timedelta(seconds=10)
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORT): cv.port
}),
}, extra=vol.ALLOW_EXTRA)
def setup(hass, config):
"""Set up AquaLogic platform."""
host = config[DOMAIN][CONF_HOST]
port = config[DOMAIN][CONF_PORT]
processor = AquaLogicProcessor(hass, host, port)
hass.data[DOMAIN] = processor
hass.bus.listen_once(EVENT_HOMEASSISTANT_START,
processor.start_listen)
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP,
processor.shutdown)
_LOGGER.debug("AquaLogicProcessor %s:%i initialized", host, port)
return True
class AquaLogicProcessor(threading.Thread):
"""AquaLogic event processor thread."""
def __init__(self, hass, host, port):
"""Initialize the data object."""
super().__init__(daemon=True)
self._hass = hass
self._host = host
self._port = port
self._shutdown = False
self._panel = None
def start_listen(self, event):
"""Start event-processing thread."""
_LOGGER.debug("Event processing thread started")
self.start()
def shutdown(self, event):
"""Signal shutdown of processing event."""
_LOGGER.debug("Event processing signaled exit")
self._shutdown = True
def data_changed(self, panel):
"""Aqualogic data changed callback."""
self._hass.helpers.dispatcher.dispatcher_send(UPDATE_TOPIC)
def run(self):
"""Event thread."""
from aqualogic.core import AquaLogic
while True:
self._panel = AquaLogic()
self._panel.connect(self._host, self._port)
self._panel.process(self.data_changed)
if self._shutdown:
return
_LOGGER.error("Connection to %s:%d lost",
self._host, self._port)
time.sleep(RECONNECT_INTERVAL.seconds)
@property
def panel(self):
"""Retrieve the AquaLogic object."""
return self._panel

View File

@@ -13,7 +13,7 @@ from homeassistant.core import callback
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import (
async_dispatcher_connect, async_dispatcher_send)
async_dispatcher_send, dispatcher_connect)
REQUIREMENTS = ['asterisk_mbox==0.5.0']
@@ -21,8 +21,11 @@ _LOGGER = logging.getLogger(__name__)
DOMAIN = 'asterisk_mbox'
SIGNAL_DISCOVER_PLATFORM = "asterisk_mbox.discover_platform"
SIGNAL_MESSAGE_REQUEST = 'asterisk_mbox.message_request'
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
SIGNAL_CDR_UPDATE = 'asterisk_mbox.message_updated'
SIGNAL_CDR_REQUEST = 'asterisk_mbox.message_request'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
@@ -41,9 +44,7 @@ def setup(hass, config):
port = conf.get(CONF_PORT)
password = conf.get(CONF_PASSWORD)
hass.data[DOMAIN] = AsteriskData(hass, host, port, password)
discovery.load_platform(hass, 'mailbox', DOMAIN, {}, config)
hass.data[DOMAIN] = AsteriskData(hass, host, port, password, config)
return True
@@ -51,31 +52,71 @@ def setup(hass, config):
class AsteriskData:
"""Store Asterisk mailbox data."""
def __init__(self, hass, host, port, password):
def __init__(self, hass, host, port, password, config):
"""Init the Asterisk data object."""
from asterisk_mbox import Client as asteriskClient
self.hass = hass
self.client = asteriskClient(host, port, password, self.handle_data)
self.messages = []
self.config = config
self.messages = None
self.cdr = None
async_dispatcher_connect(
dispatcher_connect(
self.hass, SIGNAL_MESSAGE_REQUEST, self._request_messages)
dispatcher_connect(
self.hass, SIGNAL_CDR_REQUEST, self._request_cdr)
dispatcher_connect(
self.hass, SIGNAL_DISCOVER_PLATFORM, self._discover_platform)
# Only connect after signal connection to ensure we don't miss any
self.client = asteriskClient(host, port, password, self.handle_data)
@callback
def _discover_platform(self, component):
_LOGGER.debug("Adding mailbox %s", component)
self.hass.async_create_task(discovery.async_load_platform(
self.hass, "mailbox", component, {}, self.config))
@callback
def handle_data(self, command, msg):
"""Handle changes to the mailbox."""
from asterisk_mbox.commands import CMD_MESSAGE_LIST
from asterisk_mbox.commands import (CMD_MESSAGE_LIST,
CMD_MESSAGE_CDR_AVAILABLE,
CMD_MESSAGE_CDR)
if command == CMD_MESSAGE_LIST:
_LOGGER.debug("AsteriskVM sent updated message list")
_LOGGER.debug("AsteriskVM sent updated message list: Len %d",
len(msg))
old_messages = self.messages
self.messages = sorted(
msg, key=lambda item: item['info']['origtime'], reverse=True)
async_dispatcher_send(
self.hass, SIGNAL_MESSAGE_UPDATE, self.messages)
if not isinstance(old_messages, list):
async_dispatcher_send(self.hass, SIGNAL_DISCOVER_PLATFORM,
DOMAIN)
async_dispatcher_send(self.hass, SIGNAL_MESSAGE_UPDATE,
self.messages)
elif command == CMD_MESSAGE_CDR:
_LOGGER.debug("AsteriskVM sent updated CDR list: Len %d",
len(msg.get('entries', [])))
self.cdr = msg['entries']
async_dispatcher_send(self.hass, SIGNAL_CDR_UPDATE, self.cdr)
elif command == CMD_MESSAGE_CDR_AVAILABLE:
if not isinstance(self.cdr, list):
_LOGGER.debug("AsteriskVM adding CDR platform")
self.cdr = []
async_dispatcher_send(self.hass, SIGNAL_DISCOVER_PLATFORM,
"asterisk_cdr")
async_dispatcher_send(self.hass, SIGNAL_CDR_REQUEST)
else:
_LOGGER.debug("AsteriskVM sent unknown message '%d' len: %d",
command, len(msg))
@callback
def _request_messages(self):
"""Handle changes to the mailbox."""
_LOGGER.debug("Requesting message list")
self.client.messages()
@callback
def _request_cdr(self):
"""Handle changes to the CDR."""
_LOGGER.debug("Requesting CDR list")
self.client.get_cdr()

View File

@@ -1,8 +1,27 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "No hi ha serveis de notificaci\u00f3 disponibles."
},
"error": {
"invalid_code": "Codi inv\u00e0lid, si us plau torni a provar-ho."
},
"step": {
"init": {
"description": "Seleccioneu un dels serveis de notificaci\u00f3:",
"title": "Configureu una contrasenya d'un sol \u00fas a trav\u00e9s del component de notificacions"
},
"setup": {
"description": "**notify.{notify_service}** ha enviat una contrasenya d'un sol \u00fas. Introdu\u00efu-la a continuaci\u00f3:",
"title": "Verifiqueu la configuraci\u00f3"
}
},
"title": "Contrasenya d'un sol \u00fas del servei de notificacions"
},
"totp": {
"error": {
"invalid_code": "Codi no v\u00e0lid, si us plau torni a provar-ho. Si obteniu aquest error repetidament, assegureu-vos que la data i hora de Home Assistant sigui correcta i precisa."
"invalid_code": "Codi inv\u00e0lid, si us plau torni a provar-ho. Si obteniu aquest error repetidament, assegureu-vos que la data i hora de Home Assistant sigui correcta i precisa."
},
"step": {
"init": {

View File

@@ -1,8 +1,27 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Keine Benachrichtigungsdienste verf\u00fcgbar."
},
"error": {
"invalid_code": "Ung\u00fcltiger Code, bitte versuche es erneut."
},
"step": {
"init": {
"description": "Bitte w\u00e4hle einen der Benachrichtigungsdienste:",
"title": "Einmal Passwort f\u00fcr Notify einrichten"
},
"setup": {
"description": "Ein Einmal-Passwort wurde per ** notify gesendet. {notify_service} **. Bitte gebe es unten ein:",
"title": "\u00dcberpr\u00fcfe das Setup"
}
},
"title": "Benachrichtig f\u00fcr One-Time Password"
},
"totp": {
"error": {
"invalid_code": "Ung\u00fcltiger Code, bitte versuche es erneut. Wenn Sie diesen Fehler regelm\u00e4\u00dfig erhalten, stelle sicher, dass die Uhr deines Home Assistant-Systems korrekt ist."
"invalid_code": "Ung\u00fcltiger Code, bitte versuche es erneut. Wenn du diesen Fehler regelm\u00e4\u00dfig erhalten, stelle sicher, dass die Uhr deines Home Assistant-Systems korrekt ist."
},
"step": {
"init": {

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "No notification services available."
},
"error": {
"invalid_code": "Invalid code, please try again."
},
"step": {
"init": {
"description": "Please select one of the notification services:",
"title": "Set up one-time password delivered by notify component"
},
"setup": {
"description": "A one-time password has been sent via **notify.{notify_service}**. Please enter it below:",
"title": "Verify setup"
}
},
"title": "Notify One-Time Password"
},
"totp": {
"error": {
"invalid_code": "Invalid code, please try again. If you get this error consistently, please make sure the clock of your Home Assistant system is accurate."

View File

@@ -1,8 +1,15 @@
{
"mfa_setup": {
"notify": {
"step": {
"setup": {
"description": "Un mot de passe unique a \u00e9t\u00e9 envoy\u00e9 par **notify.{notify_service}**. Veuillez le saisir ci-dessous :"
}
}
},
"totp": {
"error": {
"invalid_code": "Code invalide. S'il vous pla\u00eet essayez \u00e0 nouveau. Si cette erreur persiste, assurez-vous que l'horloge de votre syst\u00e8me Home Assistant est correcte."
"invalid_code": "Code invalide. Veuillez essayez \u00e0 nouveau. Si cette erreur persiste, assurez-vous que l'horloge de votre syst\u00e8me Home Assistant est correcte."
},
"step": {
"init": {

View File

@@ -0,0 +1,35 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "\u05d0\u05d9\u05df \u05e9\u05d9\u05e8\u05d5\u05ea\u05d9 notify \u05d6\u05de\u05d9\u05e0\u05d9\u05dd."
},
"error": {
"invalid_code": "\u05e7\u05d5\u05d3 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9, \u05d0\u05e0\u05d0 \u05e0\u05e1\u05d4 \u05e9\u05d5\u05d1."
},
"step": {
"init": {
"description": "\u05d1\u05d7\u05e8 \u05d0\u05ea \u05d0\u05d7\u05d3 \u05de\u05e9\u05e8\u05d5\u05ea\u05d9 notify",
"title": "\u05d4\u05d2\u05d3\u05e8 \u05e1\u05d9\u05e1\u05de\u05d4 \u05d7\u05d3 \u05e4\u05e2\u05de\u05d9\u05ea \u05d4\u05e0\u05e9\u05dc\u05d7\u05ea \u05e2\u05dc \u05d9\u05d3\u05d9 \u05e8\u05db\u05d9\u05d1 notify"
},
"setup": {
"description": "\u05e1\u05d9\u05e1\u05de\u05d4 \u05d7\u05d3 \u05e4\u05e2\u05de\u05d9\u05ea \u05e0\u05e9\u05dc\u05d7\u05d4 \u05e2\u05dc \u05d9\u05d3\u05d9 **{notify_service}**. \u05d4\u05d6\u05df \u05d0\u05d5\u05ea\u05d4 \u05dc\u05de\u05d8\u05d4:",
"title": "\u05d0\u05d9\u05de\u05d5\u05ea \u05d4\u05d4\u05ea\u05e7\u05e0\u05d4"
}
},
"title": "\u05dc\u05d4\u05d5\u05d3\u05d9\u05e2 \u200b\u200b\u05e2\u05dc \u05e1\u05d9\u05e1\u05de\u05d4 \u05d7\u05d3 \u05e4\u05e2\u05de\u05d9\u05ea"
},
"totp": {
"error": {
"invalid_code": "\u05e7\u05d5\u05d3 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9, \u05d0\u05e0\u05d0 \u05e0\u05e1\u05d4 \u05e9\u05d5\u05d1. \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e7\u05d1\u05dc \u05d0\u05ea \u05d4\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d4\u05d6\u05d5 \u05d1\u05d0\u05d5\u05e4\u05df \u05e2\u05e7\u05d1\u05d9, \u05d5\u05d3\u05d0 \u05e9\u05d4\u05e9\u05e2\u05d5\u05df \u05e9\u05dc \u05de\u05e2\u05e8\u05db\u05ea \u05d4 - Home Assistant \u05e9\u05dc\u05da \u05de\u05d3\u05d5\u05d9\u05e7."
},
"step": {
"init": {
"description": "\u05db\u05d3\u05d9 \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05d0\u05d9\u05de\u05d5\u05ea \u05d3\u05d5 \u05e9\u05dc\u05d1\u05d9 \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea \u05e1\u05d9\u05e1\u05de\u05d0\u05d5\u05ea \u05d7\u05d3 \u05e4\u05e2\u05de\u05d9\u05d5\u05ea \u05de\u05d1\u05d5\u05e1\u05e1\u05d5\u05ea \u05d6\u05de\u05df, \u05e1\u05e8\u05d5\u05e7 \u05d0\u05ea \u05e7\u05d5\u05d3 QR \u05e2\u05dd \u05d9\u05d9\u05e9\u05d5\u05dd \u05d4\u05d0\u05d9\u05de\u05d5\u05ea \u05e9\u05dc\u05da. \u05d0\u05dd \u05d0\u05d9\u05df \u05dc\u05da \u05d7\u05e9\u05d1\u05d5\u05df \u05db\u05d6\u05d4, \u05d0\u05e0\u05d5 \u05de\u05de\u05dc\u05d9\u05e6\u05d9\u05dd \u05e2\u05dc [Google Authenticator] (https://support.google.com/accounts/answer/1066447) \u05d0\u05d5 [Authy] (https://authy.com/). \n\n {qr_code} \n \n \u05dc\u05d0\u05d7\u05e8 \u05e1\u05e8\u05d9\u05e7\u05ea \u05d4\u05e7\u05d5\u05d3, \u05d4\u05d6\u05df \u05d0\u05ea \u05d4\u05e7\u05d5\u05d3 \u05d1\u05df \u05e9\u05e9 \u05d4\u05e1\u05e4\u05e8\u05d5\u05ea \u05de\u05d4\u05d0\u05e4\u05dc\u05d9\u05e7\u05e6\u05d9\u05d4 \u05e9\u05dc\u05da \u05db\u05d3\u05d9 \u05dc\u05d0\u05de\u05ea \u05d0\u05ea \u05d4\u05d4\u05d2\u05d3\u05e8\u05d4. \u05d0\u05dd \u05d0\u05ea\u05d4 \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d5\u05ea \u05d1\u05e1\u05e8\u05d9\u05e7\u05ea \u05e7\u05d5\u05d3 QR, \u05d1\u05e6\u05e2 \u05d4\u05d2\u05d3\u05e8\u05d4 \u05d9\u05d3\u05e0\u05d9\u05ea \u05e2\u05dd \u05e7\u05d5\u05d3 **`{code}`**.",
"title": "\u05d4\u05d2\u05d3\u05e8 \u05d0\u05d9\u05de\u05d5\u05ea \u05d3\u05d5 \u05e9\u05dc\u05d1\u05d9 \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea TOTP"
}
},
"title": "TOTP"
}
}
}

View File

@@ -1,5 +1,21 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Nincs el\u00e9rhet\u0151 \u00e9rtes\u00edt\u00e9si szolg\u00e1ltat\u00e1s."
},
"error": {
"invalid_code": "\u00c9rv\u00e9nytelen k\u00f3d, pr\u00f3b\u00e1ld \u00fajra."
},
"step": {
"init": {
"description": "V\u00e1lassz \u00e9rtes\u00edt\u00e9si szolg\u00e1ltat\u00e1st:"
},
"setup": {
"title": "Be\u00e1ll\u00edt\u00e1s ellen\u0151rz\u00e9se"
}
}
},
"totp": {
"error": {
"invalid_code": "\u00c9rv\u00e9nytelen k\u00f3d, pr\u00f3b\u00e1ld \u00fajra. Ha ez a hiba folyamatosan el\u0151fordul, akkor gy\u0151z\u0151dj meg r\u00f3la, hogy a Home Assistant rendszered \u00f3r\u00e1ja pontosan j\u00e1r."

View File

@@ -0,0 +1,16 @@
{
"mfa_setup": {
"totp": {
"error": {
"invalid_code": "Kode salah, coba lagi. Jika Anda mendapatkan kesalahan ini secara konsisten, pastikan jam pada sistem Home Assistant anda akurat."
},
"step": {
"init": {
"description": "Untuk mengaktifkan otentikasi dua faktor menggunakan password satu kali berbasis waktu, pindai kode QR dengan aplikasi otentikasi Anda. Jika Anda tidak memilikinya, kami menyarankan [Google Authenticator] (https://support.google.com/accounts/answer/1066447) atau [Authy] (https://authy.com/). \n\n {qr_code} \n \n Setelah memindai kode, masukkan kode enam digit dari aplikasi Anda untuk memverifikasi pengaturan. Jika Anda mengalami masalah saat memindai kode QR, lakukan pengaturan manual dengan kode ** ` {code} ` **.",
"title": "Siapkan otentikasi dua faktor menggunakan TOTP"
}
},
"title": "TOTP"
}
}
}

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "\uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc54c\ub9bc \uc11c\ube44\uc2a4\uac00 \uc5c6\uc2b5\ub2c8\ub2e4."
},
"error": {
"invalid_code": "\uc798\ubabb\ub41c \ucf54\ub4dc\uc785\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\ub3c4\ud574\uc8fc\uc138\uc694."
},
"step": {
"init": {
"description": "\uc54c\ub9bc \uc11c\ube44\uc2a4 \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud574\uc8fc\uc138\uc694:",
"title": "\uc54c\ub9bc \uad6c\uc131\uc694\uc18c\uac00 \uc81c\uacf5\ud558\ub294 \uc77c\ud68c\uc6a9 \ube44\ubc00\ubc88\ud638 \uc124\uc815"
},
"setup": {
"description": "**notify.{notify_service}** \uc5d0\uc11c \uc77c\ud68c\uc6a9 \ube44\ubc00\ubc88\ud638\ub97c \ubcf4\ub0c8\uc2b5\ub2c8\ub2e4. \uc544\ub798\uc758 \uacf5\ub780\uc5d0 \uc785\ub825\ud574 \uc8fc\uc138\uc694:",
"title": "\uc124\uc815 \ud655\uc778"
}
},
"title": "\uc77c\ud68c\uc6a9 \ube44\ubc00\ubc88\ud638 \uc54c\ub9bc"
},
"totp": {
"error": {
"invalid_code": "\uc798\ubabb\ub41c \ucf54\ub4dc \uc785\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\ub3c4\ud574\uc8fc\uc138\uc694. \uc774 \uc624\ub958\uac00 \uc9c0\uc18d\uc801\uc73c\ub85c \ubc1c\uc0dd\ud55c\ub2e4\uba74 Home Assistant \uc758 \uc2dc\uac04\uc124\uc815\uc774 \uc62c\ubc14\ub978\uc9c0 \ud655\uc778\ud574\ubcf4\uc138\uc694."
@@ -7,7 +26,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.",
"title": "TOTP \ub97c \uc0ac\uc6a9\ud558\uc5ec 2 \ub2e8\uacc4 \uc778\uc99d \uad6c\uc131"
"title": "TOTP \ub97c \uc0ac\uc6a9\ud558\uc5ec 2\ub2e8\uacc4 \uc778\uc99d \uad6c\uc131"
}
},
"title": "TOTP (\uc2dc\uac04 \uae30\ubc18 OTP)"

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Keen Notifikatioun's D\u00e9ngscht disponibel."
},
"error": {
"invalid_code": "Ong\u00ebltege Code, prob\u00e9iert w.e.g. nach emol."
},
"step": {
"init": {
"description": "Wielt w.e.g. een Notifikatioun's D\u00e9ngscht aus:",
"title": "Eemolegt Passwuert ariichte wat vun engem Notifikatioun's Komponente versch\u00e9ckt g\u00ebtt"
},
"setup": {
"description": "Een eemolegt Passwuert ass vun **notify.{notify_service}** gesch\u00e9ckt ginn. Gitt et w.e.g hei \u00ebnnen dr\u00ebnner an:",
"title": "Astellungen iwwerpr\u00e9iwen"
}
},
"title": "Eemolegt Passwuert Notifikatioun"
},
"totp": {
"error": {
"invalid_code": "Ong\u00ebltege Login, prob\u00e9iert w.e.g. nach emol. Falls d\u00ebse Feeler Message \u00ebmmer er\u00ebm optr\u00ebtt dann iwwerpr\u00e9ift op d'Z\u00e4it vum Home Assistant System richteg ass."

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Geen meldingsservices beschikbaar."
},
"error": {
"invalid_code": "Ongeldige code, probeer opnieuw."
},
"step": {
"init": {
"description": "Selecteer een van de meldingsdiensten:",
"title": "Stel een \u00e9\u00e9nmalig wachtwoord in dat wordt afgegeven door een meldingscomponent"
},
"setup": {
"description": "Een \u00e9\u00e9nmalig wachtwoord is verzonden via **notify. {notify_service}**. Voer het hieronder in:",
"title": "Controleer de instellingen"
}
},
"title": "Eenmalig wachtwoord melden"
},
"totp": {
"error": {
"invalid_code": "Ongeldige code, probeer het opnieuw. Als u deze fout blijft krijgen, controleer dan of de klok van uw Home Assistant systeem correct is ingesteld."

View File

@@ -0,0 +1,16 @@
{
"mfa_setup": {
"totp": {
"error": {
"invalid_code": "Ugyldig kode, pr\u00f8v igjen. Dersom du heile tida f\u00e5r denne feilen, m\u00e5 du s\u00f8rge for at klokka p\u00e5 Home Assistant-systemet ditt er n\u00f8yaktig."
},
"step": {
"init": {
"description": "For \u00e5 aktivere tofaktorautentisering ved hjelp av tidsbaserte eingangspassord, skann QR-koden med autentiseringsappen din. Dersom du ikkje har ein, vil vi r\u00e5de deg til \u00e5 bruke anten [Google Authenticator] (https://support.google.com/accounts/answer/1066447) eller [Authy] (https://authy.com/). \n\n {qr_code} \n \nN\u00e5r du har skanna koda, skriv du inn den sekssifra koda fr\u00e5 appen din for \u00e5 stadfeste oppsettet. Dersom du har problemer med \u00e5 skanne QR-koda, gjer du eit manuelt oppsett med kode ** ` {code} ` **.",
"title": "Konfigurer to-faktor-autentisering ved hjelp av TOTP"
}
},
"title": "TOTP"
}
}
}

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Ingen varslingstjenester er tilgjengelig."
},
"error": {
"invalid_code": "Ugyldig kode, vennligst pr\u00f8v igjen."
},
"step": {
"init": {
"description": "Vennligst velg en av varslingstjenestene:",
"title": "Sett opp engangspassord levert av varsel komponent"
},
"setup": {
"description": "Et engangspassord har blitt sendt via **notify.{notify_service}**. Vennligst skriv det inn nedenfor:",
"title": "Bekreft oppsettet"
}
},
"title": "Varsle engangspassord"
},
"totp": {
"error": {
"invalid_code": "Ugyldig kode, pr\u00f8v igjen. Hvis du f\u00e5r denne feilen konsekvent, m\u00e5 du s\u00f8rge for at klokken p\u00e5 Home Assistant systemet er riktig."

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Brak dost\u0119pnych us\u0142ug powiadamiania."
},
"error": {
"invalid_code": "Nieprawid\u0142owy kod, spr\u00f3buj ponownie."
},
"step": {
"init": {
"description": "Prosz\u0119 wybra\u0107 jedn\u0105 z us\u0142ugi powiadamiania:",
"title": "Skonfiguruj has\u0142o jednorazowe dostarczone przez komponent powiadomie\u0144"
},
"setup": {
"description": "Has\u0142o jednorazowe zosta\u0142o wys\u0142ane przez **notify.{notify_service}**. Wpisz je poni\u017cej:",
"title": "Sprawd\u017a konfiguracj\u0119"
}
},
"title": "Powiadomienie z has\u0142em jednorazowym"
},
"totp": {
"error": {
"invalid_code": "Nieprawid\u0142owy kod, spr\u00f3buj ponownie. Je\u015bli b\u0142\u0105d b\u0119dzie si\u0119 powtarza\u0142, upewnij si\u0119, \u017ce czas zegara systemu Home Assistant jest prawid\u0142owy."

View File

@@ -0,0 +1,15 @@
{
"mfa_setup": {
"totp": {
"error": {
"invalid_code": "C\u00f3digo inv\u00e1lido, por favor tente novamente. Se voc\u00ea obtiver este erro de forma consistente, certifique-se de que o rel\u00f3gio do sistema Home Assistant esteja correto."
},
"step": {
"init": {
"title": "Configure a autentica\u00e7\u00e3o de dois fatores usando o TOTP"
}
},
"title": "TOTP"
}
}
}

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Nenhum servi\u00e7o de notifica\u00e7\u00e3o dispon\u00edvel."
},
"error": {
"invalid_code": "C\u00f3digo inv\u00e1lido, por favor tente novamente."
},
"step": {
"init": {
"description": "Por favor, selecione um dos servi\u00e7os de notifica\u00e7\u00e3o:",
"title": "Configurar uma palavra passe entregue pela componente de notifica\u00e7\u00e3o"
},
"setup": {
"description": "Foi enviada uma palavra passe atrav\u00e9s de **notify.{notify_service}**. Por favor, insira-a:",
"title": "Verificar a configura\u00e7\u00e3o"
}
},
"title": "Notificar palavra passe de uso \u00fanico"
},
"totp": {
"error": {
"invalid_code": "C\u00f3digo inv\u00e1lido, por favor, tente novamente. Se receber este erro constantemente, por favor, certifique-se de que o rel\u00f3gio do sistema que hospeda o Home Assistent \u00e9 preciso."

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u043b\u0443\u0436\u0431 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439."
},
"error": {
"invalid_code": "\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443."
},
"step": {
"init": {
"description": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0434\u043d\u0443 \u0438\u0437 \u0441\u043b\u0443\u0436\u0431 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439:",
"title": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439"
},
"setup": {
"description": "\u041e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0447\u0435\u0440\u0435\u0437 **notify.{notify_service}**. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u043d\u0438\u0436\u0435:",
"title": "\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443"
}
},
"title": "\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0430\u0440\u043e\u043b\u0435\u0439"
},
"totp": {
"error": {
"invalid_code": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0434. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u044d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0447\u0430\u0441\u044b \u0432 \u0432\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 Home Assistant \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f."

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Ni na voljo storitev obve\u0161\u010danja."
},
"error": {
"invalid_code": "Neveljavna koda, poskusite znova."
},
"step": {
"init": {
"description": "Prosimo, izberite eno od storitev obve\u0161\u010danja:",
"title": "Nastavite enkratno geslo, ki ga dostavite z obvestilno komponento"
},
"setup": {
"description": "Enkratno geslo je poslal **notify.{notify_service} **. Vnesite ga spodaj:",
"title": "Preverite nastavitev"
}
},
"title": "Obvesti Enkratno Geslo"
},
"totp": {
"error": {
"invalid_code": "Neveljavna koda, prosimo, poskusite znova. \u010ce dobite to sporo\u010dilo ve\u010dkrat, prosimo poskrbite, da bo ura va\u0161ega Home Assistenta to\u010dna."

View File

@@ -1,5 +1,19 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Inga tillg\u00e4ngliga meddelande tj\u00e4nster."
},
"error": {
"invalid_code": "Ogiltig kod, var god f\u00f6rs\u00f6k igen."
},
"step": {
"setup": {
"description": "Ett eng\u00e5ngsl\u00f6senord har skickats av **notify.{notify_service}**. V\u00e4nligen ange det nedan:",
"title": "Verifiera installationen"
}
}
},
"totp": {
"error": {
"invalid_code": "Ogiltig kod, f\u00f6rs\u00f6k igen. Om du flera g\u00e5nger i rad f\u00e5r detta fel, se till att klockan i din Home Assistant \u00e4r korrekt inst\u00e4lld."

View File

@@ -1,5 +1,24 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "\u6ca1\u6709\u53ef\u7528\u7684\u901a\u77e5\u670d\u52a1\u3002"
},
"error": {
"invalid_code": "\u4ee3\u7801\u65e0\u6548\uff0c\u8bf7\u518d\u8bd5\u4e00\u6b21\u3002"
},
"step": {
"init": {
"description": "\u8bf7\u4ece\u4e0b\u9762\u9009\u62e9\u4e00\u4e2a\u901a\u77e5\u670d\u52a1\uff1a",
"title": "\u8bbe\u7f6e\u7531\u901a\u77e5\u7ec4\u4ef6\u4f20\u9012\u7684\u4e00\u6b21\u6027\u5bc6\u7801"
},
"setup": {
"description": "\u4e00\u6b21\u6027\u5bc6\u7801\u5df2\u7531 **notify.{notify_service}** \u53d1\u9001\u3002\u8bf7\u5728\u4e0b\u9762\u8f93\u5165\uff1a",
"title": "\u9a8c\u8bc1\u8bbe\u7f6e"
}
},
"title": "\u4e00\u6b21\u6027\u5bc6\u7801\u901a\u77e5"
},
"totp": {
"error": {
"invalid_code": "\u53e3\u4ee4\u65e0\u6548\uff0c\u8bf7\u91cd\u65b0\u8f93\u5165\u3002\u5982\u679c\u9519\u8bef\u53cd\u590d\u51fa\u73b0\uff0c\u8bf7\u786e\u4fdd Home Assistant \u7cfb\u7edf\u7684\u65f6\u95f4\u51c6\u786e\u65e0\u8bef\u3002"

View File

@@ -1,12 +1,31 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "\u6c92\u6709\u53ef\u7528\u7684\u901a\u77e5\u670d\u52d9\u3002"
},
"error": {
"invalid_code": "\u9a57\u8b49\u78bc\u7121\u6548\uff0c\u8acb\u518d\u8a66\u4e00\u6b21\u3002"
},
"step": {
"init": {
"description": "\u8acb\u9078\u64c7\u4e00\u9805\u901a\u77e5\u670d\u52d9\uff1a",
"title": "\u8a2d\u5b9a\u4e00\u6b21\u6027\u5bc6\u78bc\u50b3\u9001\u7d44\u4ef6"
},
"setup": {
"description": "\u4e00\u6b21\u6027\u5bc6\u78bc\u5df2\u900f\u904e **notify.{notify_service}** \u50b3\u9001\u3002\u8acb\u65bc\u4e0b\u65b9\u8f38\u5165\uff1a",
"title": "\u9a57\u8b49\u8a2d\u5b9a"
}
},
"title": "\u901a\u77e5\u4e00\u6b21\u6027\u5bc6\u78bc"
},
"totp": {
"error": {
"invalid_code": "\u9a57\u8b49\u78bc\u7121\u6548\uff0c\u8acb\u518d\u8a66\u4e00\u6b21\u3002\u5047\u5982\u932f\u8aa4\u6301\u7e8c\u767c\u751f\uff0c\u8acb\u5148\u78ba\u5b9a\u60a8\u7684 Home Assistant \u7cfb\u7d71\u4e0a\u7684\u6642\u9593\u8a2d\u5b9a\u6b63\u78ba\u5f8c\uff0c\u518d\u8a66\u4e00\u6b21\u3002"
},
"step": {
"init": {
"description": "\u6b32\u555f\u7528\u4e00\u6b21\u6027\u4e14\u5177\u6642\u6548\u6027\u7684\u5bc6\u78bc\u4e4b\u5169\u6b65\u9a5f\u9a57\u8b49\u529f\u80fd\uff0c\u8acb\u4f7f\u7528\u60a8\u7684\u9a57\u8b49 App \u6383\u7784\u4e0b\u65b9\u7684 QR code \u3002\u5018\u82e5\u60a8\u5c1a\u672a\u5b89\u88dd\u4efb\u4f55 App\uff0c\u63a8\u85a6\u60a8\u4f7f\u7528 [Google Authenticator](https://support.google.com/accounts/answer/1066447) \u6216 [Authy](https://authy.com/)\u3002\n\n{qr_code}\n\n\u65bc\u6383\u63cf\u4e4b\u5f8c\uff0c\u8f38\u5165 App \u4e2d\u7684\u516d\u4f4d\u6578\u5b57\u9032\u884c\u8a2d\u5b9a\u9a57\u8b49\u3002\u5047\u5982\u6383\u63cf\u51fa\u73fe\u554f\u984c\uff0c\u8acb\u624b\u52d5\u8f38\u5165\u4ee5\u4e0b\u9a57\u8b49\u78bc **`{code}`**\u3002",
"description": "\u6b32\u555f\u7528\u4e00\u6b21\u6027\u4e14\u5177\u6642\u6548\u6027\u7684\u5bc6\u78bc\u4e4b\u5169\u6b65\u9a5f\u9a57\u8b49\u529f\u80fd\uff0c\u8acb\u4f7f\u7528\u60a8\u7684\u9a57\u8b49 App \u6383\u7784\u4e0b\u65b9\u7684 QR code \u3002\u5018\u82e5\u60a8\u5c1a\u672a\u5b89\u88dd\u4efb\u4f55 App\uff0c\u63a8\u85a6\u60a8\u4f7f\u7528 [Google Authenticator](https://support.google.com/accounts/answer/1066447) \u6216 [Authy](https://authy.com/)\u3002\n\n{qr_code}\n\n\u65bc\u641c\u5c0b\u4e4b\u5f8c\uff0c\u8f38\u5165 App \u4e2d\u7684\u516d\u4f4d\u6578\u5b57\u9032\u884c\u8a2d\u5b9a\u9a57\u8b49\u3002\u5047\u5982\u641c\u5c0b\u51fa\u73fe\u554f\u984c\uff0c\u8acb\u624b\u52d5\u8f38\u5165\u4ee5\u4e0b\u9a57\u8b49\u78bc **`{code}`**\u3002",
"title": "\u4f7f\u7528 TOTP \u8a2d\u5b9a\u5169\u6b65\u9a5f\u9a57\u8b49"
}
},

View File

@@ -105,7 +105,6 @@ Home Assistant. User need to record the token in secure place.
"id": 11,
"type": "auth/long_lived_access_token",
"client_name": "GPS Logger",
"client_icon": null,
"lifespan": 365
}
@@ -433,7 +432,7 @@ def websocket_current_user(
"""Get current user."""
enabled_modules = await hass.auth.async_get_enabled_mfa(user)
connection.send_message_outside(
connection.send_message(
websocket_api.result_message(msg['id'], {
'id': user.id,
'name': user.name,
@@ -468,7 +467,7 @@ def websocket_create_long_lived_access_token(
access_token = hass.auth.async_create_access_token(
refresh_token)
connection.send_message_outside(
connection.send_message(
websocket_api.result_message(msg['id'], access_token))
hass.async_create_task(
@@ -480,8 +479,8 @@ def websocket_create_long_lived_access_token(
def websocket_refresh_tokens(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
"""Return metadata of users refresh tokens."""
current_id = connection.request.get('refresh_token_id')
connection.to_write.put_nowait(websocket_api.result_message(msg['id'], [{
current_id = connection.refresh_token_id
connection.send_message(websocket_api.result_message(msg['id'], [{
'id': refresh.id,
'client_id': refresh.client_id,
'client_name': refresh.client_name,
@@ -509,7 +508,7 @@ def websocket_delete_refresh_token(
await hass.auth.async_remove_refresh_token(refresh_token)
connection.send_message_outside(
connection.send_message(
websocket_api.result_message(msg['id'], {}))
hass.async_create_task(

View File

@@ -1,24 +1,13 @@
"""Helpers to resolve client ID/secret."""
import asyncio
from ipaddress import ip_address
from html.parser import HTMLParser
from ipaddress import ip_address, ip_network
from urllib.parse import urlparse, urljoin
import aiohttp
from aiohttp.client_exceptions import ClientError
# IP addresses of loopback interfaces
ALLOWED_IPS = (
ip_address('127.0.0.1'),
ip_address('::1'),
)
# RFC1918 - Address allocation for Private Internets
ALLOWED_NETWORKS = (
ip_network('10.0.0.0/8'),
ip_network('172.16.0.0/12'),
ip_network('192.168.0.0/16'),
)
from homeassistant.util.network import is_local
async def verify_redirect_uri(hass, client_id, redirect_uri):
@@ -185,9 +174,7 @@ def _parse_client_id(client_id):
# Not an ip address
pass
if (address is None or
address in ALLOWED_IPS or
any(address in network for network in ALLOWED_NETWORKS)):
if address is None or is_local(address):
return parts
raise ValueError('Hostname should be a domain name or local IP address')

View File

@@ -226,8 +226,9 @@ class LoginFlowResourceView(HomeAssistantView):
if result['type'] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
# @log_invalid_auth does not work here since it returns HTTP 200
# need manually log failed login attempts
if result['errors'] is not None and \
result['errors'].get('base') == 'invalid_auth':
if (result.get('errors') is not None and
result['errors'].get('base') in ['invalid_auth',
'invalid_code']):
await process_wrong_login(request)
return self.json(_prepare_result_json(result))

View File

@@ -64,7 +64,7 @@ def websocket_setup_mfa(
if flow_id is not None:
result = await flow_manager.async_configure(
flow_id, msg.get('user_input'))
connection.send_message_outside(
connection.send_message(
websocket_api.result_message(
msg['id'], _prepare_result_json(result)))
return
@@ -72,7 +72,7 @@ def websocket_setup_mfa(
mfa_module_id = msg.get('mfa_module_id')
mfa_module = hass.auth.get_auth_mfa_module(mfa_module_id)
if mfa_module is None:
connection.send_message_outside(websocket_api.error_message(
connection.send_message(websocket_api.error_message(
msg['id'], 'no_module',
'MFA module {} is not found'.format(mfa_module_id)))
return
@@ -80,7 +80,7 @@ def websocket_setup_mfa(
result = await flow_manager.async_init(
mfa_module_id, data={'user_id': connection.user.id})
connection.send_message_outside(
connection.send_message(
websocket_api.result_message(
msg['id'], _prepare_result_json(result)))
@@ -99,13 +99,13 @@ def websocket_depose_mfa(
await hass.auth.async_disable_user_mfa(
connection.user, msg['mfa_module_id'])
except ValueError as err:
connection.send_message_outside(websocket_api.error_message(
connection.send_message(websocket_api.error_message(
msg['id'], 'disable_failed',
'Cannot disable MFA Module {}: {}'.format(
mfa_module_id, err)))
return
connection.send_message_outside(
connection.send_message(
websocket_api.result_message(
msg['id'], 'done'))

View File

@@ -11,6 +11,25 @@
"error": {
"invalid_code": "Invalid code, please try again. If you get this error consistently, please make sure the clock of your Home Assistant system is accurate."
}
},
"notify": {
"title": "Notify One-Time Password",
"step": {
"init": {
"title": "Set up one-time password delivered by notify component",
"description": "Please select one of the notification services:"
},
"setup": {
"title": "Verify setup",
"description": "A one-time password has been sent via **notify.{notify_service}**. Please enter it below:"
}
},
"abort": {
"no_available_service": "No notification services available."
},
"error": {
"invalid_code": "Invalid code, please try again."
}
}
}
}

View File

@@ -17,7 +17,6 @@ from homeassistant.loader import bind_hass
from homeassistant.const import (
ATTR_ENTITY_ID, CONF_PLATFORM, STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF,
SERVICE_TOGGLE, SERVICE_RELOAD, EVENT_HOMEASSISTANT_START, CONF_ID)
from homeassistant.components import logbook
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import extract_domain_configs, script, condition
from homeassistant.helpers.entity import ToggleEntity
@@ -115,49 +114,6 @@ def is_on(hass, entity_id):
return hass.states.is_state(entity_id, STATE_ON)
@bind_hass
def turn_on(hass, entity_id=None):
"""Turn on specified automation or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TURN_ON, data)
@bind_hass
def turn_off(hass, entity_id=None):
"""Turn off specified automation or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TURN_OFF, data)
@bind_hass
def toggle(hass, entity_id=None):
"""Toggle specified automation or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TOGGLE, data)
@bind_hass
def trigger(hass, entity_id=None):
"""Trigger specified automation or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TRIGGER, data)
@bind_hass
def reload(hass):
"""Reload the automation from config."""
hass.services.call(DOMAIN, SERVICE_RELOAD)
@bind_hass
def async_reload(hass):
"""Reload the automation from config.
Returns a coroutine object.
"""
return hass.services.async_call(DOMAIN, SERVICE_RELOAD)
async def async_setup(hass, config):
"""Set up the automation."""
component = EntityComponent(_LOGGER, DOMAIN, hass,
@@ -412,8 +368,8 @@ def _async_get_action(hass, config, name):
async def action(entity_id, variables, context):
"""Execute an action."""
_LOGGER.info('Executing %s', name)
logbook.async_log_entry(
hass, name, 'has been triggered', DOMAIN, entity_id)
hass.components.logbook.async_log_entry(
name, 'has been triggered', DOMAIN, entity_id)
await script_obj.async_run(variables, context)
return action

View File

@@ -4,7 +4,6 @@ Offer event listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#event-trigger
"""
import asyncio
import logging
import voluptuous as vol
@@ -25,8 +24,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
event_type = config.get(CONF_EVENT_TYPE)
event_data_schema = vol.Schema(

View File

@@ -4,7 +4,6 @@ Offer Home Assistant core automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#homeassistant-trigger
"""
import asyncio
import logging
import voluptuous as vol
@@ -23,8 +22,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
event = config.get(CONF_EVENT)

View File

@@ -4,7 +4,6 @@ Trigger an automation when a LiteJet switch is released.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/automation.litejet/
"""
import asyncio
import logging
import voluptuous as vol
@@ -33,8 +32,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
number = config.get(CONF_NUMBER)
held_more_than = config.get(CONF_HELD_MORE_THAN)

View File

@@ -4,7 +4,6 @@ Offer MQTT listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#mqtt-trigger
"""
import asyncio
import json
import voluptuous as vol
@@ -25,8 +24,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
topic = config.get(CONF_TOPIC)
payload = config.get(CONF_PAYLOAD)
@@ -51,6 +49,6 @@ def async_trigger(hass, config, action):
'trigger': data
})
remove = yield from mqtt.async_subscribe(
remove = await mqtt.async_subscribe(
hass, topic, mqtt_automation_listener)
return remove

View File

@@ -4,7 +4,6 @@ Offer numeric state listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#numeric-state-trigger
"""
import asyncio
import logging
import voluptuous as vol
@@ -29,8 +28,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
_LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
below = config.get(CONF_BELOW)

View File

@@ -4,7 +4,6 @@ Offer state listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#state-trigger
"""
import asyncio
import voluptuous as vol
from homeassistant.core import callback
@@ -27,8 +26,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
}), cv.key_dependency(CONF_FOR, CONF_TO))
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
from_state = config.get(CONF_FROM, MATCH_ALL)

View File

@@ -4,7 +4,6 @@ Offer sun based automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#sun-trigger
"""
import asyncio
from datetime import timedelta
import logging
@@ -25,8 +24,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
event = config.get(CONF_EVENT)
offset = config.get(CONF_OFFSET)

View File

@@ -4,7 +4,6 @@ Offer template automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#template-trigger
"""
import asyncio
import logging
import voluptuous as vol
@@ -23,8 +22,7 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
value_template = config.get(CONF_VALUE_TEMPLATE)
value_template.hass = hass

View File

@@ -4,7 +4,6 @@ Offer time listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#time-trigger
"""
import asyncio
import logging
import voluptuous as vol
@@ -29,8 +28,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
}), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AT))
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
if CONF_AT in config:
at_time = config.get(CONF_AT)

View File

@@ -4,7 +4,6 @@ Offer zone automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/docs/automation/trigger/#zone-trigger
"""
import asyncio
import voluptuous as vol
from homeassistant.core import callback
@@ -27,8 +26,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
async def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
zone_entity_id = config.get(CONF_ZONE)

View File

@@ -4,7 +4,6 @@ Support for ADS binary sensors.
For more details about this platform, please refer to the documentation.
https://home-assistant.io/components/binary_sensor.ads/
"""
import asyncio
import logging
import voluptuous as vol
@@ -50,8 +49,7 @@ class AdsBinarySensor(BinarySensorDevice):
self._ads_hub = ads_hub
self.ads_var = ads_var
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register device notification."""
def update(name, value):
"""Handle device notifications."""

View File

@@ -4,7 +4,6 @@ Support for AlarmDecoder zone states- represented as binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.alarmdecoder/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
@@ -64,8 +63,7 @@ class AlarmDecoderBinarySensor(BinarySensorDevice):
self._relay_addr = relay_addr
self._relay_chan = relay_chan
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
self.hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_ZONE_FAULT, self._fault_callback)

View File

@@ -4,8 +4,6 @@ Support for IP Webcam binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.android_ip_webcam/
"""
import asyncio
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.android_ip_webcam import (
KEY_MAP, DATA_IP_WEBCAM, AndroidIPCamEntity, CONF_HOST, CONF_NAME)
@@ -13,9 +11,8 @@ from homeassistant.components.android_ip_webcam import (
DEPENDENCIES = ['android_ip_webcam']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the IP Webcam binary sensors."""
if discovery_info is None:
return
@@ -51,8 +48,7 @@ class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice):
"""Return true if the binary sensor is on."""
return self._state
@asyncio.coroutine
def async_update(self):
async def async_update(self):
"""Retrieve latest state."""
state, _ = self._ipcam.export_sensor(self._sensor)
self._state = state == 1.0

View File

@@ -4,7 +4,6 @@ Use Bayesian Inference to trigger a binary sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.bayesian/
"""
import asyncio
import logging
from collections import OrderedDict
@@ -74,9 +73,8 @@ def update_probability(prior, prob_true, prob_false):
return probability
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the Bayesian Binary sensor."""
name = config.get(CONF_NAME)
observations = config.get(CONF_OBSERVATIONS)
@@ -119,8 +117,7 @@ class BayesianBinarySensor(BinarySensorDevice):
'state': self._process_state
}
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Call when entity about to be added."""
@callback
def async_threshold_sensor_state_listener(entity, old_state,
@@ -214,7 +211,6 @@ class BayesianBinarySensor(BinarySensorDevice):
ATTR_PROBABILITY_THRESHOLD: self._probability_threshold,
}
@asyncio.coroutine
def async_update(self):
async def async_update(self):
"""Get the latest data and update the states."""
self._deviation = bool(self.probability >= self._probability_threshold)

View File

@@ -2,10 +2,11 @@
Support for Blink system camera control.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.blink/
https://home-assistant.io/components/binary_sensor.blink.
"""
from homeassistant.components.blink import DOMAIN
from homeassistant.components.blink import BLINK_DATA, BINARY_SENSORS
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import CONF_MONITORED_CONDITIONS
DEPENDENCIES = ['blink']
@@ -14,24 +15,27 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the blink binary sensors."""
if discovery_info is None:
return
data = hass.data[BLINK_DATA]
data = hass.data[DOMAIN].blink
devs = list()
for name in data.cameras:
devs.append(BlinkCameraMotionSensor(name, data))
devs.append(BlinkSystemSensor(data))
devs = []
for camera in data.sync.cameras:
for sensor_type in discovery_info[CONF_MONITORED_CONDITIONS]:
devs.append(BlinkBinarySensor(data, camera, sensor_type))
add_entities(devs, True)
class BlinkCameraMotionSensor(BinarySensorDevice):
class BlinkBinarySensor(BinarySensorDevice):
"""Representation of a Blink binary sensor."""
def __init__(self, name, data):
def __init__(self, data, camera, sensor_type):
"""Initialize the sensor."""
self._name = 'blink_' + name + '_motion_enabled'
self._camera_name = name
self.data = data
self._state = self.data.cameras[self._camera_name].armed
self._type = sensor_type
name, icon = BINARY_SENSORS[sensor_type]
self._name = "{} {} {}".format(BLINK_DATA, camera, name)
self._icon = icon
self._camera = data.sync.cameras[camera]
self._state = None
@property
def name(self):
@@ -46,29 +50,4 @@ class BlinkCameraMotionSensor(BinarySensorDevice):
def update(self):
"""Update sensor state."""
self.data.refresh()
self._state = self.data.cameras[self._camera_name].armed
class BlinkSystemSensor(BinarySensorDevice):
"""A representation of a Blink system sensor."""
def __init__(self, data):
"""Initialize the sensor."""
self._name = 'blink armed status'
self.data = data
self._state = self.data.arm
@property
def name(self):
"""Return the name of the blink sensor."""
return self._name.replace(" ", "_")
@property
def is_on(self):
"""Return the status of the sensor."""
return self._state
def update(self):
"""Update sensor state."""
self.data.refresh()
self._state = self.data.arm
self._state = self._camera.attributes[self._type]

View File

@@ -4,7 +4,6 @@ Reads vehicle status from BMW connected drive portal.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.bmw_connected_drive/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
@@ -124,7 +123,10 @@ class BMWConnectedDriveSensor(BinarySensorDevice):
if not check_control_messages:
result['check_control_messages'] = 'OK'
else:
result['check_control_messages'] = check_control_messages
cbs_list = []
for message in check_control_messages:
cbs_list.append(message['ccmDescriptionShort'])
result['check_control_messages'] = cbs_list
elif self._attribute == 'charging_status':
result['charging_status'] = vehicle_state.charging_status.value
# pylint: disable=protected-access
@@ -190,8 +192,7 @@ class BMWConnectedDriveSensor(BinarySensorDevice):
"""Schedule a state update."""
self.schedule_update_ha_state(True)
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Add callback after being added to hass.
Show latest data after startup.

View File

@@ -127,6 +127,7 @@ class DeconzBinarySensor(BinarySensorDevice):
self._sensor.uniqueid.count(':') != 7):
return None
serial = self._sensor.uniqueid.split('-', 1)[0]
bridgeid = self.hass.data[DATA_DECONZ].config.bridgeid
return {
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},
@@ -134,4 +135,5 @@ class DeconzBinarySensor(BinarySensorDevice):
'model': self._sensor.modelid,
'name': self._sensor.name,
'sw_version': self._sensor.swversion,
'via_hub': (DECONZ_DOMAIN, bridgeid),
}

View File

@@ -4,7 +4,6 @@ Interfaces with Egardia/Woonveilig alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.egardia/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
@@ -18,9 +17,8 @@ EGARDIA_TYPE_TO_DEVICE_CLASS = {'IR Sensor': 'motion',
'IR': 'motion'}
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Initialize the platform."""
if (discovery_info is None or
discovery_info[ATTR_DISCOVER_DEVICES] is None):

View File

@@ -4,7 +4,6 @@ Support for Envisalink zone states- represented as binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.envisalink/
"""
import asyncio
import logging
import datetime
@@ -22,9 +21,8 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['envisalink']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the Envisalink binary sensor devices."""
configured_zones = discovery_info['zones']
@@ -56,8 +54,7 @@ class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
_LOGGER.debug('Setting up zone: %s', zone_name)
super().__init__(zone_name, info, controller)
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_UPDATE, self._update_callback)

View File

@@ -4,7 +4,6 @@ Provides a binary sensor which is a collection of ffmpeg tools.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.ffmpeg_motion/
"""
import asyncio
import logging
import voluptuous as vol
@@ -46,13 +45,12 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the FFmpeg binary motion sensor."""
manager = hass.data[DATA_FFMPEG]
if not manager.async_run_test(config.get(CONF_INPUT)):
if not await manager.async_run_test(config.get(CONF_INPUT)):
return
entity = FFmpegMotion(hass, manager, config)
@@ -98,8 +96,7 @@ class FFmpegMotion(FFmpegBinarySensor):
self.ffmpeg = SensorMotion(
manager.binary, hass.loop, self._async_callback)
@asyncio.coroutine
def _async_start_ffmpeg(self, entity_ids):
async def _async_start_ffmpeg(self, entity_ids):
"""Start a FFmpeg instance.
This method is a coroutine.
@@ -116,7 +113,7 @@ class FFmpegMotion(FFmpegBinarySensor):
)
# run
yield from self.ffmpeg.open_sensor(
await self.ffmpeg.open_sensor(
input_source=self._config.get(CONF_INPUT),
extra_cmd=self._config.get(CONF_EXTRA_ARGUMENTS),
)

View File

@@ -4,7 +4,6 @@ Provides a binary sensor which is a collection of ffmpeg tools.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.ffmpeg_noise/
"""
import asyncio
import logging
import voluptuous as vol
@@ -43,13 +42,12 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the FFmpeg noise binary sensor."""
manager = hass.data[DATA_FFMPEG]
if not manager.async_run_test(config.get(CONF_INPUT)):
if not await manager.async_run_test(config.get(CONF_INPUT)):
return
entity = FFmpegNoise(hass, manager, config)
@@ -67,8 +65,7 @@ class FFmpegNoise(FFmpegBinarySensor):
self.ffmpeg = SensorNoise(
manager.binary, hass.loop, self._async_callback)
@asyncio.coroutine
def _async_start_ffmpeg(self, entity_ids):
async def _async_start_ffmpeg(self, entity_ids):
"""Start a FFmpeg instance.
This method is a coroutine.
@@ -82,7 +79,7 @@ class FFmpegNoise(FFmpegBinarySensor):
peak=self._config.get(CONF_PEAK),
)
yield from self.ffmpeg.open_sensor(
await self.ffmpeg.open_sensor(
input_source=self._config.get(CONF_INPUT),
output_dest=self._config.get(CONF_OUTPUT),
extra_cmd=self._config.get(CONF_EXTRA_ARGUMENTS),

View File

@@ -0,0 +1,64 @@
"""
Support for Fritzbox binary sensors.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.fritzbox/
"""
import logging
import requests
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.fritzbox import DOMAIN as FRITZBOX_DOMAIN
DEPENDENCIES = ['fritzbox']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Fritzbox binary sensor platform."""
devices = []
fritz_list = hass.data[FRITZBOX_DOMAIN]
for fritz in fritz_list:
device_list = fritz.get_devices()
for device in device_list:
if device.has_alarm:
devices.append(FritzboxBinarySensor(device, fritz))
add_entities(devices, True)
class FritzboxBinarySensor(BinarySensorDevice):
"""Representation of a binary Fritzbox device."""
def __init__(self, device, fritz):
"""Initialize the Fritzbox binary sensor."""
self._device = device
self._fritz = fritz
@property
def name(self):
"""Return the name of the entity."""
return self._device.name
@property
def device_class(self):
"""Return the class of this sensor."""
return 'window'
@property
def is_on(self):
"""Return true if sensor is on."""
if not self._device.present:
return False
return self._device.alert_state
def update(self):
"""Get latest data from the Fritzbox."""
try:
self._device.update()
except requests.exceptions.HTTPError as ex:
_LOGGER.warning("Connection error: %s", ex)
self._fritz.login()

View File

@@ -27,17 +27,20 @@ async def async_setup_platform(
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the HomematicIP Cloud binary sensor from a config entry."""
from homematicip.aio.device import (
AsyncShutterContact, AsyncMotionDetectorIndoor, AsyncSmokeDetector)
AsyncShutterContact, AsyncMotionDetectorIndoor, AsyncSmokeDetector,
AsyncWaterSensor, AsyncRotaryHandleSensor)
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home
devices = []
for device in home.devices:
if isinstance(device, AsyncShutterContact):
if isinstance(device, (AsyncShutterContact, AsyncRotaryHandleSensor)):
devices.append(HomematicipShutterContact(home, device))
elif isinstance(device, AsyncMotionDetectorIndoor):
devices.append(HomematicipMotionDetector(home, device))
elif isinstance(device, AsyncSmokeDetector):
devices.append(HomematicipSmokeDetector(home, device))
elif isinstance(device, AsyncWaterSensor):
devices.append(HomematicipWaterDetector(home, device))
if devices:
async_add_entities(devices)
@@ -91,3 +94,17 @@ class HomematicipSmokeDetector(HomematicipGenericDevice, BinarySensorDevice):
def is_on(self):
"""Return true if smoke is detected."""
return self._device.smokeDetectorAlarmType != STATE_SMOKE_OFF
class HomematicipWaterDetector(HomematicipGenericDevice, BinarySensorDevice):
"""Representation of a HomematicIP Cloud water detector."""
@property
def device_class(self):
"""Return the class of this sensor."""
return 'moisture'
@property
def is_on(self):
"""Return true if moisture or waterlevel is detected."""
return self._device.moistureDetected or self._device.waterlevelDetected

View File

@@ -4,7 +4,6 @@ Support for INSTEON dimmers via PowerLinc Modem.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.insteon/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
@@ -22,9 +21,8 @@ SENSOR_TYPES = {'openClosedSensor': 'opening',
'batterySensor': 'battery'}
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the INSTEON device class for the hass platform."""
insteon_modem = hass.data['insteon'].get('modem')

View File

@@ -4,8 +4,6 @@ Support for ISY994 binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.isy994/
"""
import asyncio
import logging
from datetime import timedelta
from typing import Callable
@@ -121,10 +119,9 @@ class ISYBinarySensorDevice(ISYDevice, BinarySensorDevice):
self._computed_state = bool(self._node.status._val)
self._status_was_unknown = False
@asyncio.coroutine
def async_added_to_hass(self) -> None:
async def async_added_to_hass(self) -> None:
"""Subscribe to the node and subnode event emitters."""
yield from super().async_added_to_hass()
await super().async_added_to_hass()
self._node.controlEvents.subscribe(self._positive_node_control_handler)
@@ -261,10 +258,9 @@ class ISYBinarySensorHeartbeat(ISYDevice, BinarySensorDevice):
self._parent_device = parent_device
self._heartbeat_timer = None
@asyncio.coroutine
def async_added_to_hass(self) -> None:
async def async_added_to_hass(self) -> None:
"""Subscribe to the node and subnode event emitters."""
yield from super().async_added_to_hass()
await super().async_added_to_hass()
self._node.controlEvents.subscribe(
self._heartbeat_node_control_handler)

View File

@@ -4,23 +4,26 @@ Support for MQTT binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mqtt/
"""
import asyncio
import logging
from typing import Optional
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.components import mqtt
from homeassistant.components import mqtt, binary_sensor
from homeassistant.components.binary_sensor import (
BinarySensorDevice, DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
CONF_FORCE_UPDATE, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON,
CONF_PAYLOAD_OFF, CONF_DEVICE_CLASS)
from homeassistant.components.mqtt import (
CONF_STATE_TOPIC, CONF_AVAILABILITY_TOPIC, CONF_PAYLOAD_AVAILABLE,
CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, MqttAvailability)
ATTR_DISCOVERY_HASH, CONF_STATE_TOPIC, CONF_AVAILABILITY_TOPIC,
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS,
MqttAvailability, MqttDiscoveryUpdate)
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
_LOGGER = logging.getLogger(__name__)
@@ -44,13 +47,28 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the MQTT binary sensor."""
if discovery_info is not None:
config = PLATFORM_SCHEMA(discovery_info)
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
async_add_entities, discovery_info=None):
"""Set up MQTT binary sensor through configuration.yaml."""
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up MQTT binary sensor dynamically through MQTT discovery."""
async def async_discover(discovery_payload):
"""Discover and add a MQTT binary sensor."""
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(hass, config, async_add_entities,
discovery_payload[ATTR_DISCOVERY_HASH])
async_dispatcher_connect(
hass, MQTT_DISCOVERY_NEW.format(binary_sensor.DOMAIN, 'mqtt'),
async_discover)
async def _async_setup_entity(hass, config, async_add_entities,
discovery_hash=None):
"""Set up the MQTT binary sensor."""
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = hass
@@ -68,19 +86,22 @@ def async_setup_platform(hass, config, async_add_entities,
config.get(CONF_PAYLOAD_NOT_AVAILABLE),
value_template,
config.get(CONF_UNIQUE_ID),
discovery_hash,
)])
class MqttBinarySensor(MqttAvailability, BinarySensorDevice):
class MqttBinarySensor(MqttAvailability, MqttDiscoveryUpdate,
BinarySensorDevice):
"""Representation a binary sensor that is updated by MQTT."""
def __init__(self, name, state_topic, availability_topic, device_class,
qos, force_update, payload_on, payload_off, payload_available,
payload_not_available, value_template,
unique_id: Optional[str]):
unique_id: Optional[str], discovery_hash):
"""Initialize the MQTT binary sensor."""
super().__init__(availability_topic, qos, payload_available,
payload_not_available)
MqttAvailability.__init__(self, availability_topic, qos,
payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash)
self._name = name
self._state = None
self._state_topic = state_topic
@@ -91,11 +112,12 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice):
self._force_update = force_update
self._template = value_template
self._unique_id = unique_id
self._discovery_hash = discovery_hash
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Subscribe mqtt events."""
yield from super().async_added_to_hass()
await MqttAvailability.async_added_to_hass(self)
await MqttDiscoveryUpdate.async_added_to_hass(self)
@callback
def state_message_received(topic, payload, qos):
@@ -115,7 +137,7 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice):
self.async_schedule_update_ha_state()
yield from mqtt.async_subscribe(
await mqtt.async_subscribe(
self.hass, self._state_topic, state_message_received, self._qos)
@property

View File

@@ -3,8 +3,6 @@
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mychevy/
"""
import asyncio
import logging
from homeassistant.components.mychevy import (
@@ -22,9 +20,8 @@ SENSORS = [
]
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the MyChevy sensors."""
if discovery_info is None:
return
@@ -75,8 +72,7 @@ class EVBinarySensor(BinarySensorDevice):
"""Return the car."""
return self._conn.get_car(self._car_vid)
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
self.hass.helpers.dispatcher.async_dispatcher_connect(
UPDATE_TOPIC, self.async_update_callback)

View File

@@ -4,7 +4,6 @@ Support for the myStrom buttons.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mystrom/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import DOMAIN, BinarySensorDevice
@@ -16,9 +15,8 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['http']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up myStrom Binary Sensor."""
hass.http.register_view(MyStromView(async_add_entities))
@@ -37,14 +35,12 @@ class MyStromView(HomeAssistantView):
self.buttons = {}
self.add_entities = add_entities
@asyncio.coroutine
def get(self, request):
async def get(self, request):
"""Handle the GET request received from a myStrom button."""
res = yield from self._handle(request.app['hass'], request.query)
res = await self._handle(request.app['hass'], request.query)
return res
@asyncio.coroutine
def _handle(self, hass, data):
async def _handle(self, hass, data):
"""Handle requests to the myStrom endpoint."""
button_action = next((
parameter for parameter in data

View File

@@ -147,6 +147,11 @@ class NestActivityZoneSensor(NestBinarySensor):
self.zone = zone
self._name = "{} {} activity".format(self._name, self.zone.name)
@property
def unique_id(self):
"""Return unique id based on camera serial and zone id."""
return "{}-{}".format(self.device.serial, self.zone.zone_id)
@property
def device_class(self):
"""Return the device class of the binary sensor."""

View File

@@ -93,7 +93,11 @@ class OpenUvBinarySensor(OpenUvEntity, BinarySensorDevice):
async def async_update(self):
"""Update the state."""
data = self.openuv.data[DATA_PROTECTION_WINDOW]['result']
data = self.openuv.data[DATA_PROTECTION_WINDOW]
if not data:
return
if self._sensor_type == TYPE_PROTECTION_WINDOW:
self._state = parse_datetime(
data['from_time']) <= utcnow() <= parse_datetime(

View File

@@ -4,18 +4,19 @@ Tracks the latency of a host by sending ICMP echo requests (ping).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.ping/
"""
import logging
import subprocess
import re
import sys
import asyncio
from datetime import timedelta
import logging
import re
import subprocess
import sys
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME, CONF_HOST
PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.const import CONF_HOST, CONF_NAME
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
@@ -48,13 +49,14 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
def setup_platform(hass, config, add_entities, discovery_info=None):
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
"""Set up the Ping Binary sensor."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
count = config.get(CONF_PING_COUNT)
add_entities([PingBinarySensor(name, PingData(host, count))], True)
async_add_entities([PingBinarySensor(name, PingData(host, count))], True)
class PingBinarySensor(BinarySensorDevice):
@@ -91,9 +93,9 @@ class PingBinarySensor(BinarySensorDevice):
ATTR_ROUND_TRIP_TIME_MIN: self.ping.data['min'],
}
def update(self):
async def async_update(self):
"""Get the latest data."""
self.ping.update()
await self.ping.update()
class PingData:
@@ -114,12 +116,13 @@ class PingData:
'ping', '-n', '-q', '-c', str(self._count), '-W1',
self._ip_address]
def ping(self):
async def ping(self):
"""Send ICMP echo request and return details if success."""
pinger = subprocess.Popen(
self._ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pinger = await asyncio.create_subprocess_shell(
' '.join(self._ping_cmd), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
try:
out = pinger.communicate()
out = await pinger.communicate()
_LOGGER.debug("Output is %s", str(out))
if sys.platform == 'win32':
match = WIN32_PING_MATCHER.search(str(out).split('\n')[-1])
@@ -128,7 +131,8 @@ class PingData:
'min': rtt_min,
'avg': rtt_avg,
'max': rtt_max,
'mdev': ''}
'mdev': '',
}
if 'max/' not in str(out):
match = PING_MATCHER_BUSYBOX.search(str(out).split('\n')[-1])
rtt_min, rtt_avg, rtt_max = match.groups()
@@ -136,18 +140,20 @@ class PingData:
'min': rtt_min,
'avg': rtt_avg,
'max': rtt_max,
'mdev': ''}
'mdev': '',
}
match = PING_MATCHER.search(str(out).split('\n')[-1])
rtt_min, rtt_avg, rtt_max, rtt_mdev = match.groups()
return {
'min': rtt_min,
'avg': rtt_avg,
'max': rtt_max,
'mdev': rtt_mdev}
'mdev': rtt_mdev,
}
except (subprocess.CalledProcessError, AttributeError):
return False
def update(self):
async def update(self):
"""Retrieve the latest details from the host."""
self.data = self.ping()
self.data = await self.ping()
self.available = bool(self.data)

View File

@@ -92,6 +92,11 @@ class RachioControllerOnlineBinarySensor(RachioControllerBinarySensor):
"""Return the name of this sensor including the controller name."""
return "{} online".format(self._controller.name)
@property
def unique_id(self) -> str:
"""Return a unique id for this entity."""
return "{}-online".format(self._controller.controller_id)
@property
def device_class(self) -> str:
"""Return the class of this device, from component DEVICE_CLASSES."""

View File

@@ -18,6 +18,7 @@ from homeassistant.const import (
CONF_HEADERS, CONF_AUTHENTICATION, HTTP_BASIC_AUTHENTICATION,
HTTP_DIGEST_AUTHENTICATION, CONF_DEVICE_CLASS)
import homeassistant.helpers.config_validation as cv
from homeassistant.exceptions import PlatformNotReady
_LOGGER = logging.getLogger(__name__)
@@ -66,13 +67,13 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
rest = RestData(method, resource, auth, headers, payload, verify_ssl)
rest.update()
if rest.data is None:
_LOGGER.error("Unable to fetch REST data from %s", resource)
return False
raise PlatformNotReady
# No need to update the sensor now because it will determine its state
# based in the rest resource that has just been retrieved.
add_entities([RestBinarySensor(
hass, rest, name, device_class, value_template)], True)
hass, rest, name, device_class, value_template)])
class RestBinarySensor(BinarySensorDevice):

View File

@@ -44,14 +44,15 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
ring = hass.data[DATA_RING]
sensors = []
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
for device in ring.doorbells:
for device in ring.doorbells: # ring.doorbells is doing I/O
for sensor_type in config[CONF_MONITORED_CONDITIONS]:
if 'doorbell' in SENSOR_TYPES[sensor_type][1]:
sensors.append(RingBinarySensor(hass,
device,
sensor_type))
for device in ring.stickup_cams:
for device in ring.stickup_cams: # ring.stickup_cams is doing I/O
for sensor_type in config[CONF_MONITORED_CONDITIONS]:
if 'stickup_cams' in SENSOR_TYPES[sensor_type][1]:
sensors.append(RingBinarySensor(hass,
device,

View File

@@ -4,7 +4,6 @@ Support for Satel Integra zone states- represented as binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.satel_integra/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
@@ -20,9 +19,8 @@ DEPENDENCIES = ['satel_integra']
_LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the Satel Integra binary sensor devices."""
if not discovery_info:
return
@@ -50,8 +48,7 @@ class SatelIntegraBinarySensor(BinarySensorDevice):
self._zone_type = zone_type
self._state = 0
@asyncio.coroutine
def async_added_to_hass(self):
async def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_ZONES_UPDATED, self._zones_updated)

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