Compare commits

..

816 Commits

Author SHA1 Message Date
Paulus Schoutsen
bac48aa9d2 Merge pull request #18857 from home-assistant/rc
0.83.2
2018-11-30 20:09:29 +01:00
Paulus Schoutsen
9b3373a15b Bumped version to 0.83.2 2018-11-30 17:53:14 +01:00
pbalogh77
474909b515 Hotfix for Fibaro wall plug (#18845)
Fibaro wall plug with a lamp plugged in was misrecognized as a color light, generating crashes in the update function.
2018-11-30 17:53:04 +01:00
Paulus Schoutsen
80f2c2b124 Always set hass_user (#18844) 2018-11-30 17:53:04 +01:00
Darren Foo
ada148eeae bump gtts-token to 1.1.3 (#18824) 2018-11-30 17:53:03 +01:00
emontnemery
449cde5396 Revert change to MQTT discovery_hash introduced in #18169 (#18763) 2018-11-30 17:53:03 +01:00
Paulus Schoutsen
3701c0f219 Merge pull request #18811 from home-assistant/rc
0.83.1
2018-11-29 23:18:13 +01:00
Paulus Schoutsen
440614dd9d Use proper signals (#18613)
* Emulated Hue not use deprecated handler

* Remove no longer needed workaround

* Add middleware directly

* Dont always load the ban config file

* Update homeassistant/components/http/ban.py

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

* Update __init__.py
2018-11-29 23:05:23 +01:00
Paulus Schoutsen
163c881ced Bumped version to 0.83.1 2018-11-29 22:58:06 +01:00
pbalogh77
0467d0563a Hotfix for crash with virtual devices (#18808)
* Quickfix for crash with virtual devices

Added try/except to critical loops of processing
Reinforced read_devices, map_device_to_type and update processing

* oops
2018-11-29 22:57:45 +01:00
Aaron Bach
31d7221c90 Remove additional self from update function in RainMachine (#18810) 2018-11-29 22:51:16 +01:00
Daniel Høyer Iversen
d9124b182a Remove self from update function in rainmachine (#18807) 2018-11-29 22:51:15 +01:00
Aaron Bach
f2b818658f Bumped py17track to 2.1.0 (#18804) 2018-11-29 22:51:15 +01:00
Eric Nagley
5a6ac9ee72 BUGFIX: handle extra fan speeds. (#18799)
* BUGFIX: add support for extra fan speeds.

* Drop extra fan speeds.

Remove catch all, drop missing fan speeds.

* fix self.speed_synonyms call. Remove un-needed keys() call
2018-11-29 22:51:14 +01:00
Paulus Schoutsen
7fa5f07218 Fix race condition in group.set (#18796) 2018-11-29 22:51:13 +01:00
Paulus Schoutsen
fa9a200e3c Render the secret (#18793) 2018-11-29 22:51:13 +01:00
Paulus Schoutsen
0ca67bf6f7 Make auth backwards compat again (#18792)
* Made auth not backwards compat

* Fix tests
2018-11-29 22:51:12 +01:00
cdce8p
f1c5e756ff Fix logbook domain filter - alexa, homekit (#18790) 2018-11-29 22:51:12 +01:00
Paulus Schoutsen
ff33d34b81 Legacy api fix (#18733)
* Set user for API password requests

* Fix tests

* Fix typing
2018-11-29 22:51:11 +01:00
Ian Richardson
601389302a Convert shopping-list update to WebSockets (#18713)
* Convert shopping-list update to WebSockets

* Update shopping_list.py

* Update test_shopping_list.py
2018-11-29 22:51:10 +01:00
Ian Richardson
2ba521caf8 Add websocket call for adding item to shopping-list (#18623) 2018-11-29 22:51:10 +01:00
Paulus Schoutsen
c6c55c4419 Merge pull request #18776 from home-assistant/rc
0.83
2018-11-29 11:45:20 +01:00
Paulus Schoutsen
1364114dc1 Bumped version to 0.83.0 2018-11-29 10:57:40 +01:00
Paulus Schoutsen
05915775e3 Bumped version to 0.83.0b3 2018-11-28 22:47:37 +01:00
Paulus Schoutsen
311c796da7 Default to on if logged in (#18766) 2018-11-28 22:47:09 +01:00
Paulus Schoutsen
f860cac4ea OwnTracks Config Entry (#18759)
* OwnTracks Config Entry

* Fix test

* Fix headers

* Lint

* Username for android only

* Update translations

* Tweak translation

* Create config entry if not there

* Update reqs

* Types

* Lint
2018-11-28 22:47:08 +01:00
Adam Mills
58e0ff0b1b Async tests for owntracks device tracker (#18681) 2018-11-28 22:47:08 +01:00
Paulus Schoutsen
f3047b9c03 Fix logbook filtering entities (#18721)
* Fix logbook filtering entities

* Fix flaky test
2018-11-27 20:16:32 +01:00
Paulus Schoutsen
775c909a8c Bumped version to 0.83.0b2 2018-11-27 20:15:57 +01:00
Paulus Schoutsen
3a8303137a Add permission checks to Rest API (#18639)
* Add permission checks to Rest API

* Clean up unnecessary method

* Remove all the tuple stuff from entity check

* Simplify perms

* Correct param name for owner permission

* Hass.io make/update user to be admin

* Types
2018-11-27 20:15:48 +01:00
Paulus Schoutsen
f9f71c4a6d Bumped version to 0.83.0b1 2018-11-26 14:20:56 +01:00
Joakim Sørensen
c3b76b40f6 Set correct default offset (#18678) 2018-11-26 14:20:49 +01:00
Bram Kragten
56c7c8ccc5 Fix vol Dict -> dict (#18637) 2018-11-26 14:20:49 +01:00
Fredrik Erlandsson
bb75a39cf1 Updated webhook_register, version bump pypoint (#18635)
* Updated webhook_register, version bump pypoint

* A binary_sensor should be a BinarySensorDevice
2018-11-26 14:20:48 +01:00
Eliseo Martelli
2f581b1a1e fixed wording that may confuse user (#18628) 2018-11-26 14:20:48 +01:00
pbalogh77
cf22060c5e Use asyncio Lock for fibaro light (#18622)
* Use asyncio Lock for fibaro light

* line length and empty line at end

* async turn_off

Turned the turn_off into async as well

* bless you, blank lines...

My local flake8 lies to me. Not cool.
2018-11-26 14:20:47 +01:00
Paulus Schoutsen
6bcedb3ac5 Updated frontend to 20181121.1 2018-11-26 14:16:30 +01:00
Paulus Schoutsen
fd7fff2ce8 Version bump to 0.83.0b0 2018-11-21 20:50:11 +01:00
Paulus Schoutsen
4e58eb8bae Updated frontend to 20181121.0 2018-11-21 20:35:46 +01:00
Paulus Schoutsen
49121f2347 Update translations 2018-11-21 20:18:56 +01:00
Fabian Affolter
708ababd78 Upgrade requests to 2.20.1 (#18615) 2018-11-21 19:58:56 +01:00
Pawel
92c0f9e4aa Fix mqtt cover inverted (#18456)
* Fixed state and position retrieval in inverted mode 100-0

* Always calculating find_percentage_in_range

* Added usage of max/min functions.
2018-11-21 15:48:44 +01:00
Martin Gross
81cac33801 Update locationsharinglib requirement to 3.0.8 (#18612) 2018-11-21 15:13:20 +01:00
Jonathan McDowell
1e3930a447 Add support for Panasonic Blu-Ray players (#18541)
* Add support for Panasonic Blu-Ray players

* Update panasonic_bluray.py

* Update panasonic_bluray.py
2018-11-21 14:22:24 +01:00
Joakim Sørensen
3cde8dc3a9 Add support for HTTPS and basic HTTP authentication for Glances (#18608)
* Add support for SSL and basic HTTP auth

* Remove blank line at the end of the file
2018-11-21 12:38:42 +01:00
Paulus Schoutsen
36c31a6293 Add permissions check in service helper (#18596)
* Add permissions check in service helper

* Lint

* Fix tests

* Lint

* Typing

* Fix unused impoert
2018-11-21 12:26:08 +01:00
Kevin Fronczak
8aa2cefd75 Upgrade blinkpy to 0.10.3 (Fixes #18341) (#18603) 2018-11-21 08:57:59 +01:00
pbalogh77
3b53003795 Fibaro components (#18487)
* Added Fibaro omcponents

Added cover, light, sensor and switch components

* Improvements based on code review

Improvements based on code review

* Fixes based on code review

Fixes based on code review

* Changes to light behavior based on code review

Changes to light behavior based on code review

* Internal changes

Changed how brightness is represented internally.
It should have no impact on functionality.
2018-11-21 06:15:54 +01:00
ehendrix23
377730a37c Change channel with play_media instead of select_source (#18474)
* Use service play_media instead of select_source

Use service play_media instead of select_source to change the channel as play_media is the right service for that.

* Log error on invalid media type

Log an error instead of raising a NotImplementedError if an invalid media type is provided.

* Changed so that success is not in else statement

Updated so that if media_type is channel that it is not in the else of an if.

* Update directv.py

Removed SELECT_SOURCE as supported feature.

* Rebased

Re-based with dev
2018-11-20 16:05:25 -07:00
Paulus Schoutsen
d9c7f777c5 Add cloud pref for Google unlock (#18600) 2018-11-20 23:23:07 +01:00
Charles Garwood
b7742999cf Update Z-Wave Tests asyncio/yield from -> async/await (#18599)
* Update lock tests

* Update binary sensor

* Update zwave component tests
2018-11-20 14:58:03 -05:00
Daniel Høyer Iversen
8742750926 Improve available for Mill heater (#18597)
* improve available for Mill heater

* typo
2018-11-20 20:00:13 +01:00
Charles Garwood
e87ecbd500 Z-Wave Lock Config Entry Support (#18209)
* Config Entry setup for zwave lock

* fix merge conflict

* lint

* Update other tests

* Fix tests

* Remove debug line and unused import
2018-11-20 14:59:34 +01:00
Fredrik Erlandsson
3838be4cb8 Add support for Daikin BRP069B41 (#18564)
* Add support for BRP069B41, fixes #18563

* Use fan_mode and swing_mode from pydaikin 0.8
2018-11-20 14:14:11 +01:00
Pascal Vizeli
0ddd502d00 Hass.io config check (#18576) 2018-11-20 13:30:09 +01:00
dapowers87
d88040eeed Revert changes that broke UI (#18495)
* Revert changes that broke UI

* Change from UNKNOWN to None

* Remove STATE_UNKNOWN import
2018-11-20 13:29:05 +01:00
Ian Richardson
44b33d45b1 Add websocket calls to shopping-list (#18392)
* Add websocket calls to shopping-list

Plan to deprecate API calls once shopping-list panel is removed from UI and replaced fully by Lovelace card

* Address ci-bot issues

* Fix violations

* Address travis complaints

* Address review comments

* Update test_shopping_list.py
2018-11-20 12:44:17 +01:00
Paulus Schoutsen
9b53b7e9e4 Bump Python-Nest to 4.0.5 (#18580)
* Fix Nest eco

* Update Python-nest to 4.0.5

* Update requirements_all.txt

* Update requirements_test_all.txt
2018-11-20 12:18:46 +01:00
Franck Nijhof
80cd8b180c Adds light switch platform (#18562)
* Adds light switch platform

* Addresses HoundCI warnings

* Addresses Flake8 reported issues

* Removes async_update call as per review
2018-11-20 11:51:34 +01:00
William Scanlon
b3e37af9b1 Added unique id to all Wink devices. (#18589) 2018-11-19 22:52:43 -05:00
Eliseo Martelli
57f7e7eedc Bumped ghlocalapi to 0.1.0 (#18584)
* mumped ghlocalapi to 0.1.0

* update requirement_all.txt
2018-11-19 15:01:26 -05:00
Sebastian Muszynski
14ad7428ea Prefix all xiaomi_aqara events (#17354) 2018-11-19 20:55:08 +01:00
Paulus Schoutsen
f86083cf52 Fix MQTT async_added_to_hass (#18575)
* Fix some invocations

* Update manual_mqtt.py
2018-11-19 20:48:26 +01:00
Soós Péter
3891f2eebe Add mikrotik SSL support (#17898)
* Update mikrotik.py

* Update mikrotik.py

* Added basic  api_ssl support

Added preliminary support to use api_ssl instead of api. It don't check the validity of the certificate need it.
At Home Assistant side add ssl = true to your sensor configuration, and don't forget to change the port too (to 8729 by default):

device_tracker:
  - platform: mikrotik
    host: 192.168.88.1
    port: 8729
    ssl: true
    username: homeassistant
    password: TopSecret

At MikroTik side you have to add or generate a certificate, and configure api_ssl to use it. Here is an example:

/certificate add common-name="Self signed demo certificate for API" days-valid=3650 name="Self signed demo certificate for API" key-usage=digital-signature,key-encipherment,tls-server,key-cert-sign,crl-sign
/certificate sign "Self signed demo certificate for API"
/ip service set api-ssl certificate="Self signed demo certificate for API"
/ip service enable api-ssl
/ip service disable api
/user group add name=homeassistant policy=read,api,!local,!telnet,!ssh,!ftp,!reboot,!write,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp
/user add group=homeassistant name=homeassistant
/user set password="TopSecret" homeassistant

* Fixed import missind ssl lib

* SSL support code cleanup, use ssl-api port by default if ssl enabled

* Restored accidentalli deleted method parameter

* Fixed Python 3.5.3 compilation errors

Fixed Python 3.5.3 compilation errors reported by Travis CI

* Removed duplicated MTK_DEFAULT_API_PORT
2018-11-19 16:54:09 +01:00
emontnemery
de9bac9ee3 Reconfigure MQTT binary_sensor component if discovery info is changed (#18169)
* Recreate component if discovery info is changed

* Update component instead of remove+add

* Set name and unique_id in __init__

* Update unit test

* Cleanup

* More cleanup

* Refactor according to review comments

* Change discovery_hash

* Review comments, add tests

* Fix handling of value_template
2018-11-19 16:49:04 +01:00
Oleksii Serdiuk
01953ab46b Darksky: Expose missing conditions for day 0 forecast (#18312)
Dark Sky Sensor didn't expose conditions for day 0 (today forecast) that
had the same name as current conditions. With this change all conditions
form day 0 (today) forecast are exposed the same way as conditions for
the rest of the days (1..7): as `dark_sky_<condition>_<day>`. As a
consequence, conditions for day 0 that were already exposed now have
`_0` suffix. This actually improves the code by removing most of
special handling, based on condition name.

To get day 0 conditions the user now has to add `- 0` to `forecast`
configuration parameter.

Conditions, for which suffix `_0` appeared: `precip_accumulation`,
`temperature_high`, `temperature_low`, `apparent_temperature_high`,
`apparent_temperature_low`, `precip_intensity_max`, `moon_phase`.

This is a breaking change!

Closes #18205
2018-11-19 14:48:52 +01:00
Daniel Perna
fc4dd4e51f Update pyhomematic to 0.1.52 and add features for lights (#18499)
* Update pyhomematic and add features for lights

* Lint

* Lint

* Update homematic.py

* Update homematic.py
2018-11-19 14:26:08 +01:00
bw3
90f3f2b1e7 Fix for epson state not updating (#18357)
* Fixed update method name

* Update epson.py
2018-11-19 13:47:52 +01:00
Fredrik Erlandsson
c1ca7beea1 Support for Point component (#17466)
* Minut Point support

* tox tests for Point

* config flow fixes

* fixes requested by @MartinHjelmare

* swedish translation :)

* fix tests
2018-11-19 12:52:21 +01:00
Anders Melchiorsen
84fd66c8a1 Template binary sensor to not track all state changes (#18573) 2018-11-19 12:10:48 +01:00
arigilder
97c493448b Correct cached stale device tracker handling (#18572)
* Fix async addition of stale devices

* Add comment to mark_stale

* Remove extraneous whitespace
2018-11-19 12:06:57 +01:00
ehendrix23
9fa34f0d77 Add support for sessions (#18518)
Added support for sessions to keep connection open with August portal, improving performance.
py-august version increased to 0.7.0
2018-11-19 11:53:27 +01:00
ehendrix23
cdcc818bf9 Remove turn_on and turn_off feature for clients (#18234)
* Enhancements for DirecTV media player

Following enhancements have been made:

1. Added debug logging
2. Added ability to change channel using select_source service of the remote platform.
3. State will now show paused if a recorded program is paused, for live TV playing will always be returned.
4. Added the following attributes:
    a. media_position: current position of the media (in seconds)
    b. media_position_updated_at: timestamp when media_position was updated.
   c. source: current source (channel).
   d. media_isbeingrecorded: if current media is being recorded or not.
   e. media_rating: TV/Movie rating of the media
   f. media_recorded: if current media is recorded or live TV
   g. media_starttime: Timestamp media was aired

Reordered properties to follow same order as how they are in __init__.py of remote platform.

* Fixed error and cleaned up few items

Fixed an issue when determining if a program is recorded or not.
Cleaned up some coding.

* Added available property

Added available property

* Disable feature TURN_ON and TURN_OFF for DVR clients

Disable the feature turn_on and turn_off for DVR clients.

* self._is_client and raise NotImplementedError

Updated setting self._is_client
Raise NotImplementedError if turn_on or turn_off is called for clients.
2018-11-19 11:47:00 +01:00
Phil Bruckner
83b4e56978 Log delay and wait_template steps in scripts (#18448)
* Log delay and wait_template steps in scripts

Help improve script debugging by logging delay and wait_template steps in scripts.

* Update tests

* Fix lint issue
2018-11-19 11:14:00 +01:00
Aleksandr Smirnov
089a2f4e71 Logbook speedup (#18376)
* filter logbook results by entity_id prior to instantiating them

* include by default, pass pep8

* pass pylint

* use entityfilter, update tests
2018-11-19 10:36:00 +01:00
emontnemery
f241becf7f Avoid race in entity_platform.async_add_entities() (#18445)
This avoids a race between multiple concurrent calls to
entity_platform.async_add_entities() which may cause
entities to be created with non-unique entity_id
2018-11-19 10:13:50 +01:00
emontnemery
7e702d3caa Fix small issue related to topic prefix (#18512)
Fix expansion of topic prefix when discovery message contains non string-type items.
2018-11-19 09:59:07 +01:00
Jeff Irion
ab8c127a4a Enable native support + ADB authentication for Fire TV (#17767)
* Enable native support + ADB authentication for Fire TV

* Remove unnecessary underscore assignments

* Bump firetv to 1.0.5.3

* Change requirements to 'firetv>=1.0.6'

* Change requirement from 'firetv>=1.0.6' to 'firetv==1.0.6'

* Address pylint errors

* Ran 'python script/gen_requirements_all.py'

* Address some minor reviewer comments

* Run 'python script/gen_requirements_all.py'

* Just use the 'requirements_all.txt' and 'requirements_test_all.txt' from the 'dev' branch...

* Edit the 'requirements_all.txt' file manually

* Pass flake8 tests

* Pass pylint tests, add extended description for 'select_source'

* More precise exception catching

* More Pythonic returns

* Import exceptions inside '__init__'

* Remove 'time.sleep' command

* Sort the imports

* Use 'config[key]' instead of 'config.get(key)'

* Remove accessing of hidden attributes; bump firetv version to 1.0.7

* Bump firetv to 1.0.7 in 'requirements_all.txt'

* Don't access 'self.firetv._adb', use 'self.available' instead

* Remove '_host' and '_adbkey' attributes

* Create the 'FireTV' object in 'setup_platform' and check the connection before instantiating the entity

* Fixed config validation for 'adbkey'

* add_devices -> add_entities

* Remove 'pylint: disable=no-name-in-module'

* Don't assume the device is available after attempting to connect

* Update the state after reconnecting

* Modifications to 'adb_decorator'

* Modifications to 'setup_platform'

* Don't update the state if the ADB reconnect attempt was unsuccessful

* 'return None' -> 'return'

* Use 'threading.Lock()' instead of a boolean for 'adb_lock'

* Use a non-blocking 'threading.Lock'
2018-11-19 07:05:58 +01:00
sdelliot
afe21b4408 Re-adding the season attribute (#18523) 2018-11-18 18:35:36 -07:00
Anders Melchiorsen
b066877453 Allow unloading of LIFX config entry (#18535) 2018-11-18 19:51:17 +01:00
Per Sandström
796933de68 Upgrade vsure to 1.5.2 (#18557)
Upgrade vsure to 1.5.2
2018-11-18 19:41:24 +01:00
Aaron Bach
8f59be2059 Make MyQ platform async (#18489)
* Make MyQ platform async

* Bumped requirements

* Member comments

* Member updates
2018-11-18 18:37:03 +01:00
Ville Skyttä
dfb8f60fe2 Upgrade pytest and pytest-cov (#18542)
* Upgrade pytest to 4.0.0

* Upgrade pytest-cov to 2.6.0
2018-11-18 09:33:01 +01:00
Daniel Høyer Iversen
3f747f1a8c Mill lib (#18529)
* Mill attr and update the lib

* lib

* heater_generation
2018-11-17 18:39:38 +01:00
Fabian Affolter
4751ad69a7 Upgrade ruamel.yaml to 0.15.78 (#18508) 2018-11-17 13:20:17 +01:00
Anders Melchiorsen
c6ca27e9b4 Improve handling of unavailable Sonos speakers (#18534) 2018-11-17 13:18:51 +01:00
Aaron Bach
e73b9b9b8f Clean up left-behind dispatcher handlers when removing RainMachine (#18488)
* Clean up left-behind dispatcher handlers when removing RainMachine

* Member comments
2018-11-17 10:42:50 +01:00
Daniel Høyer Iversen
6b2f50b29e Improve real time consumption for Tibber sensor (#18517) 2018-11-16 14:19:54 -05:00
Eliseo Martelli
fcd756d58a fixed sky_hub schema to reflect documentation (#18509) 2018-11-16 14:14:46 -05:00
Paulus Schoutsen
24db2b66ab Ban systemair-savecair (#18483) 2018-11-16 14:28:39 +01:00
Fabian Affolter
320efdb744 Upgrade sqlalchemy to 1.2.14 (#18504) 2018-11-16 14:15:53 +01:00
Fabian Affolter
9e0497875e Upgrade sphinx-autodoc-typehints to 1.5.0 (#18505) 2018-11-16 14:15:04 +01:00
Fabian Affolter
30806fa362 Upgrade numpy to 1.15.4 (#18506) 2018-11-16 14:14:40 +01:00
Fabian Affolter
9f51deb1de Upgrade youtube_dl to 2018.11.07 (#18507) 2018-11-16 14:14:20 +01:00
cdce8p
0ca94f239d Update HAP-python 2.4.1 (#18417)
* Bugfixes
2018-11-16 11:42:48 +01:00
cdce8p
ed7aea006a Add safe_mode HomeKit (#18356)
* Use: 'safe_mode: True' in case of pairing issues
2018-11-16 11:08:39 +01:00
Martin Gross
b7b8296c73 Alexa v3 name change for additionalApplianceDetails (#18485) 2018-11-15 11:15:50 -07:00
Leothlon
afb3a52b5b Fixed bug for receivers without support for new command (#18478)
* Fixed bug for receivers without support for new command

* removed extra parenthesis
2018-11-15 10:49:10 -07:00
Aaron Bach
4446b15cb0 Add Rainmachine to the device registry (#18452)
* Device registry in

* Member comments

* Hound
2018-11-15 10:43:20 -07:00
Oleksii Serdiuk
d1b5bc19da AirVisual: Show icon for air pollution level, based on its value (#18482)
Show excited, happy, neutral, sad, dead emoticon, or biohazard icon,
based on air pollution level.

Also, fix a small typo and change air quality index icon to
`mdi:chart-line`. Seems a bit more logical.
2018-11-15 10:23:46 -07:00
Paulus Schoutsen
75bb78d440 Update translations 2018-11-15 14:30:37 +01:00
Paulus Schoutsen
2d870a29c4 Merge branch 'master' into dev 2018-11-15 14:30:21 +01:00
Paulus Schoutsen
7cb7c76a83 Merge pull request #18481 from home-assistant/rc
0.82.1
2018-11-15 14:25:56 +01:00
Paulus Schoutsen
b40b934029 Bumped version to 0.82.1 2018-11-15 14:01:21 +01:00
Pascal Vizeli
5ffcb99b4f Update pyozw to 0.1.1 (#18436)
* Update pyozw to 0.1.1

* Update requirements_all.txt
2018-11-15 14:01:15 +01:00
Abílio Costa
69d358fa08 edp_redy: increase UPDATE_INTERVAL (#18429)
The server was getting a bit mad sometimes and would lock users out.
2018-11-15 14:01:14 +01:00
Fredrik Erlandsson
f36b94b376 updated pydaikin version (#18413) 2018-11-15 14:01:14 +01:00
Pawel
b5d4e18880 Changed checking of cover state closed from 0 to closed_position variable. (#18407)
Change error message to avoid expression "get_position_topic".
2018-11-15 14:01:13 +01:00
Paulus Schoutsen
43271ca0f7 Bump aioasuswrt to 1.1.6 2018-11-15 14:01:02 +01:00
Diogo Gomes
7659c33439 cancel off_delay action (#18389) 2018-11-15 13:56:14 +01:00
Clayton Nummer
b8ddbc3fdb Fix default value for optional Sense configuration parameter (#18379) 2018-11-15 13:56:13 +01:00
Bram Kragten
2aa2233d9b Fix including from sub dir (#18378)
The include path is now always relative to the root of the config dir.
2018-11-15 13:56:13 +01:00
Martin Hjelmare
6bcba1fbea Fix hangouts notify (#18372)
* Remove notify schema from hangouts platform

* Notify platforms shouldn't overwrite the notify component service
  schema. That has no effect.

* Fix hangouts service data key value
2018-11-15 13:56:12 +01:00
Jason Hunter
466d3a5ef8 catch key error when saving image (#18365) 2018-11-15 13:56:12 +01:00
Aaron Bach
8aa1283adc Add Rainmachine config entry (#18419)
* Initial stuff

* More work in place

* Starting with tests

* Device registry in place

* Hound

* Linting

* Member comments (including extracting device registry)

* Member comments (plus I forgot cleanup!)

* Hound

* More Hound

* Removed old import

* Adding config entry test to coverage

* Updated strings
2018-11-14 13:23:49 -07:00
pbalogh77
312872961f Initial support for Fibaro HomeCenter hubs (#17891)
* Fibaro HC connection, initial commit

Very first steps working, connects, fetches devices, represents sensors, binary_sensors and lights towards HA.

* Cover, switch, bugfixes

Initial support for covers
Initial support for switches
Bugfixes

* Some cleanup and improved lights

pylint based cleanup
light switches handled properly
light features reported correctly

* Added status updates and actions

Lights, Blinds, Switches are mostly working now

* Code cleanup, fiblary3 req

Fiblary3 is now in pypi, set it as req
Cleanup based on pylint

* Included in .coveragerc and added how to use guide

Included the fibaro component in coveragerc
Added usage instructions to file header

* PyLint inspired fixes

Fixed pylint warnings

* PyLint inspired fixes

PyLint inspired fixes

* updated to fiblary3 0.1.5

* Minor fixes to finally pass pull req

Fixed fiblary3 to work with python 3.5
Updated fiblary3 to 0.1.6
(added energy and batteryLevel dummies)

* module import and flake8 fixes

Finally (hopefully) figured out what lint is complaining about

* Fixed color support for lights, simplified callback

Fixed color support for lights
Simplified callback for updates
Uses updated fiblary3 for color light handling

* Lean and mean refactor

While waiting for a brave reviewer, I've been making the code smaller and easier to understand.

* Minor fixes to please HoundCI

* Removed unused component

Scenes are not implemented yet

* Nicer comments.

* DEVICE_CLASS, ignore plugins, improved mapping

Added support for device class and icons in sensors and binary_sensors
Improved mapping of sensors and added heuristic matching
Added support for hidden devices
Fixed conversion to float in sensors

* Fixed dimming

Fibaro apparently does not need, nor like the extra turnOn commands for dimmers

* flake8

* Cleanup, Light fixes, switch power

Cleanup of the component to separate init from connect, handle connection error better
Improved light handling, especially for RGBW strips and working around Fibaro quirks
Added energy and power reporting to switches

* Missing comment added

Missing comment added to please flake8

* Removed everything but bin.sensors

Stripdown, hoping for a review

* better aligned comments

OMG

* Fixes based on code review

Fixes based on code review

* Implemented stopping

Implemented stopping of StateHandler thread
Cleanup for clarity

* Minor fix

Removed unnecessary list copying

* Nicer wording on shutdown

* Minor changes based on code review

* minor fixes based on code review

* removed extra line break
2018-11-14 20:58:32 +01:00
Daniel Høyer Iversen
00235cf6f0 Improve support for 1. generation mill heater (#18423)
* Improve support for 1. gen mill heater

* style

* None operation_list for gen 1 heater

* Remove SUPPORT_OPERATION_MODE for gen 1
2018-11-14 19:35:12 +01:00
Rick van Hattem
80e616cacf Make mikrotik method setting optional as intended (#18454)
Pull request #17852 accidently made the `method` setting required.
2018-11-14 18:05:29 +01:00
Maikel Punie
c7ac216602 Readded climate.velbus (#18434)
* Readded climate.velbus

* houndci-bot changes

* Added more comments

* Fix flake8 error

* return TEMP_* constants

* more comments
2018-11-14 09:40:43 -05:00
Fredrik Erlandsson
0d43cb6d0e fixes for last version bump on pydaikin (#18438) 2018-11-14 09:38:16 -05:00
ehendrix23
d2e102ee2f Init statistics sensor upon HASS start (#18236)
* Update query to include maxAge

Updated the query from recorded to include MaxAge if set; reducing the amount of records retrieved that would otherwise be purged anyway for the sensor.

* Initialization upon HASS start

Register the state listener and read previous information from recorder once HASS is started.

* Updated test_statistics.py for HASS start

Updated test_statistics.py to start HASS and wait it is completed before running test.

* Added newline in docstring

Added newline in docstring.

* Added start of HASS to test_initialize_from_database_with_maxage

Added start of HASS to new test test_initialize_from_database_with_maxage.

* Updates based on review

Following updates based on review:
-) Removed self._hass and passing hass
-) Changed async_add_job to async_create_task
-) For state update, calling async_schedule_update_ha_state
2018-11-14 15:13:32 +01:00
Sebastian Muszynski
d2907b8e53 Add Philips Zhirui Downlight support (#18455) 2018-11-14 12:33:27 +01:00
Glenn Waters
419400f90b Bump elkm1_lib version (#18450) 2018-11-14 02:20:15 +01:00
Pascal Vizeli
532a75b487 Update pyozw to 0.1.1 (#18436)
* Update pyozw to 0.1.1

* Update requirements_all.txt
2018-11-13 23:43:01 +01:00
JC Connell
291fba0ba4 Update Magicseaweed sensor (#18446)
* Increment python-magicseaweed version.

* Update requirements_all.txt
2018-11-13 23:41:58 +01:00
Joakim Sørensen
597da90622 Fixes issue for returning the correct docker version. (#18439) 2018-11-13 21:00:21 +01:00
Abílio Costa
f14251bdcc edp_redy: increase UPDATE_INTERVAL (#18429)
The server was getting a bit mad sometimes and would lock users out.
2018-11-13 14:24:30 +01:00
kennedyshead
ebdfb56803 Bumping aioasuswrt (#18427) 2018-11-13 14:04:36 +01:00
Daniel Høyer Iversen
7aa41d66e9 Avg price for tibber sensor (#18426)
* Avg price for tibber sensor

* change to sum_price
2018-11-13 11:29:04 +01:00
Fabian Affolter
7113ec6073 Fix smhi docstrings (#18414)
* Fix docstrings

* Fix lint

* Fix another typo

* Fix mobile phone edit
2018-11-13 10:01:14 +01:00
kbickar
f78dcb96b0 Sense will not list removed devices (#18410)
* Sense will not list removed devices

* quote update
2018-11-13 08:34:11 +01:00
Fredrik Erlandsson
996da72a4c Daikin fixes (#18415)
* updated pydaikin version

* some Daikin models does not support fan settings
2018-11-13 08:33:34 +01:00
Aaron Bach
8547489014 Bumps pytile to 2.0.5 (#18395) 2018-11-12 19:10:03 -07:00
Fredrik Erlandsson
c6683cba7d updated pydaikin version (#18413) 2018-11-12 22:53:50 +01:00
Fabian Affolter
ea4480f170 Use existing constant (#18408) 2018-11-12 22:32:30 +01:00
Diogo Gomes
0ab81b03a8 cancel off_delay action (#18389) 2018-11-12 21:28:00 +01:00
Pawel
d0463942be Changed checking of cover state closed from 0 to closed_position variable. (#18407)
Change error message to avoid expression "get_position_topic".
2018-11-12 19:45:59 +00:00
Glenn Waters
275b485b36 Add support for keypad keypress (#18393)
* Add support for keypad keypress

* Update requirements_all
2018-11-12 16:10:28 +01:00
Levi Govaerts
15c77fe548 Add niko-home-control support (#18019)
* Add niko-home-control support

* Remove the sensor platform

* Minor changes

* Fix docstring
2018-11-12 15:59:52 +01:00
Philipp Wensauer
e5930da972 Update pynello to 2.0.2 (#18402)
* Update to pynello 2.0.2

* Update to pynello 2.0.2

* Update to pynello 2.0.2
2018-11-12 09:54:08 -05:00
Paulus Schoutsen
8fb6030f97 Bump frontend to 20181112.0 2018-11-12 15:14:37 +01:00
Jorim Tielemans
9eac11dcbe Filter Coinbase account wallets (#18167)
Only add sensor entities for accounts with the specified currencies.
This is a none breaking change.
If it's not specified then all account wallets will be loaded.
2018-11-12 11:26:05 +01:00
kennedyshead
afd9c44ffb Bumping aioasuswrt (#18400) 2018-11-12 11:10:53 +01:00
Hmmbob
1f06d6ac1a Update waze_travel_time.py (#18399) 2018-11-12 11:09:39 +01:00
Adam Belebczuk
ca86755409 Discord - Minor bugfixes (#18385)
Suppress PyNaCl warnings of Discord notify
2018-11-11 23:16:23 +01:00
Clayton Nummer
1f476936a2 Fix default value for optional Sense configuration parameter (#18379) 2018-11-11 22:55:45 +01:00
Eric Nagley
ddeeba20b9 Google assistant enable fan speed controls (#18373)
* Initial commit of Traits changes.

* Initial commit of tests chagnes for added FanSpeed trait.

* pylint fixes.

* Default reversible to false

* Ensure reversible returns True/False.

* Fix FanSpeed trait name and fix order.

* Add remaining checks to FanSpeed trait Test.

* Remove un-needed blank lines at EOF.

* Update homeassistant/components/google_assistant/trait.py

Co-Authored-By: marchingphoenix <eanagley@gmail.com>

* use fan.SPEED_* constants as keys to speed_synonyms dict.
convert True if() to bool() for reversible assignment.

* use fan.SPEED_OFF constant of 'on' check.
2018-11-11 22:02:33 +01:00
Aaron Bach
5129a48750 Fixed misspellings in some of the Pollen sensor names (#18382) 2018-11-11 13:01:26 -07:00
Fabian Affolter
95eae47438 Bump version to 0.83.0 2018-11-11 18:22:28 +01:00
bouni
372470f52a Fix and improvment of Swiss Hydrological Data component (#17166)
* Fix and improvment of Swiss Hydrological Data component

* changed component to get data from a REST API rather than from crawling the website

* fixed several issues and lint errors

* Fix and improvment of Swiss Hydrological Data component

* Minor changes

- Simplify the sensor configuration (expose value as attributes rather than sensor)
- Make the setup fail if station is not available
- Add unique ID
- Prepare for config flow
2018-11-11 17:48:44 +01:00
Martin Hjelmare
02cc6a2f9a Fix hangouts notify (#18372)
* Remove notify schema from hangouts platform

* Notify platforms shouldn't overwrite the notify component service
  schema. That has no effect.

* Fix hangouts service data key value
2018-11-11 17:46:28 +01:00
Jason Hunter
9cb6464c58 catch key error when saving image (#18365) 2018-11-11 17:44:41 +01:00
Jack Wilsdon
5b9a9d8e04 Return color information in Alexa Smart Home response (#18368)
Fixes #18367.
2018-11-11 17:43:01 +01:00
Ville Skyttä
9411fca955 Add more type hints to helpers (#18350)
* Add type hints to helpers.entityfilter

* Add type hints to helpers.deprecation
2018-11-11 17:39:50 +01:00
Bram Kragten
b8c06ad019 Fix including from sub dir (#18378)
The include path is now always relative to the root of the config dir.
2018-11-11 17:15:58 +01:00
Steven Looman
9c92151ad1 Upgrade async_upnp_client to 0.13.2 (#18377) 2018-11-11 15:10:03 +00:00
Daniel Høyer Iversen
f0a0ce504b Better error handling in Tibber (#18363)
* Better error handling in Tibber

* return if received error
2018-11-11 14:06:21 +01:00
Matthew Garrett
d9533127f9 Merge pull request #18364 from mjg59/avion
Bump python-avion dependency
2018-11-10 18:34:27 -08:00
Matthew Garrett
fa127188df Bump python-avion dependency
The current version of python-avion doesn't work correctly with Python 3.5.
Update it to one that does.
2018-11-10 18:03:55 -08:00
Chris Kacerguis
667b41dd4a Show battery_level as a percent vs a decimal (#18328) 2018-11-10 21:30:03 +01:00
Ville Skyttä
f236e14bd6 Upgrade pytest and pytest-sugar (#18338)
* Upgrade pytest to 3.10.0

* Upgrade pytest-sugar to 0.9.2
2018-11-10 21:08:32 +01:00
Antoine Meillet
e75f9b36f9 add heartbeat support to mysensors (#18359) 2018-11-10 21:08:03 +01:00
cdce8p
132bb7902a Update HAP-python to 2.4.0 (#18355) 2018-11-10 18:33:45 +01:00
Paulus Schoutsen
df2ab62ce9 Merge pull request #18335 from home-assistant/rc
0.82
2018-11-10 09:52:37 +01:00
Adam Belebczuk
f7c99ada9d WeMo - Change name of discovery option (#18348) 2018-11-10 09:32:09 +01:00
Tyler Page
8bd281d5a3 Update credstash.py (#18349)
* Update credstash.py

* Update requirements_all.txt
2018-11-10 08:21:39 +01:00
Adam Belebczuk
210eab16da WeMo - Change name of discovery option (#18348) 2018-11-10 08:17:24 +01:00
uchagani
64ada1ea5a bump total connect client to 0.22 (#18344) 2018-11-09 20:04:28 -05:00
Daniel Høyer Iversen
14ad5c0006 Switchmate library update (#18336) 2018-11-09 23:41:44 +01:00
Joakim Sørensen
d34c47a9e1 Rename sensor.launch to sensor.launch_library (#18337) 2018-11-09 22:24:26 +01:00
Aaron Bach
f971309113 Add support for sensors from Flu Near You (#18136)
* Add support for sensors from Flu Near You

* Added sensor for total reports with symptoms

* Member comments

* Member comments
2018-11-09 08:23:07 -07:00
Paulus Schoutsen
f8ca4cfd91 Merge remote-tracking branch 'origin/master' into rc 2018-11-09 15:44:17 +01:00
Paulus Schoutsen
4324d87673 Bumped version to 0.82.0 2018-11-09 15:42:17 +01:00
Abílio Costa
7f48a280ee fix last device ignored (#18329) 2018-11-09 15:41:21 +01:00
Paulus Schoutsen
f4c35a389d Remove Velbus climate platform (#18319) 2018-11-09 15:41:20 +01:00
Daniel Høyer Iversen
8ab2f669d2 Fix xiaomi binary_sensor warning (#18280)
* Fix xiaomi binary_sensor warning

* Fix xiaomi binary_sensor warning
2018-11-09 15:41:20 +01:00
Paulus Schoutsen
de37fc90c0 Bump frontend to 20181103.3 2018-11-09 15:40:46 +01:00
Daniel Høyer Iversen
c571637176 Fix xiaomi binary_sensor warning (#18280)
* Fix xiaomi binary_sensor warning

* Fix xiaomi binary_sensor warning
2018-11-09 11:36:00 +01:00
Abílio Costa
b803075eb4 fix last device ignored (#18329) 2018-11-09 10:41:08 +01:00
ehendrix23
ae85baf396 Restrict recorder query to include max age (#18231)
* Update query to include maxAge

Updated the query from recorded to include MaxAge if set; reducing the amount of records retrieved that would otherwise be purged anyway for the sensor.

* Added newline in docstring

Added newline in docstring.

* Add test + small fix

Added test to ensure query works correctly
Query should be greater then or equal instead of greater then. Fixed.

* Fixed lint issue

Fixed lint issue.
2018-11-08 23:08:36 +00:00
Brig Lamoreaux
05eac915d1 Srpenergy (#18036)
* Add srp_energy

* Update message on TypeError. Add check for None state.

* Add check for none in history

* Add srpenergy to Test requirements.

* Add srpenergy to requirments.

* Change = to ==.

* Change import for srpenergy

* Fix Flak8 errors

* Add srp to gen requirements script

* Change config name.

* Add daily usage test

* Add test for daily usage.

* Fix Flake8 message.

* Remove blank after docstring.

* Add srpenergy to coverage

* Bump requires version to srpenergy

* Fix type in coverage. Import from Sensor. Use dict.

* Update to 1.0.5. Check credentials on setup. Standalone test.

* Fix formating.

* Remove period. Rename _ variables.

* Fix rebase merge

* Add rebase requirement

* Improve Mock Patching.
2018-11-08 19:19:30 +01:00
horga83
8f107c46fe W800rf32 (#17920)
* Initial commit of w800rf32 component and binary_sensor.

The W800 family is an X10 RF receiver used with keypads and motion sensors etc.

* Initial commit of w800rf32 switch platform.

The W800 family is an X10 RF receiver used with keypads and motion sensors etc.

* Remove unused code.

* Additions for w800rf32 component and platform code

* Fix w800rf32 minor lint issues and make sure gen_requirements.py correctlly adds w800rf32

* Added dispatch_connect/send and refactor somewhat

* Fix missed indentation lint

* Removed shared entity dict and use async_dispatch code

* Fix long line not caught by lint

* One more line too long, missed it

* Remove unused code and changes for async

* Remove  @callback that shouldn't be there.

* Remove switch platform, can't have read only switch.

* Remove unused CONF_DEBUG

* Remove used vars and make CONF_DEVICES required

* Move CONF_OFF_DELAY to platform, only used there
2018-11-08 18:49:00 +01:00
Joakim Sørensen
fd2987e551 Add new launch sensor to keep track of space launches. (#18274)
* Add new launch sensor to keep track of space launches.

* Added attribution to Launch Library.

* Adds data class and throtle, reuse aiohttp session.

* Add one extra blank line before the new class..

* Change throttle to simpler SCAN_INTERVAL.

* Remove the usage of the LaunchData class.

* Bump pylaunches, remove . from log, fix line breaker for agency_country_code, remove CONF_ from ATTRIBUTION.
2018-11-08 16:37:11 +01:00
Matthias Urlichs
9472529d43 Doc fix: a circular dependency does not raise an error. (#18298)
This is easier to handle than raising an exception: a circular
dependency causes multiple error entries in the log, which is what we
want.

This is harder to achieve with an exception. Since there is only one
user of this code, I choose to fix the documentation -- instead of
adding a lot of mostly-useless exception handling.

Closes: #13147
2018-11-08 12:59:58 +01:00
Paulus Schoutsen
f7f0a4e811 System groups (#18303)
* Add read only and admin policies

* Migrate to 2 system groups

* Add system groups

* Add system groups admin & read only

* Dont' mutate parameters

* Fix types
2018-11-08 12:57:00 +01:00
Paulus Schoutsen
54b0cde52a Remove Velbus climate platform (#18319) 2018-11-08 11:17:44 +01:00
Joakim Sørensen
a016dd2140 Bump pyhaversion to 2.0.2 (#18318) 2018-11-08 10:07:49 +01:00
Pascal Vizeli
878e369c4a Fix log error message (#18305)
* Fix log error message

* Update __init__.py
2018-11-08 10:07:48 +01:00
Nick Touran
599542394a Added optional precision configuration option to generic_thermostat. (#18317)
* Added optional precision configuration option to generic_thermostat.

* Added optional precision configuration option to generic_thermostat.

* Style update.
2018-11-08 09:39:35 +01:00
Joakim Sørensen
7fed49c4ab Bump pyhaversion to 2.0.2 (#18318) 2018-11-08 09:27:51 +01:00
Aaron Bach
954191c385 Add support for 17track.net package sensors (#18038)
* Add support for 17track.net package sensors

* Updated CODEOWNERS

* Addressing comments

* Fixed requirements

* Member comments

* Revert "Member comments"

This reverts commit 61a19d7966.

* Member comments

* Member comments
2018-11-07 22:25:08 -07:00
Pascal Vizeli
e2fca0691e Fix log error message (#18305)
* Fix log error message

* Update __init__.py
2018-11-08 00:33:51 +01:00
Paulus Schoutsen
f24979c7cf Bumped version to 0.82.0b4 2018-11-07 21:58:18 +01:00
Jeff Wilson
5bab0018f5 Make flux switch async (#18277)
* Make flux switch async

* Fix line lengths

* Fix indentation

* Set tracker before await to avoid race condition

* Fix lint errors
2018-11-07 21:52:55 +01:00
Pascal Vizeli
f541b101c9 Bugfix discovery (delete/mqtt) call for Hass.io (#18159)
* Bugfix discovery delete call for Hass.io

* Fix host

* fix tests
2018-11-07 21:45:47 +01:00
Joakim Sørensen
0bf054fb59 Update pyruter to 1.1.0 to be able to reuse aiohttp session. (#18310)
* Update pyruter to 1.1.0 to be able to reuse aiohttp session.

* Taged correct version of pyruter.
2018-11-07 13:54:33 -05:00
kennedyshead
aa4da479b5 Add upload and download sensors and component for asuswrt (#17757)
* Adds upload and download sensors for asuswrt and makes it a component.

* Rebase

* removes warnings

* Fixing review issues

* More robust connection phase

* Generate dependencies

* Not needed try catch

* Rename sensors

* Revorked tests so they can be turned on again

* Using component setup

* Test through correct setup

* Forgot we dont need to worry about older py
2018-11-07 18:32:13 +01:00
Steven Looman
d93716bd84 Add SUPPORT_SEEK for DLNA DMR devices + now (better) providing media_image_url for DLNA DMR devices (#18157)
* Upgrade to async_upnp_client==0.13.2, now (better) providing media_image_url for DLNA DMR devices

* Add SUPPORT_SEEK for DLNA DMR devices
2018-11-07 13:48:51 +01:00
Tsvi Mostovicz
f99701f41a Upgrade hdate to 0.7.5 (#18296)
In 0.7.x the API to HDate was cleaned up so as to move logic from homeassistant to
the HDate external library.

This commit removes all the superfluous code, updates the required tests and changes the
requirement from version 0.6.5 to 0.7.5
2018-11-07 13:30:41 +01:00
Jorim Tielemans
29be78e08e Improve version sensor (#18292)
* Validate value against valid list

* Show correct name

Constants in alphabetical order.
Added default name when not showing the local/current version.

* Add icon

Icon was already defined but not set

* Unnecessary "elif" after "return" (no-else-return)
2018-11-07 13:28:25 +01:00
majuss
ec732c896d Add support for Lupusec alarm control panel (#17691)
* Adds support for Lupusec alarm control panel

* fixed various mostly cosmetic issues

* fixed generic type of binary sensors

* fixed some formatting; removed scan interval completely -> defaults now to 2 secs

* removed unused data caches; added check if binary sensor class exists

* cosmetics

* generic type fix

* small fix

* small fixes

* guard clause added

* small fixes
2018-11-07 12:51:12 +01:00
Paulus Schoutsen
00c1b40940 Add translations 2018-11-07 10:45:29 +01:00
Paulus Schoutsen
4287d1dd2d Bump frontend to 20181107.0 2018-11-07 10:45:15 +01:00
Paulus Schoutsen
e9b8b290fc Bumped version to 0.82.0b3 2018-11-07 10:37:57 +01:00
mvn23
06b9600069 Bump pyotgw to 0.3b1 (#18286)
* Bump pyotgw to 0.3b1

* Update requirements_all.txt
2018-11-07 10:37:41 +01:00
Johann Kellerman
cff4755708 SMA Guard against older pysma (#18278) 2018-11-07 10:37:40 +01:00
Pascal Vizeli
17f04c1736 Migrate python-openzwave to homeassistant-pyozw (#18268)
* Migrate python-openzwave to homeassistant-pyozw

* Update requirements_all.txt

* Fix requirements
2018-11-07 10:37:05 +01:00
Mikko Tapionlinna
0b6aa38b13 Update pynetgear to 0.5.1 (#18238) 2018-11-07 10:36:28 +01:00
Paulus Schoutsen
782f5c7d19 Bump frontend to 20181103.2 2018-11-07 10:36:15 +01:00
Oleksii Serdiuk
5cee9942a6 Darksky: Add icon to summary sensors (#18275)
The icon changes dynamically, based on summary.
2018-11-07 10:01:05 +01:00
Adam Mills
65be458ce0 Update input component tests to async (#18290) 2018-11-07 09:56:32 +01:00
Adam Mills
ce069be16e Update manual ACP tests to async (#18289) 2018-11-07 09:56:24 +01:00
Adam Mills
0d7cb54872 Update litejet automation tests to async (#18287) 2018-11-07 09:56:10 +01:00
Adam Mills
6935b62487 Remove skipped device tracker tests (#18291) 2018-11-07 09:55:55 +01:00
mvn23
e698fc2553 Bump pyotgw to 0.3b1 (#18286)
* Bump pyotgw to 0.3b1

* Update requirements_all.txt
2018-11-07 09:55:22 +01:00
Sebastian Muszynski
df3d82e0e3 Use async_add_executor_job at the xiaomi_miio platforms (#18294) 2018-11-07 09:03:35 +01:00
Johann Kellerman
35ae85e14e SMA Guard against older pysma (#18278) 2018-11-07 08:52:51 +02:00
Pascal Vizeli
c89dade619 Migrate python-openzwave to homeassistant-pyozw (#18268)
* Migrate python-openzwave to homeassistant-pyozw

* Update requirements_all.txt

* Fix requirements
2018-11-06 22:08:04 +01:00
Rohan Kapoor
bdba3852d0 Split out geofency with a component and platform (#17933)
* Split out geofency with a component and platform

* Make geofency component/device_tracker more async

* Move geofency tests to new package

* Remove coroutine in geofency callback

* Lint

* Fix coroutine in geofency callback

* Fix incorrect patch
2018-11-06 20:12:03 +01:00
Joakim Sørensen
c41ca37a04 Add Norwegian Public Transportation sensor (Ruter). (#18237)
* Add Norwegian Public Transportation sensor (Ruter).

* Corrected typo.

* change stopid to stop_id, actually use attributes, changed logging, corrected link, removed unused variable.

* Change to RuterSensor for the class, and move logic to me more readable.

* Use correct sensor class.

* Add return if blank list, remove else
2018-11-06 19:49:38 +01:00
Adam Mills
917ebed4c9 Update PR checklist with commented out code check (#18272)
Along with hopefully helping resolve these actual problems, a nudge for people to look at their own code might help catch other quick fixes before anyone else has to review a PR.
2018-11-06 19:47:19 +01:00
Paulus Schoutsen
43ae57cc59 Lint 2018-11-06 19:27:52 +01:00
Pascal Vizeli
f4d3d5904e HmIP thermostat fix with operations (#18068)
* HmIP thermostat fix with operations

* Update homematic.py
2018-11-06 16:36:12 +01:00
Paulus Schoutsen
bde02afe4f Normalize MAC addresses (#16916)
* Normalize MAC addresses

* Handle all mac formats
2018-11-06 16:33:31 +01:00
Matt Schmitt
42fea4fb97 Add services to set/update and cancel Nest ETA (#17836)
* Add service to cancel ETA

* Update test requirements

* Change service name and update logging

* Reformat logging to verify structures
2018-11-06 16:11:10 +01:00
Daniel Shokouhi
52074ee9bb Update Neato states, actions and alerts based on Neato docs (#17353)
* Update neato sstates actions and alerts based on neato docs

* Remove unused STATES
2018-11-06 16:10:39 +01:00
Georgi Kirichkov
eb385515c8 Switch OwnTracks HTTP to use webhook component (#17034)
* Update OwnTracks_HTTP to use the webhook component

* Update owntracks_http.py

* Update owntracks_http.py
2018-11-06 16:10:17 +01:00
emontnemery
589764900a Move more MQTT platforms to config entries (#18180)
* Move Lock MQTT platform to config entries

* Move MQTT JSON Light platform to config entries

* Review comments

* Review comments

* Revert mqtt_json changes
2018-11-06 16:09:46 +01:00
Filip Bednárik
9329ec2486 Add support for switches in homekit controller (#17916) 2018-11-06 15:32:32 +01:00
Ludovico de Nittis
47af194d06 Add iAlarm "triggered" support (#18263) 2018-11-06 15:30:41 +01:00
kennedyshead
39412dc930 Adding current_humidity to attributes if its not None. (#18261)
* Adding current humidity if not None

* Removed the logic in supported feature

* More appropriate placement
2018-11-06 15:18:46 +01:00
Fabian Affolter
2e517ab6bc Enable config flow for Luftdaten (#17700)
* Move file to new location

* Update requirement

* Enable config flow

* Add luftdaten

* Add tests

* Update

* Add constants

* Changes according to the review comments

* Remove wrong entry from flows

* Fix dict handling

* Add callback and use OrderedDict

* Remve leftover

* Fix

* Remove await
2018-11-06 14:27:52 +01:00
Matthew Parlane
7933bd7f91 Allow alexa to simply turn on and off climate components. (#16989) 2018-11-06 14:17:56 +01:00
Sebastian Muszynski
58c77e1f55 Add Xiaomi Air Purifier 2s support (#18260) 2018-11-06 14:16:15 +01:00
Tyler
e3a8f3a106 Add input_boolean reporting to Prometheus (#17966) 2018-11-06 13:19:36 +01:00
akloeckner
1aba4699b9 Add attributes of ARP table (#17987)
* Add attributes of ARP table

This adds the device attributes available in the ARP table and a few more. Implementation is inspired by the nmap scanner.

* lint spaces
2018-11-06 13:15:48 +01:00
4lloyd
114bc8ec18 Support eco mode option on Ziggo Mediabox XL (#17990)
* Added eco mode option to Ziggo Mediabox XL

* Changed eco_mode_on to eco_mode

* Removed eco_mode option, the player is unavailable when offline

* Timeout on connection, on/off states are handled via update

* Improved state detection and added available property
2018-11-06 13:14:52 +01:00
kennedyshead
c6f3c239bb Melissa state_attributes (#18201)
* Melissa attributes

* overide device_state_attributes rather than state_attributes

* Selected attributes

* Adding current humidity rather than a state_attribute
2018-11-06 13:08:58 +01:00
Glen Takahashi
34d7758b4a Correct expose_by_default interaction with expose_domains (#17745)
Based on the documentation here: https://www.home-assistant.io/components/google_assistant/#expose_by_default it seems that expose_by_default means all devices should be exposed unless explicitly set to false, and that regardless if this is set domains in exposed_domains should be exposed.
2018-11-06 12:53:47 +01:00
Joakim Sørensen
2c36b9db1f Add support for Google Home device tracking (#18190)
* Add support for Google Home device tracking.

* Use dict[key] for options.

* Delete googlehome.py.save

* Change stylling of name, and attr mac_address to btle_mac_address, removed unesssesarry attributes copying.
2018-11-06 12:47:53 +01:00
Filip Bednárik
24efda20bf Add additional property to HomeKitSwitch to show whether the Homekit outlet is in use (#17448)
* Add additional property to HomeKitSwitch to show whether the Homekit outlet is in use or not

* Fix issues from review - Remove unused property, simplify and rename the device_state_attributes method
2018-11-06 12:43:47 +01:00
akloeckner
3322fee814 Fritz keepalive (#18155)
* Add keepalive support

- adds keepalive support
- adds debug messages
- corrects CONF_PHONEBOOK and CONF_PREFIXES constants

* Add keepalive config constant

* Fix default value

* More visual indentation

* move to platform

* Move to platform

* Make keepalive default and remove option

* Forgot a few lines
2018-11-06 12:43:16 +01:00
Matthias Urlichs
4581a741bd Report *which* component didn't return a bool (#18258)
* Report *which* component didn't return a bool

* break over-long line
2018-11-06 12:41:39 +01:00
Matthias Urlichs
b506aafbb4 docstring fix (#18257) 2018-11-06 12:41:15 +01:00
Jorim Tielemans
121ec5c684 Add season icons (#18221)
* Add season icons

* Use STATE constants

* Calm down hound

* Update season.py
2018-11-06 12:34:11 +01:00
Matthew Treinish
087bffeaae Add workaround to use notification state for zwave lock state (#17386)
* Add workaround to use notification state for zwave lock state

There are several zwave lock models out there which do not seem to
update the lock state on non-rf events (see #11934 #14632 #14534 for
examples) including kwikset smartkey zwave plus locks (which I own).
In these cases it seems that the notifications for non-rf events the
access_control value is updated but not the primary value for the
lock state, which is what is used to set the is_locked property. To
properly have the lock state accurate for all types of notifications
on these models we need to use the access_control field. This commit
adds a workaround for the 4 models reported to exhibit this behavior
so that home-assistant will reliably set the lock state for all
device notifications.

* Add YRD220 as per adrum to workaround list

* Inline constants
2018-11-06 11:00:48 +01:00
Andrew Hayworth
2bf2214d51 Add support for locks in google assistant component (#18233)
* Add support for locks in google assistant component

This is supported by the smarthome API, but there is no documentation
for it. This work is based on an article I found with screenshots of
documentation that was erroneously uploaded:

https://www.androidpolice.com/2018/01/17/google-assistant-home-can-now-natively-control-smart-locks-august-vivint-first-supported/

Google Assistant now supports unlocking certain locks - Nest and August
come to mind - via this API, and this commit allows Home Assistant to
do so as well.

Notably, I've added a config option `allow_unlock` that controls
whether we actually honor requests to unlock a lock via the google
assistant. It defaults to false.

Additionally, we add the functionNotSupported error, which makes a
little more sense when we're unable to execute the desired state
transition.

https://developers.google.com/actions/reference/smarthome/errors-exceptions#exception_list

* Fix linter warnings

* Ensure that certain groups are never exposed to cloud entities

For example, the group.all_locks entity - we should probably never
expose this to third party cloud integrations. It's risky.

This is not configurable, but can be extended by adding to the
cloud.const.NEVER_EXPOSED_ENTITIES array.

It's implemented in a modestly hacky fashion, because we determine
whether or not a entity should be excluded/included in several ways.

Notably, we define this array in the top level const.py, to avoid
circular import problems between the cloud/alexa components.
2018-11-06 10:39:10 +01:00
Tom Harris
ddee5f8b86 Fix IOLinc sensor (#18250) 2018-11-06 10:36:52 +01:00
Robert Svensson
c5d0440041 deCONZ - manual input fallback in config flow (#18116)
* Add config flow step for manual input
Remove support for loading discovery config from json file

* Small cleanup
Fix all translations to step user instead of step init

* Revert to using step_init

* Small cleanup
Add test_gateway that was forgotten in a previous PR

* Fix hound comment

* Fix empty pydocstring
2018-11-06 10:34:24 +01:00
Bram Kragten
24c110ad3c Lovelace: Duplicate ID check on load config + caching (#18152)
* Add caching + dupl. ID check

* duplicate imports...

* lint

* remove for/else

* found

* Missed one...
2018-11-05 20:12:31 -05:00
Glenn Waters
7077e19cf8 Elk-M1 fixes (#18154)
* Fix default value for temperature unit

* Add defaults for subdomains

* Remove unused import

* Fix PR comment
2018-11-05 20:09:07 -05:00
Mikko Tapionlinna
6f568d1cf6 Update pynetgear to 0.5.1 (#18238) 2018-11-05 19:00:46 -05:00
Sebastian Muszynski
d951ed4d68 Add Xiaomi Smartmi Fresh Air System support (#18097)
* Add Xiaomi Air Fresh VA2 support

* Add LED property again (available now)
2018-11-06 00:09:15 +01:00
Daniel Høyer Iversen
3366d2c1ad Tibber login validate (#18235)
* tibber login validate

* requirements
2018-11-05 23:29:42 +01:00
ehendrix23
46b5b6240f Improve debug log information (#18230)
Added debug log information for when records are purged and added entity_id to existing debug information to identify the entity the debug information is for.
2018-11-05 23:12:46 +01:00
Paulus Schoutsen
30fccc696e Bumped version to 0.82.0b2 2018-11-05 21:41:48 +01:00
Bram Kragten
fb947288ad Check if os has chown (#18229) 2018-11-05 21:41:43 +01:00
Paulus Schoutsen
be3800d9a5 Cloud conf (#18216)
* Add original config to entityfilter

* Add alexa/google config to cloud status call

* Lint
2018-11-05 21:41:42 +01:00
Pascal Vizeli
de79c42b8a Add support for TensorFlow in official docker (#18191) 2018-11-05 21:41:42 +01:00
Pascal Vizeli
b3bd59efb0 Handle TensorFlow like OpenCV (#18185)
* Handle TensorFlow like OpenCV

* Update requirements_all.txt
2018-11-05 21:41:41 +01:00
jjlawren
31737c5100 Remove config (breaking change) (#18153) 2018-11-05 21:41:41 +01:00
Johann Kellerman
dbf6b01a60 SMA: Optional import in schema & backoff fix (#18099) 2018-11-05 21:41:40 +01:00
Bram Kragten
abf147ed57 Check if os has chown (#18229) 2018-11-05 21:41:19 +01:00
quthla
c59b038512 Add scenes as switches HomeKit (#17799) 2018-11-05 21:36:30 +01:00
Daniel Høyer Iversen
93b16e7efb Mill room temp (#18203)
* mill, avg room temp

* typo

* Mill device_state_attributes
2018-11-05 20:52:34 +01:00
ehendrix23
561f6996c6 Duplicate entities on discovery (#18074)
* Enhancements for DirecTV media player

Following enhancements have been made:

1. Added debug logging
2. Added ability to change channel using select_source service of the remote platform.
3. State will now show paused if a recorded program is paused, for live TV playing will always be returned.
4. Added the following attributes:
    a. media_position: current position of the media (in seconds)
    b. media_position_updated_at: timestamp when media_position was updated.
   c. source: current source (channel).
   d. media_isbeingrecorded: if current media is being recorded or not.
   e. media_rating: TV/Movie rating of the media
   f. media_recorded: if current media is recorded or live TV
   g. media_starttime: Timestamp media was aired

Reordered properties to follow same order as how they are in __init__.py of remote platform.

* Fixed error and cleaned up few items

Fixed an issue when determining if a program is recorded or not.
Cleaned up some coding.

* Fix issue in checking if DTV device is already configured

If a DTV device was configured before, then discovery would add this device again seperately if the name specified in the configuration is different from the name on the DTV.

This issue is fixed now. Part of the fix also ensure to allow multiple "primary" devices on the network to be discovered.
Further also added debug logging to the setup_platform.

* Further improvements

Some additional improvements related to handling the DATA_DIRECTV in hass.data.

* Fixed flake8 issue

Fixed flake8 issue

* Added available property

Added available property

* Updated to use get_locations()

Replaced doing the request for getLocations with the get_locations() API from DirectPy instead.

* Fix for checking if device is available

Fix for checking if device is available and small update to debug log message.

* Fixed lint issue

Fixed lint issue with unused variable by adding ingore for it as this is for a enumerate

* Updated try/except and removed available

Updated tr/except having the except by the statement we're doing except on.
Removed available, will be a different PR.

* Updated known_devices to be tupples in a set

Updated known_devices to be a tupple in a set, removing loop to determine if client was already added.
2018-11-05 19:33:59 +01:00
vetegrodd
b261c4b7f8 Activate kodi media player progress bar (#17626)
* Added code for progress bar

* Added doc string

* Using in

* More cleaning

* Only update position if needed.
2018-11-05 12:39:37 -05:00
cdce8p
26ba4a56e8 Ignore duplicate state changes GarageDoor HomeKit (#18149)
* Ignore duplicate state changes GarageDoor HomeKit

* Don't ignore service_call
2018-11-05 16:42:19 +01:00
Robert Svensson
dcdae325ea deCONZ - reflect hub status on entities (#18106)
* Support for controlling entity available attribute based on gateways availability

* Fix string not being in imperative mood
2018-11-05 16:21:44 +01:00
ehendrix23
3d4ff74761 Add available property to DirecTV (#18168)
* Enhancements for DirecTV media player

Following enhancements have been made:

1. Added debug logging
2. Added ability to change channel using select_source service of the remote platform.
3. State will now show paused if a recorded program is paused, for live TV playing will always be returned.
4. Added the following attributes:
    a. media_position: current position of the media (in seconds)
    b. media_position_updated_at: timestamp when media_position was updated.
   c. source: current source (channel).
   d. media_isbeingrecorded: if current media is being recorded or not.
   e. media_rating: TV/Movie rating of the media
   f. media_recorded: if current media is recorded or live TV
   g. media_starttime: Timestamp media was aired

Reordered properties to follow same order as how they are in __init__.py of remote platform.

* Fixed error and cleaned up few items

Fixed an issue when determining if a program is recorded or not.
Cleaned up some coding.

* Fix issue in checking if DTV device is already configured

If a DTV device was configured before, then discovery would add this device again seperately if the name specified in the configuration is different from the name on the DTV.

This issue is fixed now. Part of the fix also ensure to allow multiple "primary" devices on the network to be discovered.
Further also added debug logging to the setup_platform.

* Further improvements

Some additional improvements related to handling the DATA_DIRECTV in hass.data.

* Fixed flake8 issue

Fixed flake8 issue

* Added available property

Added available property

* Updated to use get_locations()

Replaced doing the request for getLocations with the get_locations() API from DirectPy instead.

* Fix for checking if device is available

Fix for checking if device is available and small update to debug log message.

* Fixed lint issue

Fixed lint issue with unused variable by adding ingore for it as this is for a enumerate

* Updated try/except and removed available

Updated tr/except having the except by the statement we're doing except on.
Removed available, will be a different PR.

* Add available property

Add the available property to the entiry.
2018-11-05 16:19:03 +01:00
Paulus Schoutsen
81fa74e5ca Remove unrelated scripts (#18219)
* Remove influxDB scripts

* Remove ancient db migrator

* Update requirements
2018-11-05 16:14:34 +01:00
kennedyshead
f9f53fd278 Removes melissa sensors (they should be state attributes as implemented in #18201) (#18214) 2018-11-05 16:10:30 +01:00
Adam Belebczuk
36524e9d3f Bump version of pywemo to 0.4.29 (#18217) 2018-11-05 13:23:46 +01:00
Paulus Schoutsen
bf54582d76 Cloud conf (#18216)
* Add original config to entityfilter

* Add alexa/google config to cloud status call

* Lint
2018-11-05 13:21:03 +01:00
Marcel Hoppe
8de79ed57c add service to reconnect the bot (#18142) 2018-11-05 13:14:22 +01:00
quthla
8ee0e0c6c6 Turn off not cancellable scripts automatically HomeKit (#17793) 2018-11-05 11:11:26 +01:00
Joakim Sørensen
a901c594a9 Add Traccar device tracker (#18200)
* Add Traccar device tracker.

* Updated pytraccar to 0.1.1

* Adds default values for optional options.

* Use dict[key] for options.

* remove logging, duplicate by core
2018-11-05 09:28:02 +01:00
Paulus Schoutsen
2e9132873a Webhook names (#18206)
* Add new automation_info param to async_trigger

* Add domain and name to webhook registration and add WS command
2018-11-05 09:23:58 +01:00
Dav0815
6e4ce35a69 Add destination and icon (#18210)
* Add destination and icon

* Update test_transport_nsw.py

* Error handling fix in external lib

* Reverse sensor name change to prevent break
2018-11-05 08:27:20 +01:00
Andrea Tosatto
1c3ef8be55 Implemented tplink_lte components and notify service via SMS (#17111)
* Implemented tplink_lte components and notify service

* Device discovery for the notify component

* Improved the config schema. Small fixes

* Improved login retry mechanism

* Log successful connection only on retries

* Removed CancelledError handlers and small fixes
2018-11-05 02:09:29 +01:00
Ville Skyttä
922f34f72d Add more type hints to helpers (#18196)
* Test typing for helpers.__init__ and temperature

* Add type hints to helpers.sun

* Add type hints to helpers.signal

* Add type hints to helpers.entity_values

* Add type hints to helpers.dispatcher
2018-11-04 22:46:42 +01:00
cdce8p
959fa81ea6 Fix temperature interval Thermostat HomeKit (#18192)
* Will round to nearest .0 or .5
2018-11-04 22:04:51 +01:00
Martin Hjelmare
9a6c229b1d Refactor mysensors message handling (#17214)
* Refactor mysensors message handling

* Add handler module and register handlers per message type or message
  sub-type. This will allow easier extension of message handling in the
  future.
* Move some common functions to a helpers module.

* Add node handler and signal

* Fix inconsistent return

* Upgrade pymysensors to 0.18.0

* Fix bug in message modification.
2018-11-04 21:08:27 +01:00
rafale77
4a7507bcea Update python-openzwave to 0.4.11 (#18160)
* Update Python OpenZWave to 0.4.11

* Update requirements_all.txt
2018-11-04 14:21:53 -05:00
Johann Kellerman
44556a86e3 SMA: Optional import in schema & backoff fix (#18099) 2018-11-04 19:09:14 +02:00
Fabian Affolter
e161dc3b77 Upgrade toonlib to 1.1.3 (#18189) 2018-11-04 17:22:03 +01:00
Troy Kelly
dbf721cd2c Added AU (Australia) (#18183)
Added missing Australia region
2018-11-04 15:46:02 +01:00
jjlawren
0992e83f8d Remove config (breaking change) (#18153) 2018-11-04 15:20:32 +01:00
Pascal Vizeli
a498e15910 Add support for TensorFlow in official docker (#18191) 2018-11-04 15:19:48 +01:00
Pascal Vizeli
27e159f63f Handle TensorFlow like OpenCV (#18185)
* Handle TensorFlow like OpenCV

* Update requirements_all.txt
2018-11-04 15:15:14 +01:00
Paulus Schoutsen
7b53238f9b Merge pull request #18188 from home-assistant/816
0.81.6
2018-11-04 14:17:23 +01:00
Paulus Schoutsen
075169a7a9 Bumped version to 0.81.6 2018-11-04 13:20:25 +01:00
Pascal Vizeli
3abe49bace Bugfix discovery (delete/mqtt) call for Hass.io (#18159)
* Bugfix discovery delete call for Hass.io

* Fix host

* fix tests
2018-11-04 13:20:20 +01:00
Pascal Vizeli
eb0d989c88 Bugfix discovery (delete/mqtt) call for Hass.io (#18159)
* Bugfix discovery delete call for Hass.io

* Fix host

* fix tests
2018-11-04 12:19:04 +01:00
Jorim Tielemans
42cb23f768 Update Coinbase icons (#18172)
* Add extra icons

and don't rely on the name

* Use dictionary for icons

use safe get() with default value

* Use better vars
2018-11-04 09:50:00 +01:00
Florian Klien
5418e0510d XMPP HTTP upload (#17426)
* notify.xmpp: first working http upload

* extension guessing for upload

* docstrings, flake8, pylint

* hass.async_add_executor_job(...)

* catch more errors, allow unverified SSL request

allow user to specify unverified SSL request to URL
cleaner code
catch more exceptions

* pylint

* catching XMPP exceptions, timeout for requests call

removed calls for roster and presence
added timeout for upload request call
cleared up debug, info, warning messages
cleared up requests call for secure and insecure retrieval of image
catching IqError, IqTimeout, XMPPError from slixmpp
docstring updated

* added timout for http upload of local files

* timeout, mimetypes, random filenames

guessing filetypes and mimetypes with stdlib mimetypes
setting a random filename for privacy
working around slixmpp timeout issues with asyncio.wait_for

* code cleanup

* added file upload for rooms/groupchats

* version bump for slixmpp to 1.4.1

added NotConnectedError, removed double catches of IqErrors
removed asyncio import

* slixmpp 1.4.1 in requirements_all

* added url and path templating

* Minor changes

* fixed review requests

fixed possible path issue for foo/../bar/ paths
fixed possible access for non-whitelisted files
fixed None or X
fixed try-else block, moved else block into try
fixed raising error in upload_file if url is None
fixed using data.get after it's already been checked
fixed added docstring for tiny get_url function
2018-11-04 09:17:05 +01:00
Anders Melchiorsen
164c68093b Improve netgear_lte logging when unconnected (#18163)
* Improve netgear_lte logging when unconnected

* Use callback
2018-11-04 09:15:57 +01:00
Jorim Tielemans
5dd691e55d Rename huawei_lte.py to test_huawei_lte.py (#18170) 2018-11-04 01:33:05 +01:00
Corey Edwards
155df912e5 Add option to manually specify device detection method (#17852)
* Add option to manually specify device detection method

* Fix style and lint issue
2018-11-03 23:48:08 +01:00
Joakim Sørensen
610b0b6494 Add Tautulli sensor platform (#17835)
* Adds Tautulli as a sensor platform.

* Remove blank last line.

* Rewrite the platform to comply with review.

* Linting issues.

* Remove tailing newline.

* Corrected typo

* Correcte check_connection, removed wierd defaults, added line in imports, removed unused var, use the correct user list.

* Use dict[key] for required config options.

* Minor changes
2018-11-03 23:47:31 +01:00
rafale77
f76ccb636c Add support for various load level devices (#18161) 2018-11-03 22:25:05 +01:00
Paulus Schoutsen
b2bdf05cae Bumped version to 0.82.0b1 2018-11-03 19:18:38 +01:00
Paulus Schoutsen
461e6acf5c Bump frontend to 20181103.1 2018-11-03 19:18:33 +01:00
Paulus Schoutsen
fbcf0880f3 Bump frontend to 20181103.1 2018-11-03 19:18:20 +01:00
Paulus Schoutsen
9bf824bf00 Bumped version to 0.82.0b0 2018-11-03 13:48:45 +01:00
Paulus Schoutsen
0009e7bde9 Merge remote-tracking branch 'origin/master' into dev 2018-11-03 13:48:19 +01:00
Paulus Schoutsen
67e62e8020 Merge remote-tracking branch 'origin/rc' into dev 2018-11-03 13:48:16 +01:00
Paulus Schoutsen
e8e135fd25 Update translations 2018-11-03 13:47:36 +01:00
Paulus Schoutsen
63e53fdf15 Bump frontend to 20181103.0 2018-11-03 13:47:13 +01:00
Paulus Schoutsen
ed3ca2b74f Merge pull request #18144 from home-assistant/rc
0.81.5
2018-11-03 13:27:15 +01:00
Paulus Schoutsen
91a93b0060 Merge remote-tracking branch 'origin/master' into rc 2018-11-03 12:38:00 +01:00
Paulus Schoutsen
6d3167fcd4 Bumped version to 0.81.5 2018-11-03 12:36:51 +01:00
jjlawren
255607f3a5 Remove FFmpeg input tests (#18131)
* Remove FFmpeg input tests

* Not needed here

* Removing tests for removed functionality

* Minor lint

* Fix tests to reflect removed config option

* Remove async service registration by request

* More lint

* Unused imports

* Make it a non-breaking change

* Update ffmpeg.py
2018-11-03 12:36:47 +01:00
jjlawren
9807ba1a5d Remove FFmpeg input tests (#18131)
* Remove FFmpeg input tests

* Not needed here

* Removing tests for removed functionality

* Minor lint

* Fix tests to reflect removed config option

* Remove async service registration by request

* More lint

* Unused imports

* Make it a non-breaking change

* Update ffmpeg.py
2018-11-03 12:36:22 +01:00
alex9446
782a90a535 Fix hassio command timeout (#17567)
* fix hassio command timeout

* Increased command timeout
2018-11-03 11:04:17 +01:00
Fabian Affolter
7caddd48cd Fix typos and update docstrings (#18137) 2018-11-03 10:24:02 +01:00
Adam Belebczuk
5c99862878 Allow disabling WeMo Discovery (#18079)
* WeMo - Disable Discovery - New config option

* WeMo - Disable Discovery - Change log level to debug

* WeMo - Disable Discovery - Change logging level
2018-11-02 21:42:24 -06:00
Pascal de Ladurantaye
6a5f9faa33 Add optional ttl config to route53 component (#18135)
* Add optional ttl config to route53 component

* linting :)
2018-11-02 21:41:26 -06:00
mtl010957
03d94df3cd Fix DTE Energy Bridge V2 scaling issue. (#18124) (#18129) 2018-11-02 22:48:17 +01:00
Jason Hunter
45484ba569 TensorFlow image_processing component (#17795)
* initial tensorflow image_processing component

* linting fixes

* make displayed attribute a summary of objects

* fix missed merge conflict and add warning supression back in for CPU type

* restructure tensorflow component to install on the fly, remove from Docker

* add both matches and summary as attributes

* address review comments

* do not use deps folder as default, as it should only be managed by HA.  Update to have tensorflow in root config directory
2018-11-02 21:57:03 +01:00
Robert Svensson
92c536ec0e Don't create a switch for POE device if said device is Cloud key (#18117) 2018-11-02 21:09:16 +01:00
Adam Mills
1f290bad94 Update fan/demo tests to async (#18109)
* Update fan/demo tests to async

* Use async_create_task
2018-11-02 21:08:22 +01:00
Adam Mills
dd938d7460 Async generic thermostat tests (#18111) 2018-11-02 21:06:59 +01:00
Paulus Schoutsen
73ed2ab164 bump frontend to 20181026.4 2018-11-02 20:09:12 +01:00
Joakim Sørensen
283407fe6c Exposes initial attribute on the entity. (#18123) 2018-11-02 16:52:02 +01:00
Aaron Bach
97e928df4a Update Pollen.com to use numpy for trend analysis (#18107)
* Update Pollen.com to use numpy for trend analysis

* Hound

* Linting
2018-11-02 15:48:22 +01:00
vacumet
a39846bad9 Changed from pifacecommon 4.1.2 to 4.2.2 to make the piface digital i/o boards work on rpi like 3 (#18101) 2018-11-02 14:44:20 +01:00
Maikel Punie
3fe895c18f Adding climate.velbus support (#18100)
* Adding climate.velbus support

* Fix version

* fixed houndci-bot

* More fixes

* Fix typos and ordering
2018-11-02 14:43:17 +01:00
Paulus Schoutsen
d7efe274c1 Merge pull request #18122 from home-assistant/rc
0.81.4
2018-11-02 14:08:21 +01:00
Paulus Schoutsen
91b7d56aa6 Bumped version to 0.81.4 2018-11-02 14:07:02 +01:00
Paulus Schoutsen
1895e03874 Frontend bump to 20181026.3 2018-11-02 14:06:49 +01:00
Adam Mills
0a301f7dcb Convert nsw rural fire tests to async (#18112) 2018-11-02 14:03:05 +01:00
Oleksii Serdiuk
58c7ee649d Darksky: Round all temperatures to 1 decimal place (#18119)
Some temperatures were not rounded to 1 decimal place:
`temperature_low`, `apparent_temperature_low`, `temperature_high`,
`apparent_temperature_high`.
2018-11-02 13:44:53 +01:00
Paulus Schoutsen
d80dce31da Merge pull request #18120 from home-assistant/rc
0.81.3
2018-11-02 13:25:53 +01:00
Diogo Gomes
94f24e6d49 Upgrade pyipma (#17992)
* bump dependency version

* Add more context to debug message

Co-Authored-By: dgomes <diogogomes@gmail.com>

* shorten debug messages
2018-11-02 13:25:32 +01:00
Paulus Schoutsen
2e169320a4 Bumped version to 0.81.3 2018-11-02 12:33:02 +01:00
Anders Melchiorsen
dce6a9f882 Fix time zone for flux switch (#18102) 2018-11-02 12:32:52 +01:00
Anders Melchiorsen
93689d68f7 Fix time zone for flux switch (#18102) 2018-11-02 12:32:41 +01:00
cdce8p
5a802c1069 Revert HomeKit update to 2.2.2 (#18069) 2018-11-02 12:31:58 +01:00
Jason Hu
602b59aed8 Change cv.string to [cv.string] (#18050) 2018-11-02 12:31:58 +01:00
Nate Clark
6f8ac7f5c9 Konnected: Pass hass_config to load_platform (#18027) 2018-11-02 12:31:57 +01:00
Tomas Hellström
5910161202 fix naming bug (#17976) 2018-11-02 12:31:56 +01:00
Paulus Schoutsen
afc70fda50 Bump frontend to 20181026.2 2018-11-02 12:31:45 +01:00
Leothlon
8613694544 Added service select_video_output and video_out attribute (#18081)
* Added service select_video_output and video_out attribute

* Fixed white lines and long lines

* Made line shorter

* Added period to comment according to flake8 rules

* Imported domain const

* Prefixed service with platform name

* changed "video output" to "hdmi output" to better reflect eiscp cammand

* video_output to hdmi_output rename
2018-11-02 11:07:36 +01:00
Neil Crosby
cb7ae5cdf2 Allow MS face detection to handle updating entities when no face is detected (#17593)
* Allow Microsoft face detection to handle updating entities when no face is detected

* Remove microsoft_face_detect_no_face_detected.json and hard code in simple empty list into the tests
2018-11-02 10:50:43 +01:00
Ville Skyttä
a4c0c34028 Use ssdp udn uuid as Samsung TV unique id (#18022) 2018-11-02 11:50:07 +02:00
kbickar
6eba7c4ff3 Add binary sensors for sense energy monitor (#17645)
* Added error handling for sense API timeouts

* Moved imports in function

* Moved imports to more appropriate function

* Change exception to custom package version

* Updated sense_energy library to 0.4.2

* Added binary sensors for individual devices

* Whitespace updates

* Split into component, sensors, binary sensors

* Fixed whitespace

* Fixed whitespace

* Moved time constant into sensor file

* Regenerated requirements

* Fixed whitespace

* Updated component dependency

* Fixed whitespace

* Code cleanup

* High and low target temps are also supported if target is supported

* Revert "High and low target temps are also supported if target is supported"

This reverts commit 66b33dc2b8.

* Added all sense components to .coveragerc

* Added check authentication exception

* binary/sensor platforms loaded in setup

* Changed to add all detected devices

* Changed to add all sensors on setup

* Code cleanup

* Whitespace

* Whitespace

* Added sense as requirement for platform

* pylint fixes

* Whitespace

* Switched requirement to dependency

* Made non-class function

* Whitespace

* Removed unneeded checks

* Increased API delay to 60 seconds

* Added guard clause for discovery_info

* Tidy code

* Whitespace
2018-11-02 10:13:14 +01:00
Rick van Hattem
82edea6077 Removed assumptions about provided upnp data (#17604)
* Removed assumptions about incomplete UPnP devices

* Removed assumptions about incomplete UPnP devices
2018-11-01 22:59:42 +01:00
Petro31
9b47af68ae Add surround programs to zone 2+ (#17445)
* Add surround programs to zone 2+

Add surround programs and surround program to any zone that supports it.

* Update yamaha.py

removed double fetching.
2018-11-01 21:26:53 +01:00
Lev Aronsky
02b46e2ba3 Ignore min_cycle_duration when manually controlling the thermostat. (#16128)
* Ignore min_cycle_duration when manually controlling the thermostat.

* style

* Generic thermostat: add minimum cycle duration to keep-alive tests.

There was a bug in previous versions of the code, that would not execute
the keep-alive action if the minimum cycle duration hasn't passed.
This test verifies that the keep-alive action is executed correctly.

* Generic thermostat: added tests to verify that changing the
thermostat mode manually triggers the switch, regardless of
minimum cycle duration.

* Updated tests to use `common` module instead of the deprecated `climate`
2018-11-01 21:25:50 +01:00
Andy Castille
e9ae862fca Update to DoorBirdPy v2 (again) (#14933)
* Update to DoorBirdPy v2

* Move get_schedule_entry to DoorBirdPy, general cleanup

* Update requirements_all.txt

* Requested changes.

* Update requirements post merge.

* Correct call to async_add_executor_job

* Update clear schedule endpoint to be async

* Refactor view and device favorite reset

* Register listeners so events show in GUI

* Add token based authorization

* Update requirements

* Linting issues

* Linting issues

* Linting issues

* Correct logging and inheritance
2018-11-01 21:23:06 +01:00
Oleksii Serdiuk
31dc6832e7 Darksky: Fetch summary for daily forecasts (#18031) 2018-11-01 21:57:32 +02:00
Pawel
c3e3f662f4 Always save current position if payload is numeric value (#16148)
* Change of behaviour. Allow user to configure either a position topic or a state topic but not
both.

* optimistic mode in set_cover and tests added

* optimistic mode in set_cover_position using percentage_position

* fixes accroding to Martin review.

* added validation schema for set_position_topic and get_position_topic

* check only set_position_topic in supported_features.

* Multidoc string fix.
2018-11-01 20:09:43 +01:00
Charles Garwood
bcea3a9cba Don't try to re-add existing Z-Wave entities (#17995)
* Keep track of created entities

* lint

* Update tests
2018-11-01 19:38:23 +01:00
Rohan Kapoor
23290fa6ee Use a fixture for dialogflow calls in unit tests (#17999)
* Use a fixture for dialogflow calls in unit tests

* Lint
2018-11-01 19:37:38 +01:00
Aaron Bach
4ee21e66dc Update Pollen.com sensor platform to include asthma info (#18024)
* Update Pollen.com sensor platform to include asthma info

* Updated requirements

* Bump to 2.2.2
2018-11-01 19:36:42 +01:00
cdce8p
4a3f754033 Revert HomeKit update to 2.2.2 (#18069) 2018-11-01 19:35:02 +01:00
Sebastian Muszynski
c75c00d568 Bump python-miio version (#18095) 2018-11-01 17:53:48 +01:00
Fabian Affolter
a9361482d9 Catch KeyError if data is not available (fixes #18082) (#18089) 2018-11-01 16:32:36 +01:00
Malte Franken
83e83520e6 Upgrade georss_client to 0.4 (#18088)
* update geojson_client to 0.3

* update georss_client to 0.4
2018-11-01 16:32:21 +01:00
Fabian Affolter
65e6c50748 Upgrade restrictedpython to 4.0b6 (#18087) 2018-11-01 14:25:45 +01:00
Simon van der Veldt
2a76347071 sensor/wunderground add device_class (#18072)
to relevant sensors
2018-11-01 14:10:43 +01:00
Fabian Affolter
c5f9220500 Upgrade psutil to 5.4.8 (#18086) 2018-11-01 09:03:18 -04:00
Mike Megally
afc109a585 Pass though file_url from extended data attrs (#17801)
* pass though file_url from extended data attrs so synology chat bot can send files

* some code cleanup
2018-11-01 13:33:51 +01:00
Fabian Affolter
a69c3953f1 Upgrade youtube_dl to 2018.10.29 (#18085) 2018-11-01 13:26:12 +01:00
Fabian Affolter
a3e77bc5f3 Upgrade sqlalchemy to 1.2.13 (#18084) 2018-11-01 13:25:45 +01:00
Fabian Affolter
957320f265 Upgrade locationsharinglib to 3.0.7 (#18083) 2018-11-01 13:00:24 +01:00
Mattias Welponer
2fce79eccf HomematicIP_Cloud fix test (#17376)
* fix-homematicip_cloud-flow_config

* remove-homematicip_cloud-flow_config-stale-print

* Fix redundant backslash between brackets
2018-11-01 12:21:59 +01:00
Fabian Affolter
caa48fab13 Upgrade astral to 1.7.1 2018-11-01 11:26:33 +01:00
Jonathan Keljo
19ebdf2cf1 Add a component for GreenEye Monitor (#16378)
* Add a component for GreenEye Monitor

[GreenEye Monitor](http://www.brultech.com/greeneye/) is an energy
monitor that can monitor emergy usage of individual circuits, count pulses
from things like water or gas meters, and monitor temperatures. This component
exposes these various sensors in Home Assistant, for both data tracking and
automation triggering purposes.

* Consolidate sensors

* lint

* .coveragerc

* - cv.ensure_list
- DOMAIN, where appropriate
- defaults to schema
- single invocation of async_load_platform
- async_create_task instead of async_add_job
- fail if no sensors
- monitors required
- async_add_entities
- call add_devices once
- remove unused schema
- use properties rather than set fields
- move _number and unique_id to GEMSensor
- remove unnecessary get(xxx, None)
- keep params on one line when possible
- new-style string format

* Fix `ensure_list` usage, log message

* Pass config through
2018-11-01 10:46:11 +01:00
akloeckner
e9f96bfd7f Allow different types to match in pilight (#17922)
* Allow different types to match

see discussion here: https://github.com/home-assistant/home-assistant/pull/17870

* lint spaces

* line length < 79
2018-11-01 10:37:19 +01:00
MatteGary
ab8299b6cf Fix in Daikin.py for set swing_mode and speed (#18013) 2018-11-01 10:29:48 +01:00
Jared Quinn
1c5800d98b Added identifier and name to connect/disconnect events (#18078)
* Added identifier and name to connect/disconnect events

* Fix indentation from failed tests
2018-11-01 09:48:44 +01:00
thoscut
bfa86b8138 Add message template support for alert component (#17516)
* Add problem text to message if available

* Revert "Add problem text to message if available"

This reverts commit 7be519bf7f.

* Cleanup setup

* Add message template support

* Fix for failing test

* Added tests

* Refactor changes

* Fix lint violation

* Fix failing tests

* Unify handling for message and done_message parameter and sending function

* Update tests

* Fix lint warnings
2018-11-01 09:48:11 +01:00
Bram Kragten
4163889c6b Add view commands to Lovelace (#18063)
* Add get and update view command

* Add add view command

* Add move view command

* Add delete command

* lint
2018-11-01 09:44:38 +01:00
Tsvi Mostovicz
329d128e03 Change test to parametrized test using pytest (#18047) 2018-11-01 09:40:31 +01:00
Jason Hu
f516550f9f Fix camera mjpeg stream handling (#18076)
* Fix handle_async_mjpeg_stream

* Lint
2018-11-01 09:28:23 +01:00
Daniel Høyer Iversen
32ee4f0714 remove schedule_update_ha_state from mill (#18080)
* remove schedule_update_ha_state from mill

* remove return
2018-11-01 09:24:25 +01:00
Joakim Sørensen
3d1a324f33 Add functionality to the version sensor (#18067)
* Added functionality to the version sensor.

* Corrected typo.

* Change default name to not cause a breaking change.

* Use vol.lower in the schema.

* Add missing blank line.

* Change order of cv.string and vol.Lower.
2018-11-01 09:20:30 +01:00
Robert Svensson
a9140dc8f5 deCONZ - retry if setup fails (#17772)
* Make component retry if setup fails
* Improve overall test coverage
2018-10-31 22:38:04 +01:00
Daniel Høyer Iversen
145677ed75 Mill, support opeation mode (#18059) 2018-10-31 21:39:13 +01:00
Johann Kellerman
7363378ac4 Update SMA sensor to pysma 0.2.2 (#17988) 2018-10-31 21:09:00 +02:00
Phil Frost
93706fa568 Report correct thermostat mode to Alexa (#18053)
We were erroneously reporting the _previous_ mode. So if the thermostat was off
and the user asks, "Alexa, set the thermostat to heat", the thermostat would be
set to heat but Alexa would respond, "The thermostat is off."

Bug caught by @Thunderbird2086 at
https://github.com/home-assistant/home-assistant/pull/17969#issuecomment-434654345
2018-10-31 16:09:13 +01:00
Bram Kragten
b763c0f902 Extract ruamel.yaml to util with secrets, lovelace ws decorators (#17958)
* Extract ruamel.yaml to util, ws decorators, secrets

* lint

* Extend SafeConstructor

Somehow my last commit is gone after rebase...

* lint

* Woof...

* Woof woof...

* Cleanup type hints

* Update homeassistant/scripts/check_config.py

* lint

* typing
2018-10-31 13:49:54 +01:00
Jason Hu
1578187376 Change cv.string to [cv.string] (#18050) 2018-10-31 12:52:21 +01:00
mvn23
b12e79e5cf Add opentherm_gw services (#17762)
* Move components/opentherm_gw.py to components/opentherm_gw/__init__.py

* Update requirements-all.txt

* Await set_clock coroutine rather than scheduling it.

* Create task for async_load_platform
2018-10-31 12:33:43 +01:00
Adam Belebczuk
239e314dc1 Add services.yaml entry for new WeMo Humidifier platform service (#18032)
* WeMo Humidifier - Add entry to services.yaml

* WeMo Humidifier - Fix typo in wemo.py

* WeMo Humidifier - Fixed incorrect parameter name
2018-10-31 10:54:15 +01:00
kennedyshead
e85e5789a2 Bumping aioasuswrt to 1.1.2 (#18042) 2018-10-31 09:44:41 +01:00
Ville Skyttä
9c840f93f0 Use const.SUN_EVENT_* more (#18039) 2018-10-31 09:10:28 +01:00
Nate Clark
dcc46226ee Konnected: Pass hass_config to load_platform (#18027) 2018-10-31 08:42:33 +02:00
Philip Rosenberg-Watt
314e5ac296 Add SMA sensor SSL verification option (#18033) 2018-10-31 08:22:55 +02:00
Gavin Mogan
9c77465c0e Upgrade to asuswrt 1.1.1 to better handle mac addresses with letters in them (#18030)
* Upgrade to asuswrt 1.1.1 to better handle mac addresses with letters in them

Signed-off-by: Gavin Mogan <git@gavinmogan.com>

* Update requirements_all as well

Signed-off-by: Gavin Mogan <git@gavinmogan.com>
2018-10-31 06:33:04 +01:00
kennedyshead
4073f63256 Async version of melissa (#17721)
* rebase upstream

* Fixed tests

* Fixing lint
2018-10-30 21:29:11 +01:00
Diogo Gomes
9565c0bd1d Upgrade pyipma (#17992)
* bump dependency version

* Add more context to debug message

Co-Authored-By: dgomes <diogogomes@gmail.com>

* shorten debug messages
2018-10-30 21:25:12 +01:00
Daniel Shokouhi
9cb5ea20af Fix Bloomsky api call (#18016) 2018-10-30 21:23:44 +01:00
Adam Belebczuk
eef9246db1 Support for WeMo Humidifier (#17996)
* Fix Vera climate component to use correct states

Changed the Vera climate component so it uses the STATE_* states from the base climate component. This will allow it to work with Google Assistant.

* Wemo Humidifier - Initial Commit

* WeMo Humidifier - First draft of component

* WeMo Humidifier - Removed direct IO from property

* WeMo Humidifier - Trivial comment change

* Added myself as codeowner for WeMo

* WeMo Humidifier - Fixed various syntax & lint issue

* WeMo Humidifier - Small comment addition

* WeMo Humidifier - Fix TypeError: 'WemoHumidifier' object is not iterable

* WeMo Humidifier - Rename set humidity service

* WeMo Humidifier - Add to .coveragerc

* WeMo Humidifier - Fixed lint/pylint issues

* WeMo Humidifier - First round of requested changes

* WeMo Humidifier - Round two of requested changes

* WeMo Humidifier - Third round of requested changes

* WeMo Humidifier - Fixed whitespace issue on dict comprehension

* WeMo Humidifier - Fourth round of requested changes

* WeMo Humidifier - Corrected typo in async_add_executor_job call

* WeMo Humidifier - Fixed spacing before inline comments
2018-10-30 21:19:49 +01:00
Neil Crosby
865ea82432 Allow jinja namespace command to work. (#18011) 2018-10-30 19:13:20 +01:00
Ville Skyttä
4d9ef9e795 Import homeassistant domain instead of hardcoding it (#17985) 2018-10-30 17:38:09 +02:00
Tsvi Mostovicz
87bd2a32e4 Change hebrew date at sunset (#17449)
* Change date at sunset

* Fix tests to actually run and add fix to component

* Make tests pass

* Use get_astral_event_next instead of get_astral_event_date

* Revert to using get_astral_event_date

* Make tox happy: reset state on tearDown
2018-10-30 15:21:58 +01:00
Rohan Kapoor
f0693f6f91 Switch mailgun webhooks to the new Mailgun webhook api (#17919)
* Switch mailgun webhooks to the webhook api

* Change mailgun strings to indicate application/json is in use

* Lint

* Revert Changes to .translations.

* Don't fail if the API key isn't set
2018-10-30 12:12:41 +01:00
Anders Melchiorsen
3de822a0e2 RFC: Static templates match no entities, not all (#17991)
* Static templates match no entities, not all

* Clean up test values
2018-10-30 12:03:27 +01:00
Nick Whyte
71b56363d3 Reverse out change #14234 BOM Weather throttle fix (#17468)
* Reverse out change #14234 BOM Weather throttle fix

Reverted back to original throttle code to ensure sensors are updated on time.

* Fixed lint issues

* Review as a commit

* Use last_updated for attributes

* lint

* lint
2018-10-30 11:56:00 +01:00
Paulus Schoutsen
f400925825 Merge remote-tracking branch 'origin/master' into dev 2018-10-30 11:39:16 +01:00
Paulus Schoutsen
20fb7b59ef Update translations 2018-10-30 11:35:40 +01:00
Paulus Schoutsen
622f23abd7 Update frontend to 20181030.0 2018-10-30 11:35:25 +01:00
Tomas Hellström
5337d0b4f3 fix naming bug (#17976) 2018-10-30 10:44:07 +01:00
Paulus Schoutsen
2aabdf29bb Merge pull request #17970 from home-assistant/rc
0.81.2
2018-10-30 08:13:59 +01:00
Luc Touraille
b71dc752fa Upgrade aiofreepybox (#17989)
- Add features to get connection status and stats
 - Improve error reporting
 - Fix issue with the authentication file (#16934)
2018-10-30 07:35:23 +01:00
Phil Frost
e16793013a Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests

This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.

I had two use cases in mind:

1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.

2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.

* Include properties in all Alexa responses

The added _AlexaResponse class provides a richer vocabulary for handlers.

Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.

* Fix setting temperature with Alexa thermostats

Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-29 22:16:35 -04:00
Daniel Høyer Iversen
98163504fb Mill service (#17971)
* Mill service

* style
2018-10-29 23:36:49 +01:00
Anton Sarukhanov
32cb666dac Update Avi-On to work with latest API (#17780)
* Update Avi-On to work with the API.

* Use voluptuous defaults instead of .get()

* Bump library version.

* Remove unnecessary voluptuous defaults. Fix manually-configured devices.

API-discovered devices are already Avion objects, but manually-configured devices need to be instantiated as Avion objects first.

* Use .get() where appropriate.

* Remove default
2018-10-29 23:29:27 +01:00
Evan Bruhn
03dd1e6870 Updated ring_doorbell dependency to 0.2.2 (#17945)
- Resolves an issue with the sensor platform for Ring Spotlight Cam devices
2018-10-29 23:27:12 +01:00
Victor Cerutti
cb73a8bbb0 Météo-france sensor : current weather and 1 hour rain forecast (#17773)
* 🌧 Meteo France rain forecast

* do not fail on wrong config

* Update name of sensor class

* do not show sensor if not working

* Update .coveragerc

* ability to submit insee location code without final 0 needed by meteo-france

* Lynting

* more lynting

* update comment

* block comment linting

* reducing length of long lines

* linting

* Update météo-france platform

Now work with pypi package and monitored conditions

* remove error log

* Update requirements_all.txt

* Increase scan interval to 5 minutes

* Update meteo_france according to review

* better error handling of location missing some monitored conditions

* fix lint error

* moving error log

Errors are now catched at sensor initialization and state is set when updating the data

* Update updating of sensor
2018-10-29 23:22:47 +01:00
Phil Frost
3169c0416e Update Alexa tests to async syntax (#17965)
See https://github.com/home-assistant/home-assistant/issues/12614
2018-10-29 17:57:27 -04:00
Paulus Schoutsen
1e03f945b5 Don't use keyset (#17984) 2018-10-29 21:32:37 +01:00
Paulus Schoutsen
a91d894132 Update requests to 2.20.0 (#17978) 2018-10-29 21:32:36 +01:00
Paulus Schoutsen
2f71f8908b Don't use keyset (#17984) 2018-10-29 21:25:17 +01:00
Paulus Schoutsen
c38a0f1bf0 Update requests to 2.20.0 (#17978) 2018-10-29 21:16:05 +01:00
ehendrix23
deeb288daf Change source, add attributes, and improve state of DirecTV (#17536)
* Enhancements for DirecTV media player

Following enhancements have been made:

1. Added debug logging
2. Added ability to change channel using select_source service of the remote platform.
3. State will now show paused if a recorded program is paused, for live TV playing will always be returned.
4. Added the following attributes:
    a. media_position: current position of the media (in seconds)
    b. media_position_updated_at: timestamp when media_position was updated.
   c. source: current source (channel).
   d. media_isbeingrecorded: if current media is being recorded or not.
   e. media_rating: TV/Movie rating of the media
   f. media_recorded: if current media is recorded or live TV
   g. media_starttime: Timestamp media was aired

Reordered properties to follow same order as how they are in __init__.py of remote platform.

* Fixed error and cleaned up few items

Fixed an issue when determining if a program is recorded or not.
Cleaned up some coding.

* Attribute last position update only updated when position changed.

The attribute media_position_updated_at will only be updated if the position changed (thus media is playing for recorded or live TV).
Added assumed_state; will be set to False if in standby or when a recorded show is watched. For live TV it will be set to True.

* Added some empty lines for easier reading

Added some empty lines before returns to improve readability.

* Seperated words in constants

Seperated the words in constants.

* Fix _lastupdate to _last_update

Split words in _lastupdate to _last_update as I missed it.
2018-10-29 21:06:37 +01:00
Paulus Schoutsen
d6913c6914 Fix operation mode for Alexa thermostat (#17972) 2018-10-29 20:52:34 +01:00
Phil Frost
af5eacf303 Fix spelling error in log output (#17963) 2018-10-29 19:40:32 +01:00
Mariusz Łuciów
a87a5d266e Fixed copy-paste errors (#17948) 2018-10-29 19:32:58 +01:00
jxwolstenholme
027f173a08 Added codeowner for bt_smarthub (#17947) 2018-10-29 19:27:03 +01:00
Paulus Schoutsen
66d0fb7dbf Bumped version to 0.81.2 2018-10-29 19:22:59 +01:00
Paulus Schoutsen
3a8891d9ac Pass hass_config to load_platform (#17952)
* Pass hass_config to load_platform

* Fix tests

* Lint
2018-10-29 19:22:40 +01:00
Robert Svensson
04e0fd1d46 Fix controller not being stored when setup fails and sequentially fails the retry functionality (#17927) 2018-10-29 19:21:38 +01:00
Paulus Schoutsen
6ae345b01c Pass hass_config to load_platform (#17952)
* Pass hass_config to load_platform

* Fix tests

* Lint
2018-10-29 19:21:21 +01:00
Robert Svensson
b03e6050c5 Fix controller not being stored when setup fails and sequentially fails the retry functionality (#17927) 2018-10-29 19:09:54 +01:00
Paulus Schoutsen
98dfbf2565 Disable upnp from being discovered (#17937) 2018-10-29 15:52:30 +01:00
Paulus Schoutsen
3740424725 Fix venv check (#17939)
* Fix venv check

* Lint
2018-10-29 15:50:44 +01:00
Paulus Schoutsen
360addfb0b Fix incorrect chevy discovery (#17942) 2018-10-29 15:49:57 +01:00
Paulus Schoutsen
f4ac317d64 Permissions improv (#17811)
* Break up permissions file.

* Granular entity permissions

* Add "all" entity permission

* Lint

* Fix types
2018-10-29 11:28:04 +01:00
Joakim Sørensen
d1ef875132 Fix for verify_ssl in the pi_hole sensor. (#17910) 2018-10-29 11:27:37 +01:00
Steven Looman
96c5e4c507 Fixes for upnp-component/#17753 and missing hass-data when only setup from config entry (#17868)
* Upgrade to async_upnp_client==0.13.0, fixing #17753

* Fix missing 'local_ip' when upnp-component itself is not setup, but ConfigEntry is
2018-10-29 08:10:01 +01:00
Rohan Kapoor
851d7e22e7 Make light.yeelight stop doing IO when accessing properties (#17917) 2018-10-29 08:07:57 +01:00
Anders Melchiorsen
e5c97fdcab Extract entity ids from all templates (#17902) 2018-10-29 08:03:10 +01:00
Ville Skyttä
3e6de21302 Upgrade pytest to 3.9.3 (#17921) 2018-10-29 07:02:34 +01:00
Robert Svensson
4579717317 Axis - prepare for config entry (#17566)
Make component more in line with other more modern components in preparation for config entry support.
2018-10-29 06:52:30 +01:00
kennedyshead
3802fec568 Merge conflicting changes (#17761) 2018-10-28 23:49:55 +01:00
Richard Patel
b62b3b26f2 Monitor all sensor types by default to rtorrent (#17894)
* Default to all sensor types for monitoring

* Cleanup code

* 👀

* Chop long line
2018-10-28 23:37:28 +01:00
Eduard van Valkenburg
62752e0065 Updated Brunt code owner (#17854)
* Updated Brunt code owner

* Fix platform
2018-10-28 23:03:43 +01:00
Julius Mittenzwei
df65d2151d updated version of xknx (#17912) 2018-10-28 23:03:27 +01:00
Ville Skyttä
c9c707e368 Start type annotating/testing helpers (#17858)
* Add type hints to helpers.intent and location

* Test typing for helpers.icon, json, and typing

* Add type hints to helpers.state

* Add type hints to helpers.translation
2018-10-28 21:12:52 +02:00
Luca Angemi
0f877711a0 Fixes Telegram webhooks (#17554) 2018-10-28 19:39:23 +01:00
Rohan Kapoor
60080a529d Migrate dialogflow over to the new webhook component (#17804)
* Migrate dialogflow over to the new webhook component

* Updating dialogflow unit tests

* Lint

* Revert changes to HomeAssistantView

* Use json_response from aiohttp
2018-10-28 19:25:43 +01:00
Mariusz Łuciów
38576e5b74 Corrected fan device type in google assistant to fan (#17792) 2018-10-28 14:53:47 +01:00
emontnemery
3f3955c1cd Fix RFLink issue #17875 (#17889) 2018-10-28 13:57:44 +01:00
Evan Bruhn
6cb735271f Fix logi_circle sensor update method naming (#17909)
Resolves regression in 0.81
2018-10-28 13:46:28 +01:00
Lindsay Ward
0acd4b28f9 Add myself to CODEOWNERS for Yeelight Sunflower light platform (#17896) 2018-10-28 12:18:44 +01:00
Paulus Schoutsen
b6a799499a Merge pull request #17895 from home-assistant/rc
0.81.1
2018-10-28 08:37:44 +01:00
Adam Belebczuk
cbadd64b28 Fix Vera climate component to use correct states (#17892)
Changed the Vera climate component so it uses the STATE_* states from the base climate component. This will allow it to work with Google Assistant.
2018-10-28 08:35:57 +01:00
Paulus Schoutsen
29c9081ca1 Bumped version to 0.81.1 2018-10-27 23:54:15 +02:00
Paulus Schoutsen
1f07909a14 Move migrate to separate WS command (#17890) 2018-10-27 23:54:15 +02:00
Paulus Schoutsen
21686c9263 Allow a list ofr update entity (#17860)
* Allow a list ofr update entity

* Update services.yaml

* Update services.yaml
2018-10-27 23:54:15 +02:00
Aaron Bach
edf2974979 Fixes an issue with OpenUV config import failing (#17831)
* Fixes an issue with OpenUV config import failing

* Update

* Update __init__.py

* Update config_flow.py
2018-10-27 23:54:15 +02:00
Paulus Schoutsen
ea75e3bfa8 bump frontend to 20181026.1 2018-10-27 23:54:15 +02:00
Paulus Schoutsen
9cd8a86eb4 Move migrate to separate WS command (#17890) 2018-10-27 23:51:40 +02:00
Rohan Kapoor
d6e4208665 Switch to using Client from twilio.rest rather than the deleted TwilioRestClient (#17883) 2018-10-27 21:37:07 +02:00
Rohan Kapoor
a0d4595f78 Switch to using Client from twilio.rest rather than the deleted TwilioRestClient (#17885) 2018-10-27 21:36:47 +02:00
Paulus Schoutsen
649bc55a3b Allow a list ofr update entity (#17860)
* Allow a list ofr update entity

* Update services.yaml

* Update services.yaml
2018-10-27 21:34:33 +02:00
Aaron Bach
a22aad50e1 Fixes an issue with OpenUV config import failing (#17831)
* Fixes an issue with OpenUV config import failing

* Update

* Update __init__.py

* Update config_flow.py
2018-10-27 11:07:08 -06:00
Florian Klien
92e9c2aa72 adding myself as yessssms codeowner (#17862) 2018-10-27 14:23:04 +02:00
Ryan Wagoner
2adf5918f5 Fix Alexa unsupported operation_mode off (#17844) 2018-10-27 11:57:04 +02:00
Daniel Høyer Iversen
21870e2167 Mill device state attributes (#17834)
* Mill device state attributes

* lower case
2018-10-27 09:17:48 +02:00
Abílio Costa
6b7cbca04c Alexa motion sensor (#17798)
* Alexa: add motion sensors

* Alexa: add motion sensor tests

* Fix comparison and lint
2018-10-26 23:43:31 +02:00
Fabian Affolter
8a4c78b69f Minor changes to the config validation (#17808) 2018-10-26 23:39:11 +02:00
Mariusz Łuciów
cfbd84f450 Added vacuum dock and pause/unpause traits (#17657) 2018-10-26 23:02:07 +02:00
cgtobi
9f146a3954 Raise PlatformNotReady for RMVtransport if API not available (#17635)
* Raise PlatformNotReady if API not available

* Delete whitespaces

* Revert unwanted breaking changes

* Revert deleted line

* Update homeassistant/components/sensor/rmvtransport.py

* Use await asyncio.wait
2018-10-26 20:18:14 +02:00
Paulus Schoutsen
e28170a0a6 Merge pull request #17809 from home-assistant/rc
0.81
2018-10-26 19:45:29 +02:00
Bram Kragten
3175627363 Add delete command (#17816) 2018-10-26 17:29:33 +02:00
Yevgeniy
86d7bc4962 Add snow to Openweathermap precipitation forecast (#17551)
* Add snow to Openweathermap precipitation forecast

* Fix lint

* Fix pylint

* Add missing docstring
2018-10-26 15:50:30 +02:00
Fabian Affolter
434c848104 Minor changes (#17812) 2018-10-26 15:45:57 +02:00
kennedyshead
92bad453f2 Bumping aioasuswrt version (#17814) 2018-10-26 15:45:38 +02:00
Paulus Schoutsen
644c33cc1e Convert MQTT Light tests to async (#17754) 2018-10-26 15:10:05 +02:00
Bram Kragten
b7896491e3 Lovelace ws: add move command (#17806)
* Check for unique ids + ids are strings

* Add move command

* Add test for move

* lint

* more lint

* Address comments

* Update test
2018-10-26 12:56:14 +02:00
Paulus Schoutsen
dcf8aba150 frontend bump 2018-10-26 12:55:57 +02:00
Paulus Schoutsen
cce8b1183f frontend bump 2018-10-26 12:55:44 +02:00
Paulus Schoutsen
e276e899cf Convert automation tests to async (#17794)
* Convert automation tests to async

* Fix 8 last tests

* Lint
2018-10-26 11:31:14 +02:00
Jeroen ter Heerdt
3f4798b5c3 MQTT Vacuum now passes error messages. (#17685)
* MQTT Vacuum now passes error messages.

* Fixing pylint error

* Use string formatting
2018-10-26 11:07:39 +02:00
Fabian Affolter
714d44c503 Upgrade numpy to 1.15.3 (#17796) 2018-10-26 10:35:21 +02:00
Paulus Schoutsen
121a59abe0 Bumped version to 0.81.0 2018-10-26 10:22:26 +02:00
Paulus Schoutsen
0c7b0bdb44 Fix unloading an entry can leave states around (#17786)
* Add test that tests unloading on remove

* Add more test things

* Untangle entity remove code from entity platform

* Don't add default implementation of async_will_remove

* Keep entity weakref alive
2018-10-26 10:19:59 +02:00
Tomas Hellström
c4b2c2bfcf SMHI weather component not showing correct values in current forecast (#17783)
* fixes not showing current forecast correctly

* Update config_flow.py

* Update smhi.py

* Update requirements_all.txt

* Update requirements_test_all.txt
2018-10-26 10:19:58 +02:00
cdce8p
bc67115df3 Update HAP-python to 2.3.0 (#17778)
* Update HAP-python to 2.3.0

* Fix tests
2018-10-26 10:19:58 +02:00
Aaron Bach
af03390c4f Fixed an incorrect reference in the entity registry (#17775) 2018-10-26 10:19:57 +02:00
Paulus Schoutsen
a4773dc3e4 Update translations 2018-10-26 10:19:28 +02:00
Paulus Schoutsen
ad903f9917 Bump frontend to 20181026.0 2018-10-26 10:19:23 +02:00
Paulus Schoutsen
c00da509a1 Update translations 2018-10-26 10:18:10 +02:00
Paulus Schoutsen
9e286d7c1f Bump frontend to 20181026.0 2018-10-26 10:17:40 +02:00
Andrey Kupreychik
9e33398a7b Bumped NDMS2 client to 0.0.5 to fix unicode characters support (#17803) 2018-10-26 10:06:53 +02:00
Leonardo Brondani Schenkel
47003fc04f deCONZ: configure service can now use 'field' as a subpath together with 'entity' (#17722)
Allow both 'entity' and 'field' to be used simultaneously, where 'field' is used as a sub-path of the device path that is defined by 'entity'.
2018-10-26 09:15:26 +02:00
Rohan Kapoor
b7b62a90e2 Delete sensor.yahoo_finance (#17805) 2018-10-26 08:29:41 +02:00
Ben Schattinger
901c4f18cb Install face_recognition on Docker build (#17502)
* Install face_recognition on Docker

* Update setup_docker_prereqs
2018-10-25 22:56:10 +02:00
Ville Skyttä
43048962f2 Upgrade flake8 to 3.6.0 (#17770)
* Upgrade flake8 to 3.6.0

* flake8/pylint comment tweaks

* flake8 F841 fixes

* flake8 W605 fix

* Ignore pyflakes bug #373 false positives

https://github.com/PyCQA/pyflakes/issues/373

* pycodestyle bug #811 workaround

https://github.com/PyCQA/pycodestyle/issues/811
2018-10-25 23:15:20 +03:00
Paulus Schoutsen
77bf10e37c Fix unloading an entry can leave states around (#17786)
* Add test that tests unloading on remove

* Add more test things

* Untangle entity remove code from entity platform

* Don't add default implementation of async_will_remove

* Keep entity weakref alive
2018-10-25 19:57:36 +02:00
Abílio Costa
9c7d3c2a63 Add contact sensors to alexa smart home (#17704)
* add contact sensors to alexa smart home

* door sensors are binary_sensors

* fix tests; cleanup

* lint

* fix state

* Add missing doc string
2018-10-25 16:46:43 +02:00
Paulus Schoutsen
312d49caec Allow creating signed urls (#17759)
* Allow creating signed urls

* Fix parameter

* Lint
2018-10-25 16:44:57 +02:00
Paulus Schoutsen
b5284aa445 Fix device reg considered changed (#17764)
* Fix device reg considered changed

* Better syntax
2018-10-25 16:43:11 +02:00
Jan van Helvoort
b6e8cafdea typo (#17787) 2018-10-25 09:58:09 -04:00
liaanvdm
3c68db32d6 Restore manual alarm-control-panel state using async_get_last_state (#17521)
* Restore manual alarm-control-panel state using async_get_last_state

This is to address issue #10793

* Added tests for restoring manual alarm state on startup

* Cleaned up test formatting

* Fixed more linting errors

* Changed async methods to use asynch/await syntax

* Removed unused asyncio import
2018-10-25 12:21:20 +02:00
Tomas Hellström
544a3b929f SMHI weather component not showing correct values in current forecast (#17783)
* fixes not showing current forecast correctly

* Update config_flow.py

* Update smhi.py

* Update requirements_all.txt

* Update requirements_test_all.txt
2018-10-25 10:16:09 +02:00
kennedyshead
67d92c4f5d This makes mqtt_template tests async (#17784) 2018-10-25 10:00:07 +02:00
kennedyshead
8bebfba21a Testing async in MQTT_json lights (#17768) 2018-10-25 09:54:53 +02:00
Rohan Kapoor
5024a80d61 Migrate twilio webhooks to the webhook component (#17715)
* Migrate twilio webhooks to the webhook component

* Fix typos in twilio

* Mock out twilio in the tests

* Lint

* Fix regression in twilio response
2018-10-25 09:46:22 +02:00
cdce8p
599390d985 Update HAP-python to 2.3.0 (#17778)
* Update HAP-python to 2.3.0

* Fix tests
2018-10-25 09:45:56 +02:00
Fabian Affolter
577cf0991f Remove username from log entry (#17777) 2018-10-25 09:43:40 +02:00
Fabian Affolter
aa157e17f9 Add wind gust (fixes #17766) (#17774) 2018-10-25 09:33:23 +02:00
Aaron Bach
bd23145331 Fixed an incorrect reference in the entity registry (#17775) 2018-10-24 21:53:18 -06:00
Manuel de la Rosa
a629e1bec2 Add Mexican Spanish language (#17735) 2018-10-24 22:56:14 +02:00
kennedyshead
ec7d33f277 Async MQTT sensor room (#17765) 2018-10-24 22:20:52 +02:00
kennedyshead
c099c259ea Async tests for MQTT lock (#17763) 2018-10-24 22:20:25 +02:00
Paulus Schoutsen
a3ec37834b Bumped version to 0.81.0b2 2018-10-24 22:15:57 +02:00
Fabian Affolter
3d841681d7 Remove day (fixes #17741) (#17743) 2018-10-24 22:15:51 +02:00
Bram Kragten
295a004326 Lovelace ws: add card (#17730)
* Change set to update

* Add 'add card'

* Woof.
2018-10-24 22:15:50 +02:00
Charles Garwood
8de0824688 Add cover to supported platforms (#17725) 2018-10-24 22:15:50 +02:00
Glenn Waters
edc1cbdc32 Elk-M1 climate (#17679)
* Initial climate for Elk-M1.

* Tidy

* fix hound error

* fix hound error
2018-10-24 22:15:49 +02:00
Paulus Schoutsen
1788eaf037 Update frontend to 20181024.0 2018-10-24 22:15:35 +02:00
Paulus Schoutsen
52974ff742 Update frontend to 20181024.0 2018-10-24 22:15:21 +02:00
Fabian Affolter
54d463e746 Update name (fixes #17752) (#17756) 2018-10-24 18:59:52 +02:00
Paulus Schoutsen
c7c0ed89c8 Convert auth websocket commands to use async_response decorator (#17755) 2018-10-24 15:23:09 +02:00
Fabian Affolter
8283f50e22 Remove day (fixes #17741) (#17743) 2018-10-24 14:14:01 +02:00
Daniel Høyer Iversen
86e67e4712 Clean up clicksend_tts (#17749)
* Clean up clicksend_tts

* style
2018-10-24 14:13:07 +02:00
Hedda
ad3d7c9523 Update zha __init__.py to reflect new Zigbee name stylization by the Zigbee Alliance (#17751)
Zigbee Alliance has changed their stylized writing (and logo) of the Zigbee name from “ZigBee” to “Zigbee”, as in they are no longer writing Zigbee with a capital “B” in the middle of the name.
2018-10-24 14:12:30 +02:00
Rohan Kapoor
a10fb94e9e Remove webhook_id from yaml config for mailgun (#17732) 2018-10-24 13:37:07 +02:00
Paulus Schoutsen
08fe7c3ece Pytest tests (#17750)
* Convert core tests

* Convert component tests to use pytest assert

* Lint 🤷‍♂️

* Fix test

* Fix 3 typos in docs
2018-10-24 12:10:05 +02:00
Charles Garwood
4222f7562b Add cover to supported platforms (#17725) 2018-10-24 11:53:45 +02:00
Glenn Waters
6ac9677168 Elk-M1 climate (#17679)
* Initial climate for Elk-M1.

* Tidy

* fix hound error

* fix hound error
2018-10-24 11:15:59 +02:00
Steven Looman
fc8af22191 IGD review fixes (#17400)
* Fix discovery-dependency for upnp

* Only delete port mappings on EVENT_HOMEASSISTANT_STOP + refactoring MockDevice

* Call and store local_ip from async_setup

* Don't depend on http-component

* Remove discovery dependency
2018-10-23 21:52:01 +02:00
Bram Kragten
0f69be117f Lovelace ws: add card (#17730)
* Change set to update

* Add 'add card'

* Woof.
2018-10-23 21:48:35 +02:00
Ville Skyttä
2734a30f37 Upgrade mypy to 0.641 (#17734) 2018-10-23 21:06:58 +02:00
Ville Skyttä
65a8882426 Upgrade pytest to 3.9.2 (#17736) 2018-10-23 21:06:37 +02:00
jxwolstenholme
7be7a8de30 Add device tracking for the BT Smart Hub router (#17158)
* Support for BT smarthub router device tracking

* Update requirements_all.txt for bt_smarthub device tracker

* Added bt_smarthub.py exclusion

* Update .coveragerc

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Fix linting issues

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update bt_smarthub.py

* Update .coveragerc

* Update bt_smarthub.py

* Minor changes

* Update bt_smarthub.py

* Update bt_smarthub.py
2018-10-23 18:35:21 +02:00
Fabian Affolter
f9973696f3 Rename readthedocs file (#17718)
* Rename file

* Add requirements file
2018-10-23 17:39:17 +02:00
Andrey Kupreychik
9798ff019f Don't call off_delay_listener if not needed (#17712)
Don't call off_delay_listener if 'OFF' is actually received
Moved `off_delay_listener` to be defined once
2018-10-23 14:21:03 +02:00
kennedyshead
f6f549dc3c Removes re-init (#17724) 2018-10-23 14:15:56 +02:00
Paulus Schoutsen
4750656f1a Bumped version to 0.81.0b1 2018-10-23 14:09:47 +02:00
Jaxom Nutt
011cc624b6 Bug fix for clicksend (#17713)
* Bug fix

Current version causes 500 error since it is sending an array of from numbers to ClickSend. Changing the from number to 'hass' identifies all messages as coming from Home Assistant making them more recognisable and removes the bug.

* Amendment

Changed it to use 'hass' as the default instead of defaulting to the recipient which is the array. Would have worked if users set their own name but users who were using the default were experiencing the issue.

* Added DEFAULT_SENDER variable
2018-10-23 14:09:41 +02:00
Anders Melchiorsen
2d9a964953 Update limitlessled to 1.1.3 (#17703) 2018-10-23 14:09:40 +02:00
Matt Snyder
87133a0e77 Update flux library version (#17677) 2018-10-23 14:09:40 +02:00
Nicko van Someren
fe8dec27a3 Fixed issue #16903 re exception with multiple simultanious writes (#17636)
Reworked tests/components/emulated_hue/test_init.py to not be
dependent on the specific internal implementation of util/jsonn.py
2018-10-23 14:09:39 +02:00
Bram Kragten
b5323cd894 Add lovelace websocket get and set card (#17600)
* Add ws get, set card

* lint+fix test

* Add test for set

* Added more tests, catch unsupported yaml constructors

Like !include will now give an error in the frontend.

* lint
2018-10-23 14:09:39 +02:00
Malte Franken
23316a8344 Geo location trigger added (#16967)
* zone trigger supports entity id pattern

* fixed lint error

* fixed test code

* initial version of new geo_location trigger

* revert to original

* simplified code and added tests

* refactored geo_location trigger to be based on a source defined by the entity

* amended test cases

* small refactorings
2018-10-23 14:09:38 +02:00
ehendrix23
4a757b7994 Set available property (#17706)
Will set the available property to False if unable to communicate with August lock or doorbell.
HTTP request errors (i.e. timeout, connection error, HTTP error) will not result in traceback. Instead an error will be logged.
2018-10-23 14:09:08 +02:00
Daniel Høyer Iversen
37a667c2de clean up clicksend (#17723) 2018-10-23 14:06:42 +02:00
Paulus Schoutsen
86ecd7555a Update translations 2018-10-23 14:05:03 +02:00
Paulus Schoutsen
02f55b039c Update frontend to 20181023.0 2018-10-23 14:04:37 +02:00
Paulus Schoutsen
398ea40189 Update translations 2018-10-23 14:04:25 +02:00
Paulus Schoutsen
cf0bd6470a Update frontend to 20181023.0 2018-10-23 14:03:38 +02:00
kennedyshead
0723c7f5dc Just use debug instead of error if the binary_sensor does not get data (#17720) 2018-10-23 13:03:01 +02:00
Dougal Matthews
7def587c93 Only strip from the bluetooth name if it isn't None (#17719)
This prevents the following traceback that will otherwise occur.

    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
        result = self.fn(*self.args, **self.kwargs)
      File "/usr/local/lib/python3.6/site-packages/homeassistant/components/device_tracker/bluetooth_le_tracker.py", line 107, in update_ble
        see_device(address, devs[address], new_device=True)
      File "/usr/local/lib/python3.6/site-packages/homeassistant/components/device_tracker/bluetooth_le_tracker.py", line 47, in see_device
        see(mac=BLE_PREFIX + address, host_name=name.strip("\x00"),
    AttributeError: 'NoneType' object has no attribute 'strip'
2018-10-23 12:33:56 +02:00
Rohan Kapoor
d5a5695411 Migrate Mailgun to use the webhook component (#17464)
* Switch mailgun to use webhook api

* Generalize webhook_config_entry_flow

* Add tests for webhook_config_entry_flow

* Add tests for mailgun

* Remove old mailgun file from .coveragerc

* Refactor WebhookFlowHandler into config_entry_flow

* Remove test of helper func from IFTTT

* Lint
2018-10-23 11:14:46 +02:00
kennedyshead
277a9a3995 Async version for asuswrt (#17692)
* Testing async data for asuswrt

* Moved to lib
2018-10-23 11:08:11 +02:00
Nicko van Someren
50f0eac7f3 Fixed issue #16903 re exception with multiple simultanious writes (#17636)
Reworked tests/components/emulated_hue/test_init.py to not be
dependent on the specific internal implementation of util/jsonn.py
2018-10-23 10:54:03 +02:00
Jaxom Nutt
44e35b7f52 Bug fix for clicksend (#17713)
* Bug fix

Current version causes 500 error since it is sending an array of from numbers to ClickSend. Changing the from number to 'hass' identifies all messages as coming from Home Assistant making them more recognisable and removes the bug.

* Amendment

Changed it to use 'hass' as the default instead of defaulting to the recipient which is the array. Would have worked if users set their own name but users who were using the default were experiencing the issue.

* Added DEFAULT_SENDER variable
2018-10-23 10:28:49 +02:00
Yegor Vialov
324587b2db Away mode temperature fix for generic thermostat (#17641)
* Resolves /home-assistant/home-assistant#17433

Away mode temperature issue fix for generic_thermostat

* Debug messages removed from generic_thermostat.py

* Test for repeat away_mode set

Test for fix of generic thermostat issue when away_mode was set several times in a row.

* Code style fix in generic_thermostat

* Remove blank line in the end of generic_thermostat

* Fix style
2018-10-23 09:04:47 +02:00
Fabian Affolter
ad3d0c4e99 Upgrade Sphinx to 1.8.1 (#17701) 2018-10-23 07:12:12 +02:00
Anders Melchiorsen
3014930371 Update limitlessled to 1.1.3 (#17703) 2018-10-23 07:11:55 +02:00
Aaron Bach
b773a9049c Updated simplisafe-python to 3.1.13 (#17696) 2018-10-22 22:49:12 +02:00
Sébastien RAMAGE
4e8cd7281c All supported domains should be exposed by default (#17579)
According to documentation, all supported domains should be exposed by default
https://www.home-assistant.io/components/google_assistant/#expose_by_default
2018-10-22 20:07:11 +02:00
Tom Monck JR
fd9370da39 Add readthedoc.yml file to specify the version of python to run during documentation building. (#17642) 2018-10-22 20:05:00 +02:00
Manuel de la Rosa
399f8a72c3 Fix Mexican Spanish identifier (#17674)
Mexican Spanish identifier is "es-MX" instead of "en-MX".
2018-10-22 20:02:55 +02:00
Malte Franken
75e42acfe7 Geo location trigger added (#16967)
* zone trigger supports entity id pattern

* fixed lint error

* fixed test code

* initial version of new geo_location trigger

* revert to original

* simplified code and added tests

* refactored geo_location trigger to be based on a source defined by the entity

* amended test cases

* small refactorings
2018-10-22 20:01:01 +02:00
Tommy Jonsson
42a444712b Add missing hangouts data/image to notify service (#17576)
* add missing hangouts image_file/url to notify services

Missed adding support for hangouts image to notify service

* default in schema
2018-10-22 19:36:29 +02:00
Daniel Høyer Iversen
61a96aecc0 Mill, support more heater types (#17676)
* mill, suport more heater types

* mill requirements
2018-10-22 19:32:19 +02:00
Bram Kragten
96105ef6e7 Add lovelace websocket get and set card (#17600)
* Add ws get, set card

* lint+fix test

* Add test for set

* Added more tests, catch unsupported yaml constructors

Like !include will now give an error in the frontend.

* lint
2018-10-22 14:45:13 +02:00
Matt Snyder
0524c51c1a Update flux library version (#17677) 2018-10-22 07:04:47 +02:00
Paulus Schoutsen
ebaf7f8c00 Bumped version to 0.81.0b0 2018-10-21 20:34:50 +02:00
Paulus Schoutsen
355005114b Update translations 2018-10-21 20:34:28 +02:00
Paulus Schoutsen
8f529b20d7 Bump frontend to 20181021.0 2018-10-21 20:34:12 +02:00
Richard Patel
b2faa67ab7 Add new rtorrent sensor (#17421)
* New rtorrent sensor

* Fix lint issue

* Fix another lint issue

* Fix pylint issue

* how many python linters do you guys use

* Cleanup code

* python linting

* newline
2018-10-21 20:12:51 +02:00
Luke Fritz
95371fe4a6 Bump pyarlo==0.2.2 (#17673)
* Bump pyarlo to 0.2.2, fixes #17427

* Increase log level for refresh message to clear up logs
2018-10-21 19:54:51 +02:00
Mathieu Velten
2d980f2a92 Update pynetgear to 0.5.0 (#17652) 2018-10-21 19:54:01 +02:00
Oscar Tin Lai
b6d3a199ce Add support for Dyson Hot+Cool Fan as a climate device (#14598)
* Added support for dyson hot+cool fan as climate device

* Removed decimal place in kelvin units conversion

Minor edits to be consistent with Dyson's internal conversion of temperature from kelvin to celsius. It does not include decimal place to convert between kelvin and celsius.

* made changes according to comments

* Refactored target temp logics, fixed enum issues

* changed name of component to entity

* removed temperature conversion for min/max property

* changed back to 644 permission

* added extra tests for almost-all coverage

* changed assert method to avoid lack of certain method in py35

* added test_setup_component

* shorten line length

* fixed mock spec and added checking of message listener is called

* added doc string and debug msg

* shorten line length

* removed pending target temp
2018-10-21 17:35:07 +02:00
Fabian Affolter
731753b604 Upgrade holidays to 0.9.8 (#17656) 2018-10-21 15:07:44 +02:00
Fabian Affolter
cf24687024 Upgrade async_timeout to 3.0.1 (#17655) 2018-10-21 14:13:30 +02:00
Daniel Høyer Iversen
ef93d48d50 available to switchmate (#17640) 2018-10-21 13:41:27 +02:00
emontnemery
9982867d66 Very minor cleanup of RFLink components (#17649) 2018-10-21 13:05:02 +02:00
Paulus Schoutsen
bdfd473aaa Reconnect if sub info comes in that is valid again (#17651) 2018-10-21 12:16:24 +02:00
Daniel Høyer Iversen
7e3d0f0700 Remove ryobi from .coveragerc (#17647) 2018-10-21 11:21:09 +02:00
guillaume1410
c03b137130 Removing ryobi gdo (#17637) 2018-10-21 08:08:35 +02:00
Raymon de Looff
85dbf1eed3 Upgrade dsmr_parser to 0.12 (#17634) 2018-10-20 22:07:47 +02:00
mvn23
237ac08076 Add opentherm_gw binary sensor support (#17625)
* Add OpenTherm Gateway binary sensor support.

* opentherm_gw binary_sensor platform does not need polling.
2018-10-20 18:51:01 +02:00
Bob Clough
2e973c7572 Fix mqtt light brightness slider (#17075)
* Enable brightness slider for RGB

If we are using RGB with no brightness topic, the brighness slider
should still be visible, as we can scale the RGB amount to give us the
brightness.

* Output RGB scaled by brightness

If we are outputting to an RGB device, but do not have a dedicated
brightness topic set, when the brightness slider is changed, we should
output the current colour's HS, with the V coming from the brightness
slider.

* Brightness from RGB when we're not using a brightness topic

When we aren't using a brightness topic, set the brightness slider based
on the received value from an RGB -> HSV conversion.

* Test for new brightness state scaled by RGB

This adds a test to make sure the brightness stored in the state is
being computed correctly from the RGB value when a dedicated brightness
topic is not set.

* Changes from review

Fixes formatting of supported features flags, and checks HS colour
hasn't been set when operating in RGB-only mode

* Set optimistic brightness correctly in rgb mode

When we're using rgb mode to set the brightness, we want to set
optimistic brightness if:

we are running in optimistic mode
OR
the brightness state topic isn't set and we have a brightness command topic
OR
the rgb state topic isn't set and we don't have a brightness command topic

* Add test for turn_on in RGB brightness mode
2018-10-20 12:37:25 -04:00
Julien Debaru
e980d1b9fe Fix linky sensor login error (#17110)
* Fix linky sensor login error

* Make platform fail-safe

Adding following enhancements:
* Make sure the platform loads correctly by making the first API request in setup_platform.
* Close the session after each API call.
* Use timeout parameter everywhere.

* Fix Hound CI error: line too long.

* Update pylinky library

* Remove LinkyClient from update()
2018-10-20 15:30:10 +02:00
Robert Svensson
26b7c2de7e deCONZ - Add support for Xiaomi window covers (#17337)
Add support for Xiaomi window covers
2018-10-20 15:13:23 +02:00
Daniel Shokouhi
ab826b8fe2 Use cached robot serial for Neato update (#17633)
* Use cached robot serial for neato update

* Hound
2018-10-20 14:28:30 +02:00
cdce8p
a9a8cbbd10 Homekit component cleanup (#17627)
* hass.async_add_executor_job
* Fix accessories.run -> async_track_state_change
* Fixed media_player test
* Flags are now local vars
* consistent use of " and '
2018-10-20 00:14:05 +02:00
Glenn Waters
3655fefec2 Add Elk-M1 sensor platform (#17342)
* Initial sensor version.

* Add Elk-M1 sensor services. Initial version of services.yaml.

* Fix lint errors.

* Fix PR comments.

* fix PR comment

* Fix PR comment

* Fix PR comments

* fix
2018-10-19 23:41:04 +02:00
cdce8p
ff33cbd22f Add water_heater support to HomeKit (#17614)
* Homekit add support for water_heater
* Added tests
2018-10-19 21:04:05 +02:00
Nick Touran
e343f5521c Upgrade gstreamer-player to 1.1.2 (#17568)
* Upgrade gstreamer-player to 1.1.2

* Updated requirements for gstreamer-player properly.
2018-10-19 18:11:47 +02:00
Steven Looman
f7bc44955c Upgrade async_upnp_client to 0.12.7 (#17601) 2018-10-19 18:10:04 +02:00
Nick Horvath
df2c3cdded Bump thermoworks version to fix conflict from upstream pyrebase sseclient (#17620) 2018-10-19 17:48:46 +02:00
ehendrix23
f504e5ef61 Add doorsense sensor for August 3rd Gen Smart Lock Pro (#17299)
* Add doorsense sensor for August 3rd Gen Smart Lock Pro

Add a binary sensor to August for the August 3rd Gen Smart Lock Pro doorsense sensor.

This is a re-do from PR 17116 https://github.com/home-assistant/home-assistant/pull/17116 that I closed due to rebase issue on my end.

* Changed to use snjoetw provided code

Going through the py-august I found that snjoetw had provided updated versions for the august component (august.py and binary_sensor/august.py) to include DoorSense sensor.
Changed what I did to to what snjoetw provided instead as he split it into 2 classes; much cleaner I think.

I modified his coding with:
   Fixes that were done to the August component and not part of the coding snjoetw provided.
   Added the debug logging improvement I had done in the code.

Note, fix I committed earlier for lock atribute (lock/august.py) is thus still the same.

* Reverted change from add_device to add_entities

Missed an item when merging snjoetw's code with current. Fixed.

* Updated call from add_devices to add_entities as well

Updated the call from add_devices to add_entities.

* Fixed permissions on files

Fixed permissions on components/august.py and binary_snesor/august.py

* Changed if/else to if/continue

Changed logic so that if the door sensor state is unknown during initalization the debug log is written and then continue the loop instead of using if/else logic.

* Added available property for Door Sensor

Added the available property for the Door Sensor and setting it to False if a status unknown is received.

* Updated setting self._available

Changed line for setting self._available to what Martin provided. Much  more efficient to read. :-)
2018-10-19 09:37:02 +02:00
Thomas Lovén
8bf58e1df5 Revert "De-syncing binary_sensor.ping (#17056)" (#17606)
This reverts commit 11d5671ee0.
2018-10-19 09:29:48 +02:00
Thomas Lovén
90183bd682 Tuya light icon fix (#17605)
* Fix for tuya light icons going too bright

* Make sure other values aren't strings either
2018-10-19 09:17:19 +02:00
jjlawren
88ec73ed8f Add missing await for coroutine (#17609) 2018-10-19 09:10:41 +02:00
mvn23
7baffed7b7 Add sensor support to opentherm_gw (#17314)
* Add OpenTherm Gateway sensor platform.

* Add OTGW_ variables to list of supported sensors.

* Order imports.

* Add OpenTherm Gateway binary sensor support.

* Revert "Add OpenTherm Gateway binary sensor support."

This reverts commit 115acaa912.

* Import COMP_SENSOR from sensor component rather than defining it.

* Update opentherm_gw sensor platform docs url.

* Update dependency to v0.2b1
Old version had incorrect variable names for some of the sensors

* Update requirements_all.txt

* Address review findings.

* Update .coveragerc
2018-10-19 07:31:19 +02:00
Anders Melchiorsen
cc4d29d42a Fix flux switch update interval (#17458) 2018-10-18 23:04:22 +02:00
emontnemery
10c1378195 Add binary_sensor support to RFlink (#17146)
* Add binary_sensor support to RFlink

* Add support for aliases

* Fix review comments

* Refactor, add tests

* Review comments

* Review comments

* Review comments

* Review comments
2018-10-18 22:28:40 +02:00
Ville Skyttä
cf3a97ff3c Upgrade pytest to 3.9.1 (#17598) 2018-10-18 21:31:52 +02:00
Kevin Fronczak
222ba96b3e Bump blinkpy version to 0.10.1 (#17595) 2018-10-18 21:30:46 +02:00
Nikolay Vasilchuk
6239a523cc Fix: Xiaomi Plug state is set twice (#17482)
* Xiaomi Plug UI fix #17422

* Review
2018-10-18 20:28:43 +02:00
Malte Franken
7eb6e49df7 Fixing race condition in geo location platforms (#17581)
* fixed race condition where obsolete entities kept listening for dispatcher signals

* making tests python 3.5 compatible
2018-10-18 15:25:48 +02:00
Paulus Schoutsen
7e91c0dc83 Merge branch 'master' into dev 2018-10-18 14:59:14 +02:00
Paulus Schoutsen
b1a05e7605 Merge pull request #17578 from home-assistant/rc
0.80.3
2018-10-18 14:55:46 +02:00
Paulus Schoutsen
cd90bb4161 Bumped version to 0.80.3 2018-10-18 13:58:58 +02:00
Paulus Schoutsen
17d0fe02c7 Update snapcast to 2.0.9 (#17573) 2018-10-18 13:58:48 +02:00
Steven Looman
43b140be5e Upgrade async_upnp_client to 0.12.6 (#17560) 2018-10-18 13:58:48 +02:00
Steven Looman
9ded16ccc3 Update to async-upnp-client==0.12.5 (#17401) 2018-10-18 13:58:47 +02:00
Marcel Hoppe
91dc0c3731 update hangups to 0.4.6 and fix Issue #16593 hangouts reconnects. (#17518) 2018-10-18 13:57:04 +02:00
Paulus Schoutsen
6e4a99cec0 Bump frontend to 20181018.0 2018-10-18 13:52:52 +02:00
Paulus Schoutsen
20bd14defb Bump frontend to 20181018.0 2018-10-18 13:52:38 +02:00
Paulus Schoutsen
20fa6c5383 Update snapcast to 2.0.9 (#17573) 2018-10-18 11:06:32 +02:00
Matthew Garrett
e2a1e21c8d Add support for LG soundbars (#17570)
* Add LG soundbar support

We can autodiscover these, so for now let's skip any local configuration.
Currently we expose volume, source and equaliser preset - we can expose the
other volume controls and options as well if necessary, but I don't know
whether it's worth it.

* Add discovery of LG devices

This is a generic discovery type that doesn't obviously contain enough
information to identify whether we're talking to a speaker system or any
other kind of device - on the other hand I haven't been able to find any
other LG devices that respond like this, so we can cross that bridge when
we get to it.

* Lint
2018-10-18 10:39:33 +02:00
Brian Gianforcaro
45878c6df0 Upgrade twilio package to version 6.19.1 (#17395) (#17424)
- Bump twilio requirement to latest 6.19.1 version

- The generic response type is gone in the latest
  versions of the twilio package. It appears we were
  generating an empty response just to get the empty
  xml body. TwilML is the new base class all responses
  inherit from. So I've switched the code over to using
  and empty TwilML object instead.

- The exception type was moved to a different location.
2018-10-18 09:17:55 +02:00
Daniel Høyer Iversen
3e5233d115 danielhiversen as mill codeowner (#17571) 2018-10-18 08:12:09 +02:00
Jorim Tielemans
b50c93ccb7 Validate ports as a port (#17549)
* Validate ports as port

Better than just a positive integer since it limits the range from 1 to 65535.

* Validate port for Axis

* Validate port for Xiaomi Home Camera

* Validate port for Modbus

* Validate port for Yamaha MusicCast Receivers

* Update zhong_hong.py

Validate port as a port, the gateway address as positive_int
Also moved the default values to their variable

* Validate port for the Asterisk Voicemail interface

* Fix lint

* Validate port for Xiaomi Cameras
2018-10-17 23:09:05 +02:00
Eduard van Valkenburg
50a66abd80 Updated package to fix #16960 (#17555) 2018-10-17 22:56:54 +02:00
Steven Looman
7106d9e9d4 Upgrade async_upnp_client to 0.12.6 (#17560) 2018-10-17 22:56:21 +02:00
ehendrix23
daf9d28565 Fix mold_indicator errors at startup (#17346)
* Initial changes to resolve issue 16733

Added logic to ensure that if the state is unknown during startup that the error about being unable to parse the value is not logged.
Further,  also ensured that if an attribute is set to None it does not try to convert the None value to Fahrenheit as that will cause an error.

* Cleaned up and added few comments

Cleaned up some lines based on flake8 and pylint.
Added some comment lines on the items added.

* Changed to async and using async_added_to_hass

Changed sensor to use async.
Registering state tracking for sensors and initial setup is now done upon the home assistant start event.

* Updated test and small fix

Updated test to handle unavailable state of sensor and return of None for attributes when data is unavailable.
Ensured that atributes are set to None when state is unavailable due to incorrect data.

* Fixed some flake8 issues in test

Fixed some flake8 issues in test_moldindicator.py.

* Updates based on review

Updates based on review from MartinHjelmare

* Added sensor entity_id to logger errors

Added sensor entity_id to logger error messages
Update test to use constant STATE_UNKNOWN instead of fixed string.
2018-10-17 18:42:39 +02:00
Bram Kragten
33860bf23c Adding id to lovelace cards in ui-lovelace.yaml (#17498)
* ID is added to cards without ID in ui-lovelace.yaml when loaded

* Hound

* Remove ui-lovelace.yaml

* Nicer get

* Update tests

* If YAML dump fails, config not gone

* Add tests

* Woof!

* Remove nosetests

* Address comments

* Woof...

* Delete test.yaml

* update rights to saved file

* fix

* line break
2018-10-17 16:31:06 +02:00
Paulus Schoutsen
95c43d634b Bump frontend to 20181017.0 2018-10-17 14:16:49 +02:00
Paulus Schoutsen
a5b9f5040f Update translations 2018-10-17 14:12:41 +02:00
cgtobi
e83a9aace4 Remove unnecessary call (#17514) 2018-10-17 10:53:05 +02:00
Anders Melchiorsen
1e4463957d Scan all network interfaces for LIFX bulbs (#17530) 2018-10-17 10:50:13 +02:00
Paulus Schoutsen
326787ef1a Add another 3 days leeway to give time for payment processing times (#17542) 2018-10-17 10:45:01 +02:00
Ville Skyttä
15f4ed74ac Tweak sensors comments in default config (#17526)
Makes it more clear that there should be only one sensors section, and
that the weather prediction comment applies only to the yr platform.
2018-10-17 09:58:41 +02:00
Ville Skyttä
b7b4224429 Huawei LTE sensor improvements (#17533)
* Sensor value formatting improvements

* Make default names more consistent with other sensors

* Improve unique id formatting
2018-10-17 09:00:15 +02:00
Kevin Fronczak
5088e7ee49 Blink update - fixes #17316 (#17538)
* Updgrae blinkpy to 0.10.0

- Remove status sensor (API endpoint unreliable for this)
- Wifi strength reports in wifi bars rather than dBm (result of new API
endpoint)
- Added unique ids based on serial number

* Update requirements
2018-10-17 08:38:03 +02:00
Nate Clark
11004bcf34 Manual IP & port configuration for Konnected devices (#17120)
* add capability for manually specifying IP and port of Konnected device(s)

* add config options for blink and discovery settings

* import konnected only in functions where needed

* updates from code review feedback

* convert manual_discovery to async

* code review updates; use correct sync vs async
2018-10-17 00:39:32 +02:00
Brant Knudson
83db673bd0 Add unique_id to Vera entities (#17450)
I believe this adds registry support. The UI allows me to change
the entity ID now.

For example, a light bulb called "BasementHallLight" in the Vera
has an initial Entity ID like light.basementhalllight_108, where
108 is the unique ID that the Vera assigned the device when I
added it to the z-wave network.

Now I can use the UI to change the Entity ID to
light.basementhalllight and I can still turn it on and off.
2018-10-16 23:27:57 +02:00
Marcel Hoppe
6b3e4ca7bd update hangups to 0.4.6 and fix Issue #16593 hangouts reconnects. (#17518) 2018-10-16 20:09:34 +02:00
Daniel Høyer Iversen
aa176312a5 Update switchmate library (#17519) 2018-10-16 20:08:34 +02:00
Daniel Høyer Iversen
6235aae196 Update mill library (#17520) 2018-10-16 20:08:04 +02:00
Ben Lebherz
764ea06795 Fix unhandled exception which creates many useless logs (#17508)
* Fix unhandled exception which creates many useless logs

* recover old component logic, sorry

* remove inline conditional
2018-10-16 16:41:38 +02:00
Charles Garwood
9c52a3ce22 Z-Wave Device Registry Support (#17291)
* Add device_registry support for sensor and switch domains

* Add device_registry support for light

* Add device registry to binary_sensor, climate, cover

* Add device registry to zwave fan

* Fix test for config entry loading

* lint

* revert erroneous modification

* Revert device_registry.py change
2018-10-16 14:58:25 +02:00
Tsvi Mostovicz
c6d9ceca63 Bump hdate version to 0.6.5 (#17510)
* Bump hdate version to 0.6.4

* Bump to 0.6.5

* Change test so we check when passing tzinfo object
2018-10-16 13:45:39 +02:00
ehendrix23
fee87cd6ed Add LogBook support to HomeKit (#17180) 2018-10-16 13:32:53 +02:00
William Scanlon
71ab8a9b1a Moved Wink water heater from climate to water heater. (#17504)
* Moved Wink water heater from climate to water heater.

* Remove deprecated states from Tuya

* Update toon.py

* Update toon.py

* Lint
2018-10-16 11:27:01 +02:00
Robert Svensson
a795093705 UniFi POE control (#17011)
* First commit

* Feature complete?

* Add dependency

* Move setting poe mode logic to library

* Use guard clauses

* Bump requirement to 2

* Simplify saving switches with poe off

* Store and use poe mode

* Fix indentation

* Fix flake8

* Configuration future proofing

* Bump dependency to v3

* Add first test

* Proper use of defaults with config flow (thanks helto)

* Appease hound

* Make sure there can't be duplicate entries of combination host+site

* More tests

* More tests

* 98% coverage of controller

* Fix hound comments

* Config flow step init not necessary

* Use async_current_entries to check if host and site for controller is used

* Remove storing/restoring poe off devices to slim PR

* First batch of switch tests

* More switch tests.

* Small improvements and clean up

* Make tests pass
Don't name device in device registry

* Dont process clients that belong to non-UniFi POE switches

* Allow selection of site from a list in config flow

* Fix double blank lines in method

* Update codeowners
2018-10-16 10:35:35 +02:00
Nikolay Vasilchuk
0c0c471447 Fix: Connection pool of Request object is smaller than optimal value (8) (#17483) 2018-10-16 10:22:57 +02:00
Daniel Shokouhi
dc7e5e3af4 Add unique_id for Ring (#17497) 2018-10-16 10:06:00 +02:00
Aaron Bach
a9389d2d43 Bumps simplisafe-python to 3.1.12 (#17509)
* Bumps simplisafe-python to 3.1.12

* Updated requirements
2018-10-15 22:54:32 -06:00
Alexander Lyon
993a02b8c4 Fix the sabnzbd component api error (#17014)
* Bump pysabnzbd version number

* Pass hass aiohttp session to pysabnzbd
2018-10-16 00:18:59 +02:00
Aaron Bach
29c2b2fe79 Clean up OpenUV config flow (#17349)
* Cleaned up OpenUV config flow

* Added proper listener removal

* Added proper exception

* Unnecessary exception message

* Moved API key error to correct place

* Member-requested changes (part 1)

* Hound

* Member-requested changes (part 2)

* Cleanup

* Fixed tests
2018-10-15 13:21:21 -06:00
Daniel Perna
73197c9a6c Update pyhomematic to 0.1.51 (#17491) 2018-10-15 21:15:26 +02:00
Anders Melchiorsen
1a5048baaf Add device info for LIFX (#17330)
* Add device info for LIFX

* Address review comments
2018-10-15 20:46:33 +02:00
Daniel Perna
9718a17351 Fix HomeMatic availability detection (#17341)
* Fix availability detection
2018-10-15 20:34:03 +02:00
Dougal Matthews
6feacbbfe1 Include the name of the Volumio media player in errors (#17481)
When you have multiple Volumio media players it can be hard to determine
which one has a problem without this information.
2018-10-15 19:11:12 +02:00
emontnemery
2ceb4d2d1e Refactor RFLink component (#17402)
* Start refactor of RFLink component

* alias _id not added correctly

Aliases for sensor not added correctly
And some debug traces.

* Update rflink.py

* Cleanup, fix review comments

* Call event handlers directly when processing initial event

* Use hass.async_create_task when adding discovered device

* Review comments

* Review comments
2018-10-15 15:35:33 +02:00
Pascal Vizeli
0904ff45fe Cleanup HM Notify platform (#17355)
* Cleanup HM Notify platform

* Fix python 3.5.4

* Update homematic.py

* Update homematic.py
2018-10-15 13:26:09 +02:00
Niels Mündler
d6752d2270 Fix rangefilter (#17473)
* Fix rangefilter

RangeFilter would break for lower or upper bounds of 0, evaluating to False and thus not being handled correctly as bounds

* Add test for zero bounds
2018-10-15 12:24:21 +02:00
Julius Mittenzwei
373e3b12d8 Switched to async_fire (#17472) 2018-10-15 12:16:40 +02:00
Paulus Schoutsen
e985f30247 Fix websocket API (#17471) 2018-10-15 11:48:36 +02:00
Adam
22bf4d0783 Re-assign conditions (#17364) 2018-10-15 11:43:27 +02:00
kennedyshead
1cbb5b8e51 State is set to UNKNOWN rather than ON in order to make UI have an play/pause button (#17357) 2018-10-15 11:42:27 +02:00
Paulus Schoutsen
ac79ff9e24 Add context to scripts run by template entities (#17329) 2018-10-15 11:38:49 +02:00
Anders Melchiorsen
0bf10b0b09 Fire an event when timer gets out of sync (#17398) 2018-10-15 11:34:36 +02:00
Ville Skyttä
31981fde7e Make dicttoxml logging less verbose (#17446) 2018-10-15 11:25:38 +02:00
Ville Skyttä
4fce051838 Add RSRQ, RSRP, and SINR to huawei_lte default sensors (#17425)
These are important LTE signal monitoring values.
2018-10-15 11:22:49 +02:00
Rohan Kapoor
bd450ee9ff Migrate CONF_WEBHOOK_ID to homeassistant.const (#17460)
* Migrate CONF_WEBHOOK_ID to homeassistant.const

* Switch over all instances of webhook_id to the const

* Switch last instance of webhook_id to the const

* automation: conf constants for conf

* webhook: conf constants for conf
2018-10-15 11:18:21 +02:00
Malte Franken
879924fea4 refactored to make its code structure similar to nsw_rural_fire_service_feed platform (#17461) 2018-10-15 11:17:46 +02:00
Pascal Vizeli
3b0db291dd Bugfix eventstream with EOF on end (#17465) 2018-10-15 10:31:49 +02:00
Julius Mittenzwei
a71cc67efb Fix NoEntitySpecifiedError during knx startup (#17366)
* Potential fix for #13699

* removed uneccessary initialization of hass

* removed hass from signature
2018-10-15 03:29:36 +02:00
Tsvi Mostovicz
c5905ee5ca Show torah reading during weekdays (#17447)
* Add support for showing torah reading on weekdays as well

* Update docstrings for test functions
2018-10-14 23:55:11 +02:00
Craig J. Midwinter
3edcc9420a Update pysher version (#17455) 2018-10-14 23:51:15 +02:00
Aaron Bach
b022dde622 Bumped simplisafe-python to 3.1.11 (#17454)
* Bumped simplisafe-python to 3.1.10

* Updated requirements

* Updated requirements
2018-10-14 14:26:44 -06:00
kennedyshead
1187e0aea5 Remove day as a conf option (#17452) 2018-10-14 21:33:18 +02:00
Daniel Høyer Iversen
a401be9b1b New climate device (#17313)
* initial version of millheater

* Remove unused imports

* Add some comments

* separate lib

* fix review comments
2018-10-14 20:22:20 +02:00
Paulus Schoutsen
ed683d8c2c Update frontend to 20181014.0 2018-10-14 19:17:30 +02:00
Fabian Affolter
d4061b73b0 Upgrade youtube_dl to 2018.10.05 (#17429) 2018-10-14 17:14:06 +02:00
Fabian Affolter
9305ea9a6b Upgrade numpy to 1.15.2 (#17431) 2018-10-14 17:13:25 +02:00
Fabian Affolter
7b0c88c54b Update docstrings (#17435) 2018-10-14 17:12:34 +02:00
Fabian Affolter
253e154a79 Minor updates (#17436) 2018-10-14 17:11:39 +02:00
Fabian Affolter
daf48a3b1f Minor updates (#17437) 2018-10-14 17:10:46 +02:00
Fabian Affolter
5ac0469ef9 Upgrade python-telegram-bot to 11.1.0 (#17441) 2018-10-14 17:08:17 +02:00
Malte Franken
fccaf7f919 NSW Rural Fire Service platform (#16802)
* initial integration with nsw rural fire service feed

* improved test coverage

* updated requirements

* grouped imports

* removed debug print statement

* moved manager's startup code into separate call

* simplified feed update code

* simplified feed update code

* simplified device state attribute code

* added source to conform with pr #17339

* fixed lint

* refactored how entities are managed

* fixed pylint

* simplified signalling
2018-10-14 14:11:25 +02:00
Brant Knudson
f198859441 Upgrade pyvera to 0.2.45 (#17419)
This release adds support for garage door openers. A garage door
opener will show up as a switch.
2018-10-14 09:26:34 +02:00
333ryan18
a302112879 Bump Totalconnect (#17418)
* Update totalconnect.py

* Update requirements_all.txt
2018-10-14 09:25:24 +02:00
William Scanlon
6a8eb8d0a1 Moved econet from climate to water heater (#17322)
* Moved econet from climate to water heater

* Updated .coveragerc

* Fixed requirements_all.txt
2018-10-13 23:16:44 +02:00
Fredrik Baberg
f23708ce6f Update Vagrant Windows support (#17205)
* Update Vagrantfile with Hyper-V support

* Correction to name.

* Exclude files in Vagrant provision tests
2018-10-13 23:02:00 +02:00
noxhirsch
0dd3640c78 Adding support for HmIP-SLO (outdoor brightness sensor) (#17413)
* Add IPBrightnessSensor

* Add ILLUMINATION unit & icon

* Update homematic.py

* Added missing entry
2018-10-13 22:58:41 +02:00
J4nsen
d0da265166 Fix netio component (#17411)
* bump pynetio to 0.1.9.1 to actually use provided credentials.

* cast to int to fix TypeError

* update requirements_all.txt
2018-10-13 21:09:10 +02:00
Dan Klaffenbach
3ca3fe7015 homematic: Support additional property for sabotage detection (#17407)
At least HM-Sec-Sir-WM uses ERROR_SABOTAGE, see:

    pyhomematic.devicetypes.actors.RFSiren
2018-10-13 21:08:06 +02:00
Miloš Bunčić
ef8253c549 Added ssl and verify_ssl parameters in ddwrt device tracker component (#17406)
* Added ssl and verify_ssl parameters in ddwrt device tracker component

* Set defaults in validation
2018-10-13 21:04:51 +02:00
Keiran S
78e29cd3fa Add AWS Route53 Dynamic DNS support (#17072)
* Add AWS Route53 dynamic DNS support to Home Assistant

* Remove line breaks
2018-10-13 21:03:30 +02:00
Ville Skyttä
9c178cf488 Add unique id to syncthru sensors (#17399) 2018-10-13 14:31:53 +02:00
Steven Looman
e6d002c377 Update to async-upnp-client==0.12.5 (#17401) 2018-10-13 14:29:12 +02:00
Tommy Jonsson
70281a148b Fix hangout.send_message requiring data key (#17393) 2018-10-13 10:54:35 +02:00
Florian Klien
d4b092706a XMPP async (#17283)
* new lib dependencies, working old xmpp

* non working aioxmpp

* reverting to sync xmpp

will try slixmpp instead of aioxmpp

reasons:
echo bot example of aioxmpp had blocking behavior (slixmpp echo bot works fine)
closer API to sleekxmpp
less dependencies than aioxmpp

* first working slixmpp version

* DEBUG messages, changed MUC call

the joinMUC method changed from sleekxmpp to slixmpp
added debug messages
better name for cleanup callback

* flake8

* little cleanup, tested MUC

* requirements_all

* dependencies managed by slixmpp, removed debug messages

* resource configurable by user, requirements updated

* changed __init__ parameter code format

* removed trailing dots from LOG messages

* changed super call to python3 format
2018-10-13 10:37:42 +02:00
Tom Harris
db536797be Bump insteonplm version to 0.15.0 (#17384) 2018-10-13 10:33:34 +02:00
Martin Berg
d9d27733d1 Fix arm/disarm calls. (#17381) 2018-10-13 10:30:49 +02:00
Daniel Shokouhi
5f16f3c3a6 Add unique_id for Bloomsky (#17383)
* Add unique_id for Bloomsky

* Add bloomsky camera unique ID
2018-10-13 10:23:00 +02:00
Daniel Shokouhi
d3672f36fb Add unique_id for Neato (#17369)
* Add unique_id for Neato

* Only send the serial per review comments
2018-10-13 00:33:13 +02:00
Daniel Shokouhi
3cf6c76f8b Add unique_id for Lightify (#17377) 2018-10-13 00:32:35 +02:00
Tom French
434d1d7d63 Added option to use a location other than home (#17340) 2018-10-12 20:04:52 +02:00
Aaron Bach
401e22fc0c Add config entry for SimpliSafe (#17148)
* Initial move into component

* Base functionality in place

* Starting tests in place

* All config entry tests in place

* Made default scan interval more obvious and removed extra logging

* Inherit default scan interval from alarm_control_panel

* Updated coveragerc and CODEOWNERS

* Member-requested changes

* Hound

* Updated requirements

* Updated tests

* Member-requested changes

* Owner-requested changes

* Constant cleanup

* Fixed config flow test

* Owner-requested updates

* Updated requirements

* Using async_will_remove_from_hass

* Corrected scan interval logic

* Fixed tests

* Owner-requested changes

* Additional logging

* Owner-requested changes
2018-10-12 19:07:47 +02:00
Malte Franken
1f863830e1 Adding source attribute to geo location platforms (#17339)
* added source attribute to all geo_location platforms

* amended test cases

* constant moved and source method now forces subclasses to override
2018-10-12 16:48:02 +02:00
Paulus Schoutsen
6971e84ddf Update translations 2018-10-12 14:58:09 +02:00
Paulus Schoutsen
397c4336bc Update frontend 2018-10-12 14:57:35 +02:00
kennedyshead
e00ed84d84 The ping command will not detect device in standby as off (#17358) 2018-10-12 14:51:03 +02:00
Jedmeng
7b28963a88 Fix setting opple light color temperature (#17359) 2018-10-12 14:50:20 +02:00
Sebastian Muszynski
5a00cc5afc Provide an individual color temperature range per Yeelight model (#17305)
* Provide an individual color temperature range per Yeelight model

* Fix lint

* Bump yeelight version

* Remove unused const

* Enable SUPPORT_COLOR_TEMP for BulbType.WhiteTemp
2018-10-12 11:35:33 +02:00
Martin Mois
cb3d62eeef notify.homematic (#16973)
* Add notify.homematic_signalgen

* Update homematic_signalgen.py, test_homematic_signalgen.py

* Added new files to .coveragerc

* Fixed review comments from houndci-bot

* Fixed pylint errors

* Regenerate requirements_test_all.txt by script/gen_requirements_all.py

* Fix flake8 warnings

* Renamed notify.homematic_signalgen to notify.homematic and made it generic

* Update .coveragerc and requirements_test_all.txt

* Removed the terms signal generator from the sources.
2018-10-12 09:36:52 +02:00
Daniel Perna
241d87e9d3 Add exception handling to dnsip sensor (#17332)
* Add exception handling to dnsip sensor

* Refactor import

* Fix exception
2018-10-12 09:30:35 +02:00
emontnemery
b2789d9883 Support abbreviations in discovery topic (#16635)
* Support abbreviations in discovery topic

* Add abbreviations for all words. Add testcase.

Add missing docstring.

* Add missing abbreviations

* Support topic prefix

* Update test case

* Restrict topic prefix

* Fix merge

* Simplify abbreviations expanding, assume TOPIC_PREFIX is one character long

* Support abbreviated keys instead of words

* Remove redundant abbreviations

* Remove extra spaces in abbreviation list

* Make topic prefix less restrictive

* Make topix prefix a bit more restrictive again
2018-10-12 08:51:16 +02:00
shred86
7bb60068d7 Color control for Abode RGB lights (#17347)
* Color control support for Abode lights

* Updated add_devices to add_entities

* Update line length

* Changed elif to if for pylint warning
2018-10-12 08:47:14 +02:00
Daniel Shokouhi
1c23a36f46 Set botvac availability (#17350)
* Set botvac availability

* Lint

* Reduce availability calls per review comments
2018-10-12 08:40:45 +02:00
Zhong Jianxin
0ea5a73e8d Fix motion sensor in Aqara LAN protocol V2 (#17240) 2018-10-12 08:34:32 +02:00
Mister Wil
6df3c480b3 Bump version of abodepy to 0.14.0 (#17336) 2018-10-11 22:00:51 +02:00
Paulus Schoutsen
61f7a39748 Add permissions foundation (#16890)
* Add permission foundation

* Address comments

* typing

* False > True

* Convert more lambdas

* Use constants

* Remove support for False

* Fix only allow True
2018-10-11 19:24:25 +02:00
emontnemery
5961f2f577 Add support for off_delay to MQTT binary_sensor (#16993)
* Add support for off_delay to MQTT binary_sensor

* Fix debounce, add testcase

* Make off_delay number of seconds instead of timedelta

* Update mqtt.py

* Fix testcase, remove CONF_OFF_DELAY from const.py
2018-10-11 19:14:23 +02:00
Paulus Schoutsen
61bf4d8a29 Add user events (#17328) 2018-10-11 17:06:51 +02:00
Nikolay Vasilchuk
44477f3d32 Logbook: filter by entity and period (#17095)
* Filter logbook by entity_id

* Filter logbook by period

* Simple test

* houndci-bot review

* Tests

* Test fix

* Test Fix
2018-10-11 14:15:04 +02:00
Karim Geiger
ed45dff6e8 Implement turn_off and turn_on actions for eq3btsmart (#17168)
* Implement turn_off and turn_on actions for eq3btsmart

This commit implements the turn_off and turn_on methods for eq3btsmart. Turning the device off will set the thermostat to "OFF". Turning it on will set it to "AUTO".

* Add missing support flags for on/off feature

* Fix line length
2018-10-11 13:25:48 +02:00
Nikolay Vasilchuk
2a35a3901e Template Lock (#17288)
* Template Lock component

* Tests

* CI Fix

* Don't track templates if they have result in MATCH_ALL

* async/await

* houndci-bot review fix
2018-10-11 12:53:54 +02:00
Paulus Schoutsen
ebff253cc9 still update sensor on startup (#17319) 2018-10-11 11:38:35 +02:00
Pascal Vizeli
f5d3aa1826 Hass.io auth/sso part2 (#17324)
* Update discovery.py

* Create const.py

* Update auth.py

* Update const.py

* Update const.py

* Update http.py

* Update handler.py

* Update auth.py

* Update auth.py

* Update test_auth.py
2018-10-11 10:55:38 +02:00
uchagani
cffb704311 Enable BMW component to be unit system aware (#17197)
* Enable BMW component to be unit system aware

* lint fixes

* use constants for config entries

* remove configuration from component and rely only on HA config of unit_system

* remove unused import

* update code to reflect feedback

* lint fixes

* remove unnecessary comments

* rework return statement to satisfy pylint

* more lint fixes

* add tests for volume utils

* lint fixes

* more lint fixes

* remove unnecessary comments
2018-10-11 10:55:22 +02:00
Martin Hjelmare
58af332d21 Allow tradfri groups for new imported entries (#17310)
* Clean up leftover config schema option

* Allow import groups via new config yaml setup

* Fix and add test

* Add a test without groups for legacy import

* Change default import groups to False

* Fix I/O in test
2018-10-11 10:37:34 +02:00
George Marshall
ef2c8b2e5b Update python_openzwave==0.4.10 (#17323) 2018-10-11 10:59:16 +03:00
Fabien Piuzzi
9fa7906aef Made it possible to define multiple Octoprint printers (#16519)
* Made it possible to define multiple octoprint printers

* style fix

* Added configuration option for octoprint port

* SSL support in octoprint platform configuration

* Octoprint component now auto loads sensor and binary_sensor platforms

* preliminary support for auto discovery of octoprint servers

* Moved sensors and binary sensors configuration into main octoprint configuration

* Using base_url as the key for storing api in the octoprint component

* made sure to not supersede the platforms' domains

* bugfix: continue setting up other printers if one fails

* flake8 style correction

* Added icons to sensors

* Fail platform setup if no printers were successfully added

* Simplified custom validator
2018-10-11 09:52:13 +02:00
Dav0815
c6c5d40056 Transport NSW (#17242)
* Resubmission of development

* Clean up

* Finishing touch and clean up

* Remove not needed error check
2018-10-11 09:44:17 +02:00
Rohan Kapoor
d7cd1a2b4b Implement ZoneMinder run states (#17198) 2018-10-11 09:38:31 +02:00
Fabian Affolter
7e8973a315 Update file header (#17317) 2018-10-11 07:43:15 +02:00
Pascal Vizeli
3f87d41381 Fix auth for hass.io (#17318)
* Update test_auth.py

* Update auth.py

* Update test_auth.py
2018-10-11 01:02:00 +02:00
Fabian Affolter
8d9da4e7b9 Upgrade construct to 2.9.45 (#16362) 2018-10-10 23:52:45 +02:00
Glenn Waters
93e3596e5a Add Elk-M1 switch and scene platforms (#17256)
* Add Elk-M1 switch platform.

* Fix travis error.

* Fix very annoying lint error.

* Fix PR comments.

* Fix comment.

* Fix lint errors.

* Fix PR comments.

* Fix PR

Apologize. Going too fast. You should not have to find those.
2018-10-10 19:05:19 +02:00
zhumuht
c434ad6af5 fix_broadlink_sp2_show_energy (#17271)
* fix_broadlink_sp2_show_energy

Signed-off-by: 朱海涛 <zhumu.zht@alibaba-inc.com>

* fix_broadlink_sp2_show_energy

Signed-off-by: 朱海涛 <zhumu.zht@alibaba-inc.com>

* fix_broadlink_sp2_show_energy

Signed-off-by: 朱海涛 <zhumu.zht@alibaba-inc.com>

* fix_broadlink_sp2_show_energy

Signed-off-by: 朱海涛 <zhumu.zht@alibaba-inc.com>

* fix_broadlink_sp2_show_energy

Signed-off-by: 朱海涛 <zhumu.zht@alibaba-inc.com>
2018-10-10 18:56:00 +02:00
cgtobi
99c6622ee2 Add direction configuration (#17308) 2018-10-10 17:59:55 +02:00
Paulus Schoutsen
9d4dbd7d97 ABC config entries (#17309) 2018-10-10 16:02:03 +02:00
Paulus Schoutsen
d16e6c8524 Update translations 2018-10-10 14:25:21 +02:00
Paul Annekov
052c094425 fixed 'on_startup() takes 0 positional arguments but 1 was given' (#17295) 2018-10-10 14:24:30 +02:00
Pascal Vizeli
40e0966d7f Hassio auth (#17274)
* Create auth.py

* Update auth.py

* Update auth.py

* Update __init__.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Add tests

* Update test_auth.py

* Update auth.py

* Update test_auth.py

* Update auth.py
2018-10-10 14:07:51 +02:00
Joshi
ad4d5666fe Yamaha AVR update and change Sound Mode only on main_zone (#17241)
* Add support for sound_mode for Yamaha rxv media_player

* Catch ParseError Exeption on surround_program for unsupported models

* Catch all Exeptions from rxv

* only get sound mode list / current sound mode on main_zone
2018-10-10 14:07:33 +02:00
definitio
7f896bfb40 WIP: Don't set initial values for MQTT HVAC in non-optimistic mode (#17268)
* Don't set initial temperature in non-optimistic mode

* Fix tests

* Don't set initial values in non-optimistic mode

For fan mode, current operation and swing mode

* Fix tests again
2018-10-10 14:06:53 +02:00
Pascal Vizeli
83dd961fde Fix hassio discovery (#17275)
* Update discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Update test_discovery.py

* Fix tests

* fix lint
2018-10-10 13:50:11 +02:00
Paulus Schoutsen
a1dac28e4b Template sensors to not track all state changes (#17276)
* Disable template sensor match all

* Only manual update template sensors that match all
2018-10-10 13:49:15 +02:00
Martin Hjelmare
e5c3a4be80 Fix and clean haveibeenpwned (#17306)
* Move first forced data fetching and update to async_added_to_hass.
* Clean up code.
2018-10-10 13:46:03 +02:00
Ville Skyttä
707b7c202d Narrow scope of various pylint inline disables (#15364)
* Narrow scope of various pylint inline disables

* Whitespace tweaks
2018-10-10 12:17:11 +02:00
Teemu R
78c38749ab Xiaomi Vacuum: keep error state active after erroring (#16562)
* Check for got_error to keep consistent error reporting

* reword a comment
2018-10-10 12:16:32 +02:00
Markus Nigbur
670c75e844 Added resolve_state to template distance function (#17290)
_resolve_state was already used in the "closest" function, to allow for states and entity ids
2018-10-10 11:49:24 +02:00
Colby Rome
419725e1a9 Add Verizon Fios Quantum Gateway device_tracker platform (#17023)
* wrote quantum_gateway.py

* ran gen_requirements script

* fixed linting errors, added docstrings

* update .coveragerc

* fixed typo

* add myself to contributors

* single quotes for single words

* added error handling to prevent stacktrace

* updated my pypi library

* houndci fixes - added RequestException

* added password to config schema
2018-10-10 08:23:31 +02:00
cgtobi
cfc175d71d Make rmvtransport async (#17225)
* Make rmvtransport async

* Make rmv transport async

* Make async tests

* Update rmvtransport module version

* Remove unnecessary import

* Make rmvtransport async

* Make rmv transport async

* Make async tests

* Update rmvtransport module version

* Remove unnecessary import

* Update requirements

* Remove async loop

* Fix wrong import

* Fix stupidness

* Remove unnecessary import

* Bump upstream version

* Don't store the session

* Refactor tests

* Add test for no data

* Fix linter issues

* Fix stale docstring

* Fix stale docstring

* Remove unnecessary test code

* Remove unnecessary import

* Add configurable timeout

* Remove global variable
2018-10-10 08:10:42 +02:00
hanzoh
8310f4a1cf Add valve level to HmIP thermostat attributes (#17297) 2018-10-09 18:53:49 -06:00
Fabian Affolter
5022cf8a6c Upgrade locationsharinglib to 3.0.6 (#17294) 2018-10-10 00:02:07 +02:00
Fabian Affolter
2cd99e5a97 Upgrade shodan to 1.10.4 (#17292) 2018-10-09 22:37:50 +02:00
Alok Saboo
26f2e3dd8b Fix samsung bug (#17285) 2018-10-09 21:43:59 +02:00
mvn23
fc67f5eef3 Rewrite opentherm_gw to a component (#17133)
* Rewrite opentherm_gw to a component which loads the opentherm_gw climate platform.

* Add OpenTherm Gateway sensor platform.

* Remove library imports from platforms (use hass.data instead)
* Update .coveragerc
* Update docstrings to use new component documentation url

* Add OpenTherm Gateway binary sensor support.
Fix houndci findings.

* Revert "Add OpenTherm Gateway binary sensor support."

This reverts commit 5711dc4c25.

* Revert "Add OpenTherm Gateway sensor platform."

This reverts commit b3505ed561.

* Remove import from platform, use hass.data instead.
Update .coveragerc
Update docstrings
Update requirements_all.txt
General code cleanup

* Fix review findings.
Avoid using hass.data within connect_and_subscribe.
2018-10-09 21:06:24 +02:00
dickesW
2aeb0efc7c Fixed Temperature for HMIP-WeatherStation Plus/Basic (#17216) 2018-10-09 11:19:21 -06:00
Markus Nigbur
a99ba0a1d4 Bumped fints component to version 1.0.1 (#17280) 2018-10-09 11:18:46 -06:00
Paulus Schoutsen
e903f7ffda Manual updates (#17278) 2018-10-09 16:54:38 +02:00
Charles Garwood
cf249e3e5e Z-Wave Config Entry Support (#17119)
* Initial Z-Wave Config Entry Support

* Use conf.get() for config import

* Uncomment test

* Re-add line breaks

* tabs -> space

* Unused import cleanup & lint fixes

* Remove unused config flow link step

* Address comments

* Remove unused import

* Fix tests

* Check for valid usb_path

* Test for Z-Stick in config flow

* Pass config dir to ZWaveOption

* Auto-generate Network Key if none provided

* Test fixes

* Address comments & more start network service registration

* add_executor_job for options.lock()
2018-10-09 16:30:55 +02:00
damarco
5167658a1d Add support for zha custom cluster mappings (#16714)
* Add support for custom cluster mappings

* Refactor sub_component mapping
2018-10-09 12:53:02 +02:00
definitio
6bf3f9e748 Fix mpd timeout error (#17254)
* Increase mpd client timeout

* Update mpd.py
2018-10-09 12:24:39 +02:00
Daniel Perna
9d56730b8d Add optional "all" parameter for groups (#17179)
* Added optional mode parameter

* Cleanup

* Using boolean configuration

* Fix invalid syntax

* Added tests for all-parameter

* Grammar

* Lint

* Docstrings

* Better description
2018-10-09 10:14:55 +02:00
Otto Winter
26cf5acd5b Make async_track_time_change smarter (#17199)
* Make async_track_time_change smarter

* Move to util/dt

* Remove unnecessary check

* Lint

* Remove tzinfo check

* Remove check

* Add comment about async_track_point_in_utc_time

* Fix typing check

* Lint
2018-10-09 10:14:18 +02:00
Otto Winter
9190fe1c21 Add device registry to MQTT fan (#17250) 2018-10-09 10:13:42 +02:00
marcolertora
0c34c50d2f Added lumitek/ankuoo recswitch component (#15764)
* Added lumitek/ankuoo recswitch component

* cosmetics

* remove callback

* cosmetics

* update requirements pyrecswitch==1.0.2

* add in .coveragerc
2018-10-09 10:13:03 +02:00
Sebastian Muszynski
757ba3b60e Add basic support of the Philips Zhirui desk lamp (philips.light.mono1) (#17258) 2018-10-09 10:11:34 +02:00
Sebastian Muszynski
882c4b73ae Fix ambient light state of the Philips Eyecare Lamp (Closes: #16269) (#17259) 2018-10-09 10:11:14 +02:00
Steven Looman
4455a287fc Add defaults, fixing #17229 (#17261) 2018-10-09 10:07:30 +02:00
Anders Melchiorsen
5db7d702c8 Remove warning on script delay (#17264)
* Remove warning on script delay

* Use suppress
2018-10-09 10:06:42 +02:00
Tomas Hellström
540d22d603 Swedish weather institute weather component (#16717)
* SMHI Component

* Clean up typos

* Fixed default values first config to home location (tests will follow)

* Fixed tests and removed unused function

* Minor fixup after comments from @kane610

* add support for precipitation in forecast

* Removed old async_step_init not needed.
2018-10-08 23:54:55 +02:00
Teemu R
56a43436d7 Bump python-miio requirement (#17260) 2018-10-08 22:33:06 +02:00
Nick Horvath
1393766659 Thermoworks Smoke Sensor (#16139)
* Add support for monitoring the temperature of a thermoworks smoke thermometer.

* Use string formatting.

* Add line break.

* Add error handling for authentication.

* Fix linting errors.

* Fix quotes.

* Bump thermoworks_smoke library version.

* Review changes for @MartinHjelmare

* Add unique id attribute and change battery attribute to the standard "battery_level".

* requested changes to snake case and monitored conditions

* fix lint error

* exclude firmware from state attrs. rename original_unit to unit_of_min_max so it's more clear what it is for.

* add device_info

* add regex validator for exclude

* undo device info stuff

* remove serial number from attributes even though other components are allowed to have it...

* exclude firmware
2018-10-08 22:15:38 +02:00
Paulus Schoutsen
68d72931c4 block external IP (#17248)
* block external IP

* Update __init__.py
2018-10-08 20:50:24 +02:00
Jari Ylimäinen
0c0184973b Add configurable temperature step for MQTT climate component (#16201)
* Add configurable temperature step

* Remove temp step from climate component
2018-10-08 20:24:25 +02:00
damarco
59ec469722 Use only_cache parameter in binary_sensor.zha.Remote (#16711) 2018-10-08 20:23:26 +02:00
Paulus Schoutsen
68472b8241 Add a webhook automation trigger (#17246) 2018-10-08 20:16:37 +02:00
Glenn Waters
9380fca97e Add Elk light platform (#17222)
* Add Elk light platform.

* Add ElkM1 light code. Doh.

* Fix PR comments.

* Fix hound errors.

* Fix PR comment.

* Move state from base to class(s) where used
2018-10-08 17:30:27 +02:00
Paulus Schoutsen
c3b1121d77 Add group foundation (#16935)
Add group foundation
2018-10-08 16:35:38 +02:00
Otto Winter
dd55ff87c8 Add device registry to MQTT cover (#17245)
* Add device registry to MQTT cover

* Fix tests
2018-10-08 16:13:44 +02:00
Malte Franken
b637b48bd8 emptying device state attributes if the update from the feed fails (#17249) 2018-10-08 16:13:08 +02:00
emontnemery
42fb886d71 Add support for HS color to mqtt light (#16958)
* Add support for HS color to mqtt light

* Warn if hs state update is invalid
2018-10-08 15:36:57 +02:00
Otto Winter
9290f245bf Convert MQTT fan to config entry (#17247) 2018-10-08 14:59:04 +02:00
Otto Winter
c41ef65da6 Add device registry to MQTT switches (#17244) 2018-10-08 14:57:07 +02:00
Otto Winter
744dd42ad3 Add device registry to MQTT binary sensor (#17243) 2018-10-08 14:44:00 +02:00
Matt Schmitt
27f0331f0f 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 14:19:23 +02:00
Malte Franken
394ffc40b6 updated georss-client library to 0.3 (#17239) 2018-10-08 13:32:16 +02:00
Paulus Schoutsen
d5f5273c31 Guard for bad device info (#17238) 2018-10-08 12:53:51 +02:00
Otto Winter
af2402ea59 Implement base for MQTT device registry integration (#16943)
* Implement base for MQTT device registry integration

* Lint

* Lint

* Address comments

* Lint

* Lint

* Address comments

* Only add keys if specified

See https://github.com/home-assistant/home-assistant/pull/17136#discussion_r223267185
2018-10-08 12:53:30 +02:00
Daniel Lashua
71a0274b12 Add Support for Xiaomi Vibration Sensor (#16422) 2018-10-08 12:08:46 +02:00
Otto Winter
3f498bd042 Fix potential MQTT discovery race condition (#17208)
* Fix potential MQTT discovery race condition

* Rename data key
2018-10-08 10:59:43 +02:00
MatteGary
ee5e1fa355 Daikin Climate - Better integration with Climate base component (#16913)
* Daikin Climate - Better integration with Climate base component

Made some modification in order to better integrate the Daikin AC Component with the base Climate Component.
Benefits are:
Support localization for Operation Mode
Support for Homekit Integration (if the AC is turned On, now the status is updated in Homekit)

* Build bug fixing

* Bug fixing in Set Operation_Mode functionality

Fixed to .title() functionality in matching the Operation_Mode

* Fix useless code

* Fix hound bug

* Bug fixing

Change in list of Operation Mode

* Trailing white space fix

* Compile fixing

* Whitespace fix
2018-10-08 10:49:54 +02:00
William Scanlon
f2d8f3bcb8 Water heater support (#17058)
* Moved econet to water_heater

* Wink and Econet are now in water heater!

* Removed away mode from econet and added demo water heater

* Added demo tests

* Updated coveragerc

* Fix lint issues.

* updated requirements all

* Requirements all actually updated.

* Reset wink and econet and fixed service.

* Reset wink and econet to the correct dev state

* Reset requirements_all and .coveragerc and removed the new econet and wink water_heater files

* Removed @bind_hass service methods

* Actually reset the .coverage file

* Fixed the tests

* Addressed @MartinHjelmare's comments

* Removed unused import

* Switched to async_add_executor_job

* Fixed lint

* Removed is_on

* Added celsius demo water heater and tests.

* Removed metric import
2018-10-08 10:38:07 +02:00
Sebastian Muszynski
ff4204244b Fix data_key and power_consumed attribute of the Aqara Wall Switch (Closes: #16457) (#17235) 2018-10-08 10:37:27 +02:00
Paulus Schoutsen
a54e242245 Fix SPC (#17236) 2018-10-08 10:20:18 +02:00
Oliver
849665b9ca Pushed to version 0.7.6 of denonavr library to add more sound modes (#17227) 2018-10-08 09:32:14 +02:00
Sebastian Muszynski
315f83e1ea Add some new model names of Xiaomi Aqara devices (#17234)
* Add additional model name of the Xiaomi Aqara Button (WXKG11LM)

* Add additional model name of the Xiaomi Aqara Wireless Switch (WXKG02LM, WXKG03LM)

* Bump PyXiaomiGateway version
2018-10-08 09:32:01 +02:00
Paulus Schoutsen
4b7f85518f Prevent accidental device reg override (#17136) 2018-10-08 09:30:40 +02:00
Daniel Høyer Iversen
59d78b060f danielhiversen as codeowner for met.no (#17232) 2018-10-08 08:36:32 +02:00
Martin Berg
e922dd10ba Init sub-components using global var. (#17220) 2018-10-07 23:30:09 +02:00
Paulus Schoutsen
2de1193fd9 Update translations 2018-10-07 23:26:46 +02:00
Paulus Schoutsen
c12bbddc0b Update frontend to 20181007.0 2018-10-07 23:26:23 +02:00
Anders Melchiorsen
086c71525e Add config entry for LIFX (#17201)
* Add config entry for LIFX

* Use list for dependencies

* Obsolete the platform config

* Use DOMAIN

* Use async_create_task
2018-10-07 23:14:53 +02:00
Glenn Waters
06a64c0167 Add support for ElkM1 alarm/automation panel (#16952)
* Add support for ElkM1 alarm/automation panel.

* fix lines too long

* Address PR comments

* Fix hound ci errors

* Changes for PR comments

* Use vol.Range for checking range value

* Address PR comments

* Fix lint errors

* Added elkm1-lib requirement

* Update coverage to exclude elk

* Fix flake8 errors

* Fix flake8 error

* Cleanup config parsing

* Add housecode converter

* fix PR comments

* fix syntax error

* Fix PR comment
2018-10-07 21:45:36 +02:00
Daniel Høyer Iversen
c1ed9edd26 Add forecast for Met.no (#17109)
test met

met no 0.3.0

fix line length

fix line length
2018-10-07 21:00:12 +02:00
emontnemery
1d7d82fde5 Fix aliases support for RFLink sensors (#17190) 2018-10-07 13:14:37 +02:00
Brian Towles
592e1dc96a Enable new registry rename for Insteon (#17171)
* Enable new registry rename for Insteon

* Segment unique_id from name
2018-10-07 13:12:33 +02:00
Anders Melchiorsen
6e81ae096e Disallow list/dict for string configuration (#17202) 2018-10-07 12:35:44 +02:00
Per Sandström
c8266c6692 vsure version 1.5.0 (#17209) 2018-10-07 12:33:16 +02:00
Philip Rosenberg-Watt
8fda705377 Fix Todoist custom project update (#17115)
* Fix Todoist custom project update

Custom projects were not refreshing the API state and were using
local/stored state. This resulted in invalid tasks being retained upon
update. This change resets the local Todoist API state, syncs it, and
then continues normal update operation(s) on the Todoist project data
object.

* Remove blank line after docstring

* Update logging call

* Simplify logging
2018-10-07 01:38:25 +02:00
cdce8p
5d6562a73f Bugfix switch flux - light service call (#17187)
* Bugfix switch flux - light service call

* Change x_val and y_val test
2018-10-06 23:30:07 +02:00
Guy Khmelnitsky
9285831fa1 Upgrade boto3 to 1.9.16 (#17140) 2018-10-06 20:46:20 +02:00
Per Sandström
760047f964 Verisure standard config for scan interval (#17192)
* verisure configurable polling

* fix indentation
2018-10-06 20:03:22 +02:00
Anders Melchiorsen
8683eeb908 Upgrade aiolifx_effects to 0.2.1 (#17188) 2018-10-06 14:32:54 +02:00
Fabian Affolter
75e236de73 Add myself to more sensors (#17185) 2018-10-06 09:54:03 +02:00
Fabian Affolter
169abe637c Update core, add myself and introduce grouping (#17175) 2018-10-06 07:16:06 +02:00
cdce8p
07d90c6c55 Fix device_tracker service call & cleanup (#17173)
* Bugfix group service - device_tracker

* Cleanup
2018-10-05 23:09:55 +02:00
Paulus Schoutsen
a66db59359 Fix data used for logbook (#17172)
* Fix data used for logbook

* Lint
2018-10-05 23:07:27 +02:00
Fabian Affolter
bed1b96f5a Revert "Update core, add myself and introduce grouping"
This reverts commit 13106a9b55.
2018-10-05 21:46:26 +02:00
Fabian Affolter
13106a9b55 Update core, add myself and introduce grouping 2018-10-05 21:45:14 +02:00
kennedyshead
7598067b55 Adding myself as melissa owner (#17157) 2018-10-05 20:48:20 +02:00
Paulus Schoutsen
5e7d4a57a3 Fix incorrect yaml in hangouts (#17169) 2018-10-05 20:21:09 +02:00
Paulus Schoutsen
1061c369f1 Bumped version to 0.81.0.dev0 2018-10-05 19:54:15 +02:00
1163 changed files with 57642 additions and 26883 deletions

View File

@@ -76,16 +76,13 @@ omit =
homeassistant/components/daikin.py
homeassistant/components/*/daikin.py
homeassistant/components/deconz/*
homeassistant/components/*/deconz.py
homeassistant/components/digital_ocean.py
homeassistant/components/*/digital_ocean.py
homeassistant/components/dominos.py
homeassistant/components/doorbird.py
homeassistant/components/*/doorbird.py
homeassistant/components/doorbird.py
homeassistant/components/*/doorbird.py
homeassistant/components/dweet.py
homeassistant/components/*/dweet.py
@@ -102,6 +99,9 @@ omit =
homeassistant/components/egardia.py
homeassistant/components/*/egardia.py
homeassistant/components/elkm1/*
homeassistant/components/*/elkm1.py
homeassistant/components/enocean.py
homeassistant/components/*/enocean.py
@@ -120,12 +120,18 @@ omit =
homeassistant/components/eufy.py
homeassistant/components/*/eufy.py
homeassistant/components/fibaro.py
homeassistant/components/*/fibaro.py
homeassistant/components/gc100.py
homeassistant/components/*/gc100.py
homeassistant/components/google.py
homeassistant/components/*/google.py
homeassistant/components/greeneye_monitor.py
homeassistant/components/sensor/greeneye_monitor.py
homeassistant/components/habitica/*
homeassistant/components/*/habitica.py
@@ -200,13 +206,15 @@ omit =
homeassistant/components/logi_circle.py
homeassistant/components/*/logi_circle.py
homeassistant/components/lupusec.py
homeassistant/components/*/lupusec.py
homeassistant/components/lutron.py
homeassistant/components/*/lutron.py
homeassistant/components/lutron_caseta.py
homeassistant/components/*/lutron_caseta.py
homeassistant/components/mailgun.py
homeassistant/components/*/mailgun.py
homeassistant/components/matrix.py
@@ -245,12 +253,19 @@ omit =
homeassistant/components/opencv.py
homeassistant/components/*/opencv.py
homeassistant/components/opentherm_gw/*
homeassistant/components/*/opentherm_gw.py
homeassistant/components/openuv/__init__.py
homeassistant/components/*/openuv.py
homeassistant/components/pilight.py
homeassistant/components/*/pilight.py
homeassistant/components/point/__init__.py
homeassistant/components/point/const.py
homeassistant/components/*/point.py
homeassistant/components/switch/qwikswitch.py
homeassistant/components/light/qwikswitch.py
@@ -260,7 +275,7 @@ omit =
homeassistant/components/raincloud.py
homeassistant/components/*/raincloud.py
homeassistant/components/rainmachine/*
homeassistant/components/rainmachine/__init__.py
homeassistant/components/*/rainmachine.py
homeassistant/components/raspihats.py
@@ -284,6 +299,12 @@ omit =
homeassistant/components/scsgate.py
homeassistant/components/*/scsgate.py
homeassistant/components/sense.py
homeassistant/components/*/sense.py
homeassistant/components/simplisafe/__init__.py
homeassistant/components/*/simplisafe.py
homeassistant/components/sisyphus.py
homeassistant/components/*/sisyphus.py
@@ -322,10 +343,12 @@ omit =
homeassistant/components/toon.py
homeassistant/components/*/toon.py
homeassistant/components/tplink_lte.py
homeassistant/components/*/tplink_lte.py
homeassistant/components/tradfri.py
homeassistant/components/*/tradfri.py
homeassistant/components/twilio.py
homeassistant/components/notify/twilio_sms.py
homeassistant/components/notify/twilio_call.py
@@ -355,6 +378,9 @@ omit =
homeassistant/components/*/webostv.py
homeassistant/components/w800rf32.py
homeassistant/components/*/w800rf32.py
homeassistant/components/wemo.py
homeassistant/components/*/wemo.py
@@ -379,7 +405,7 @@ omit =
homeassistant/components/zigbee.py
homeassistant/components/*/zigbee.py
homeassistant/components/zoneminder.py
homeassistant/components/zoneminder/*
homeassistant/components/*/zoneminder.py
homeassistant/components/tuya.py
@@ -395,7 +421,6 @@ omit =
homeassistant/components/alarm_control_panel/ifttt.py
homeassistant/components/alarm_control_panel/manual_mqtt.py
homeassistant/components/alarm_control_panel/nx584.py
homeassistant/components/alarm_control_panel/simplisafe.py
homeassistant/components/alarm_control_panel/totalconnect.py
homeassistant/components/alarm_control_panel/yale_smart_alarm.py
homeassistant/components/apiai.py
@@ -426,7 +451,6 @@ omit =
homeassistant/components/camera/xeoma.py
homeassistant/components/camera/xiaomi.py
homeassistant/components/camera/yi.py
homeassistant/components/climate/econet.py
homeassistant/components/climate/ephember.py
homeassistant/components/climate/eq3btsmart.py
homeassistant/components/climate/flexit.py
@@ -434,8 +458,8 @@ omit =
homeassistant/components/climate/homematic.py
homeassistant/components/climate/honeywell.py
homeassistant/components/climate/knx.py
homeassistant/components/climate/mill.py
homeassistant/components/climate/oem.py
homeassistant/components/climate/opentherm_gw.py
homeassistant/components/climate/proliphix.py
homeassistant/components/climate/radiotherm.py
homeassistant/components/climate/sensibo.py
@@ -451,7 +475,6 @@ omit =
homeassistant/components/cover/myq.py
homeassistant/components/cover/opengarage.py
homeassistant/components/cover/rpi_gpio.py
homeassistant/components/cover/ryobi_gdo.py
homeassistant/components/cover/scsgate.py
homeassistant/components/device_tracker/actiontec.py
homeassistant/components/device_tracker/aruba.py
@@ -461,11 +484,13 @@ omit =
homeassistant/components/device_tracker/bluetooth_le_tracker.py
homeassistant/components/device_tracker/bluetooth_tracker.py
homeassistant/components/device_tracker/bt_home_hub_5.py
homeassistant/components/device_tracker/bt_smarthub.py
homeassistant/components/device_tracker/cisco_ios.py
homeassistant/components/device_tracker/ddwrt.py
homeassistant/components/device_tracker/freebox.py
homeassistant/components/device_tracker/fritz.py
homeassistant/components/device_tracker/google_maps.py
homeassistant/components/device_tracker/googlehome.py
homeassistant/components/device_tracker/gpslogger.py
homeassistant/components/device_tracker/hitron_coda.py
homeassistant/components/device_tracker/huawei_router.py
@@ -478,6 +503,7 @@ omit =
homeassistant/components/device_tracker/netgear.py
homeassistant/components/device_tracker/nmap_tracker.py
homeassistant/components/device_tracker/ping.py
homeassistant/components/device_tracker/quantum_gateway.py
homeassistant/components/device_tracker/ritassist.py
homeassistant/components/device_tracker/sky_hub.py
homeassistant/components/device_tracker/snmp.py
@@ -487,12 +513,14 @@ omit =
homeassistant/components/device_tracker/tile.py
homeassistant/components/device_tracker/tomato.py
homeassistant/components/device_tracker/tplink.py
homeassistant/components/device_tracker/traccar.py
homeassistant/components/device_tracker/trackr.py
homeassistant/components/device_tracker/ubus.py
homeassistant/components/downloader.py
homeassistant/components/emoncms_history.py
homeassistant/components/emulated_hue/upnp.py
homeassistant/components/fan/mqtt.py
homeassistant/components/fan/wemo.py
homeassistant/components/folder_watcher.py
homeassistant/components/foursquare.py
homeassistant/components/goalfeed.py
@@ -500,6 +528,7 @@ omit =
homeassistant/components/image_processing/dlib_face_detect.py
homeassistant/components/image_processing/dlib_face_identify.py
homeassistant/components/image_processing/seven_segments.py
homeassistant/components/image_processing/tensorflow.py
homeassistant/components/keyboard_remote.py
homeassistant/components/keyboard.py
homeassistant/components/light/avion.py
@@ -519,6 +548,7 @@ omit =
homeassistant/components/light/lw12wifi.py
homeassistant/components/light/mystrom.py
homeassistant/components/light/nanoleaf_aurora.py
homeassistant/components/light/niko_home_control.py
homeassistant/components/light/opple.py
homeassistant/components/light/osramlightify.py
homeassistant/components/light/piglow.py
@@ -561,6 +591,7 @@ omit =
homeassistant/components/media_player/itunes.py
homeassistant/components/media_player/kodi.py
homeassistant/components/media_player/lg_netcast.py
homeassistant/components/media_player/lg_soundbar.py
homeassistant/components/media_player/liveboxplaytv.py
homeassistant/components/media_player/mediaroom.py
homeassistant/components/media_player/mpchc.py
@@ -569,6 +600,7 @@ omit =
homeassistant/components/media_player/nadtcp.py
homeassistant/components/media_player/onkyo.py
homeassistant/components/media_player/openhome.py
homeassistant/components/media_player/panasonic_bluray.py
homeassistant/components/media_player/panasonic_viera.py
homeassistant/components/media_player/pandora.py
homeassistant/components/media_player/philips_js.py
@@ -604,6 +636,7 @@ omit =
homeassistant/components/notify/gntp.py
homeassistant/components/notify/group.py
homeassistant/components/notify/hipchat.py
homeassistant/components/notify/homematic.py
homeassistant/components/notify/instapush.py
homeassistant/components/notify/kodi.py
homeassistant/components/notify/lannouncer.py
@@ -636,6 +669,7 @@ omit =
homeassistant/components/remember_the_milk/__init__.py
homeassistant/components/remote/harmony.py
homeassistant/components/remote/itach.py
homeassistant/components/route53.py
homeassistant/components/scene/hunterdouglas_powerview.py
homeassistant/components/scene/lifx_cloud.py
homeassistant/components/sensor/airvisual.py
@@ -682,6 +716,7 @@ omit =
homeassistant/components/sensor/fints.py
homeassistant/components/sensor/fitbit.py
homeassistant/components/sensor/fixer.py
homeassistant/components/sensor/flunearyou.py
homeassistant/components/sensor/folder.py
homeassistant/components/sensor/foobot.py
homeassistant/components/sensor/fritzbox_callmonitor.py
@@ -706,12 +741,14 @@ omit =
homeassistant/components/sensor/kwb.py
homeassistant/components/sensor/lacrosse.py
homeassistant/components/sensor/lastfm.py
homeassistant/components/sensor/launch_library.py
homeassistant/components/sensor/linky.py
homeassistant/components/sensor/linux_battery.py
homeassistant/components/sensor/loopenergy.py
homeassistant/components/sensor/luftdaten.py
homeassistant/components/sensor/lyft.py
homeassistant/components/sensor/magicseaweed.py
homeassistant/components/sensor/meteo_france.py
homeassistant/components/sensor/metoffice.py
homeassistant/components/sensor/miflora.py
homeassistant/components/sensor/mitemp_bt.py
@@ -747,11 +784,13 @@ omit =
homeassistant/components/sensor/radarr.py
homeassistant/components/sensor/rainbird.py
homeassistant/components/sensor/ripple.py
homeassistant/components/sensor/rtorrent.py
homeassistant/components/sensor/ruter.py
homeassistant/components/sensor/scrape.py
homeassistant/components/sensor/sense.py
homeassistant/components/sensor/sensehat.py
homeassistant/components/sensor/serial_pm.py
homeassistant/components/sensor/serial.py
homeassistant/components/sensor/seventeentrack.py
homeassistant/components/sensor/sht31.py
homeassistant/components/sensor/shodan.py
homeassistant/components/sensor/sigfox.py
@@ -771,11 +810,14 @@ omit =
homeassistant/components/sensor/swiss_public_transport.py
homeassistant/components/sensor/syncthru.py
homeassistant/components/sensor/synologydsm.py
homeassistant/components/sensor/srp_energy.py
homeassistant/components/sensor/systemmonitor.py
homeassistant/components/sensor/sytadin.py
homeassistant/components/sensor/tank_utility.py
homeassistant/components/sensor/tautulli.py
homeassistant/components/sensor/ted5000.py
homeassistant/components/sensor/temper.py
homeassistant/components/sensor/thermoworks_smoke.py
homeassistant/components/sensor/time_date.py
homeassistant/components/sensor/torque.py
homeassistant/components/sensor/trafikverket_weatherstation.py
@@ -816,6 +858,7 @@ omit =
homeassistant/components/switch/pulseaudio_loopback.py
homeassistant/components/switch/rainbird.py
homeassistant/components/switch/rest.py
homeassistant/components/switch/recswitch.py
homeassistant/components/switch/rpi_rf.py
homeassistant/components/switch/snmp.py
homeassistant/components/switch/switchbot.py
@@ -832,6 +875,7 @@ omit =
homeassistant/components/tts/picotts.py
homeassistant/components/vacuum/mqtt.py
homeassistant/components/vacuum/roomba.py
homeassistant/components/water_heater/econet.py
homeassistant/components/watson_iot.py
homeassistant/components/weather/bom.py
homeassistant/components/weather/buienradar.py

View File

@@ -13,6 +13,7 @@
## Checklist:
- [ ] The code change is tested and works locally.
- [ ] Local tests pass with `tox`. **Your PR cannot be merged unless tests pass**
- [ ] There is no commented out code in this PR.
If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [home-assistant.io](https://github.com/home-assistant/home-assistant.io)

10
.readthedocs.yml Normal file
View File

@@ -0,0 +1,10 @@
# .readthedocs.yml
build:
image: latest
python:
version: 3.6
setup_py_install: true
requirements_file: requirements_docs.txt

View File

@@ -2,62 +2,75 @@
# when the code that they own is touched.
# https://github.com/blog/2392-introducing-code-owners
# Home Assistant Core
setup.py @home-assistant/core
homeassistant/*.py @home-assistant/core
homeassistant/helpers/* @home-assistant/core
homeassistant/util/* @home-assistant/core
homeassistant/components/api.py @home-assistant/core
homeassistant/components/auth/* @home-assistant/core
homeassistant/components/automation/* @home-assistant/core
homeassistant/components/cloud/* @home-assistant/core
homeassistant/components/config/* @home-assistant/core
homeassistant/components/configurator.py @home-assistant/core
homeassistant/components/group.py @home-assistant/core
homeassistant/components/conversation/* @home-assistant/core
homeassistant/components/frontend/* @home-assistant/core
homeassistant/components/group/* @home-assistant/core
homeassistant/components/history.py @home-assistant/core
homeassistant/components/http/* @home-assistant/core
homeassistant/components/input_*.py @home-assistant/core
homeassistant/components/introduction.py @home-assistant/core
homeassistant/components/logger.py @home-assistant/core
homeassistant/components/lovelace/* @home-assistant/core
homeassistant/components/mqtt/* @home-assistant/core
homeassistant/components/panel_custom.py @home-assistant/core
homeassistant/components/panel_iframe.py @home-assistant/core
homeassistant/components/persistent_notification.py @home-assistant/core
homeassistant/components/onboarding/* @home-assistant/core
homeassistant/components/persistent_notification/* @home-assistant/core
homeassistant/components/scene/__init__.py @home-assistant/core
homeassistant/components/scene/hass.py @home-assistant/core
homeassistant/components/script.py @home-assistant/core
homeassistant/components/shell_command.py @home-assistant/core
homeassistant/components/sun.py @home-assistant/core
homeassistant/components/updater.py @home-assistant/core
homeassistant/components/weblink.py @home-assistant/core
homeassistant/components/weblink/* @home-assistant/core
homeassistant/components/websocket_api.py @home-assistant/core
homeassistant/components/zone.py @home-assistant/core
homeassistant/components/zone/* @home-assistant/core
# HomeAssistant developer Teams
# Home Assistant Developer Teams
Dockerfile @home-assistant/docker
virtualization/Docker/* @home-assistant/docker
homeassistant/components/zwave/* @home-assistant/z-wave
homeassistant/components/*/zwave.py @home-assistant/z-wave
homeassistant/components/hassio.py @home-assistant/hassio
homeassistant/components/hassio/* @home-assistant/hassio
# Individual components
# Individual platforms
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/binary_sensor/threshold.py @fabaff
homeassistant/components/camera/yi.py @bachya
homeassistant/components/climate/ephember.py @ttroy50
homeassistant/components/climate/eq3btsmart.py @rytilahti
homeassistant/components/climate/mill.py @danielhiversen
homeassistant/components/climate/sensibo.py @andrey-git
homeassistant/components/cover/brunt.py @eavanvalkenburg
homeassistant/components/cover/group.py @cdce8p
homeassistant/components/cover/template.py @PhracturedBlue
homeassistant/components/device_tracker/asuswrt.py @kennedyshead
homeassistant/components/device_tracker/automatic.py @armills
homeassistant/components/device_tracker/huawei_router.py @abmantis
homeassistant/components/device_tracker/quantum_gateway.py @cisasteelersfan
homeassistant/components/device_tracker/tile.py @bachya
homeassistant/components/device_tracker/bt_smarthub.py @jxwolstenholme
homeassistant/components/history_graph.py @andrey-git
homeassistant/components/light/lifx.py @amelchio
homeassistant/components/influx.py @fabaff
homeassistant/components/light/lifx_legacy.py @amelchio
homeassistant/components/light/tplink.py @rytilahti
homeassistant/components/light/yeelight.py @rytilahti
homeassistant/components/light/yeelightsunflower.py @lindsaymarkward
homeassistant/components/lock/nello.py @pschmitt
homeassistant/components/lock/nuki.py @pschmitt
homeassistant/components/media_player/emby.py @mezz64
@@ -65,74 +78,181 @@ homeassistant/components/media_player/kodi.py @armills
homeassistant/components/media_player/liveboxplaytv.py @pschmitt
homeassistant/components/media_player/mediaroom.py @dgomes
homeassistant/components/media_player/monoprice.py @etsinko
homeassistant/components/media_player/mpd.py @fabaff
homeassistant/components/media_player/sonos.py @amelchio
homeassistant/components/media_player/xiaomi_tv.py @fattdev
homeassistant/components/media_player/yamaha_musiccast.py @jalmeroth
homeassistant/components/no_ip.py @fabaff
homeassistant/components/notify/file.py @fabaff
homeassistant/components/notify/flock.py @fabaff
homeassistant/components/notify/instapush.py @fabaff
homeassistant/components/notify/mastodon.py @fabaff
homeassistant/components/notify/smtp.py @fabaff
homeassistant/components/notify/syslog.py @fabaff
homeassistant/components/notify/xmpp.py @fabaff
homeassistant/components/notify/yessssms.py @flowolf
homeassistant/components/plant.py @ChristianKuehnel
homeassistant/components/scene/lifx_cloud.py @amelchio
homeassistant/components/sensor/airvisual.py @bachya
homeassistant/components/sensor/alpha_vantage.py @fabaff
homeassistant/components/sensor/bitcoin.py @fabaff
homeassistant/components/sensor/cpuspeed.py @fabaff
homeassistant/components/sensor/cups.py @fabaff
homeassistant/components/sensor/darksky.py @fabaff
homeassistant/components/sensor/file.py @fabaff
homeassistant/components/sensor/filter.py @dgomes
homeassistant/components/sensor/fixer.py @fabaff
homeassistant/components/sensor/flunearyou.py.py @bachya
homeassistant/components/sensor/gearbest.py @HerrHofrat
homeassistant/components/sensor/gitter.py @fabaff
homeassistant/components/sensor/glances.py @fabaff
homeassistant/components/sensor/gpsd.py @fabaff
homeassistant/components/sensor/irish_rail_transport.py @ttroy50
homeassistant/components/sensor/jewish_calendar.py @tsvi
homeassistant/components/sensor/linux_battery.py @fabaff
homeassistant/components/sensor/miflora.py @danielhiversen @ChristianKuehnel
homeassistant/components/sensor/min_max.py @fabaff
homeassistant/components/sensor/moon.py @fabaff
homeassistant/components/sensor/netdata.py @fabaff
homeassistant/components/sensor/nsw_fuel_station.py @nickw444
homeassistant/components/sensor/pi_hole.py @fabaff
homeassistant/components/sensor/pollen.py @bachya
homeassistant/components/sensor/pvoutput.py @fabaff
homeassistant/components/sensor/qnap.py @colinodell
homeassistant/components/sensor/scrape.py @fabaff
homeassistant/components/sensor/serial.py @fabaff
homeassistant/components/sensor/seventeentrack.py @bachya
homeassistant/components/sensor/shodan.py @fabaff
homeassistant/components/sensor/sma.py @kellerza
homeassistant/components/sensor/sql.py @dgomes
homeassistant/components/sensor/statistics.py @fabaff
homeassistant/components/sensor/swiss*.py @fabaff
homeassistant/components/sensor/sytadin.py @gautric
homeassistant/components/sensor/time_data.py @fabaff
homeassistant/components/sensor/version.py @fabaff
homeassistant/components/sensor/waqi.py @andrey-git
homeassistant/components/sensor/worldclock.py @fabaff
homeassistant/components/shiftr.py @fabaff
homeassistant/components/spaceapi.py @fabaff
homeassistant/components/switch/tplink.py @rytilahti
homeassistant/components/vacuum/roomba.py @pschmitt
homeassistant/components/weather/__init__.py @fabaff
homeassistant/components/weather/darksky.py @fabaff
homeassistant/components/weather/demo.py @fabaff
homeassistant/components/weather/met.py @danielhiversen
homeassistant/components/weather/openweathermap.py @fabaff
homeassistant/components/xiaomi_aqara.py @danielhiversen @syssi
# A
homeassistant/components/arduino.py @fabaff
homeassistant/components/*/arduino.py @fabaff
homeassistant/components/*/arest.py @fabaff
homeassistant/components/*/axis.py @kane610
# B
homeassistant/components/blink/* @fronzbot
homeassistant/components/*/blink.py @fronzbot
homeassistant/components/bmw_connected_drive.py @ChristianKuehnel
homeassistant/components/*/bmw_connected_drive.py @ChristianKuehnel
homeassistant/components/*/broadlink.py @danielhiversen
# C
homeassistant/components/counter/* @fabaff
# D
homeassistant/components/*/deconz.py @kane610
homeassistant/components/digital_ocean.py @fabaff
homeassistant/components/*/digital_ocean.py @fabaff
homeassistant/components/dweet.py @fabaff
homeassistant/components/*/dweet.py @fabaff
# E
homeassistant/components/ecovacs.py @OverloadUT
homeassistant/components/*/ecovacs.py @OverloadUT
homeassistant/components/edp_redy.py @abmantis
homeassistant/components/*/edp_redy.py @abmantis
homeassistant/components/edp_redy.py @abmantis
homeassistant/components/eight_sleep.py @mezz64
homeassistant/components/*/eight_sleep.py @mezz64
# H
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
# K
homeassistant/components/knx.py @Julius2342
homeassistant/components/*/knx.py @Julius2342
homeassistant/components/konnected.py @heythisisnate
homeassistant/components/*/konnected.py @heythisisnate
# L
homeassistant/components/lifx.py @amelchio
homeassistant/components/*/lifx.py @amelchio
homeassistant/components/luftdaten/* @fabaff
homeassistant/components/*/luftdaten.py @fabaff
# M
homeassistant/components/matrix.py @tinloaf
homeassistant/components/*/matrix.py @tinloaf
homeassistant/components/melissa.py @kennedyshead
homeassistant/components/*/melissa.py @kennedyshead
homeassistant/components/*/mystrom.py @fabaff
# O
homeassistant/components/openuv/* @bachya
homeassistant/components/*/openuv.py @bachya
# Q
homeassistant/components/qwikswitch.py @kellerza
homeassistant/components/*/qwikswitch.py @kellerza
# R
homeassistant/components/rainmachine/* @bachya
homeassistant/components/*/rainmachine.py @bachya
homeassistant/components/*/random.py @fabaff
homeassistant/components/*/rfxtrx.py @danielhiversen
# S
homeassistant/components/simplisafe/* @bachya
homeassistant/components/*/simplisafe.py @bachya
# T
homeassistant/components/tahoma.py @philklei
homeassistant/components/*/tahoma.py @philklei
homeassistant/components/tesla.py @zabuldon
homeassistant/components/*/tesla.py @zabuldon
homeassistant/components/tellduslive.py @molobrakos @fredrike
homeassistant/components/*/tellduslive.py @molobrakos @fredrike
homeassistant/components/tesla.py @zabuldon
homeassistant/components/*/tesla.py @zabuldon
homeassistant/components/thethingsnetwork.py @fabaff
homeassistant/components/*/thethingsnetwork.py @fabaff
homeassistant/components/tibber/* @danielhiversen
homeassistant/components/*/tibber.py @danielhiversen
homeassistant/components/tradfri/* @ggravlingen
homeassistant/components/*/tradfri.py @ggravlingen
# U
homeassistant/components/unifi.py @kane610
homeassistant/components/switch/unifi.py @kane610
homeassistant/components/upcloud.py @scop
homeassistant/components/*/upcloud.py @scop
# V
homeassistant/components/velux.py @Julius2342
homeassistant/components/*/velux.py @Julius2342
# W
homeassistant/components/wemo.py @sqldiablo
homeassistant/components/*/wemo.py @sqldiablo
# X
homeassistant/components/*/xiaomi_aqara.py @danielhiversen @syssi
homeassistant/components/*/xiaomi_miio.py @rytilahti @syssi
homeassistant/components/zoneminder.py @rohankapoorcom
# Z
homeassistant/components/zoneminder/ @rohankapoorcom
homeassistant/components/*/zoneminder.py @rohankapoorcom
# Other code
homeassistant/scripts/check_config.py @kellerza

View File

@@ -11,6 +11,7 @@ LABEL maintainer="Paulus Schoutsen <Paulus@PaulusSchoutsen.nl>"
#ENV INSTALL_FFMPEG no
#ENV INSTALL_LIBCEC no
#ENV INSTALL_SSOCR no
#ENV INSTALL_DLIB no
#ENV INSTALL_IPERF3 no
VOLUME /config
@@ -27,7 +28,7 @@ COPY requirements_all.txt requirements_all.txt
# Uninstall enum34 because some dependencies install it but breaks Python 3.4+.
# See PR #8103 for more info.
RUN pip3 install --no-cache-dir -r requirements_all.txt && \
pip3 install --no-cache-dir mysqlclient psycopg2 uvloop cchardet cython
pip3 install --no-cache-dir mysqlclient psycopg2 uvloop cchardet cython tensorflow
# Copy source
COPY . .

View File

@@ -13,9 +13,13 @@ from homeassistant.core import callback, HomeAssistant
from homeassistant.util import dt as dt_util
from . import auth_store, models
from .const import GROUP_ID_ADMIN
from .mfa_modules import auth_mfa_module_from_config, MultiFactorAuthModule
from .providers import auth_provider_from_config, AuthProvider, LoginFlow
EVENT_USER_ADDED = 'user_added'
EVENT_USER_REMOVED = 'user_removed'
_LOGGER = logging.getLogger(__name__)
_MfaModuleDict = Dict[str, MultiFactorAuthModule]
_ProviderKey = Tuple[str, Optional[str]]
@@ -114,6 +118,10 @@ class AuthManager:
"""Retrieve a user."""
return await self._store.async_get_user(user_id)
async def async_get_group(self, group_id: str) -> Optional[models.Group]:
"""Retrieve all groups."""
return await self._store.async_get_group(group_id)
async def async_get_user_by_credentials(
self, credentials: models.Credentials) -> Optional[models.User]:
"""Get a user by credential, return None if not found."""
@@ -124,25 +132,41 @@ class AuthManager:
return None
async def async_create_system_user(self, name: str) -> models.User:
async def async_create_system_user(
self, name: str,
group_ids: Optional[List[str]] = None) -> models.User:
"""Create a system user."""
return await self._store.async_create_user(
user = await self._store.async_create_user(
name=name,
system_generated=True,
is_active=True,
group_ids=group_ids or [],
)
self.hass.bus.async_fire(EVENT_USER_ADDED, {
'user_id': user.id
})
return user
async def async_create_user(self, name: str) -> models.User:
"""Create a user."""
kwargs = {
'name': name,
'is_active': True,
'group_ids': [GROUP_ID_ADMIN]
} # type: Dict[str, Any]
if await self._user_should_be_owner():
kwargs['is_owner'] = True
return await self._store.async_create_user(**kwargs)
user = await self._store.async_create_user(**kwargs)
self.hass.bus.async_fire(EVENT_USER_ADDED, {
'user_id': user.id
})
return user
async def async_get_or_create_user(self, credentials: models.Credentials) \
-> models.User:
@@ -162,12 +186,18 @@ class AuthManager:
info = await auth_provider.async_user_meta_for_credentials(
credentials)
return await self._store.async_create_user(
user = await self._store.async_create_user(
credentials=credentials,
name=info.name,
is_active=info.is_active,
)
self.hass.bus.async_fire(EVENT_USER_ADDED, {
'user_id': user.id
})
return user
async def async_link_user(self, user: models.User,
credentials: models.Credentials) -> None:
"""Link credentials to an existing user."""
@@ -185,6 +215,21 @@ class AuthManager:
await self._store.async_remove_user(user)
self.hass.bus.async_fire(EVENT_USER_REMOVED, {
'user_id': user.id
})
async def async_update_user(self, user: models.User,
name: Optional[str] = None,
group_ids: Optional[List[str]] = None) -> None:
"""Update a user."""
kwargs = {} # type: Dict[str,Any]
if name is not None:
kwargs['name'] = name
if group_ids is not None:
kwargs['group_ids'] = group_ids
await self._store.async_update_user(user, **kwargs)
async def async_activate_user(self, user: models.User) -> None:
"""Activate a user."""
await self._store.async_activate_user(user)
@@ -314,7 +359,6 @@ class AuthManager:
"""Create a new access token."""
self._store.async_log_refresh_token_usage(refresh_token, remote_ip)
# pylint: disable=no-self-use
now = dt_util.utcnow()
return jwt.encode({
'iss': refresh_token.id,

View File

@@ -10,9 +10,14 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.util import dt as dt_util
from . import models
from .const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY
from .permissions import system_policies
from .permissions.types import PolicyType # noqa: F401
STORAGE_VERSION = 1
STORAGE_KEY = 'auth'
GROUP_NAME_ADMIN = 'Administrators'
GROUP_NAME_READ_ONLY = 'Read Only'
class AuthStore:
@@ -28,9 +33,26 @@ class AuthStore:
"""Initialize the auth store."""
self.hass = hass
self._users = None # type: Optional[Dict[str, models.User]]
self._groups = None # type: Optional[Dict[str, models.Group]]
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY,
private=True)
async def async_get_groups(self) -> List[models.Group]:
"""Retrieve all users."""
if self._groups is None:
await self._async_load()
assert self._groups is not None
return list(self._groups.values())
async def async_get_group(self, group_id: str) -> Optional[models.Group]:
"""Retrieve all users."""
if self._groups is None:
await self._async_load()
assert self._groups is not None
return self._groups.get(group_id)
async def async_get_users(self) -> List[models.User]:
"""Retrieve all users."""
if self._users is None:
@@ -51,14 +73,27 @@ class AuthStore:
self, name: Optional[str], is_owner: Optional[bool] = None,
is_active: Optional[bool] = None,
system_generated: Optional[bool] = None,
credentials: Optional[models.Credentials] = None) -> models.User:
credentials: Optional[models.Credentials] = None,
group_ids: Optional[List[str]] = None) -> models.User:
"""Create a new user."""
if self._users is None:
await self._async_load()
assert self._users is not None
assert self._users is not None
assert self._groups is not None
groups = []
for group_id in (group_ids or []):
group = self._groups.get(group_id)
if group is None:
raise ValueError('Invalid group specified {}'.format(group_id))
groups.append(group)
kwargs = {
'name': name
'name': name,
# Until we get group management, we just put everyone in the
# same group.
'groups': groups,
} # type: Dict[str, Any]
if is_owner is not None:
@@ -98,6 +133,33 @@ class AuthStore:
self._users.pop(user.id)
self._async_schedule_save()
async def async_update_user(
self, user: models.User, name: Optional[str] = None,
is_active: Optional[bool] = None,
group_ids: Optional[List[str]] = None) -> None:
"""Update a user."""
assert self._groups is not None
if group_ids is not None:
groups = []
for grid in group_ids:
group = self._groups.get(grid)
if group is None:
raise ValueError("Invalid group specified.")
groups.append(group)
user.groups = groups
user.invalidate_permission_cache()
for attr_name, value in (
('name', name),
('is_active', is_active),
):
if value is not None:
setattr(user, attr_name, value)
self._async_schedule_save()
async def async_activate_user(self, user: models.User) -> None:
"""Activate a user."""
user.is_active = True
@@ -219,14 +281,95 @@ class AuthStore:
return
users = OrderedDict() # type: Dict[str, models.User]
groups = OrderedDict() # type: Dict[str, models.Group]
# When creating objects we mention each attribute explicetely. This
# Soft-migrating data as we load. We are going to make sure we have a
# read only group and an admin group. There are two states that we can
# migrate from:
# 1. Data from a recent version which has a single group without policy
# 2. Data from old version which has no groups
has_admin_group = False
has_read_only_group = False
group_without_policy = None
# When creating objects we mention each attribute explicitly. This
# prevents crashing if user rolls back HA version after a new property
# was added.
for group_dict in data.get('groups', []):
policy = None # type: Optional[PolicyType]
if group_dict['id'] == GROUP_ID_ADMIN:
has_admin_group = True
name = GROUP_NAME_ADMIN
policy = system_policies.ADMIN_POLICY
system_generated = True
elif group_dict['id'] == GROUP_ID_READ_ONLY:
has_read_only_group = True
name = GROUP_NAME_READ_ONLY
policy = system_policies.READ_ONLY_POLICY
system_generated = True
else:
name = group_dict['name']
policy = group_dict.get('policy')
system_generated = False
# We don't want groups without a policy that are not system groups
# This is part of migrating from state 1
if policy is None:
group_without_policy = group_dict['id']
continue
groups[group_dict['id']] = models.Group(
id=group_dict['id'],
name=name,
policy=policy,
system_generated=system_generated,
)
# If there are no groups, add all existing users to the admin group.
# This is part of migrating from state 2
migrate_users_to_admin_group = (not groups and
group_without_policy is None)
# If we find a no_policy_group, we need to migrate all users to the
# admin group. We only do this if there are no other groups, as is
# the expected state. If not expected state, not marking people admin.
# This is part of migrating from state 1
if groups and group_without_policy is not None:
group_without_policy = None
# This is part of migrating from state 1 and 2
if not has_admin_group:
admin_group = _system_admin_group()
groups[admin_group.id] = admin_group
# This is part of migrating from state 1 and 2
if not has_read_only_group:
read_only_group = _system_read_only_group()
groups[read_only_group.id] = read_only_group
for user_dict in data['users']:
# Collect the users group.
user_groups = []
for group_id in user_dict.get('group_ids', []):
# This is part of migrating from state 1
if group_id == group_without_policy:
group_id = GROUP_ID_ADMIN
user_groups.append(groups[group_id])
# This is part of migrating from state 2
if (not user_dict['system_generated'] and
migrate_users_to_admin_group):
user_groups.append(groups[GROUP_ID_ADMIN])
users[user_dict['id']] = models.User(
name=user_dict['name'],
groups=user_groups,
id=user_dict['id'],
is_owner=user_dict['is_owner'],
is_active=user_dict['is_active'],
@@ -286,6 +429,7 @@ class AuthStore:
)
users[rt_dict['user_id']].refresh_tokens[token.id] = token
self._groups = groups
self._users = users
@callback
@@ -300,10 +444,12 @@ class AuthStore:
def _data_to_save(self) -> Dict:
"""Return the data to store."""
assert self._users is not None
assert self._groups is not None
users = [
{
'id': user.id,
'group_ids': [group.id for group in user.groups],
'is_owner': user.is_owner,
'is_active': user.is_active,
'name': user.name,
@@ -312,6 +458,19 @@ class AuthStore:
for user in self._users.values()
]
groups = []
for group in self._groups.values():
g_dict = {
'id': group.id,
# Name not read for sys groups. Kept here for backwards compat
'name': group.name
} # type: Dict[str, Any]
if group.id not in (GROUP_ID_READ_ONLY, GROUP_ID_ADMIN):
g_dict['policy'] = group.policy
groups.append(g_dict)
credentials = [
{
'id': credential.id,
@@ -348,6 +507,7 @@ class AuthStore:
return {
'users': users,
'groups': groups,
'credentials': credentials,
'refresh_tokens': refresh_tokens,
}
@@ -355,3 +515,30 @@ class AuthStore:
def _set_defaults(self) -> None:
"""Set default values for auth store."""
self._users = OrderedDict() # type: Dict[str, models.User]
groups = OrderedDict() # type: Dict[str, models.Group]
admin_group = _system_admin_group()
groups[admin_group.id] = admin_group
read_only_group = _system_read_only_group()
groups[read_only_group.id] = read_only_group
self._groups = groups
def _system_admin_group() -> models.Group:
"""Create system admin group."""
return models.Group(
name=GROUP_NAME_ADMIN,
id=GROUP_ID_ADMIN,
policy=system_policies.ADMIN_POLICY,
system_generated=True,
)
def _system_read_only_group() -> models.Group:
"""Create read only group."""
return models.Group(
name=GROUP_NAME_READ_ONLY,
id=GROUP_ID_READ_ONLY,
policy=system_policies.READ_ONLY_POLICY,
system_generated=True,
)

View File

@@ -3,3 +3,6 @@ from datetime import timedelta
ACCESS_TOKEN_EXPIRATION = timedelta(minutes=30)
MFA_SESSION_EXPIRATION = timedelta(minutes=5)
GROUP_ID_ADMIN = 'system-admin'
GROUP_ID_READ_ONLY = 'system-read-only'

View File

@@ -104,7 +104,7 @@ class SetupFlow(data_entry_flow.FlowHandler):
-> Dict[str, Any]:
"""Handle the first step of setup flow.
Return self.async_show_form(step_id='init') if user_input == None.
Return self.async_show_form(step_id='init') if user_input is None.
Return self.async_create_entry(data={'result': result}) if finish.
"""
errors = {} # type: Dict[str, str]

View File

@@ -176,7 +176,7 @@ class TotpSetupFlow(SetupFlow):
-> Dict[str, Any]:
"""Handle the first step of setup flow.
Return self.async_show_form(step_id='init') if user_input == None.
Return self.async_show_form(step_id='init') if user_input is None.
Return self.async_create_entry(data={'result': result}) if finish.
"""
import pyotp

View File

@@ -7,6 +7,8 @@ import attr
from homeassistant.util import dt as dt_util
from . import permissions as perm_mdl
from .const import GROUP_ID_ADMIN
from .util import generate_secret
TOKEN_TYPE_NORMAL = 'normal'
@@ -14,6 +16,16 @@ TOKEN_TYPE_SYSTEM = 'system'
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN = 'long_lived_access_token'
@attr.s(slots=True)
class Group:
"""A group."""
name = attr.ib(type=str) # type: Optional[str]
policy = attr.ib(type=perm_mdl.PolicyType)
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
system_generated = attr.ib(type=bool, default=False)
@attr.s(slots=True)
class User:
"""A user."""
@@ -24,6 +36,8 @@ class User:
is_active = attr.ib(type=bool, default=False)
system_generated = attr.ib(type=bool, default=False)
groups = attr.ib(type=List, factory=list, cmp=False) # type: List[Group]
# List of credentials of a user.
credentials = attr.ib(
type=list, factory=list, cmp=False
@@ -34,6 +48,41 @@ class User:
type=dict, factory=dict, cmp=False
) # type: Dict[str, RefreshToken]
_permissions = attr.ib(
type=Optional[perm_mdl.PolicyPermissions],
init=False,
cmp=False,
default=None,
)
@property
def permissions(self) -> perm_mdl.AbstractPermissions:
"""Return permissions object for user."""
if self.is_owner:
return perm_mdl.OwnerPermissions
if self._permissions is not None:
return self._permissions
self._permissions = perm_mdl.PolicyPermissions(
perm_mdl.merge_policies([
group.policy for group in self.groups]))
return self._permissions
@property
def is_admin(self) -> bool:
"""Return if user is part of the admin group."""
if self.is_owner:
return True
return self.is_active and any(
gr.id == GROUP_ID_ADMIN for gr in self.groups)
def invalidate_permission_cache(self) -> None:
"""Invalidate permission cache."""
self._permissions = None
@attr.s(slots=True)
class RefreshToken:

View File

@@ -0,0 +1,67 @@
"""Permissions for Home Assistant."""
import logging
from typing import ( # noqa: F401
cast, Any, Callable, Dict, List, Mapping, Set, Tuple, Union)
import voluptuous as vol
from .const import CAT_ENTITIES
from .types import PolicyType
from .entities import ENTITY_POLICY_SCHEMA, compile_entities
from .merge import merge_policies # noqa
POLICY_SCHEMA = vol.Schema({
vol.Optional(CAT_ENTITIES): ENTITY_POLICY_SCHEMA
})
_LOGGER = logging.getLogger(__name__)
class AbstractPermissions:
"""Default permissions class."""
_cached_entity_func = None
def _entity_func(self) -> Callable[[str, str], bool]:
"""Return a function that can test entity access."""
raise NotImplementedError
def check_entity(self, entity_id: str, key: str) -> bool:
"""Check if we can access entity."""
entity_func = self._cached_entity_func
if entity_func is None:
entity_func = self._cached_entity_func = self._entity_func()
return entity_func(entity_id, key)
class PolicyPermissions(AbstractPermissions):
"""Handle permissions."""
def __init__(self, policy: PolicyType) -> None:
"""Initialize the permission class."""
self._policy = policy
def _entity_func(self) -> Callable[[str, str], bool]:
"""Return a function that can test entity access."""
return compile_entities(self._policy.get(CAT_ENTITIES))
def __eq__(self, other: Any) -> bool:
"""Equals check."""
# pylint: disable=protected-access
return (isinstance(other, PolicyPermissions) and
other._policy == self._policy)
class _OwnerPermissions(AbstractPermissions):
"""Owner permissions."""
# pylint: disable=no-self-use
def _entity_func(self) -> Callable[[str, str], bool]:
"""Return a function that can test entity access."""
return lambda entity_id, key: True
OwnerPermissions = _OwnerPermissions() # pylint: disable=invalid-name

View File

@@ -0,0 +1,7 @@
"""Permission constants."""
CAT_ENTITIES = 'entities'
SUBCAT_ALL = 'all'
POLICY_READ = 'read'
POLICY_CONTROL = 'control'
POLICY_EDIT = 'edit'

View File

@@ -0,0 +1,145 @@
"""Entity permissions."""
from functools import wraps
from typing import ( # noqa: F401
Callable, Dict, List, Tuple, Union)
import voluptuous as vol
from .const import SUBCAT_ALL, POLICY_READ, POLICY_CONTROL, POLICY_EDIT
from .types import CategoryType, ValueType
SINGLE_ENTITY_SCHEMA = vol.Any(True, vol.Schema({
vol.Optional(POLICY_READ): True,
vol.Optional(POLICY_CONTROL): True,
vol.Optional(POLICY_EDIT): True,
}))
ENTITY_DOMAINS = 'domains'
ENTITY_ENTITY_IDS = 'entity_ids'
ENTITY_VALUES_SCHEMA = vol.Any(True, vol.Schema({
str: SINGLE_ENTITY_SCHEMA
}))
ENTITY_POLICY_SCHEMA = vol.Any(True, vol.Schema({
vol.Optional(SUBCAT_ALL): SINGLE_ENTITY_SCHEMA,
vol.Optional(ENTITY_DOMAINS): ENTITY_VALUES_SCHEMA,
vol.Optional(ENTITY_ENTITY_IDS): ENTITY_VALUES_SCHEMA,
}))
def _entity_allowed(schema: ValueType, key: str) \
-> Union[bool, None]:
"""Test if an entity is allowed based on the keys."""
if schema is None or isinstance(schema, bool):
return schema
assert isinstance(schema, dict)
return schema.get(key)
def compile_entities(policy: CategoryType) \
-> Callable[[str, str], bool]:
"""Compile policy into a function that tests policy."""
# None, Empty Dict, False
if not policy:
def apply_policy_deny_all(entity_id: str, key: str) -> bool:
"""Decline all."""
return False
return apply_policy_deny_all
if policy is True:
def apply_policy_allow_all(entity_id: str, key: str) -> bool:
"""Approve all."""
return True
return apply_policy_allow_all
assert isinstance(policy, dict)
domains = policy.get(ENTITY_DOMAINS)
entity_ids = policy.get(ENTITY_ENTITY_IDS)
all_entities = policy.get(SUBCAT_ALL)
funcs = [] # type: List[Callable[[str, str], Union[None, bool]]]
# The order of these functions matter. The more precise are at the top.
# If a function returns None, they cannot handle it.
# If a function returns a boolean, that's the result to return.
# Setting entity_ids to a boolean is final decision for permissions
# So return right away.
if isinstance(entity_ids, bool):
def allowed_entity_id_bool(entity_id: str, key: str) -> bool:
"""Test if allowed entity_id."""
return entity_ids # type: ignore
return allowed_entity_id_bool
if entity_ids is not None:
def allowed_entity_id_dict(entity_id: str, key: str) \
-> Union[None, bool]:
"""Test if allowed entity_id."""
return _entity_allowed(
entity_ids.get(entity_id), key) # type: ignore
funcs.append(allowed_entity_id_dict)
if isinstance(domains, bool):
def allowed_domain_bool(entity_id: str, key: str) \
-> Union[None, bool]:
"""Test if allowed domain."""
return domains
funcs.append(allowed_domain_bool)
elif domains is not None:
def allowed_domain_dict(entity_id: str, key: str) \
-> Union[None, bool]:
"""Test if allowed domain."""
domain = entity_id.split(".", 1)[0]
return _entity_allowed(domains.get(domain), key) # type: ignore
funcs.append(allowed_domain_dict)
if isinstance(all_entities, bool):
def allowed_all_entities_bool(entity_id: str, key: str) \
-> Union[None, bool]:
"""Test if allowed domain."""
return all_entities
funcs.append(allowed_all_entities_bool)
elif all_entities is not None:
def allowed_all_entities_dict(entity_id: str, key: str) \
-> Union[None, bool]:
"""Test if allowed domain."""
return _entity_allowed(all_entities, key)
funcs.append(allowed_all_entities_dict)
# Can happen if no valid subcategories specified
if not funcs:
def apply_policy_deny_all_2(entity_id: str, key: str) -> bool:
"""Decline all."""
return False
return apply_policy_deny_all_2
if len(funcs) == 1:
func = funcs[0]
@wraps(func)
def apply_policy_func(entity_id: str, key: str) -> bool:
"""Apply a single policy function."""
return func(entity_id, key) is True
return apply_policy_func
def apply_policy_funcs(entity_id: str, key: str) -> bool:
"""Apply several policy functions."""
for func in funcs:
result = func(entity_id, key)
if result is not None:
return result
return False
return apply_policy_funcs

View File

@@ -0,0 +1,65 @@
"""Merging of policies."""
from typing import ( # noqa: F401
cast, Dict, List, Set)
from .types import PolicyType, CategoryType
def merge_policies(policies: List[PolicyType]) -> PolicyType:
"""Merge policies."""
new_policy = {} # type: Dict[str, CategoryType]
seen = set() # type: Set[str]
for policy in policies:
for category in policy:
if category in seen:
continue
seen.add(category)
new_policy[category] = _merge_policies([
policy.get(category) for policy in policies])
cast(PolicyType, new_policy)
return new_policy
def _merge_policies(sources: List[CategoryType]) -> CategoryType:
"""Merge a policy."""
# When merging policies, the most permissive wins.
# This means we order it like this:
# True > Dict > None
#
# True: allow everything
# Dict: specify more granular permissions
# None: no opinion
#
# If there are multiple sources with a dict as policy, we recursively
# merge each key in the source.
policy = None # type: CategoryType
seen = set() # type: Set[str]
for source in sources:
if source is None:
continue
# A source that's True will always win. Shortcut return.
if source is True:
return True
assert isinstance(source, dict)
if policy is None:
policy = cast(CategoryType, {})
assert isinstance(policy, dict)
for key in source:
if key in seen:
continue
seen.add(key)
key_sources = []
for src in sources:
if isinstance(src, dict):
key_sources.append(src.get(key))
policy[key] = _merge_policies(key_sources)
return policy

View File

@@ -0,0 +1,14 @@
"""System policies."""
from .const import CAT_ENTITIES, SUBCAT_ALL, POLICY_READ
ADMIN_POLICY = {
CAT_ENTITIES: True,
}
READ_ONLY_POLICY = {
CAT_ENTITIES: {
SUBCAT_ALL: {
POLICY_READ: True
}
}
}

View File

@@ -0,0 +1,31 @@
"""Common code for permissions."""
from typing import ( # noqa: F401
Mapping, Union, Any)
# MyPy doesn't support recursion yet. So writing it out as far as we need.
ValueType = Union[
# Example: entities.all = { read: true, control: true }
Mapping[str, bool],
bool,
None
]
SubCategoryType = Union[
# Example: entities.domains = { light: … }
Mapping[str, ValueType],
bool,
None
]
CategoryType = Union[
# Example: entities.domains
Mapping[str, SubCategoryType],
# Example: entities.all
Mapping[str, ValueType],
bool,
None
]
# Example: { entities: … }
PolicyType = Mapping[str, CategoryType]

View File

@@ -179,7 +179,7 @@ class LoginFlow(data_entry_flow.FlowHandler):
-> Dict[str, Any]:
"""Handle the first step of login flow.
Return self.async_show_form(step_id='init') if user_input == None.
Return self.async_show_form(step_id='init') if user_input is None.
Return await self.async_finish(flow_result) if login init step pass.
"""
raise NotImplementedError

View File

@@ -4,16 +4,19 @@ Support Legacy API password auth provider.
It will be removed when auth system production ready
"""
import hmac
from typing import Any, Dict, Optional, cast
from typing import Any, Dict, Optional, cast, TYPE_CHECKING
import voluptuous as vol
from homeassistant.components.http import HomeAssistantHTTP # noqa: F401
from homeassistant.core import callback
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from . import AuthProvider, AUTH_PROVIDER_SCHEMA, AUTH_PROVIDERS, LoginFlow
from ..models import Credentials, UserMeta
from .. import AuthManager
from ..models import Credentials, UserMeta, User
if TYPE_CHECKING:
from homeassistant.components.http import HomeAssistantHTTP # noqa: F401
USER_SCHEMA = vol.Schema({
@@ -31,6 +34,24 @@ class InvalidAuthError(HomeAssistantError):
"""Raised when submitting invalid authentication."""
async def async_get_user(hass: HomeAssistant) -> User:
"""Return the legacy API password user."""
auth = cast(AuthManager, hass.auth) # type: ignore
found = None
for prv in auth.auth_providers:
if prv.type == 'legacy_api_password':
found = prv
break
if found is None:
raise ValueError('Legacy API password provider not found')
return await auth.async_get_or_create_user(
await found.async_get_or_create_credentials({})
)
@AUTH_PROVIDERS.register('legacy_api_password')
class LegacyApiPasswordAuthProvider(AuthProvider):
"""Example auth provider based on hardcoded usernames and passwords."""

View File

@@ -12,6 +12,8 @@ import itertools as it
import logging
from typing import Awaitable
import voluptuous as vol
import homeassistant.core as ha
import homeassistant.config as conf_util
from homeassistant.exceptions import HomeAssistantError
@@ -21,11 +23,16 @@ from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE,
SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART,
RESTART_EXIT_CODE)
from homeassistant.helpers import config_validation as cv
_LOGGER = logging.getLogger(__name__)
SERVICE_RELOAD_CORE_CONFIG = 'reload_core_config'
SERVICE_CHECK_CONFIG = 'check_config'
SERVICE_UPDATE_ENTITY = 'update_entity'
SCHEMA_UPDATE_ENTITY = vol.Schema({
ATTR_ENTITY_ID: cv.entity_ids
})
def is_on(hass, entity_id=None):
@@ -133,12 +140,23 @@ async def async_setup(hass: ha.HomeAssistant, config: dict) -> Awaitable[bool]:
if call.service == SERVICE_HOMEASSISTANT_RESTART:
hass.async_create_task(hass.async_stop(RESTART_EXIT_CODE))
async def async_handle_update_service(call):
"""Service handler for updating an entity."""
tasks = [hass.helpers.entity_component.async_update_entity(entity)
for entity in call.data[ATTR_ENTITY_ID]]
if tasks:
await asyncio.wait(tasks)
hass.services.async_register(
ha.DOMAIN, SERVICE_HOMEASSISTANT_STOP, async_handle_core_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_HOMEASSISTANT_RESTART, async_handle_core_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_CHECK_CONFIG, async_handle_core_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_UPDATE_ENTITY, async_handle_update_service,
schema=SCHEMA_UPDATE_ENTITY)
async def async_handle_reload_config(call):
"""Service handler for reloading core config."""

View File

@@ -18,7 +18,7 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['abodepy==0.13.1']
REQUIREMENTS = ['abodepy==0.14.0']
_LOGGER = logging.getLogger(__name__)

View File

@@ -13,9 +13,10 @@ from homeassistant.const import (
CONF_PENDING_TIME, CONF_TRIGGER_TIME)
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 Demo alarm control panel platform."""
add_entities([
async_add_entities([
manual.ManualAlarm(hass, 'Alarm', '1234', None, False, {
STATE_ALARM_ARMED_AWAY: {
CONF_DELAY_TIME: datetime.timedelta(seconds=0),

View File

@@ -0,0 +1,204 @@
"""
Each ElkM1 area will be created as a separate alarm_control_panel in HASS.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.elkm1/
"""
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.const import (
ATTR_CODE, ATTR_ENTITY_ID, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_ARMING, STATE_ALARM_DISARMED,
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED)
from homeassistant.components.elkm1 import (
DOMAIN as ELK_DOMAIN, create_elk_entities, ElkEntity)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import (
async_dispatcher_connect, async_dispatcher_send)
DEPENDENCIES = [ELK_DOMAIN]
SIGNAL_ARM_ENTITY = 'elkm1_arm'
SIGNAL_DISPLAY_MESSAGE = 'elkm1_display_message'
ELK_ALARM_SERVICE_SCHEMA = vol.Schema({
vol.Required(ATTR_ENTITY_ID, default=[]): cv.entity_ids,
vol.Required(ATTR_CODE): vol.All(vol.Coerce(int), vol.Range(0, 999999)),
})
DISPLAY_MESSAGE_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID, default=[]): cv.entity_ids,
vol.Optional('clear', default=2): vol.In([0, 1, 2]),
vol.Optional('beep', default=False): cv.boolean,
vol.Optional('timeout', default=0): vol.Range(min=0, max=65535),
vol.Optional('line1', default=''): cv.string,
vol.Optional('line2', default=''): cv.string,
})
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the ElkM1 alarm platform."""
if discovery_info is None:
return
elk = hass.data[ELK_DOMAIN]['elk']
entities = create_elk_entities(hass, elk.areas, 'area', ElkArea, [])
async_add_entities(entities, True)
def _dispatch(signal, entity_ids, *args):
for entity_id in entity_ids:
async_dispatcher_send(
hass, '{}_{}'.format(signal, entity_id), *args)
def _arm_service(service):
entity_ids = service.data.get(ATTR_ENTITY_ID, [])
arm_level = _arm_services().get(service.service)
args = (arm_level, service.data.get(ATTR_CODE))
_dispatch(SIGNAL_ARM_ENTITY, entity_ids, *args)
for service in _arm_services():
hass.services.async_register(
alarm.DOMAIN, service, _arm_service, ELK_ALARM_SERVICE_SCHEMA)
def _display_message_service(service):
entity_ids = service.data.get(ATTR_ENTITY_ID, [])
data = service.data
args = (data['clear'], data['beep'], data['timeout'],
data['line1'], data['line2'])
_dispatch(SIGNAL_DISPLAY_MESSAGE, entity_ids, *args)
hass.services.async_register(
alarm.DOMAIN, 'elkm1_alarm_display_message',
_display_message_service, DISPLAY_MESSAGE_SERVICE_SCHEMA)
def _arm_services():
from elkm1_lib.const import ArmLevel
return {
'elkm1_alarm_arm_vacation': ArmLevel.ARMED_VACATION.value,
'elkm1_alarm_arm_home_instant': ArmLevel.ARMED_STAY_INSTANT.value,
'elkm1_alarm_arm_night_instant': ArmLevel.ARMED_NIGHT_INSTANT.value,
}
class ElkArea(ElkEntity, alarm.AlarmControlPanel):
"""Representation of an Area / Partition within the ElkM1 alarm panel."""
def __init__(self, element, elk, elk_data):
"""Initialize Area as Alarm Control Panel."""
super().__init__(element, elk, elk_data)
self._changed_by_entity_id = ''
self._state = None
async def async_added_to_hass(self):
"""Register callback for ElkM1 changes."""
await super().async_added_to_hass()
for keypad in self._elk.keypads:
keypad.add_callback(self._watch_keypad)
async_dispatcher_connect(
self.hass, '{}_{}'.format(SIGNAL_ARM_ENTITY, self.entity_id),
self._arm_service)
async_dispatcher_connect(
self.hass, '{}_{}'.format(SIGNAL_DISPLAY_MESSAGE, self.entity_id),
self._display_message)
def _watch_keypad(self, keypad, changeset):
if keypad.area != self._element.index:
return
if changeset.get('last_user') is not None:
self._changed_by_entity_id = self.hass.data[
ELK_DOMAIN]['keypads'].get(keypad.index, '')
self.async_schedule_update_ha_state(True)
@property
def code_format(self):
"""Return the alarm code format."""
return '^[0-9]{4}([0-9]{2})?$'
@property
def state(self):
"""Return the state of the element."""
return self._state
@property
def device_state_attributes(self):
"""Attributes of the area."""
from elkm1_lib.const import AlarmState, ArmedStatus, ArmUpState
attrs = self.initial_attrs()
elmt = self._element
attrs['is_exit'] = elmt.is_exit
attrs['timer1'] = elmt.timer1
attrs['timer2'] = elmt.timer2
if elmt.armed_status is not None:
attrs['armed_status'] = \
ArmedStatus(elmt.armed_status).name.lower()
if elmt.arm_up_state is not None:
attrs['arm_up_state'] = ArmUpState(elmt.arm_up_state).name.lower()
if elmt.alarm_state is not None:
attrs['alarm_state'] = AlarmState(elmt.alarm_state).name.lower()
attrs['changed_by_entity_id'] = self._changed_by_entity_id
return attrs
def _element_changed(self, element, changeset):
from elkm1_lib.const import ArmedStatus
elk_state_to_hass_state = {
ArmedStatus.DISARMED.value: STATE_ALARM_DISARMED,
ArmedStatus.ARMED_AWAY.value: STATE_ALARM_ARMED_AWAY,
ArmedStatus.ARMED_STAY.value: STATE_ALARM_ARMED_HOME,
ArmedStatus.ARMED_STAY_INSTANT.value: STATE_ALARM_ARMED_HOME,
ArmedStatus.ARMED_TO_NIGHT.value: STATE_ALARM_ARMED_NIGHT,
ArmedStatus.ARMED_TO_NIGHT_INSTANT.value: STATE_ALARM_ARMED_NIGHT,
ArmedStatus.ARMED_TO_VACATION.value: STATE_ALARM_ARMED_AWAY,
}
if self._element.alarm_state is None:
self._state = None
elif self._area_is_in_alarm_state():
self._state = STATE_ALARM_TRIGGERED
elif self._entry_exit_timer_is_running():
self._state = STATE_ALARM_ARMING \
if self._element.is_exit else STATE_ALARM_PENDING
else:
self._state = elk_state_to_hass_state[self._element.armed_status]
def _entry_exit_timer_is_running(self):
return self._element.timer1 > 0 or self._element.timer2 > 0
def _area_is_in_alarm_state(self):
from elkm1_lib.const import AlarmState
return self._element.alarm_state >= AlarmState.FIRE_ALARM.value
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
self._element.disarm(int(code))
async def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
from elkm1_lib.const import ArmLevel
self._element.arm(ArmLevel.ARMED_STAY.value, int(code))
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
from elkm1_lib.const import ArmLevel
self._element.arm(ArmLevel.ARMED_AWAY.value, int(code))
async def async_alarm_arm_night(self, code=None):
"""Send arm night command."""
from elkm1_lib.const import ArmLevel
self._element.arm(ArmLevel.ARMED_NIGHT.value, int(code))
async def _arm_service(self, arm_level, code):
self._element.arm(arm_level, code)
async def _display_message(self, clear, beep, timeout, line1, line2):
"""Display a message on all keypads for the area."""
self._element.display_message(clear, beep, timeout, line1, line2)

View File

@@ -12,10 +12,10 @@ import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED)
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyialarm==0.2']
REQUIREMENTS = ['pyialarm==0.3']
_LOGGER = logging.getLogger(__name__)
@@ -89,6 +89,8 @@ class IAlarmPanel(alarm.AlarmControlPanel):
state = STATE_ALARM_ARMED_AWAY
elif status == self._client.ARMED_STAY:
state = STATE_ALARM_ARMED_HOME
elif status == self._client.TRIGGERED:
state = STATE_ALARM_TRIGGERED
else:
state = None

View File

@@ -0,0 +1,67 @@
"""
This component provides HA alarm_control_panel support for Lupusec System.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.lupusec/
"""
from datetime import timedelta
from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.lupusec import DOMAIN as LUPUSEC_DOMAIN
from homeassistant.components.lupusec import LupusecDevice
from homeassistant.const import (STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED)
DEPENDENCIES = ['lupusec']
ICON = 'mdi:security'
SCAN_INTERVAL = timedelta(seconds=2)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up an alarm control panel for a Lupusec device."""
if discovery_info is None:
return
data = hass.data[LUPUSEC_DOMAIN]
alarm_devices = [LupusecAlarm(data, data.lupusec.get_alarm())]
add_entities(alarm_devices)
class LupusecAlarm(LupusecDevice, AlarmControlPanel):
"""An alarm_control_panel implementation for Lupusec."""
@property
def icon(self):
"""Return the icon."""
return ICON
@property
def state(self):
"""Return the state of the device."""
if self._device.is_standby:
state = STATE_ALARM_DISARMED
elif self._device.is_away:
state = STATE_ALARM_ARMED_AWAY
elif self._device.is_home:
state = STATE_ALARM_ARMED_HOME
else:
state = None
return state
def alarm_arm_away(self, code=None):
"""Send arm away command."""
self._device.set_away()
def alarm_disarm(self, code=None):
"""Send disarm command."""
self._device.set_standby()
def alarm_arm_home(self, code=None):
"""Send arm home command."""
self._device.set_home()

View File

@@ -21,6 +21,7 @@ from homeassistant.const import (
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_point_in_time
import homeassistant.util.dt as dt_util
from homeassistant.helpers.restore_state import async_get_last_state
_LOGGER = logging.getLogger(__name__)
@@ -306,3 +307,10 @@ class ManualAlarm(alarm.AlarmControlPanel):
state_attr[ATTR_POST_PENDING_STATE] = self._state
return state_attr
async def async_added_to_hass(self):
"""Run when entity about to be added to hass."""
state = await async_get_last_state(self.hass, self.entity_id)
if state:
self._state = state.state
self._state_ts = state.last_updated

View File

@@ -335,11 +335,8 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
return state_attr
def async_added_to_hass(self):
"""Subscribe to MQTT events.
This method must be run in the event loop and returns a coroutine.
"""
async def async_added_to_hass(self):
"""Subscribe to MQTT events."""
async_track_state_change(
self.hass, self.entity_id, self._async_state_changed_listener
)
@@ -359,7 +356,7 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
_LOGGER.warning("Received unexpected payload: %s", payload)
return
return mqtt.async_subscribe(
await mqtt.async_subscribe(
self.hass, self._command_topic, message_received, self._qos)
async def _async_state_changed_listener(self, entity_id, old_state,

View File

@@ -79,3 +79,55 @@ ifttt_push_alarm_state:
state:
description: The state to which the alarm control panel has to be set.
example: 'armed_night'
elkm1_alarm_arm_vacation:
description: Arm the ElkM1 in vacation mode.
fields:
entity_id:
description: Name of alarm control panel to arm.
example: 'alarm_control_panel.main'
code:
description: An code to arm the alarm control panel.
example: 1234
elkm1_alarm_arm_home_instant:
description: Arm the ElkM1 in home instant mode.
fields:
entity_id:
description: Name of alarm control panel to arm.
example: 'alarm_control_panel.main'
code:
description: An code to arm the alarm control panel.
example: 1234
elkm1_alarm_arm_night_instant:
description: Arm the ElkM1 in night instant mode.
fields:
entity_id:
description: Name of alarm control panel to arm.
example: 'alarm_control_panel.main'
code:
description: An code to arm the alarm control panel.
example: 1234
elkm1_alarm_display_message:
description: Display a message on all of the ElkM1 keypads for an area.
fields:
entity_id:
description: Name of alarm control panel to display messages on.
example: 'alarm_control_panel.main'
clear:
description: 0=clear message, 1=clear message with * key, 2=Display until timeout; default 2
example: 1
beep:
description: 0=no beep, 1=beep; default 0
example: 1
timeout:
description: Time to display message, 0=forever, max 65535, default 0
example: 4242
line1:
description: Up to 16 characters of text (truncated if too long). Default blank.
example: The answer to life,
line2:
description: Up to 16 characters of text (truncated if too long). Default blank.
example: the universe, and everything.

View File

@@ -1,5 +1,5 @@
"""
Interfaces with SimpliSafe alarm control panel.
This platform provides alarm control functionality for SimpliSafe.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.simplisafe/
@@ -7,86 +7,44 @@ https://home-assistant.io/components/alarm_control_panel.simplisafe/
import logging
import re
import voluptuous as vol
from homeassistant.components.alarm_control_panel import (
PLATFORM_SCHEMA, AlarmControlPanel)
from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.simplisafe.const import (
DATA_CLIENT, DOMAIN, TOPIC_UPDATE)
from homeassistant.const import (
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==3.1.2']
CONF_CODE, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
_LOGGER = logging.getLogger(__name__)
ATTR_ALARM_ACTIVE = "alarm_active"
ATTR_TEMPERATURE = "temperature"
DATA_FILE = '.simplisafe'
DEFAULT_NAME = 'SimpliSafe'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_CODE): cv.string,
})
ATTR_ALARM_ACTIVE = 'alarm_active'
ATTR_TEMPERATURE = 'temperature'
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
"""Set up the SimpliSafe platform."""
from simplipy import API
from simplipy.errors import SimplipyError
"""Set up a SimpliSafe alarm control panel based on existing config."""
pass
username = config[CONF_USERNAME]
password = config[CONF_PASSWORD]
name = config.get(CONF_NAME)
code = config.get(CONF_CODE)
websession = aiohttp_client.async_get_clientsession(hass)
config_data = await hass.async_add_executor_job(
load_json, hass.config.path(DATA_FILE))
try:
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
config_data = {'refresh_token': simplisafe.refresh_token}
await hass.async_add_executor_job(
save_json, hass.config.path(DATA_FILE), config_data)
systems = await simplisafe.get_systems()
async_add_entities(
[SimpliSafeAlarm(system, name, code) for system in systems], True)
async def async_setup_entry(hass, entry, async_add_entities):
"""Set up a SimpliSafe alarm control panel based on a config entry."""
systems = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id]
async_add_entities([
SimpliSafeAlarm(system, entry.data.get(CONF_CODE))
for system in systems
], True)
class SimpliSafeAlarm(AlarmControlPanel):
"""Representation of a SimpliSafe alarm."""
def __init__(self, system, name, code):
def __init__(self, system, code):
"""Initialize the SimpliSafe alarm."""
self._async_unsub_dispatcher_connect = None
self._attrs = {}
self._code = str(code) if code else None
self._name = name
self._code = code
self._system = system
self._state = None
@@ -98,9 +56,7 @@ class SimpliSafeAlarm(AlarmControlPanel):
@property
def name(self):
"""Return the name of the device."""
if self._name:
return self._name
return 'Alarm {}'.format(self._system.system_id)
return self._system.address
@property
def code_format(self):
@@ -128,6 +84,21 @@ class SimpliSafeAlarm(AlarmControlPanel):
_LOGGER.warning("Wrong code entered for %s", state)
return check
async def async_added_to_hass(self):
"""Register callbacks."""
@callback
def update():
"""Update the state."""
self.async_schedule_update_ha_state(True)
self._async_unsub_dispatcher_connect = async_dispatcher_connect(
self.hass, TOPIC_UPDATE, update)
async def async_will_remove_from_hass(self) -> None:
"""Disconnect dispatcher listener when removed."""
if self._async_unsub_dispatcher_connect:
self._async_unsub_dispatcher_connect()
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'disarming'):
@@ -151,22 +122,24 @@ class SimpliSafeAlarm(AlarmControlPanel):
async def async_update(self):
"""Update alarm status."""
await self._system.update()
from simplipy.system import SystemStates
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
await self._system.update()
self._attrs[ATTR_ALARM_ACTIVE] = self._system.alarm_going_off
if self._system.temperature:
self._attrs[ATTR_TEMPERATURE] = self._system.temperature
if self._system.state == SystemStates.error:
return
if self._system.state == SystemStates.off:
self._state = STATE_ALARM_DISARMED
elif self._system.state in (SystemStates.home,
SystemStates.home_count):
self._state = STATE_ALARM_ARMED_HOME
elif self._system.state in (SystemStates.away, SystemStates.away_count,
SystemStates.exit_delay):
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = None

View File

@@ -18,7 +18,7 @@ from homeassistant.const import (
STATE_ALARM_ARMED_CUSTOM_BYPASS)
REQUIREMENTS = ['total_connect_client==0.18']
REQUIREMENTS = ['total_connect_client==0.22']
_LOGGER = logging.getLogger(__name__)

View File

@@ -24,23 +24,25 @@ _LOGGER = logging.getLogger(__name__)
DOMAIN = 'alert'
ENTITY_ID_FORMAT = DOMAIN + '.{}'
CONF_DONE_MESSAGE = 'done_message'
CONF_CAN_ACK = 'can_acknowledge'
CONF_NOTIFIERS = 'notifiers'
CONF_REPEAT = 'repeat'
CONF_SKIP_FIRST = 'skip_first'
CONF_ALERT_MESSAGE = 'message'
CONF_DONE_MESSAGE = 'done_message'
DEFAULT_CAN_ACK = True
DEFAULT_SKIP_FIRST = False
ALERT_SCHEMA = vol.Schema({
vol.Required(CONF_NAME): cv.string,
vol.Optional(CONF_DONE_MESSAGE): cv.string,
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_STATE, default=STATE_ON): cv.string,
vol.Required(CONF_REPEAT): vol.All(cv.ensure_list, [vol.Coerce(float)]),
vol.Required(CONF_CAN_ACK, default=DEFAULT_CAN_ACK): cv.boolean,
vol.Required(CONF_SKIP_FIRST, default=DEFAULT_SKIP_FIRST): cv.boolean,
vol.Optional(CONF_ALERT_MESSAGE): cv.template,
vol.Optional(CONF_DONE_MESSAGE): cv.template,
vol.Required(CONF_NOTIFIERS): cv.ensure_list})
CONFIG_SCHEMA = vol.Schema({
@@ -62,31 +64,47 @@ def is_on(hass, entity_id):
async def async_setup(hass, config):
"""Set up the Alert component."""
alerts = config.get(DOMAIN)
all_alerts = {}
entities = []
for object_id, cfg in config[DOMAIN].items():
if not cfg:
cfg = {}
name = cfg.get(CONF_NAME)
watched_entity_id = cfg.get(CONF_ENTITY_ID)
alert_state = cfg.get(CONF_STATE)
repeat = cfg.get(CONF_REPEAT)
skip_first = cfg.get(CONF_SKIP_FIRST)
message_template = cfg.get(CONF_ALERT_MESSAGE)
done_message_template = cfg.get(CONF_DONE_MESSAGE)
notifiers = cfg.get(CONF_NOTIFIERS)
can_ack = cfg.get(CONF_CAN_ACK)
entities.append(Alert(hass, object_id, name,
watched_entity_id, alert_state, repeat,
skip_first, message_template,
done_message_template, notifiers,
can_ack))
if not entities:
return False
async def async_handle_alert_service(service_call):
"""Handle calls to alert services."""
alert_ids = service.extract_entity_ids(hass, service_call)
for alert_id in alert_ids:
alert = all_alerts[alert_id]
alert.async_set_context(service_call.context)
if service_call.service == SERVICE_TURN_ON:
await alert.async_turn_on()
elif service_call.service == SERVICE_TOGGLE:
await alert.async_toggle()
else:
await alert.async_turn_off()
for alert in entities:
if alert.entity_id != alert_id:
continue
# Setup alerts
for entity_id, alert in alerts.items():
entity = Alert(hass, entity_id,
alert[CONF_NAME], alert.get(CONF_DONE_MESSAGE),
alert[CONF_ENTITY_ID], alert[CONF_STATE],
alert[CONF_REPEAT], alert[CONF_SKIP_FIRST],
alert[CONF_NOTIFIERS], alert[CONF_CAN_ACK])
all_alerts[entity.entity_id] = entity
alert.async_set_context(service_call.context)
if service_call.service == SERVICE_TURN_ON:
await alert.async_turn_on()
elif service_call.service == SERVICE_TOGGLE:
await alert.async_toggle()
else:
await alert.async_turn_off()
# Setup service calls
hass.services.async_register(
@@ -99,7 +117,7 @@ async def async_setup(hass, config):
DOMAIN, SERVICE_TOGGLE, async_handle_alert_service,
schema=ALERT_SERVICE_SCHEMA)
tasks = [alert.async_update_ha_state() for alert in all_alerts.values()]
tasks = [alert.async_update_ha_state() for alert in entities]
if tasks:
await asyncio.wait(tasks, loop=hass.loop)
@@ -109,16 +127,25 @@ async def async_setup(hass, config):
class Alert(ToggleEntity):
"""Representation of an alert."""
def __init__(self, hass, entity_id, name, done_message, watched_entity_id,
state, repeat, skip_first, notifiers, can_ack):
def __init__(self, hass, entity_id, name, watched_entity_id,
state, repeat, skip_first, message_template,
done_message_template, notifiers, can_ack):
"""Initialize the alert."""
self.hass = hass
self._name = name
self._alert_state = state
self._skip_first = skip_first
self._message_template = message_template
if self._message_template is not None:
self._message_template.hass = hass
self._done_message_template = done_message_template
if self._done_message_template is not None:
self._done_message_template.hass = hass
self._notifiers = notifiers
self._can_ack = can_ack
self._done_message = done_message
self._delay = [timedelta(minutes=val) for val in repeat]
self._next_delay = 0
@@ -184,7 +211,7 @@ class Alert(ToggleEntity):
self._cancel()
self._ack = False
self._firing = False
if self._done_message and self._send_done_message:
if self._send_done_message:
await self._notify_done_message()
self.async_schedule_update_ha_state()
@@ -204,18 +231,31 @@ class Alert(ToggleEntity):
if not self._ack:
_LOGGER.info("Alerting: %s", self._name)
self._send_done_message = True
for target in self._notifiers:
await self.hass.services.async_call(
DOMAIN_NOTIFY, target, {ATTR_MESSAGE: self._name})
if self._message_template is not None:
message = self._message_template.async_render()
else:
message = self._name
await self._send_notification_message(message)
await self._schedule_notify()
async def _notify_done_message(self, *args):
"""Send notification of complete alert."""
_LOGGER.info("Alerting: %s", self._done_message)
_LOGGER.info("Alerting: %s", self._done_message_template)
self._send_done_message = False
if self._done_message_template is None:
return
message = self._done_message_template.async_render()
await self._send_notification_message(message)
async def _send_notification_message(self, message):
for target in self._notifiers:
await self.hass.services.async_call(
DOMAIN_NOTIFY, target, {ATTR_MESSAGE: self._done_message})
DOMAIN_NOTIFY, target, {ATTR_MESSAGE: message})
async def async_turn_on(self, **kwargs):
"""Async Unacknowledge alert."""

File diff suppressed because it is too large Load Diff

View File

@@ -49,10 +49,9 @@ def setup(hass, config):
# It doesn't really matter why we're not able to get the status, just that
# we can't.
# pylint: disable=broad-except
try:
DATA.update(no_throttle=True)
except Exception:
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Failure while testing APCUPSd status retrieval.")
return False
return True

View File

@@ -20,7 +20,8 @@ from homeassistant.const import (
URL_API_SERVICES, URL_API_STATES, URL_API_STATES_ENTITY, URL_API_STREAM,
URL_API_TEMPLATE, __version__)
import homeassistant.core as ha
from homeassistant.exceptions import TemplateError
from homeassistant.auth.permissions.const import POLICY_READ
from homeassistant.exceptions import TemplateError, Unauthorized
from homeassistant.helpers import template
from homeassistant.helpers.service import async_get_all_descriptions
from homeassistant.helpers.state import AsyncTrackStates
@@ -81,6 +82,8 @@ class APIEventStream(HomeAssistantView):
async def get(self, request):
"""Provide a streaming interface for the event bus."""
if not request['hass_user'].is_admin:
raise Unauthorized()
hass = request.app['hass']
stop_obj = object()
to_write = asyncio.Queue(loop=hass.loop)
@@ -185,7 +188,13 @@ class APIStatesView(HomeAssistantView):
@ha.callback
def get(self, request):
"""Get current states."""
return self.json(request.app['hass'].states.async_all())
user = request['hass_user']
entity_perm = user.permissions.check_entity
states = [
state for state in request.app['hass'].states.async_all()
if entity_perm(state.entity_id, 'read')
]
return self.json(states)
class APIEntityStateView(HomeAssistantView):
@@ -197,6 +206,10 @@ class APIEntityStateView(HomeAssistantView):
@ha.callback
def get(self, request, entity_id):
"""Retrieve state of entity."""
user = request['hass_user']
if not user.permissions.check_entity(entity_id, POLICY_READ):
raise Unauthorized(entity_id=entity_id)
state = request.app['hass'].states.get(entity_id)
if state:
return self.json(state)
@@ -204,6 +217,8 @@ class APIEntityStateView(HomeAssistantView):
async def post(self, request, entity_id):
"""Update state of entity."""
if not request['hass_user'].is_admin:
raise Unauthorized(entity_id=entity_id)
hass = request.app['hass']
try:
data = await request.json()
@@ -236,6 +251,8 @@ class APIEntityStateView(HomeAssistantView):
@ha.callback
def delete(self, request, entity_id):
"""Remove entity."""
if not request['hass_user'].is_admin:
raise Unauthorized(entity_id=entity_id)
if request.app['hass'].states.async_remove(entity_id):
return self.json_message("Entity removed.")
return self.json_message("Entity not found.", HTTP_NOT_FOUND)
@@ -261,6 +278,8 @@ class APIEventView(HomeAssistantView):
async def post(self, request, event_type):
"""Fire events."""
if not request['hass_user'].is_admin:
raise Unauthorized()
body = await request.text()
try:
event_data = json.loads(body) if body else None
@@ -346,6 +365,8 @@ class APITemplateView(HomeAssistantView):
async def post(self, request):
"""Render a template."""
if not request['hass_user'].is_admin:
raise Unauthorized()
try:
data = await request.json()
tpl = template.Template(data['template'], request.app['hass'])
@@ -363,6 +384,8 @@ class APIErrorLog(HomeAssistantView):
async def get(self, request):
"""Retrieve API error log."""
if not request['hass_user'].is_admin:
raise Unauthorized()
return web.FileResponse(request.app['hass'].data[DATA_LOGGING])

View File

@@ -163,7 +163,7 @@ async def async_setup(hass, config):
async def atv_discovered(service, info):
"""Set up an Apple TV that was auto discovered."""
await _setup_atv(hass, {
await _setup_atv(hass, config, {
CONF_NAME: info['name'],
CONF_HOST: info['host'],
CONF_LOGIN_ID: info['properties']['hG'],
@@ -172,7 +172,7 @@ async def async_setup(hass, config):
discovery.async_listen(hass, SERVICE_APPLE_TV, atv_discovered)
tasks = [_setup_atv(hass, conf) for conf in config.get(DOMAIN, [])]
tasks = [_setup_atv(hass, config, conf) for conf in config.get(DOMAIN, [])]
if tasks:
await asyncio.wait(tasks, loop=hass.loop)
@@ -187,7 +187,7 @@ async def async_setup(hass, config):
return True
async def _setup_atv(hass, atv_config):
async def _setup_atv(hass, hass_config, atv_config):
"""Set up an Apple TV."""
import pyatv
name = atv_config.get(CONF_NAME)
@@ -212,10 +212,10 @@ async def _setup_atv(hass, atv_config):
}
hass.async_create_task(discovery.async_load_platform(
hass, 'media_player', DOMAIN, atv_config))
hass, 'media_player', DOMAIN, atv_config, hass_config))
hass.async_create_task(discovery.async_load_platform(
hass, 'remote', DOMAIN, atv_config))
hass, 'remote', DOMAIN, atv_config, hass_config))
class AppleTVPowerManager:

View File

@@ -16,7 +16,7 @@ from homeassistant.const import (
from homeassistant.helpers.event import track_time_interval
from homeassistant.helpers.dispatcher import dispatcher_send
REQUIREMENTS = ['pyarlo==0.2.0']
REQUIREMENTS = ['pyarlo==0.2.2']
_LOGGER = logging.getLogger(__name__)
@@ -81,7 +81,7 @@ def setup(hass, config):
def hub_refresh(event_time):
"""Call ArloHub to refresh information."""
_LOGGER.info("Updating Arlo Hub component")
_LOGGER.debug("Updating Arlo Hub component")
hass.data[DATA_ARLO].update(update_cameras=True,
update_base_station=True)
dispatcher_send(hass, SIGNAL_UPDATE_ARLO)

View File

@@ -31,7 +31,7 @@ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_PORT): int,
vol.Required(CONF_PORT): cv.port,
}),
}, extra=vol.ALLOW_EXTRA)

View File

@@ -0,0 +1,68 @@
"""
Support for ASUSWRT devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/asuswrt/
"""
import logging
import voluptuous as vol
from homeassistant.const import (
CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_PORT, CONF_MODE,
CONF_PROTOCOL)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.discovery import async_load_platform
REQUIREMENTS = ['aioasuswrt==1.1.11']
_LOGGER = logging.getLogger(__name__)
DOMAIN = "asuswrt"
DATA_ASUSWRT = DOMAIN
CONF_PUB_KEY = 'pub_key'
CONF_SSH_KEY = 'ssh_key'
CONF_REQUIRE_IP = 'require_ip'
DEFAULT_SSH_PORT = 22
SECRET_GROUP = 'Password or SSH Key'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_PROTOCOL, default='ssh'): vol.In(['ssh', 'telnet']),
vol.Optional(CONF_MODE, default='router'): vol.In(['router', 'ap']),
vol.Optional(CONF_PORT, default=DEFAULT_SSH_PORT): cv.port,
vol.Optional(CONF_REQUIRE_IP, default=True): cv.boolean,
vol.Exclusive(CONF_PASSWORD, SECRET_GROUP): cv.string,
vol.Exclusive(CONF_SSH_KEY, SECRET_GROUP): cv.isfile,
vol.Exclusive(CONF_PUB_KEY, SECRET_GROUP): cv.isfile
}),
}, extra=vol.ALLOW_EXTRA)
async def async_setup(hass, config):
"""Set up the asuswrt component."""
from aioasuswrt.asuswrt import AsusWrt
conf = config[DOMAIN]
api = AsusWrt(conf[CONF_HOST], conf.get(CONF_PORT),
conf.get(CONF_PROTOCOL) == 'telnet',
conf[CONF_USERNAME],
conf.get(CONF_PASSWORD, ''),
conf.get('ssh_key', conf.get('pub_key', '')),
conf.get(CONF_MODE), conf.get(CONF_REQUIRE_IP))
await api.connection.async_connect()
if not api.is_connected:
_LOGGER.error("Unable to setup asuswrt component")
return False
hass.data[DATA_ASUSWRT] = api
hass.async_create_task(async_load_platform(
hass, 'sensor', DOMAIN, {}, config))
hass.async_create_task(async_load_platform(
hass, 'device_tracker', DOMAIN, {}, config))
return True

View File

@@ -4,7 +4,6 @@ Support for August devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/august/
"""
import logging
from datetime import timedelta
@@ -12,8 +11,9 @@ import voluptuous as vol
from requests import RequestException
import homeassistant.helpers.config_validation as cv
from homeassistant.core import callback
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, CONF_TIMEOUT)
CONF_PASSWORD, CONF_USERNAME, CONF_TIMEOUT, EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers import discovery
from homeassistant.util import Throttle
@@ -21,7 +21,7 @@ _LOGGER = logging.getLogger(__name__)
_CONFIGURING = {}
REQUIREMENTS = ['py-august==0.6.0']
REQUIREMENTS = ['py-august==0.7.0']
DEFAULT_TIMEOUT = 10
ACTIVITY_FETCH_LIMIT = 10
@@ -117,13 +117,15 @@ def setup_august(hass, config, api, authenticator):
if DOMAIN in _CONFIGURING:
hass.components.configurator.request_done(_CONFIGURING.pop(DOMAIN))
hass.data[DATA_AUGUST] = AugustData(api, authentication.access_token)
hass.data[DATA_AUGUST] = AugustData(
hass, api, authentication.access_token)
for component in AUGUST_COMPONENTS:
discovery.load_platform(hass, component, DOMAIN, {}, config)
return True
if state == AuthenticationState.BAD_PASSWORD:
_LOGGER.error("Invalid password provided")
return False
if state == AuthenticationState.REQUIRES_VALIDATION:
request_configuration(hass, config, api, authenticator)
@@ -136,9 +138,16 @@ def setup(hass, config):
"""Set up the August component."""
from august.api import Api
from august.authenticator import Authenticator
from requests import Session
conf = config[DOMAIN]
api = Api(timeout=conf.get(CONF_TIMEOUT))
try:
api_http_session = Session()
except RequestException as ex:
_LOGGER.warning("Creating HTTP session failed with: %s", str(ex))
api_http_session = None
api = Api(timeout=conf.get(CONF_TIMEOUT), http_session=api_http_session)
authenticator = Authenticator(
api,
@@ -154,8 +163,9 @@ def setup(hass, config):
class AugustData:
"""August data object."""
def __init__(self, api, access_token):
def __init__(self, hass, api, access_token):
"""Init August data object."""
self._hass = hass
self._api = api
self._access_token = access_token
self._doorbells = self._api.get_doorbells(self._access_token) or []
@@ -165,8 +175,25 @@ class AugustData:
self._doorbell_detail_by_id = {}
self._lock_status_by_id = {}
self._lock_detail_by_id = {}
self._door_state_by_id = {}
self._activities_by_id = {}
@callback
def august_api_stop(event):
"""Close the API HTTP session."""
_LOGGER.debug("Closing August HTTP session")
try:
self._api.http_session.close()
self._api.http_session = None
except RequestException:
pass
_LOGGER.debug("August HTTP session closed.")
self._hass.bus.listen_once(
EVENT_HOMEASSISTANT_STOP, august_api_stop)
_LOGGER.debug("Registered for HASS stop event")
@property
def house_ids(self):
"""Return a list of house_ids."""
@@ -184,6 +211,7 @@ class AugustData:
def get_device_activities(self, device_id, *activity_types):
"""Return a list of activities."""
_LOGGER.debug("Getting device activities")
self._update_device_activities()
activities = self._activities_by_id.get(device_id, [])
@@ -199,7 +227,11 @@ class AugustData:
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def _update_device_activities(self, limit=ACTIVITY_FETCH_LIMIT):
"""Update data object with latest from August API."""
_LOGGER.debug("Start retrieving device activities")
for house_id in self.house_ids:
_LOGGER.debug("Updating device activity for house id %s",
house_id)
activities = self._api.get_house_activities(self._access_token,
house_id,
limit=limit)
@@ -208,6 +240,7 @@ class AugustData:
for device_id in device_ids:
self._activities_by_id[device_id] = [a for a in activities if
a.device_id == device_id]
_LOGGER.debug("Completed retrieving device activities")
def get_doorbell_detail(self, doorbell_id):
"""Return doorbell detail."""
@@ -218,14 +251,30 @@ class AugustData:
def _update_doorbells(self):
detail_by_id = {}
_LOGGER.debug("Start retrieving doorbell details")
for doorbell in self._doorbells:
detail_by_id[doorbell.device_id] = self._api.get_doorbell_detail(
self._access_token, doorbell.device_id)
_LOGGER.debug("Updating doorbell status for %s",
doorbell.device_name)
try:
detail_by_id[doorbell.device_id] =\
self._api.get_doorbell_detail(
self._access_token, doorbell.device_id)
except RequestException as ex:
_LOGGER.error("Request error trying to retrieve doorbell"
" status for %s. %s", doorbell.device_name, ex)
detail_by_id[doorbell.device_id] = None
except Exception:
detail_by_id[doorbell.device_id] = None
raise
_LOGGER.debug("Completed retrieving doorbell details")
self._doorbell_detail_by_id = detail_by_id
def get_lock_status(self, lock_id):
"""Return lock status."""
"""Return status if the door is locked or unlocked.
This is status for the lock itself.
"""
self._update_locks()
return self._lock_status_by_id.get(lock_id)
@@ -234,17 +283,69 @@ class AugustData:
self._update_locks()
return self._lock_detail_by_id.get(lock_id)
def get_door_state(self, lock_id):
"""Return status if the door is open or closed.
This is the status from the door sensor.
"""
self._update_doors()
return self._door_state_by_id.get(lock_id)
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def _update_doors(self):
state_by_id = {}
_LOGGER.debug("Start retrieving door status")
for lock in self._locks:
_LOGGER.debug("Updating door status for %s",
lock.device_name)
try:
state_by_id[lock.device_id] = self._api.get_lock_door_status(
self._access_token, lock.device_id)
except RequestException as ex:
_LOGGER.error("Request error trying to retrieve door"
" status for %s. %s", lock.device_name, ex)
state_by_id[lock.device_id] = None
except Exception:
state_by_id[lock.device_id] = None
raise
_LOGGER.debug("Completed retrieving door status")
self._door_state_by_id = state_by_id
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def _update_locks(self):
status_by_id = {}
detail_by_id = {}
_LOGGER.debug("Start retrieving locks status")
for lock in self._locks:
status_by_id[lock.device_id] = self._api.get_lock_status(
self._access_token, lock.device_id)
detail_by_id[lock.device_id] = self._api.get_lock_detail(
self._access_token, lock.device_id)
_LOGGER.debug("Updating lock status for %s",
lock.device_name)
try:
status_by_id[lock.device_id] = self._api.get_lock_status(
self._access_token, lock.device_id)
except RequestException as ex:
_LOGGER.error("Request error trying to retrieve door"
" status for %s. %s", lock.device_name, ex)
status_by_id[lock.device_id] = None
except Exception:
status_by_id[lock.device_id] = None
raise
try:
detail_by_id[lock.device_id] = self._api.get_lock_detail(
self._access_token, lock.device_id)
except RequestException as ex:
_LOGGER.error("Request error trying to retrieve door"
" details for %s. %s", lock.device_name, ex)
detail_by_id[lock.device_id] = None
except Exception:
detail_by_id[lock.device_id] = None
raise
_LOGGER.debug("Completed retrieving locks status")
self._lock_status_by_id = status_by_id
self._lock_detail_by_id = detail_by_id

View File

@@ -0,0 +1,26 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "\u017d\u00e1dn\u00e9 oznamovac\u00ed slu\u017eby nejsou k dispozici."
},
"error": {
"invalid_code": "Neplatn\u00fd k\u00f3d, zkuste to znovu."
},
"step": {
"init": {
"description": "Vyberte pros\u00edm jednu z oznamovac\u00edch slu\u017eeb:",
"title": "Nastavte jednor\u00e1zov\u00e9 heslo dodan\u00e9 komponentou notify"
},
"setup": {
"title": "Ov\u011b\u0159en\u00ed nastaven\u00ed"
}
}
},
"totp": {
"error": {
"invalid_code": "Neplatn\u00fd k\u00f3d, zkuste to znovu. Pokud se tato chyba opakuje, ujist\u011bte se, \u017ee hodiny syst\u00e9mu Home Assistant jsou spr\u00e1vn\u011b nastaveny."
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "No hay servicios de notificaci\u00f3n disponibles."
},
"error": {
"invalid_code": "C\u00f3digo inv\u00e1lido, por favor int\u00e9ntelo de nuevo."
},
"step": {
"init": {
"description": "Seleccione uno de los servicios de notificaci\u00f3n:",
"title": "Configure una contrase\u00f1a de un solo uso entregada por el componente de notificaci\u00f3n"
},
"setup": {
"description": "Se ha enviado una contrase\u00f1a de un solo uso a trav\u00e9s de ** notificar. {notify_service} **. Por favor introd\u00facela a continuaci\u00f3n:",
"title": "Verificar la configuraci\u00f3n"
}
},
"title": "Notificar la contrase\u00f1a de un solo uso"
},
"totp": {
"error": {
"invalid_code": "C\u00f3digo inv\u00e1lido, por favor int\u00e9ntalo de nuevo. Si recibes este error de forma consistente, por favor aseg\u00farate de que el reloj de tu Home Assistant es correcto."
},
"step": {
"init": {
"description": "Para activar la autenticaci\u00f3n de dos factores utilizando contrase\u00f1as de un solo uso basadas en el tiempo, escanea el c\u00f3digo QR con tu aplicaci\u00f3n de autenticaci\u00f3n. Si no tienes una, te recomendamos [Autenticador de Google] (https://support.google.com/accounts/answer/1066447) o [Authy] (https://authy.com/). \n\n {qr_code} \n \nDespu\u00e9s de escanear el c\u00f3digo, introduce el c\u00f3digo de seis d\u00edgitos de tu aplicaci\u00f3n para verificar la configuraci\u00f3n. Si tienes problemas para escanear el c\u00f3digo QR, realiza una configuraci\u00f3n manual con el c\u00f3digo ** ` {code} ` **.",
"title": "Configure la autenticaci\u00f3n de dos factores utilizando TOTP"
}
},
"title": "TOTP"
}
}
}

View File

@@ -1,6 +1,27 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Nessun servizio di notifica disponibile."
},
"error": {
"invalid_code": "Codice non valido, per favore riprovare."
},
"step": {
"init": {
"description": "Selezionare uno dei servizi di notifica:"
},
"setup": {
"description": "\u00c8 stata inviata una password monouso tramite **notify.{notify_service}**. Per favore, inseriscila qui sotto:",
"title": "Verifica l'installazione"
}
},
"title": "Notifica la Password monouso"
},
"totp": {
"error": {
"invalid_code": "Codice non valido, per favore riprovare. Se riscontri spesso questo errore, assicurati che l'orologio del sistema Home Assistant sia accurato."
},
"step": {
"init": {
"description": "Per attivare l'autenticazione a due fattori utilizzando password monouso basate sul tempo, eseguire la scansione del codice QR con l'app di autenticazione. Se non ne hai uno, ti consigliamo [Google Authenticator] (https://support.google.com/accounts/answer/1066447) o [Authy] (https://authy.com/). \n\n {qr_code} \n \n Dopo aver scansionato il codice, inserisci il codice a sei cifre dalla tua app per verificare la configurazione. Se riscontri problemi con la scansione del codice QR, esegui una configurazione manuale con codice ** ` {code} ` **.",

View File

@@ -1,5 +1,12 @@
{
"mfa_setup": {
"notify": {
"step": {
"setup": {
"title": "Verificar a configura\u00e7\u00e3o"
}
}
},
"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."

View File

@@ -10,22 +10,22 @@
"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"
"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:",
"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"
"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."
"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 Assistant \u00e9 preciso."
},
"step": {
"init": {
"description": "Para ativar a autentica\u00e7\u00e3o com dois fatores utilizando passwords unicas temporais (OTP), ler o c\u00f3digo QR com a sua aplica\u00e7\u00e3o de autentica\u00e7\u00e3o. Se voc\u00ea n\u00e3o tiver uma, recomendamos [Google Authenticator](https://support.google.com/accounts/answer/1066447) ou [Authy](https://authy.com/).\n\n{qr_code}\n\nDepois de ler o c\u00f3digo, introduza o c\u00f3digo de seis d\u00edgitos fornecido pela sua aplica\u00e7\u00e3o para verificar a configura\u00e7\u00e3o. Se tiver problemas a ler o c\u00f3digo QR, fa\u00e7a uma configura\u00e7\u00e3o manual com o c\u00f3digo **`{c\u00f3digo}`**.",
"description": "Para ativar a autentica\u00e7\u00e3o com dois fatores utilizando palavras-passe de uso \u00fanico (OTP), ler o c\u00f3digo QR com a sua aplica\u00e7\u00e3o de autentica\u00e7\u00e3o. Se n\u00e3o tiver uma, recomendamos [Google Authenticator](https://support.google.com/accounts/answer/1066447) ou [Authy](https://authy.com/).\n\n{qr_code}\n\nDepois de ler o c\u00f3digo, introduza o c\u00f3digo de seis d\u00edgitos fornecido pela sua aplica\u00e7\u00e3o para verificar a configura\u00e7\u00e3o. Se tiver problemas a ler o c\u00f3digo QR, fa\u00e7a uma configura\u00e7\u00e3o manual com o c\u00f3digo **`{code}`**.",
"title": "Configurar autentica\u00e7\u00e3o com dois fatores usando TOTP"
}
},

View File

@@ -0,0 +1,34 @@
{
"mfa_setup": {
"notify": {
"abort": {
"no_available_service": "Nu sunt disponibile servicii de notificare."
},
"error": {
"invalid_code": "Cod invalid, va rugam incercati din nou."
},
"step": {
"init": {
"description": "Selecta\u021bi unul dintre serviciile de notificare:",
"title": "Configura\u021bi o parol\u0103 unic\u0103 livrat\u0103 de o component\u0103 de notificare"
},
"setup": {
"description": "O parol\u0103 unic\u0103 a fost trimis\u0103 prin **notify.{notify_service}**. Introduce\u021bi parola mai jos:",
"title": "Verifica\u021bi configurarea"
}
},
"title": "Notifica\u021bi o parol\u0103 unic\u0103"
},
"totp": {
"error": {
"invalid_code": "Cod invalid, va rugam incercati din nou. Dac\u0103 primi\u021bi aceast\u0103 eroare \u00een mod consecvent, asigura\u021bi-v\u0103 c\u0103 ceasul sistemului dvs. Home Assistant este corect."
},
"step": {
"init": {
"title": "Configura\u021bi autentificarea cu doi factori utiliz\u00e2nd TOTP"
}
},
"title": "TOTP"
}
}
}

View File

@@ -129,6 +129,7 @@ from homeassistant.auth.models import User, Credentials, \
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
from homeassistant.components import websocket_api
from homeassistant.components.http import KEY_REAL_IP
from homeassistant.components.http.auth import async_sign_path
from homeassistant.components.http.ban import log_invalid_auth
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.components.http.view import HomeAssistantView
@@ -169,6 +170,14 @@ SCHEMA_WS_DELETE_REFRESH_TOKEN = \
vol.Required('refresh_token_id'): str,
})
WS_TYPE_SIGN_PATH = 'auth/sign_path'
SCHEMA_WS_SIGN_PATH = \
websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
vol.Required('type'): WS_TYPE_SIGN_PATH,
vol.Required('path'): str,
vol.Optional('expires', default=30): int,
})
RESULT_TYPE_CREDENTIALS = 'credentials'
RESULT_TYPE_USER = 'user'
@@ -201,6 +210,11 @@ async def async_setup(hass, config):
websocket_delete_refresh_token,
SCHEMA_WS_DELETE_REFRESH_TOKEN
)
hass.components.websocket_api.async_register_command(
WS_TYPE_SIGN_PATH,
websocket_sign_path,
SCHEMA_WS_SIGN_PATH
)
await login_flow.async_setup(hass, store_result)
await mfa_setup_flow.async_setup(hass)
@@ -424,54 +438,46 @@ def _create_auth_code_store():
@websocket_api.ws_require_user()
@callback
def websocket_current_user(
@websocket_api.async_response
async def websocket_current_user(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
"""Return the current user."""
async def async_get_current_user(user):
"""Get current user."""
enabled_modules = await hass.auth.async_get_enabled_mfa(user)
user = connection.user
enabled_modules = await hass.auth.async_get_enabled_mfa(user)
connection.send_message(
websocket_api.result_message(msg['id'], {
'id': user.id,
'name': user.name,
'is_owner': user.is_owner,
'credentials': [{'auth_provider_type': c.auth_provider_type,
'auth_provider_id': c.auth_provider_id}
for c in user.credentials],
'mfa_modules': [{
'id': module.id,
'name': module.name,
'enabled': module.id in enabled_modules,
} for module in hass.auth.auth_mfa_modules],
}))
hass.async_create_task(async_get_current_user(connection.user))
connection.send_message(
websocket_api.result_message(msg['id'], {
'id': user.id,
'name': user.name,
'is_owner': user.is_owner,
'credentials': [{'auth_provider_type': c.auth_provider_type,
'auth_provider_id': c.auth_provider_id}
for c in user.credentials],
'mfa_modules': [{
'id': module.id,
'name': module.name,
'enabled': module.id in enabled_modules,
} for module in hass.auth.auth_mfa_modules],
}))
@websocket_api.ws_require_user()
@callback
def websocket_create_long_lived_access_token(
@websocket_api.async_response
async def websocket_create_long_lived_access_token(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
"""Create or a long-lived access token."""
async def async_create_long_lived_access_token(user):
"""Create or a long-lived access token."""
refresh_token = await hass.auth.async_create_refresh_token(
user,
client_name=msg['client_name'],
client_icon=msg.get('client_icon'),
token_type=TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN,
access_token_expiration=timedelta(days=msg['lifespan']))
refresh_token = await hass.auth.async_create_refresh_token(
connection.user,
client_name=msg['client_name'],
client_icon=msg.get('client_icon'),
token_type=TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN,
access_token_expiration=timedelta(days=msg['lifespan']))
access_token = hass.auth.async_create_access_token(
refresh_token)
access_token = hass.auth.async_create_access_token(
refresh_token)
connection.send_message(
websocket_api.result_message(msg['id'], access_token))
hass.async_create_task(
async_create_long_lived_access_token(connection.user))
connection.send_message(
websocket_api.result_message(msg['id'], access_token))
@websocket_api.ws_require_user()
@@ -494,22 +500,28 @@ def websocket_refresh_tokens(
@websocket_api.ws_require_user()
@callback
def websocket_delete_refresh_token(
@websocket_api.async_response
async def websocket_delete_refresh_token(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
"""Handle a delete refresh token request."""
async def async_delete_refresh_token(user, refresh_token_id):
"""Delete a refresh token."""
refresh_token = connection.user.refresh_tokens.get(refresh_token_id)
refresh_token = connection.user.refresh_tokens.get(msg['refresh_token_id'])
if refresh_token is None:
return websocket_api.error_message(
msg['id'], 'invalid_token_id', 'Received invalid token')
if refresh_token is None:
return websocket_api.error_message(
msg['id'], 'invalid_token_id', 'Received invalid token')
await hass.auth.async_remove_refresh_token(refresh_token)
await hass.auth.async_remove_refresh_token(refresh_token)
connection.send_message(
websocket_api.result_message(msg['id'], {}))
connection.send_message(
websocket_api.result_message(msg['id'], {}))
hass.async_create_task(
async_delete_refresh_token(connection.user, msg['refresh_token_id']))
@websocket_api.ws_require_user()
@callback
def websocket_sign_path(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
"""Handle a sign path request."""
connection.send_message(websocket_api.result_message(msg['id'], {
'path': async_sign_path(hass, connection.refresh_token_id, msg['path'],
timedelta(seconds=msg['expires']))
}))

View File

@@ -400,6 +400,9 @@ async def _async_process_trigger(hass, config, trigger_configs, name, action):
This method is a coroutine.
"""
removes = []
info = {
'name': name
}
for conf in trigger_configs:
platform = await async_prepare_setup_platform(
@@ -408,7 +411,7 @@ async def _async_process_trigger(hass, config, trigger_configs, name, action):
if platform is None:
return None
remove = await platform.async_trigger(hass, conf, action)
remove = await platform.async_trigger(hass, conf, action, info)
if not remove:
_LOGGER.error("Error setting up trigger %s", name)

View File

@@ -24,7 +24,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for events based on configuration."""
event_type = config.get(CONF_EVENT_TYPE)
event_data_schema = vol.Schema(

View File

@@ -0,0 +1,74 @@
"""
Offer geo location automation rules.
For more details about this automation trigger, please refer to the
documentation at
https://home-assistant.io/docs/automation/trigger/#geo-location-trigger
"""
import voluptuous as vol
from homeassistant.components.geo_location import DOMAIN
from homeassistant.core import callback
from homeassistant.const import (
CONF_EVENT, CONF_PLATFORM, CONF_SOURCE, CONF_ZONE, EVENT_STATE_CHANGED)
from homeassistant.helpers import (
condition, config_validation as cv)
from homeassistant.helpers.config_validation import entity_domain
EVENT_ENTER = 'enter'
EVENT_LEAVE = 'leave'
DEFAULT_EVENT = EVENT_ENTER
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'geo_location',
vol.Required(CONF_SOURCE): cv.string,
vol.Required(CONF_ZONE): entity_domain('zone'),
vol.Required(CONF_EVENT, default=DEFAULT_EVENT):
vol.Any(EVENT_ENTER, EVENT_LEAVE),
})
def source_match(state, source):
"""Check if the state matches the provided source."""
return state and state.attributes.get('source') == source
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
source = config.get(CONF_SOURCE).lower()
zone_entity_id = config.get(CONF_ZONE)
trigger_event = config.get(CONF_EVENT)
@callback
def state_change_listener(event):
"""Handle specific state changes."""
# Skip if the event is not a geo_location entity.
if not event.data.get('entity_id').startswith(DOMAIN):
return
# Skip if the event's source does not match the trigger's source.
from_state = event.data.get('old_state')
to_state = event.data.get('new_state')
if not source_match(from_state, source) \
and not source_match(to_state, source):
return
zone_state = hass.states.get(zone_entity_id)
from_match = condition.zone(hass, zone_state, from_state)
to_match = condition.zone(hass, zone_state, to_state)
# pylint: disable=too-many-boolean-expressions
if trigger_event == EVENT_ENTER and not from_match and to_match or \
trigger_event == EVENT_LEAVE and from_match and not to_match:
hass.async_run_job(action({
'trigger': {
'platform': 'geo_location',
'source': source,
'entity_id': event.data.get('entity_id'),
'from_state': from_state,
'to_state': to_state,
'zone': zone_state,
'event': trigger_event,
},
}, context=event.context))
return hass.bus.async_listen(EVENT_STATE_CHANGED, state_change_listener)

View File

@@ -22,7 +22,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for events based on configuration."""
event = config.get(CONF_EVENT)

View File

@@ -32,7 +32,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for events based on configuration."""
number = config.get(CONF_NUMBER)
held_more_than = config.get(CONF_HELD_MORE_THAN)

View File

@@ -24,7 +24,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
topic = config.get(CONF_TOPIC)
payload = config.get(CONF_PAYLOAD)

View File

@@ -28,7 +28,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
_LOGGER = logging.getLogger(__name__)
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
below = config.get(CONF_BELOW)

View File

@@ -26,7 +26,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
}), cv.key_dependency(CONF_FOR, CONF_TO))
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
from_state = config.get(CONF_FROM, MATCH_ALL)

View File

@@ -24,7 +24,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for events based on configuration."""
event = config.get(CONF_EVENT)
offset = config.get(CONF_OFFSET)

View File

@@ -22,7 +22,7 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
value_template = config.get(CONF_VALUE_TEMPLATE)
value_template.hass = hass

View File

@@ -28,7 +28,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
}), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AT))
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
if CONF_AT in config:
at_time = config.get(CONF_AT)

View File

@@ -11,13 +11,14 @@ from aiohttp import hdrs
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import CONF_PLATFORM
from homeassistant.const import CONF_PLATFORM, CONF_WEBHOOK_ID
import homeassistant.helpers.config_validation as cv
from . import DOMAIN as AUTOMATION_DOMAIN
DEPENDENCIES = ('webhook',)
_LOGGER = logging.getLogger(__name__)
CONF_WEBHOOK_ID = 'webhook_id'
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'webhook',
@@ -40,10 +41,11 @@ async def _handle_webhook(action, hass, webhook_id, request):
hass.async_run_job(action, {'trigger': result})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Trigger based on incoming webhooks."""
webhook_id = config.get(CONF_WEBHOOK_ID)
hass.components.webhook.async_register(
AUTOMATION_DOMAIN, automation_info['name'],
webhook_id, partial(_handle_webhook, action))
@callback

View File

@@ -26,7 +26,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
async def async_trigger(hass, config, action):
async def async_trigger(hass, config, action, automation_info):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
zone_entity_id = config.get(CONF_ZONE)

View File

@@ -10,24 +10,21 @@ import voluptuous as vol
from homeassistant.components.discovery import SERVICE_AXIS
from homeassistant.const import (
ATTR_LOCATION, ATTR_TRIPPED, CONF_EVENT, CONF_HOST, CONF_INCLUDE,
ATTR_LOCATION, CONF_EVENT, CONF_HOST, CONF_INCLUDE,
CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_TRIGGER_TIME, CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.helpers.entity import Entity
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = ['axis==14']
REQUIREMENTS = ['axis==16']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'axis'
CONFIG_FILE = 'axis.conf'
AXIS_DEVICES = {}
EVENT_TYPES = ['motion', 'vmd3', 'pir', 'sound',
'daynight', 'tampering', 'input']
@@ -38,6 +35,7 @@ AXIS_INCLUDE = EVENT_TYPES + PLATFORMS
AXIS_DEFAULT_HOST = '192.168.0.90'
AXIS_DEFAULT_USERNAME = 'root'
AXIS_DEFAULT_PASSWORD = 'pass'
DEFAULT_PORT = 80
DEVICE_SCHEMA = vol.Schema({
vol.Required(CONF_INCLUDE):
@@ -47,7 +45,7 @@ DEVICE_SCHEMA = vol.Schema({
vol.Optional(CONF_USERNAME, default=AXIS_DEFAULT_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD, default=AXIS_DEFAULT_PASSWORD): cv.string,
vol.Optional(CONF_TRIGGER_TIME, default=0): cv.positive_int,
vol.Optional(CONF_PORT, default=80): cv.positive_int,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(ATTR_LOCATION, default=''): cv.string,
})
@@ -98,8 +96,6 @@ def request_configuration(hass, config, name, host, serialnumber):
return False
if setup_device(hass, config, device_config):
del device_config['events']
del device_config['signal']
config_file = load_json(hass.config.path(CONFIG_FILE))
config_file[serialnumber] = dict(device_config)
save_json(hass.config.path(CONFIG_FILE), config_file)
@@ -145,9 +141,11 @@ def request_configuration(hass, config, name, host, serialnumber):
def setup(hass, config):
"""Set up for Axis devices."""
hass.data[DOMAIN] = {}
def _shutdown(call):
"""Stop the event stream on shutdown."""
for serialnumber, device in AXIS_DEVICES.items():
for serialnumber, device in hass.data[DOMAIN].items():
_LOGGER.info("Stopping event stream for %s.", serialnumber)
device.stop()
@@ -159,7 +157,7 @@ def setup(hass, config):
name = discovery_info['hostname']
serialnumber = discovery_info['properties']['macaddress']
if serialnumber not in AXIS_DEVICES:
if serialnumber not in hass.data[DOMAIN]:
config_file = load_json(hass.config.path(CONFIG_FILE))
if serialnumber in config_file:
# Device config previously saved to file
@@ -177,7 +175,7 @@ def setup(hass, config):
request_configuration(hass, config, name, host, serialnumber)
else:
# Device already registered, but on a different IP
device = AXIS_DEVICES[serialnumber]
device = hass.data[DOMAIN][serialnumber]
device.config.host = host
dispatcher_send(hass, DOMAIN + '_' + device.name + '_new_ip', host)
@@ -194,7 +192,7 @@ def setup(hass, config):
def vapix_service(call):
"""Service to send a message."""
for _, device in AXIS_DEVICES.items():
for device in hass.data[DOMAIN].values():
if device.name == call.data[CONF_NAME]:
response = device.vapix.do_request(
call.data[SERVICE_CGI],
@@ -213,7 +211,7 @@ def setup(hass, config):
def setup_device(hass, config, device_config):
"""Set up an Axis device."""
from axis import AxisDevice
import axis
def signal_callback(action, event):
"""Call to configure events when initialized on event stream."""
@@ -228,18 +226,32 @@ def setup_device(hass, config, device_config):
discovery.load_platform(
hass, component, DOMAIN, event_config, config)
event_types = list(filter(lambda x: x in device_config[CONF_INCLUDE],
EVENT_TYPES))
device_config['events'] = event_types
device_config['signal'] = signal_callback
device = AxisDevice(hass.loop, **device_config)
device.name = device_config[CONF_NAME]
event_types = [
event
for event in device_config[CONF_INCLUDE]
if event in EVENT_TYPES
]
if device.serial_number is None:
# If there is no serial number a connection could not be made
_LOGGER.error("Couldn't connect to %s", device_config[CONF_HOST])
device = axis.AxisDevice(
loop=hass.loop, host=device_config[CONF_HOST],
username=device_config[CONF_USERNAME],
password=device_config[CONF_PASSWORD],
port=device_config[CONF_PORT], web_proto='http',
event_types=event_types, signal=signal_callback)
try:
hass.data[DOMAIN][device.vapix.serial_number] = device
except axis.Unauthorized:
_LOGGER.error("Credentials for %s are faulty",
device_config[CONF_HOST])
return False
except axis.RequestError:
return False
device.name = device_config[CONF_NAME]
for component in device_config[CONF_INCLUDE]:
if component == 'camera':
camera_config = {
@@ -252,51 +264,6 @@ def setup_device(hass, config, device_config):
discovery.load_platform(
hass, component, DOMAIN, camera_config, config)
AXIS_DEVICES[device.serial_number] = device
if event_types:
hass.add_job(device.start)
return True
class AxisDeviceEvent(Entity):
"""Representation of a Axis device event."""
def __init__(self, event_config):
"""Initialize the event."""
self.axis_event = event_config[CONF_EVENT]
self._name = '{}_{}_{}'.format(
event_config[CONF_NAME], self.axis_event.event_type,
self.axis_event.id)
self.location = event_config[ATTR_LOCATION]
self.axis_event.callback = self._update_callback
def _update_callback(self):
"""Update the sensor's state, if needed."""
self.schedule_update_ha_state(True)
@property
def name(self):
"""Return the name of the event."""
return self._name
@property
def device_class(self):
"""Return the class of the event."""
return self.axis_event.event_class
@property
def should_poll(self):
"""Return the polling state. No polling needed."""
return False
@property
def device_state_attributes(self):
"""Return the state attributes of the event."""
attr = {}
tripped = self.axis_event.is_tripped
attr[ATTR_TRIPPED] = 'True' if tripped else 'False'
attr[ATTR_LOCATION] = self.location
return attr

View File

@@ -0,0 +1,15 @@
vapix_call:
description: Configure device using Vapix parameter management.
fields:
name:
description: Name of device to Configure. [Required]
example: M1065-W
cgi:
description: Which cgi to call on device. [Optional] Default is 'param.cgi'
example: 'applications/control.cgi'
action:
description: What type of call. [Optional] Default is 'update'
example: 'start'
param:
description: What parameter to operate on. [Required]
example: 'package=VideoMotionDetection'

View File

@@ -4,19 +4,30 @@ Support for August binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.august/
"""
import logging
from datetime import timedelta, datetime
from homeassistant.components.august import DATA_AUGUST
from homeassistant.components.binary_sensor import (BinarySensorDevice)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['august']
SCAN_INTERVAL = timedelta(seconds=5)
def _retrieve_door_state(data, lock):
"""Get the latest state of the DoorSense sensor."""
return data.get_door_state(lock.device_id)
def _retrieve_online_state(data, doorbell):
"""Get the latest state of the sensor."""
detail = data.get_doorbell_detail(doorbell.device_id)
if detail is None:
return None
return detail.is_online
@@ -46,7 +57,11 @@ def _activity_time_based_state(data, doorbell, activity_types):
# Sensor types: Name, device_class, state_provider
SENSOR_TYPES = {
SENSOR_TYPES_DOOR = {
'door_open': ['Open', 'door', _retrieve_door_state],
}
SENSOR_TYPES_DOORBELL = {
'doorbell_ding': ['Ding', 'occupancy', _retrieve_ding_state],
'doorbell_motion': ['Motion', 'motion', _retrieve_motion_state],
'doorbell_online': ['Online', 'connectivity', _retrieve_online_state],
@@ -58,22 +73,51 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
data = hass.data[DATA_AUGUST]
devices = []
from august.lock import LockDoorStatus
for door in data.locks:
for sensor_type in SENSOR_TYPES_DOOR:
state_provider = SENSOR_TYPES_DOOR[sensor_type][2]
if state_provider(data, door) is LockDoorStatus.UNKNOWN:
_LOGGER.debug(
"Not adding sensor class %s for lock %s ",
SENSOR_TYPES_DOOR[sensor_type][1], door.device_name
)
continue
_LOGGER.debug(
"Adding sensor class %s for %s",
SENSOR_TYPES_DOOR[sensor_type][1], door.device_name
)
devices.append(AugustDoorBinarySensor(data, sensor_type, door))
for doorbell in data.doorbells:
for sensor_type in SENSOR_TYPES:
devices.append(AugustBinarySensor(data, sensor_type, doorbell))
for sensor_type in SENSOR_TYPES_DOORBELL:
_LOGGER.debug("Adding doorbell sensor class %s for %s",
SENSOR_TYPES_DOORBELL[sensor_type][1],
doorbell.device_name)
devices.append(
AugustDoorbellBinarySensor(data, sensor_type,
doorbell)
)
add_entities(devices, True)
class AugustBinarySensor(BinarySensorDevice):
"""Representation of an August binary sensor."""
class AugustDoorBinarySensor(BinarySensorDevice):
"""Representation of an August Door binary sensor."""
def __init__(self, data, sensor_type, doorbell):
def __init__(self, data, sensor_type, door):
"""Initialize the sensor."""
self._data = data
self._sensor_type = sensor_type
self._doorbell = doorbell
self._door = door
self._state = None
self._available = False
@property
def available(self):
"""Return the availability of this sensor."""
return self._available
@property
def is_on(self):
@@ -83,15 +127,58 @@ class AugustBinarySensor(BinarySensorDevice):
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return SENSOR_TYPES[self._sensor_type][1]
return SENSOR_TYPES_DOOR[self._sensor_type][1]
@property
def name(self):
"""Return the name of the binary sensor."""
return "{} {}".format(self._door.device_name,
SENSOR_TYPES_DOOR[self._sensor_type][0])
def update(self):
"""Get the latest state of the sensor."""
state_provider = SENSOR_TYPES_DOOR[self._sensor_type][2]
self._state = state_provider(self._data, self._door)
self._available = self._state is not None
from august.lock import LockDoorStatus
self._state = self._state == LockDoorStatus.OPEN
class AugustDoorbellBinarySensor(BinarySensorDevice):
"""Representation of an August binary sensor."""
def __init__(self, data, sensor_type, doorbell):
"""Initialize the sensor."""
self._data = data
self._sensor_type = sensor_type
self._doorbell = doorbell
self._state = None
self._available = False
@property
def available(self):
"""Return the availability of this sensor."""
return self._available
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return SENSOR_TYPES_DOORBELL[self._sensor_type][1]
@property
def name(self):
"""Return the name of the binary sensor."""
return "{} {}".format(self._doorbell.device_name,
SENSOR_TYPES[self._sensor_type][0])
SENSOR_TYPES_DOORBELL[self._sensor_type][0])
def update(self):
"""Get the latest state of the sensor."""
state_provider = SENSOR_TYPES[self._sensor_type][2]
state_provider = SENSOR_TYPES_DOORBELL[self._sensor_type][2]
self._state = state_provider(self._data, self._doorbell)
self._available = self._state is not None

View File

@@ -7,10 +7,11 @@ https://home-assistant.io/components/binary_sensor.axis/
from datetime import timedelta
import logging
from homeassistant.components.axis import AxisDeviceEvent
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import CONF_TRIGGER_TIME
from homeassistant.helpers.event import track_point_in_utc_time
from homeassistant.const import (
ATTR_LOCATION, CONF_EVENT, CONF_NAME, CONF_TRIGGER_TIME)
from homeassistant.core import callback
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.util.dt import utcnow
DEPENDENCIES = ['axis']
@@ -20,48 +21,71 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Axis binary devices."""
add_entities([AxisBinarySensor(hass, discovery_info)], True)
add_entities([AxisBinarySensor(discovery_info)], True)
class AxisBinarySensor(AxisDeviceEvent, BinarySensorDevice):
class AxisBinarySensor(BinarySensorDevice):
"""Representation of a binary Axis event."""
def __init__(self, hass, event_config):
def __init__(self, event_config):
"""Initialize the Axis binary sensor."""
self.hass = hass
self._state = False
self._delay = event_config[CONF_TRIGGER_TIME]
self._timer = None
AxisDeviceEvent.__init__(self, event_config)
self.axis_event = event_config[CONF_EVENT]
self.device_name = event_config[CONF_NAME]
self.location = event_config[ATTR_LOCATION]
self.delay = event_config[CONF_TRIGGER_TIME]
self.remove_timer = None
async def async_added_to_hass(self):
"""Subscribe sensors events."""
self.axis_event.callback = self._update_callback
def _update_callback(self):
"""Update the sensor's state, if needed."""
if self.remove_timer is not None:
self.remove_timer()
self.remove_timer = None
if self.delay == 0 or self.is_on:
self.schedule_update_ha_state()
else: # Run timer to delay updating the state
@callback
def _delay_update(now):
"""Timer callback for sensor update."""
_LOGGER.debug("%s called delayed (%s sec) update",
self.name, self.delay)
self.async_schedule_update_ha_state()
self.remove_timer = None
self.remove_timer = async_track_point_in_utc_time(
self.hass, _delay_update,
utcnow() + timedelta(seconds=self.delay))
@property
def is_on(self):
"""Return true if event is active."""
return self._state
return self.axis_event.is_tripped
def update(self):
"""Get the latest data and update the state."""
self._state = self.axis_event.is_tripped
@property
def name(self):
"""Return the name of the event."""
return '{}_{}_{}'.format(
self.device_name, self.axis_event.event_type, self.axis_event.id)
def _update_callback(self):
"""Update the sensor's state, if needed."""
self.update()
@property
def device_class(self):
"""Return the class of the event."""
return self.axis_event.event_class
if self._timer is not None:
self._timer()
self._timer = None
@property
def should_poll(self):
"""No polling needed."""
return False
if self._delay > 0 and not self.is_on:
# Set timer to wait until updating the state
def _delay_update(now):
"""Timer callback for sensor update."""
_LOGGER.debug("%s called delayed (%s sec) update",
self._name, self._delay)
self.schedule_update_ha_state()
self._timer = None
@property
def device_state_attributes(self):
"""Return the state attributes of the event."""
attr = {}
self._timer = track_point_in_utc_time(
self.hass, _delay_update,
utcnow() + timedelta(seconds=self._delay))
else:
self.schedule_update_ha_state()
attr[ATTR_LOCATION] = self.location
return attr

View File

@@ -50,6 +50,12 @@ class BloomSkySensor(BinarySensorDevice):
self._sensor_name = sensor_name
self._name = '{} {}'.format(device['DeviceName'], sensor_name)
self._state = None
self._unique_id = '{}-{}'.format(self._device_id, self._sensor_name)
@property
def unique_id(self):
"""Return a unique ID."""
return self._unique_id
@property
def name(self):

View File

@@ -8,6 +8,7 @@ import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.bmw_connected_drive import DOMAIN as BMW_DOMAIN
from homeassistant.const import LENGTH_KILOMETERS
DEPENDENCIES = ['bmw_connected_drive']
@@ -117,7 +118,8 @@ class BMWConnectedDriveSensor(BinarySensorDevice):
result['lights_parking'] = vehicle_state.parking_lights.value
elif self._attribute == 'condition_based_services':
for report in vehicle_state.condition_based_services:
result.update(self._format_cbs_report(report))
result.update(
self._format_cbs_report(report))
elif self._attribute == 'check_control_messages':
check_control_messages = vehicle_state.check_control_messages
if not check_control_messages:
@@ -175,8 +177,7 @@ class BMWConnectedDriveSensor(BinarySensorDevice):
self._state = (vehicle_state._attributes['connectionStatus'] ==
'CONNECTED')
@staticmethod
def _format_cbs_report(report):
def _format_cbs_report(self, report):
result = {}
service_type = report.service_type.lower().replace('_', ' ')
result['{} status'.format(service_type)] = report.state.value
@@ -184,8 +185,10 @@ class BMWConnectedDriveSensor(BinarySensorDevice):
result['{} date'.format(service_type)] = \
report.due_date.strftime('%Y-%m-%d')
if report.due_distance is not None:
result['{} distance'.format(service_type)] = \
'{} km'.format(report.due_distance)
distance = round(self.hass.config.units.length(
report.due_distance, LENGTH_KILOMETERS))
result['{} distance'.format(service_type)] = '{} {}'.format(
distance, self.hass.config.units.length_unit)
return result
def update_callback(self):

View File

@@ -6,8 +6,8 @@ https://home-assistant.io/components/binary_sensor.deconz/
"""
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.deconz.const import (
ATTR_DARK, ATTR_ON, CONF_ALLOW_CLIP_SENSOR, DOMAIN as DATA_DECONZ,
DATA_DECONZ_ID, DATA_DECONZ_UNSUB, DECONZ_DOMAIN)
ATTR_DARK, ATTR_ON, CONF_ALLOW_CLIP_SENSOR, DECONZ_REACHABLE,
DOMAIN as DECONZ_DOMAIN)
from homeassistant.const import ATTR_BATTERY_LEVEL
from homeassistant.core import callback
from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
@@ -24,6 +24,8 @@ async def async_setup_platform(hass, config, async_add_entities,
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the deCONZ binary sensor."""
gateway = hass.data[DECONZ_DOMAIN]
@callback
def async_add_sensor(sensors):
"""Add binary sensor from deCONZ."""
@@ -33,29 +35,35 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for sensor in sensors:
if sensor.type in DECONZ_BINARY_SENSOR and \
not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
entities.append(DeconzBinarySensor(sensor))
entities.append(DeconzBinarySensor(sensor, gateway))
async_add_entities(entities, True)
hass.data[DATA_DECONZ_UNSUB].append(
gateway.listeners.append(
async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_sensor))
async_add_sensor(hass.data[DATA_DECONZ].sensors.values())
async_add_sensor(gateway.api.sensors.values())
class DeconzBinarySensor(BinarySensorDevice):
"""Representation of a binary sensor."""
def __init__(self, sensor):
def __init__(self, sensor, gateway):
"""Set up sensor and add update callback to get data from websocket."""
self._sensor = sensor
self.gateway = gateway
self.unsub_dispatcher = None
async def async_added_to_hass(self):
"""Subscribe sensors events."""
self._sensor.register_async_callback(self.async_update_callback)
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id
self.gateway.deconz_ids[self.entity_id] = self._sensor.deconz_id
self.unsub_dispatcher = async_dispatcher_connect(
self.hass, DECONZ_REACHABLE, self.async_update_callback)
async def async_will_remove_from_hass(self) -> None:
"""Disconnect sensor object when removed."""
if self.unsub_dispatcher is not None:
self.unsub_dispatcher()
self._sensor.remove_callback(self.async_update_callback)
self._sensor = None
@@ -100,7 +108,7 @@ class DeconzBinarySensor(BinarySensorDevice):
@property
def available(self):
"""Return True if sensor is available."""
return self._sensor.reachable
return self.gateway.available and self._sensor.reachable
@property
def should_poll(self):
@@ -127,7 +135,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
bridgeid = self.gateway.api.config.bridgeid
return {
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},

View File

@@ -49,10 +49,6 @@ 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 await manager.async_run_test(config.get(CONF_INPUT)):
return
entity = FFmpegMotion(hass, manager, config)
async_add_entities([entity])

View File

@@ -46,10 +46,6 @@ 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 await manager.async_run_test(config.get(CONF_INPUT)):
return
entity = FFmpegNoise(hass, manager, config)
async_add_entities([entity])

View File

@@ -0,0 +1,74 @@
"""
Support for Fibaro binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.fibaro/
"""
import logging
from homeassistant.components.binary_sensor import (
BinarySensorDevice, ENTITY_ID_FORMAT)
from homeassistant.components.fibaro import (
FIBARO_CONTROLLER, FIBARO_DEVICES, FibaroDevice)
DEPENDENCIES = ['fibaro']
_LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = {
'com.fibaro.doorSensor': ['Door', 'mdi:window-open', 'door'],
'com.fibaro.windowSensor': ['Window', 'mdi:window-open', 'window'],
'com.fibaro.smokeSensor': ['Smoke', 'mdi:smoking', 'smoke'],
'com.fibaro.FGMS001': ['Motion', 'mdi:run', 'motion'],
'com.fibaro.heatDetector': ['Heat', 'mdi:fire', 'heat'],
}
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Perform the setup for Fibaro controller devices."""
if discovery_info is None:
return
add_entities(
[FibaroBinarySensor(device, hass.data[FIBARO_CONTROLLER])
for device in hass.data[FIBARO_DEVICES]['binary_sensor']], True)
class FibaroBinarySensor(FibaroDevice, BinarySensorDevice):
"""Representation of a Fibaro Binary Sensor."""
def __init__(self, fibaro_device, controller):
"""Initialize the binary_sensor."""
self._state = None
super().__init__(fibaro_device, controller)
self.entity_id = ENTITY_ID_FORMAT.format(self.ha_id)
stype = None
if fibaro_device.type in SENSOR_TYPES:
stype = fibaro_device.type
elif fibaro_device.baseType in SENSOR_TYPES:
stype = fibaro_device.baseType
if stype:
self._device_class = SENSOR_TYPES[stype][2]
self._icon = SENSOR_TYPES[stype][1]
else:
self._device_class = None
self._icon = None
@property
def icon(self):
"""Icon to use in the frontend, if any."""
return self._icon
@property
def device_class(self):
"""Return the device class of the sensor."""
return self._device_class
@property
def is_on(self):
"""Return true if sensor is on."""
return self._state
def update(self):
"""Get the latest data and update the state."""
self._state = self.current_binary_state

View File

@@ -57,7 +57,8 @@ class InsteonBinarySensor(InsteonEntity, BinarySensorDevice):
"""Return the boolean response if the node is on."""
on_val = bool(self._insteon_device_state.value)
if self._insteon_device_state.name == 'lightSensor':
if self._insteon_device_state.name in ['lightSensor',
'openClosedSensor']:
return not on_val
return on_val

View File

@@ -69,7 +69,7 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
entities = []
for device_name in discovery_info[ATTR_DISCOVER_DEVICES]:
device = hass.data[DATA_KNX].xknx.devices[device_name]
entities.append(KNXBinarySensor(hass, device))
entities.append(KNXBinarySensor(device))
async_add_entities(entities)
@@ -87,7 +87,7 @@ def async_add_entities_config(hass, config, async_add_entities):
reset_after=config.get(CONF_RESET_AFTER))
hass.data[DATA_KNX].xknx.devices.add(binary_sensor)
entity = KNXBinarySensor(hass, binary_sensor)
entity = KNXBinarySensor(binary_sensor)
automations = config.get(CONF_AUTOMATION)
if automations is not None:
for automation in automations:
@@ -103,11 +103,9 @@ def async_add_entities_config(hass, config, async_add_entities):
class KNXBinarySensor(BinarySensorDevice):
"""Representation of a KNX binary sensor."""
def __init__(self, hass, device):
def __init__(self, device):
"""Initialize of KNX binary sensor."""
self.device = device
self.hass = hass
self.async_register_callbacks()
self.automations = []
@callback
@@ -118,6 +116,10 @@ class KNXBinarySensor(BinarySensorDevice):
await self.async_update_ha_state()
self.device.register_device_updated_cb(after_update_callback)
async def async_added_to_hass(self):
"""Store register state change callback."""
self.async_register_callbacks()
@property
def name(self):
"""Return the name of the KNX device."""

View File

@@ -0,0 +1,53 @@
"""
This component provides HA binary_sensor support for Lupusec Security System.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.lupusec/
"""
import logging
from datetime import timedelta
from homeassistant.components.lupusec import (LupusecDevice,
DOMAIN as LUPUSEC_DOMAIN)
from homeassistant.components.binary_sensor import (BinarySensorDevice,
DEVICE_CLASSES)
DEPENDENCIES = ['lupusec']
SCAN_INTERVAL = timedelta(seconds=2)
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up a sensor for an Lupusec device."""
if discovery_info is None:
return
import lupupy.constants as CONST
data = hass.data[LUPUSEC_DOMAIN]
device_types = [CONST.TYPE_OPENING]
devices = []
for device in data.lupusec.get_devices(generic_type=device_types):
devices.append(LupusecBinarySensor(data, device))
add_entities(devices)
class LupusecBinarySensor(LupusecDevice, BinarySensorDevice):
"""A binary sensor implementation for Lupusec device."""
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._device.is_on
@property
def device_class(self):
"""Return the class of the binary sensor."""
if self._device.generic_type not in DEVICE_CLASSES:
return None
return self._device.generic_type

View File

@@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mqtt/
"""
import logging
from typing import Optional
import voluptuous as vol
@@ -15,19 +14,22 @@ 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)
CONF_PAYLOAD_OFF, CONF_DEVICE_CLASS, CONF_DEVICE)
from homeassistant.components.mqtt import (
ATTR_DISCOVERY_HASH, CONF_STATE_TOPIC, CONF_AVAILABILITY_TOPIC,
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS,
MqttAvailability, MqttDiscoveryUpdate)
MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
subscription)
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
import homeassistant.helpers.event as evt
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'MQTT Binary sensor'
CONF_OFF_DELAY = 'off_delay'
CONF_UNIQUE_ID = 'unique_id'
DEFAULT_PAYLOAD_OFF = 'OFF'
DEFAULT_PAYLOAD_ON = 'ON'
@@ -41,9 +43,12 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
vol.Optional(CONF_OFF_DELAY):
vol.All(vol.Coerce(int), vol.Range(min=0)),
# Integrations shouldn't never expose unique_id through configuration
# this here is an exception because MQTT is a msg transport, not a protocol
vol.Optional(CONF_UNIQUE_ID): cv.string,
vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA,
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@@ -74,53 +79,89 @@ async def _async_setup_entity(hass, config, async_add_entities,
value_template.hass = hass
async_add_entities([MqttBinarySensor(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_AVAILABILITY_TOPIC),
config.get(CONF_DEVICE_CLASS),
config.get(CONF_QOS),
config.get(CONF_FORCE_UPDATE),
config.get(CONF_PAYLOAD_ON),
config.get(CONF_PAYLOAD_OFF),
config.get(CONF_PAYLOAD_AVAILABLE),
config.get(CONF_PAYLOAD_NOT_AVAILABLE),
value_template,
config.get(CONF_UNIQUE_ID),
discovery_hash,
config,
discovery_hash
)])
class MqttBinarySensor(MqttAvailability, MqttDiscoveryUpdate,
BinarySensorDevice):
MqttEntityDeviceInfo, 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], discovery_hash):
def __init__(self, config, discovery_hash):
"""Initialize the MQTT binary sensor."""
MqttAvailability.__init__(self, availability_topic, qos,
payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash)
self._name = name
self._config = config
self._state = None
self._state_topic = state_topic
self._device_class = device_class
self._payload_on = payload_on
self._payload_off = payload_off
self._qos = qos
self._force_update = force_update
self._template = value_template
self._unique_id = unique_id
self._discovery_hash = discovery_hash
self._sub_state = None
self._delay_listener = None
self._name = None
self._state_topic = None
self._device_class = None
self._payload_on = None
self._payload_off = None
self._qos = None
self._force_update = None
self._off_delay = None
self._template = None
self._unique_id = None
# Load config
self._setup_from_config(config)
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
device_config = config.get(CONF_DEVICE)
MqttAvailability.__init__(self, availability_topic, self._qos,
payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash,
self.discovery_update)
MqttEntityDeviceInfo.__init__(self, device_config)
async def async_added_to_hass(self):
"""Subscribe mqtt events."""
await MqttAvailability.async_added_to_hass(self)
await MqttDiscoveryUpdate.async_added_to_hass(self)
await self._subscribe_topics()
async def discovery_update(self, discovery_payload):
"""Handle updated discovery message."""
config = PLATFORM_SCHEMA(discovery_payload)
self._setup_from_config(config)
await self.availability_discovery_update(config)
await self._subscribe_topics()
self.async_schedule_update_ha_state()
def _setup_from_config(self, config):
"""(Re)Setup the entity."""
self._name = config.get(CONF_NAME)
self._state_topic = config.get(CONF_STATE_TOPIC)
self._device_class = config.get(CONF_DEVICE_CLASS)
self._qos = config.get(CONF_QOS)
self._force_update = config.get(CONF_FORCE_UPDATE)
self._off_delay = config.get(CONF_OFF_DELAY)
self._payload_on = config.get(CONF_PAYLOAD_ON)
self._payload_off = config.get(CONF_PAYLOAD_OFF)
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None and value_template.hass is None:
value_template.hass = self.hass
self._template = value_template
self._unique_id = config.get(CONF_UNIQUE_ID)
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@callback
def off_delay_listener(now):
"""Switch device off after a delay."""
self._delay_listener = None
self._state = False
self.async_schedule_update_ha_state()
@callback
def state_message_received(topic, payload, qos):
def state_message_received(_topic, payload, _qos):
"""Handle a new received MQTT state message."""
if self._template is not None:
payload = self._template.async_render_with_possible_json_value(
@@ -135,10 +176,26 @@ class MqttBinarySensor(MqttAvailability, MqttDiscoveryUpdate,
self._name, self._state_topic)
return
if self._delay_listener is not None:
self._delay_listener()
self._delay_listener = None
if (self._state and self._off_delay is not None):
self._delay_listener = evt.async_call_later(
self.hass, self._off_delay, off_delay_listener)
self.async_schedule_update_ha_state()
await mqtt.async_subscribe(
self.hass, self._state_topic, state_message_received, self._qos)
self._sub_state = await subscription.async_subscribe_topics(
self.hass, self._sub_state,
{'state_topic': {'topic': self._state_topic,
'msg_callback': state_message_received,
'qos': self._qos}})
async def async_will_remove_from_hass(self):
"""Unsubscribe when removed."""
await subscription.async_unsubscribe_topics(self.hass, self._sub_state)
await MqttAvailability.async_will_remove_from_hass(self)
@property
def should_poll(self):

View File

@@ -7,45 +7,33 @@ https://home-assistant.io/components/binary_sensor.octoprint/
import logging
import requests
import voluptuous as vol
from homeassistant.const import CONF_NAME, CONF_MONITORED_CONDITIONS
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv
from homeassistant.components.octoprint import (BINARY_SENSOR_TYPES,
DOMAIN as COMPONENT_DOMAIN)
from homeassistant.components.binary_sensor import BinarySensorDevice
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['octoprint']
DOMAIN = "octoprint"
DEFAULT_NAME = 'OctoPrint'
SENSOR_TYPES = {
# API Endpoint, Group, Key, unit
'Printing': ['printer', 'state', 'printing', None],
'Printing Error': ['printer', 'state', 'error', None]
}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)):
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the available OctoPrint binary sensors."""
octoprint_api = hass.data[DOMAIN]["api"]
name = config.get(CONF_NAME)
monitored_conditions = config.get(
CONF_MONITORED_CONDITIONS, SENSOR_TYPES.keys())
if discovery_info is None:
return
name = discovery_info['name']
base_url = discovery_info['base_url']
monitored_conditions = discovery_info['sensors']
octoprint_api = hass.data[COMPONENT_DOMAIN][base_url]
devices = []
for octo_type in monitored_conditions:
new_sensor = OctoPrintBinarySensor(
octoprint_api, octo_type, SENSOR_TYPES[octo_type][2],
name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
SENSOR_TYPES[octo_type][1], 'flags')
octoprint_api, octo_type, BINARY_SENSOR_TYPES[octo_type][2],
name, BINARY_SENSOR_TYPES[octo_type][3],
BINARY_SENSOR_TYPES[octo_type][0],
BINARY_SENSOR_TYPES[octo_type][1], 'flags')
devices.append(new_sensor)
add_entities(devices, True)

View File

@@ -0,0 +1,145 @@
"""
Support for OpenTherm Gateway binary sensors.
For more details about this platform, please refer to the documentation at
http://home-assistant.io/components/binary_sensor.opentherm_gw/
"""
import logging
from homeassistant.components.binary_sensor import (
BinarySensorDevice, ENTITY_ID_FORMAT)
from homeassistant.components.opentherm_gw import (
DATA_GW_VARS, DATA_OPENTHERM_GW, SIGNAL_OPENTHERM_GW_UPDATE)
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import async_generate_entity_id
DEVICE_CLASS_COLD = 'cold'
DEVICE_CLASS_HEAT = 'heat'
DEVICE_CLASS_PROBLEM = 'problem'
DEPENDENCIES = ['opentherm_gw']
_LOGGER = logging.getLogger(__name__)
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the OpenTherm Gateway binary sensors."""
if discovery_info is None:
return
gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
sensor_info = {
# [device_class, friendly_name]
gw_vars.DATA_MASTER_CH_ENABLED: [
None, "Thermostat Central Heating Enabled"],
gw_vars.DATA_MASTER_DHW_ENABLED: [
None, "Thermostat Hot Water Enabled"],
gw_vars.DATA_MASTER_COOLING_ENABLED: [
None, "Thermostat Cooling Enabled"],
gw_vars.DATA_MASTER_OTC_ENABLED: [
None, "Thermostat Outside Temperature Correction Enabled"],
gw_vars.DATA_MASTER_CH2_ENABLED: [
None, "Thermostat Central Heating 2 Enabled"],
gw_vars.DATA_SLAVE_FAULT_IND: [
DEVICE_CLASS_PROBLEM, "Boiler Fault Indication"],
gw_vars.DATA_SLAVE_CH_ACTIVE: [
DEVICE_CLASS_HEAT, "Boiler Central Heating Status"],
gw_vars.DATA_SLAVE_DHW_ACTIVE: [
DEVICE_CLASS_HEAT, "Boiler Hot Water Status"],
gw_vars.DATA_SLAVE_FLAME_ON: [
DEVICE_CLASS_HEAT, "Boiler Flame Status"],
gw_vars.DATA_SLAVE_COOLING_ACTIVE: [
DEVICE_CLASS_COLD, "Boiler Cooling Status"],
gw_vars.DATA_SLAVE_CH2_ACTIVE: [
DEVICE_CLASS_HEAT, "Boiler Central Heating 2 Status"],
gw_vars.DATA_SLAVE_DIAG_IND: [
DEVICE_CLASS_PROBLEM, "Boiler Diagnostics Indication"],
gw_vars.DATA_SLAVE_DHW_PRESENT: [None, "Boiler Hot Water Present"],
gw_vars.DATA_SLAVE_CONTROL_TYPE: [None, "Boiler Control Type"],
gw_vars.DATA_SLAVE_COOLING_SUPPORTED: [None, "Boiler Cooling Support"],
gw_vars.DATA_SLAVE_DHW_CONFIG: [
None, "Boiler Hot Water Configuration"],
gw_vars.DATA_SLAVE_MASTER_LOW_OFF_PUMP: [
None, "Boiler Pump Commands Support"],
gw_vars.DATA_SLAVE_CH2_PRESENT: [
None, "Boiler Central Heating 2 Present"],
gw_vars.DATA_SLAVE_SERVICE_REQ: [
DEVICE_CLASS_PROBLEM, "Boiler Service Required"],
gw_vars.DATA_SLAVE_REMOTE_RESET: [None, "Boiler Remote Reset Support"],
gw_vars.DATA_SLAVE_LOW_WATER_PRESS: [
DEVICE_CLASS_PROBLEM, "Boiler Low Water Pressure"],
gw_vars.DATA_SLAVE_GAS_FAULT: [
DEVICE_CLASS_PROBLEM, "Boiler Gas Fault"],
gw_vars.DATA_SLAVE_AIR_PRESS_FAULT: [
DEVICE_CLASS_PROBLEM, "Boiler Air Pressure Fault"],
gw_vars.DATA_SLAVE_WATER_OVERTEMP: [
DEVICE_CLASS_PROBLEM, "Boiler Water Overtemperature"],
gw_vars.DATA_REMOTE_TRANSFER_DHW: [
None, "Remote Hot Water Setpoint Transfer Support"],
gw_vars.DATA_REMOTE_TRANSFER_MAX_CH: [
None, "Remote Maximum Central Heating Setpoint Write Support"],
gw_vars.DATA_REMOTE_RW_DHW: [
None, "Remote Hot Water Setpoint Write Support"],
gw_vars.DATA_REMOTE_RW_MAX_CH: [
None, "Remote Central Heating Setpoint Write Support"],
gw_vars.DATA_ROVRD_MAN_PRIO: [
None, "Remote Override Manual Change Priority"],
gw_vars.DATA_ROVRD_AUTO_PRIO: [
None, "Remote Override Program Change Priority"],
gw_vars.OTGW_GPIO_A_STATE: [None, "Gateway GPIO A State"],
gw_vars.OTGW_GPIO_B_STATE: [None, "Gateway GPIO B State"],
gw_vars.OTGW_IGNORE_TRANSITIONS: [None, "Gateway Ignore Transitions"],
gw_vars.OTGW_OVRD_HB: [None, "Gateway Override High Byte"],
}
sensors = []
for var in discovery_info:
device_class = sensor_info[var][0]
friendly_name = sensor_info[var][1]
entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, var, hass=hass)
sensors.append(OpenThermBinarySensor(entity_id, var, device_class,
friendly_name))
async_add_entities(sensors)
class OpenThermBinarySensor(BinarySensorDevice):
"""Represent an OpenTherm Gateway binary sensor."""
def __init__(self, entity_id, var, device_class, friendly_name):
"""Initialize the binary sensor."""
self.entity_id = entity_id
self._var = var
self._state = None
self._device_class = device_class
self._friendly_name = friendly_name
async def async_added_to_hass(self):
"""Subscribe to updates from the component."""
_LOGGER.debug(
"Added OpenTherm Gateway binary sensor %s", self._friendly_name)
async_dispatcher_connect(self.hass, SIGNAL_OPENTHERM_GW_UPDATE,
self.receive_report)
async def receive_report(self, status):
"""Handle status updates from the component."""
self._state = bool(status.get(self._var))
self.async_schedule_update_ha_state()
@property
def name(self):
"""Return the friendly name."""
return self._friendly_name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@property
def device_class(self):
"""Return the class of this device."""
return self._device_class
@property
def should_poll(self):
"""Return False because entity pushes its state."""
return False

View File

@@ -50,12 +50,12 @@ class OpenUvBinarySensor(OpenUvEntity, BinarySensorDevice):
"""Initialize the sensor."""
super().__init__(openuv)
self._async_unsub_dispatcher_connect = None
self._entry_id = entry_id
self._icon = icon
self._latitude = openuv.client.latitude
self._longitude = openuv.client.longitude
self._name = name
self._dispatch_remove = None
self._sensor_type = sensor_type
self._state = None
@@ -80,16 +80,20 @@ class OpenUvBinarySensor(OpenUvEntity, BinarySensorDevice):
return '{0}_{1}_{2}'.format(
self._latitude, self._longitude, self._sensor_type)
@callback
def _update_data(self):
"""Update the state."""
self.async_schedule_update_ha_state(True)
async def async_added_to_hass(self):
"""Register callbacks."""
self._dispatch_remove = async_dispatcher_connect(
self.hass, TOPIC_UPDATE, self._update_data)
self.async_on_remove(self._dispatch_remove)
@callback
def update():
"""Update the state."""
self.async_schedule_update_ha_state(True)
self._async_unsub_dispatcher_connect = async_dispatcher_connect(
self.hass, TOPIC_UPDATE, update)
async def async_will_remove_from_hass(self):
"""Disconnect dispatcher listener when removed."""
if self._async_unsub_dispatcher_connect:
self._async_unsub_dispatcher_connect()
async def async_update(self):
"""Update the state."""

View File

@@ -37,8 +37,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_VARIABLE): cv.string,
vol.Required(CONF_PAYLOAD): vol.Schema(dict),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PAYLOAD_ON, default='on'): cv.string,
vol.Optional(CONF_PAYLOAD_OFF, default='off'): cv.string,
vol.Optional(CONF_PAYLOAD_ON, default='on'): vol.Any(
cv.positive_int, cv.small_float, cv.string),
vol.Optional(CONF_PAYLOAD_OFF, default='off'): vol.Any(
cv.positive_int, cv.small_float, cv.string),
vol.Optional(CONF_DISARM_AFTER_TRIGGER, default=False): cv.boolean,
vol.Optional(CONF_RESET_DELAY_SEC, default=30): cv.positive_int
})

View File

@@ -4,19 +4,18 @@ 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 asyncio
from datetime import timedelta
import logging
import re
import subprocess
import re
import sys
from datetime import timedelta
import voluptuous as vol
from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.const import CONF_HOST, CONF_NAME
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME, CONF_HOST
_LOGGER = logging.getLogger(__name__)
@@ -49,14 +48,13 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
def setup_platform(hass, config, 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)
async_add_entities([PingBinarySensor(name, PingData(host, count))], True)
add_entities([PingBinarySensor(name, PingData(host, count))], True)
class PingBinarySensor(BinarySensorDevice):
@@ -93,9 +91,9 @@ class PingBinarySensor(BinarySensorDevice):
ATTR_ROUND_TRIP_TIME_MIN: self.ping.data['min'],
}
async def async_update(self):
def update(self):
"""Get the latest data."""
await self.ping.update()
self.ping.update()
class PingData:
@@ -116,13 +114,12 @@ class PingData:
'ping', '-n', '-q', '-c', str(self._count), '-W1',
self._ip_address]
async def ping(self):
def ping(self):
"""Send ICMP echo request and return details if success."""
pinger = await asyncio.create_subprocess_shell(
' '.join(self._ping_cmd), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
pinger = subprocess.Popen(
self._ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
try:
out = await pinger.communicate()
out = pinger.communicate()
_LOGGER.debug("Output is %s", str(out))
if sys.platform == 'win32':
match = WIN32_PING_MATCHER.search(str(out).split('\n')[-1])
@@ -131,8 +128,7 @@ 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()
@@ -140,20 +136,18 @@ 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
async def update(self):
def update(self):
"""Retrieve the latest details from the host."""
self.data = await self.ping()
self.data = self.ping()
self.available = bool(self.data)

View File

@@ -0,0 +1,104 @@
"""
Support for Minut Point.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.point/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.point import MinutPointEntity
from homeassistant.components.point.const import (
DOMAIN as POINT_DOMAIN, NEW_DEVICE, SIGNAL_WEBHOOK)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
_LOGGER = logging.getLogger(__name__)
EVENTS = {
'battery': # On means low, Off means normal
('battery_low', ''),
'button_press': # On means the button was pressed, Off means normal
('short_button_press', ''),
'cold': # On means cold, Off means normal
('temperature_low', 'temperature_risen_normal'),
'connectivity': # On means connected, Off means disconnected
('device_online', 'device_offline'),
'dry': # On means too dry, Off means normal
('humidity_low', 'humidity_risen_normal'),
'heat': # On means hot, Off means normal
('temperature_high', 'temperature_dropped_normal'),
'moisture': # On means wet, Off means dry
('humidity_high', 'humidity_dropped_normal'),
'sound': # On means sound detected, Off means no sound (clear)
('avg_sound_high', 'sound_level_dropped_normal'),
'tamper': # On means the point was removed or attached
('tamper', ''),
}
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Point's binary sensors based on a config entry."""
device_id = config_entry.data[NEW_DEVICE]
client = hass.data[POINT_DOMAIN][config_entry.entry_id]
async_add_entities((MinutPointBinarySensor(client, device_id, device_class)
for device_class in EVENTS), True)
class MinutPointBinarySensor(MinutPointEntity, BinarySensorDevice):
"""The platform class required by Home Assistant."""
def __init__(self, point_client, device_id, device_class):
"""Initialize the entity."""
super().__init__(point_client, device_id, device_class)
self._async_unsub_hook_dispatcher_connect = None
self._events = EVENTS[device_class]
self._is_on = None
async def async_added_to_hass(self):
"""Call when entity is added to hass."""
await super().async_added_to_hass()
self._async_unsub_hook_dispatcher_connect = async_dispatcher_connect(
self.hass, SIGNAL_WEBHOOK, self._webhook_event)
async def async_will_remove_from_hass(self):
"""Disconnect dispatcher listener when removed."""
await super().async_will_remove_from_hass()
if self._async_unsub_hook_dispatcher_connect:
self._async_unsub_hook_dispatcher_connect()
@callback
def _update_callback(self):
"""Update the value of the sensor."""
if not self.is_updated:
return
if self._events[0] in self.device.ongoing_events:
self._is_on = True
else:
self._is_on = None
self.async_schedule_update_ha_state()
@callback
def _webhook_event(self, data, webhook):
"""Process new event from the webhook."""
if self.device.webhook != webhook:
return
_type = data.get('event', {}).get('type')
if _type not in self._events:
return
_LOGGER.debug("Recieved webhook: %s", _type)
if _type == self._events[0]:
self._is_on = True
if _type == self._events[1]:
self._is_on = None
self.async_schedule_update_ha_state()
@property
def is_on(self):
"""Return the state of the binary sensor."""
if self.device_class == 'connectivity':
# connectivity is the other way around.
return not self._is_on
return self._is_on

View File

@@ -8,28 +8,29 @@ import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.rainmachine import (
BINARY_SENSORS, DATA_RAINMACHINE, SENSOR_UPDATE_TOPIC, TYPE_FREEZE,
TYPE_FREEZE_PROTECTION, TYPE_HOT_DAYS, TYPE_HOURLY, TYPE_MONTH,
TYPE_RAINDELAY, TYPE_RAINSENSOR, TYPE_WEEKDAY, RainMachineEntity)
from homeassistant.const import CONF_MONITORED_CONDITIONS
BINARY_SENSORS, DATA_CLIENT, DOMAIN as RAINMACHINE_DOMAIN,
SENSOR_UPDATE_TOPIC, TYPE_FREEZE, TYPE_FREEZE_PROTECTION, TYPE_HOT_DAYS,
TYPE_HOURLY, TYPE_MONTH, TYPE_RAINDELAY, TYPE_RAINSENSOR, TYPE_WEEKDAY,
RainMachineEntity)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
DEPENDENCIES = ['rainmachine']
_LOGGER = logging.getLogger(__name__)
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
"""Set up the RainMachine Switch platform."""
if discovery_info is None:
return
"""Set up RainMachine binary sensors based on the old way."""
pass
rainmachine = hass.data[DATA_RAINMACHINE]
async def async_setup_entry(hass, entry, async_add_entities):
"""Set up RainMachine binary sensors based on a config entry."""
rainmachine = hass.data[RAINMACHINE_DOMAIN][DATA_CLIENT][entry.entry_id]
binary_sensors = []
for sensor_type in discovery_info[CONF_MONITORED_CONDITIONS]:
for sensor_type in rainmachine.binary_sensor_conditions:
name, icon = BINARY_SENSORS[sensor_type]
binary_sensors.append(
RainMachineBinarySensor(rainmachine, sensor_type, name, icon))
@@ -70,15 +71,15 @@ class RainMachineBinarySensor(RainMachineEntity, BinarySensorDevice):
return '{0}_{1}'.format(
self.rainmachine.device_mac.replace(':', ''), self._sensor_type)
@callback
def _update_data(self):
"""Update the state."""
self.async_schedule_update_ha_state(True)
async def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SENSOR_UPDATE_TOPIC, self._update_data)
@callback
def update():
"""Update the state."""
self.async_schedule_update_ha_state(True)
self._dispatcher_handlers.append(async_dispatcher_connect(
self.hass, SENSOR_UPDATE_TOPIC, update))
async def async_update(self):
"""Update the state."""

View File

@@ -0,0 +1,105 @@
"""
Support for Rflink binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.rflink/
"""
import logging
import voluptuous as vol
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.components.rflink import (
CONF_ALIASES, CONF_DEVICES, RflinkDevice)
from homeassistant.const import (
CONF_FORCE_UPDATE, CONF_NAME, CONF_DEVICE_CLASS)
import homeassistant.helpers.config_validation as cv
import homeassistant.helpers.event as evt
CONF_OFF_DELAY = 'off_delay'
DEFAULT_FORCE_UPDATE = False
DEPENDENCIES = ['rflink']
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_DEVICES, default={}): {
cv.string: vol.Schema({
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE):
cv.boolean,
vol.Optional(CONF_OFF_DELAY): cv.positive_int,
vol.Optional(CONF_ALIASES, default=[]):
vol.All(cv.ensure_list, [cv.string]),
})
},
}, extra=vol.ALLOW_EXTRA)
def devices_from_config(domain_config):
"""Parse configuration and add Rflink sensor devices."""
devices = []
for device_id, config in domain_config[CONF_DEVICES].items():
device = RflinkBinarySensor(device_id, **config)
devices.append(device)
return devices
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the Rflink platform."""
async_add_entities(devices_from_config(config))
class RflinkBinarySensor(RflinkDevice, BinarySensorDevice):
"""Representation of an Rflink binary sensor."""
def __init__(self, device_id, device_class=None,
force_update=None, off_delay=None,
**kwargs):
"""Handle sensor specific args and super init."""
self._state = None
self._device_class = device_class
self._force_update = force_update
self._off_delay = off_delay
self._delay_listener = None
super().__init__(device_id, **kwargs)
def _handle_event(self, event):
"""Domain specific event handler."""
command = event['command']
if command == 'on':
self._state = True
elif command == 'off':
self._state = False
if (self._state and self._off_delay is not None):
def off_delay_listener(now):
"""Switch device off after a delay."""
self._delay_listener = None
self._state = False
self.async_schedule_update_ha_state()
if self._delay_listener is not None:
self._delay_listener()
self._delay_listener = evt.async_call_later(
self.hass, self._off_delay, off_delay_listener)
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@property
def device_class(self):
"""Return the class of this sensor."""
return self._device_class
@property
def force_update(self):
"""Force update."""
return self._force_update

View File

@@ -73,6 +73,7 @@ class RingBinarySensor(BinarySensorDevice):
SENSOR_TYPES.get(self._sensor_type)[0])
self._device_class = SENSOR_TYPES.get(self._sensor_type)[2]
self._state = None
self._unique_id = '{}-{}'.format(self._data.id, self._sensor_type)
@property
def name(self):
@@ -89,6 +90,11 @@ class RingBinarySensor(BinarySensorDevice):
"""Return the class of the binary sensor."""
return self._device_class
@property
def unique_id(self):
"""Return a unique ID."""
return self._unique_id
@property
def device_state_attributes(self):
"""Return the state attributes."""

View File

@@ -0,0 +1,117 @@
"""
Support for monitoring a Sense energy sensor device.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.sense/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.sense import SENSE_DATA
DEPENDENCIES = ['sense']
_LOGGER = logging.getLogger(__name__)
BIN_SENSOR_CLASS = 'power'
MDI_ICONS = {'ac': 'air-conditioner',
'aquarium': 'fish',
'car': 'car-electric',
'computer': 'desktop-classic',
'cup': 'coffee',
'dehumidifier': 'water-off',
'dishes': 'dishwasher',
'drill': 'toolbox',
'fan': 'fan',
'freezer': 'fridge-top',
'fridge': 'fridge-bottom',
'game': 'gamepad-variant',
'garage': 'garage',
'grill': 'stove',
'heat': 'fire',
'heater': 'radiatior',
'humidifier': 'water',
'kettle': 'kettle',
'leafblower': 'leaf',
'lightbulb': 'lightbulb',
'media_console': 'set-top-box',
'modem': 'router-wireless',
'outlet': 'power-socket-us',
'papershredder': 'shredder',
'printer': 'printer',
'pump': 'water-pump',
'settings': 'settings',
'skillet': 'pot',
'smartcamera': 'webcam',
'socket': 'power-plug',
'sound': 'speaker',
'stove': 'stove',
'trash': 'trash-can',
'tv': 'television',
'vacuum': 'robot-vacuum',
'washer': 'washing-machine'}
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Sense sensor."""
if discovery_info is None:
return
data = hass.data[SENSE_DATA]
sense_devices = data.get_discovered_device_data()
devices = [SenseDevice(data, device) for device in sense_devices
if device['tags']['DeviceListAllowed'] == 'true']
add_entities(devices)
def sense_to_mdi(sense_icon):
"""Convert sense icon to mdi icon."""
return 'mdi:' + MDI_ICONS.get(sense_icon, 'power-plug')
class SenseDevice(BinarySensorDevice):
"""Implementation of a Sense energy device binary sensor."""
def __init__(self, data, device):
"""Initialize the sensor."""
self._name = device['name']
self._id = device['id']
self._icon = sense_to_mdi(device['icon'])
self._data = data
self._state = False
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@property
def name(self):
"""Return the name of the binary sensor."""
return self._name
@property
def unique_id(self):
"""Return the id of the binary sensor."""
return self._id
@property
def icon(self):
"""Return the icon of the binary sensor."""
return self._icon
@property
def device_class(self):
"""Return the device class of the binary sensor."""
return BIN_SENSOR_CLASS
def update(self):
"""Retrieve latest state."""
from sense_energy.sense_api import SenseAPITimeoutException
try:
self._data.get_realtime()
except SenseAPITimeoutException:
_LOGGER.error("Timeout retrieving data")
return
self._state = self._name in self._data.active_devices

View File

@@ -15,7 +15,7 @@ from homeassistant.components.binary_sensor import (
from homeassistant.const import (
ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, CONF_VALUE_TEMPLATE,
CONF_ICON_TEMPLATE, CONF_ENTITY_PICTURE_TEMPLATE,
CONF_SENSORS, CONF_DEVICE_CLASS, EVENT_HOMEASSISTANT_START)
CONF_SENSORS, CONF_DEVICE_CLASS, EVENT_HOMEASSISTANT_START, MATCH_ALL)
from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import async_generate_entity_id
@@ -55,22 +55,49 @@ async def async_setup_platform(hass, config, async_add_entities,
icon_template = device_config.get(CONF_ICON_TEMPLATE)
entity_picture_template = device_config.get(
CONF_ENTITY_PICTURE_TEMPLATE)
entity_ids = (device_config.get(ATTR_ENTITY_ID) or
value_template.extract_entities())
entity_ids = set()
manual_entity_ids = device_config.get(ATTR_ENTITY_ID)
invalid_templates = []
for tpl_name, template in (
(CONF_VALUE_TEMPLATE, value_template),
(CONF_ICON_TEMPLATE, icon_template),
(CONF_ENTITY_PICTURE_TEMPLATE, entity_picture_template),
):
if template is None:
continue
template.hass = hass
if manual_entity_ids is not None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids == MATCH_ALL:
entity_ids = MATCH_ALL
# Cut off _template from name
invalid_templates.append(tpl_name[:-9])
elif entity_ids != MATCH_ALL:
entity_ids |= set(template_entity_ids)
if manual_entity_ids is not None:
entity_ids = manual_entity_ids
elif entity_ids != MATCH_ALL:
entity_ids = list(entity_ids)
if invalid_templates:
_LOGGER.warning(
'Template binary sensor %s has no entity ids configured to'
' track nor were we able to extract the entities to track'
' from the %s template(s). This entity will only be able'
' to be updated manually.',
device, ', '.join(invalid_templates))
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
device_class = device_config.get(CONF_DEVICE_CLASS)
delay_on = device_config.get(CONF_DELAY_ON)
delay_off = device_config.get(CONF_DELAY_OFF)
if value_template is not None:
value_template.hass = hass
if icon_template is not None:
icon_template.hass = hass
if entity_picture_template is not None:
entity_picture_template.hass = hass
sensors.append(
BinarySensorTemplate(
hass, device, friendly_name, device_class, value_template,
@@ -117,10 +144,12 @@ class BinarySensorTemplate(BinarySensorDevice):
@callback
def template_bsensor_startup(event):
"""Update template on startup."""
async_track_state_change(
self.hass, self._entities, template_bsensor_state_listener)
if self._entities != MATCH_ALL:
# Track state change only for valid templates
async_track_state_change(
self.hass, self._entities, template_bsensor_state_listener)
self.hass.async_add_job(self.async_check_state)
self.async_check_state()
self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, template_bsensor_startup)
@@ -218,3 +247,7 @@ class BinarySensorTemplate(BinarySensorDevice):
async_track_same_state(
self.hass, period, set_state, entity_ids=self._entities,
async_check_same_func=lambda *args: self._async_render() == state)
async def async_update(self):
"""Force update of the state from the template."""
self.async_check_state()

View File

@@ -15,14 +15,14 @@ from homeassistant.components.binary_sensor import (
BinarySensorDevice)
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, CONF_DEVICE_CLASS, CONF_ENTITY_ID,
CONF_FRIENDLY_NAME, STATE_UNKNOWN)
CONF_FRIENDLY_NAME, STATE_UNKNOWN, CONF_SENSORS)
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.event import async_track_state_change
from homeassistant.util import utcnow
REQUIREMENTS = ['numpy==1.15.1']
REQUIREMENTS = ['numpy==1.15.4']
_LOGGER = logging.getLogger(__name__)
@@ -38,7 +38,6 @@ CONF_INVERT = 'invert'
CONF_MAX_SAMPLES = 'max_samples'
CONF_MIN_GRADIENT = 'min_gradient'
CONF_SAMPLE_DURATION = 'sample_duration'
CONF_SENSORS = 'sensors'
SENSOR_SCHEMA = vol.Schema({
vol.Required(CONF_ENTITY_ID): cv.entity_id,
@@ -78,9 +77,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
)
if not sensors:
_LOGGER.error("No sensors added")
return False
return
add_entities(sensors)
return True
class SensorTrend(BinarySensorDevice):

View File

@@ -0,0 +1,132 @@
"""
Support for w800rf32 binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.w800rf32/
"""
import logging
import voluptuous as vol
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.components.w800rf32 import (W800RF32_DEVICE)
from homeassistant.const import (CONF_DEVICE_CLASS, CONF_NAME, CONF_DEVICES)
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import event as evt
from homeassistant.util import dt as dt_util
from homeassistant.helpers.dispatcher import (async_dispatcher_connect)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['w800rf32']
CONF_OFF_DELAY = 'off_delay'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_DEVICES): {
cv.string: vol.Schema({
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_OFF_DELAY):
vol.All(cv.time_period, cv.positive_timedelta)
})
},
}, extra=vol.ALLOW_EXTRA)
async def async_setup_platform(hass, config,
add_entities, discovery_info=None):
"""Set up the Binary Sensor platform to w800rf32."""
binary_sensors = []
# device_id --> "c1 or a3" X10 device. entity (type dictionary)
# --> name, device_class etc
for device_id, entity in config[CONF_DEVICES].items():
_LOGGER.debug("Add %s w800rf32.binary_sensor (class %s)",
entity[CONF_NAME], entity.get(CONF_DEVICE_CLASS))
device = W800rf32BinarySensor(
device_id, entity.get(CONF_NAME), entity.get(CONF_DEVICE_CLASS),
entity.get(CONF_OFF_DELAY))
binary_sensors.append(device)
add_entities(binary_sensors)
class W800rf32BinarySensor(BinarySensorDevice):
"""A representation of a w800rf32 binary sensor."""
def __init__(self, device_id, name, device_class=None, off_delay=None):
"""Initialize the w800rf32 sensor."""
self._signal = W800RF32_DEVICE.format(device_id)
self._name = name
self._device_class = device_class
self._off_delay = off_delay
self._state = False
self._delay_listener = None
@callback
def _off_delay_listener(self, now):
"""Switch device off after a delay."""
self._delay_listener = None
self.update_state(False)
@property
def name(self):
"""Return the device name."""
return self._name
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def device_class(self):
"""Return the sensor class."""
return self._device_class
@property
def is_on(self):
"""Return true if the sensor state is True."""
return self._state
@callback
def binary_sensor_update(self, event):
"""Call for control updates from the w800rf32 gateway."""
import W800rf32 as w800rf32mod
if not isinstance(event, w800rf32mod.W800rf32Event):
return
dev_id = event.device
command = event.command
_LOGGER.debug(
"BinarySensor update (Device ID: %s Command %s ...)",
dev_id, command)
# Update the w800rf32 device state
if command in ('On', 'Off'):
is_on = command == 'On'
self.update_state(is_on)
if (self.is_on and self._off_delay is not None and
self._delay_listener is None):
self._delay_listener = evt.async_track_point_in_time(
self.hass, self._off_delay_listener,
dt_util.utcnow() + self._off_delay)
def update_state(self, state):
"""Update the state of the device."""
self._state = state
self.async_schedule_update_ha_state()
async def async_added_to_hass(self):
"""Register update callback."""
async_dispatcher_connect(self.hass, self._signal,
self.binary_sensor_update)

View File

@@ -14,15 +14,16 @@ from homeassistant.const import CONF_NAME, WEEKDAYS
from homeassistant.components.binary_sensor import BinarySensorDevice
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['holidays==0.9.7']
REQUIREMENTS = ['holidays==0.9.8']
_LOGGER = logging.getLogger(__name__)
# List of all countries currently supported by holidays
# There seems to be no way to get the list out at runtime
ALL_COUNTRIES = [
'Argentina', 'AR', 'Australia', 'AU', 'Austria', 'AT', 'Belarus', 'BY'
'Belgium', 'BE', 'Canada', 'CA', 'Colombia', 'CO', 'Czech', 'CZ',
'Argentina', 'AR', 'Australia', 'AU', 'Austria', 'AT',
'Brazil', 'BR', 'Belarus', 'BY', 'Belgium', 'BE',
'Canada', 'CA', 'Colombia', 'CO', 'Croatia', 'HR', 'Czech', 'CZ',
'Denmark', 'DK', 'England', 'EuropeanCentralBank', 'ECB', 'TAR',
'Finland', 'FI', 'France', 'FRA', 'Germany', 'DE', 'Hungary', 'HU',
'India', 'IND', 'Ireland', 'Isle of Man', 'Italy', 'IT', 'Japan', 'JP',
@@ -30,7 +31,7 @@ ALL_COUNTRIES = [
'Northern Ireland', 'Norway', 'NO', 'Polish', 'PL', 'Portugal', 'PT',
'PortugalExt', 'PTE', 'Scotland', 'Slovenia', 'SI', 'Slovakia', 'SK',
'South Africa', 'ZA', 'Spain', 'ES', 'Sweden', 'SE', 'Switzerland', 'CH',
'UnitedKingdom', 'UK', 'UnitedStates', 'US', 'Wales',
'Ukraine', 'UA', 'UnitedKingdom', 'UK', 'UnitedStates', 'US', 'Wales',
]
ALLOWED_DAYS = WEEKDAYS + ['holiday']

View File

@@ -4,6 +4,8 @@ import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.xiaomi_aqara import (PY_XIAOMI_GATEWAY,
XiaomiDevice)
from homeassistant.core import callback
from homeassistant.helpers.event import async_call_later
_LOGGER = logging.getLogger(__name__)
@@ -36,21 +38,24 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
elif model in ['natgas', 'sensor_natgas']:
devices.append(XiaomiNatgasSensor(device, gateway))
elif model in ['switch', 'sensor_switch',
'sensor_switch.aq2', 'sensor_switch.aq3']:
'sensor_switch.aq2', 'sensor_switch.aq3',
'remote.b1acn01']:
if 'proto' not in device or int(device['proto'][0:1]) == 1:
data_key = 'status'
else:
data_key = 'button_0'
devices.append(XiaomiButton(device, 'Switch', data_key,
hass, gateway))
elif model in ['86sw1', 'sensor_86sw1', 'sensor_86sw1.aq1']:
elif model in ['86sw1', 'sensor_86sw1', 'sensor_86sw1.aq1',
'remote.b186acn01']:
if 'proto' not in device or int(device['proto'][0:1]) == 1:
data_key = 'channel_0'
else:
data_key = 'button_0'
devices.append(XiaomiButton(device, 'Wall Switch', data_key,
hass, gateway))
elif model in ['86sw2', 'sensor_86sw2', 'sensor_86sw2.aq1']:
elif model in ['86sw2', 'sensor_86sw2', 'sensor_86sw2.aq1',
'remote.b286acn01']:
if 'proto' not in device or int(device['proto'][0:1]) == 1:
data_key_left = 'channel_0'
data_key_right = 'channel_1'
@@ -65,6 +70,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
'dual_channel', hass, gateway))
elif model in ['cube', 'sensor_cube', 'sensor_cube.aqgl01']:
devices.append(XiaomiCube(device, hass, gateway))
elif model in ['vibration', 'vibration.aq1']:
devices.append(XiaomiVibration(device, 'Vibration',
'status', gateway))
else:
_LOGGER.warning('Unmapped Device Model %s', model)
add_entities(devices)
@@ -144,6 +155,7 @@ class XiaomiMotionSensor(XiaomiBinarySensor):
"""Initialize the XiaomiMotionSensor."""
self._hass = hass
self._no_motion_since = 0
self._unsub_set_no_motion = None
if 'proto' not in device or int(device['proto'][0:1]) == 1:
data_key = 'status'
else:
@@ -158,6 +170,13 @@ class XiaomiMotionSensor(XiaomiBinarySensor):
attrs.update(super().device_state_attributes)
return attrs
@callback
def _async_set_no_motion(self, now):
"""Set state to False."""
self._unsub_set_no_motion = None
self._state = False
self.async_schedule_update_ha_state()
def parse_data(self, data, raw_data):
"""Parse data sent by gateway."""
if raw_data['cmd'] == 'heartbeat':
@@ -179,11 +198,20 @@ class XiaomiMotionSensor(XiaomiBinarySensor):
return False
if value == MOTION:
self._should_poll = True
if self.entity_id is not None:
self._hass.bus.fire('motion', {
'entity_id': self.entity_id
})
if self._data_key == 'motion_status':
if self._unsub_set_no_motion:
self._unsub_set_no_motion()
self._unsub_set_no_motion = async_call_later(
self._hass,
180,
self._async_set_no_motion
)
else:
self._should_poll = True
if self.entity_id is not None:
self._hass.bus.fire('xiaomi_aqara.motion', {
'entity_id': self.entity_id
})
self._no_motion_since = 0
if self._state:
@@ -311,6 +339,41 @@ class XiaomiSmokeSensor(XiaomiBinarySensor):
return False
class XiaomiVibration(XiaomiBinarySensor):
"""Representation of a Xiaomi Vibration Sensor."""
def __init__(self, device, name, data_key, xiaomi_hub):
"""Initialize the XiaomiVibration."""
self._last_action = None
super().__init__(device, name, xiaomi_hub, data_key, None)
@property
def device_state_attributes(self):
"""Return the state attributes."""
attrs = {ATTR_LAST_ACTION: self._last_action}
attrs.update(super().device_state_attributes)
return attrs
def parse_data(self, data, raw_data):
"""Parse data sent by gateway."""
value = data.get(self._data_key)
if value is None:
return False
if value not in ('vibrate', 'tilt', 'free_fall'):
_LOGGER.warning("Unsupported movement_type detected: %s",
value)
return False
self.hass.bus.fire('xiaomi_aqara.movement', {
'entity_id': self.entity_id,
'movement_type': value
})
self._last_action = value
return True
class XiaomiButton(XiaomiBinarySensor):
"""Representation of a Xiaomi Button."""
@@ -354,7 +417,7 @@ class XiaomiButton(XiaomiBinarySensor):
_LOGGER.warning("Unsupported click_type detected: %s", value)
return False
self._hass.bus.fire('click', {
self._hass.bus.fire('xiaomi_aqara.click', {
'entity_id': self.entity_id,
'click_type': click_type
})
@@ -390,14 +453,14 @@ class XiaomiCube(XiaomiBinarySensor):
def parse_data(self, data, raw_data):
"""Parse data sent by gateway."""
if self._data_key in data:
self._hass.bus.fire('cube_action', {
self._hass.bus.fire('xiaomi_aqara.cube_action', {
'entity_id': self.entity_id,
'action_type': data[self._data_key]
})
self._last_action = data[self._data_key]
if 'rotate' in data:
self._hass.bus.fire('cube_action', {
self._hass.bus.fire('xiaomi_aqara.cube_action', {
'entity_id': self.entity_id,
'action_type': 'rotate',
'action_value': float(data['rotate'].replace(",", "."))

View File

@@ -13,7 +13,7 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['zha']
# ZigBee Cluster Library Zone Type to Home Assistant device class
# Zigbee Cluster Library Zone Type to Home Assistant device class
CLASS_MAPPING = {
0x000d: 'motion',
0x0015: 'opening',
@@ -145,7 +145,7 @@ class Remote(zha.Entity, BinarySensorDevice):
_domain = DOMAIN
class OnOffListener:
"""Listener for the OnOff ZigBee cluster."""
"""Listener for the OnOff Zigbee cluster."""
def __init__(self, entity):
"""Initialize OnOffListener."""
@@ -170,7 +170,7 @@ class Remote(zha.Entity, BinarySensorDevice):
pass
class LevelListener:
"""Listener for the LevelControl ZigBee cluster."""
"""Listener for the LevelControl Zigbee cluster."""
def __init__(self, entity):
"""Initialize LevelListener."""
@@ -253,5 +253,9 @@ class Remote(zha.Entity, BinarySensorDevice):
"""Retrieve latest state."""
from zigpy.zcl.clusters.general import OnOff
result = await zha.safe_read(
self._endpoint.out_clusters[OnOff.cluster_id], ['on_off'])
self._endpoint.out_clusters[OnOff.cluster_id],
['on_off'],
allow_cache=False,
only_cache=(not self._initialized)
)
self._state = result.get('on_off', self._state)

View File

@@ -1,5 +1,5 @@
"""
Contains functionality to use a ZigBee device as a binary sensor.
Contains functionality to use a Zigbee device as a binary sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.zigbee/
@@ -23,7 +23,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the ZigBee binary sensor platform."""
"""Set up the Zigbee binary sensor platform."""
add_entities(
[ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))], True)

View File

@@ -7,10 +7,11 @@ https://home-assistant.io/components/binary_sensor.zwave/
import logging
import datetime
import homeassistant.util.dt as dt_util
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.event import track_point_in_time
from homeassistant.components import zwave
from homeassistant.components.zwave import ( # noqa pylint: disable=unused-import
async_setup_platform, workaround)
from homeassistant.components.zwave import workaround
from homeassistant.components.binary_sensor import (
DOMAIN,
BinarySensorDevice)
@@ -19,6 +20,23 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = []
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Old method of setting up Z-Wave binary sensors."""
pass
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Z-Wave binary sensors from Config Entry."""
@callback
def async_add_binary_sensor(binary_sensor):
"""Add Z-Wave binary sensor."""
async_add_entities([binary_sensor])
async_dispatcher_connect(hass, 'zwave_new_binary_sensor',
async_add_binary_sensor)
def get_device(values, **kwargs):
"""Create Z-Wave entity device."""
device_mapping = workaround.get_device_mapping(values.primary)

View File

@@ -15,7 +15,7 @@ from homeassistant.const import (
CONF_BINARY_SENSORS, CONF_SENSORS, CONF_FILENAME,
CONF_MONITORED_CONDITIONS, TEMP_FAHRENHEIT)
REQUIREMENTS = ['blinkpy==0.10.0']
REQUIREMENTS = ['blinkpy==0.10.3']
_LOGGER = logging.getLogger(__name__)

View File

@@ -54,7 +54,7 @@ class BloomSky:
"""Handle all communication with the BloomSky API."""
# API documentation at http://weatherlution.com/bloomsky-api/
API_URL = 'https://api.bloomsky.com/api/skydata'
API_URL = 'http://api.bloomsky.com/api/skydata'
def __init__(self, api_key):
"""Initialize the BookSky."""

View File

@@ -9,7 +9,7 @@ import logging
import voluptuous as vol
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD)
from homeassistant.helpers import discovery
from homeassistant.helpers.event import track_utc_time_change
import homeassistant.helpers.config_validation as cv
@@ -85,6 +85,7 @@ def setup_account(account_config: dict, hass, name: str) \
password = account_config[CONF_PASSWORD]
region = account_config[CONF_REGION]
read_only = account_config[CONF_READ_ONLY]
_LOGGER.debug('Adding new account %s', name)
cd_account = BMWConnectedDriveAccount(username, password, region, name,
read_only)

View File

@@ -68,6 +68,7 @@ class GoogleCalendarData:
self.event = None
def _prepare_query(self):
# pylint: disable=import-error
from httplib2 import ServerNotFoundError
try:

View File

@@ -518,6 +518,8 @@ class TodoistProjectData:
def update(self):
"""Get the latest data."""
if self._id is None:
self._api.reset_state()
self._api.sync()
project_task_data = [
task for task in self._api.state[TASKS]
if not self._project_id_whitelist or
@@ -527,6 +529,7 @@ class TodoistProjectData:
# If we have no data, we can just return right away.
if not project_task_data:
_LOGGER.debug("No data for %s", self._name)
self.event = None
return True
@@ -541,6 +544,8 @@ class TodoistProjectData:
if not project_tasks:
# We had no valid tasks
_LOGGER.debug("No valid tasks for %s", self._name)
self.event = None
return True
# Make sure the task collection is reset to prevent an

View File

@@ -299,7 +299,8 @@ class Camera(Entity):
a direct stream from the camera.
This method must be run in the event loop.
"""
await self.handle_async_still_stream(request, self.frame_interval)
return await self.handle_async_still_stream(
request, self.frame_interval)
@property
def state(self):

View File

@@ -59,8 +59,7 @@ class AmcrestCam(Camera):
"""Return an MJPEG stream."""
# The snapshot implementation is handled by the parent class
if self._stream_source == STREAM_SOURCE_LIST['snapshot']:
await super().handle_async_mjpeg_stream(request)
return
return await super().handle_async_mjpeg_stream(request)
if self._stream_source == STREAM_SOURCE_LIST['mjpeg']:
# stream an MJPEG image stream directly from the camera
@@ -69,20 +68,22 @@ class AmcrestCam(Camera):
stream_coro = websession.get(
streaming_url, auth=self._token, timeout=TIMEOUT)
await async_aiohttp_proxy_web(self.hass, request, stream_coro)
return await async_aiohttp_proxy_web(
self.hass, request, stream_coro)
else:
# streaming via fmpeg
from haffmpeg import CameraMjpeg
# streaming via ffmpeg
from haffmpeg import CameraMjpeg
streaming_url = self._camera.rtsp_url(typeno=self._resolution)
stream = CameraMjpeg(self._ffmpeg.binary, loop=self.hass.loop)
await stream.open_camera(
streaming_url, extra_cmd=self._ffmpeg_arguments)
streaming_url = self._camera.rtsp_url(typeno=self._resolution)
stream = CameraMjpeg(self._ffmpeg.binary, loop=self.hass.loop)
await stream.open_camera(
streaming_url, extra_cmd=self._ffmpeg_arguments)
await async_aiohttp_proxy_stream(
try:
return await async_aiohttp_proxy_stream(
self.hass, request, stream,
'multipart/x-mixed-replace;boundary=ffserver')
finally:
await stream.close()
@property

View File

@@ -101,10 +101,12 @@ class ArloCam(Camera):
await stream.open_camera(
video.video_url, extra_cmd=self._ffmpeg_arguments)
await async_aiohttp_proxy_stream(
self.hass, request, stream,
'multipart/x-mixed-replace;boundary=ffserver')
await stream.close()
try:
return await async_aiohttp_proxy_stream(
self.hass, request, stream,
'multipart/x-mixed-replace;boundary=ffserver')
finally:
await stream.close()
@property
def name(self):

View File

@@ -53,6 +53,11 @@ class BloomSkyCamera(Camera):
return self._last_image
@property
def unique_id(self):
"""Return a unique ID."""
return self._id
@property
def name(self):
"""Return the name of this BloomSky device."""

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