Compare commits

..

829 Commits
0.58 ... 0.63

Author SHA1 Message Date
Paulus Schoutsen
0e16f7f307 Merge pull request #12267 from home-assistant/release-0-63
0.63
2018-02-10 14:00:29 -08:00
Slava
18aa1037dd Update limitlessled requirement to v1.0.9 (#12275)
* Update limitlessled requirement to v1.0.9

* trigger cla

* take back empty line
2018-02-10 13:11:05 -08:00
Paulus Schoutsen
aad26599ae Retry keyset cloud (#12270)
* Use less threads in helpers.event tests

* Add helpers.event.async_call_later

* Cloud: retry fetching keyset
2018-02-10 13:11:05 -08:00
escoand
a9412d27aa allow wildcards in subscription (#12247)
* allow wildcards in subscription

* remove whitespaces

* make function public

* also implement for mqtt_json

* avoid mqtt-outside topic matching

* add wildcard tests

* add not matching wildcard tests

* fix not-matching tests
2018-02-10 13:11:04 -08:00
Paulus Schoutsen
3333dcc6c2 Version bump to 0.63 2018-02-09 14:55:20 -08:00
Paulus Schoutsen
681dc72a15 Merge branch 'master' into dev 2018-02-09 14:54:27 -08:00
Anton Lundin
b0780110c7 One bug fix and one improvement to the statistics sensor. (#12259)
* Correct time on recorder loaded values in statistics sensor

Previously, the current time was used when initial values was loaded
form the recorder component. This changes that to use the stored time
from recorder instead.

Signed-off-by: Anton Lundin <glance@acc.umu.se>

* Expose min / max age of values in the statistics sensor

This is very useful when doing derived calculations, for example in a
template sensor.

Signed-off-by: Anton Lundin <glance@acc.umu.se>
2018-02-09 23:50:05 +01:00
Paulus Schoutsen
b087ea101d Update frontend to 20180209.0 2018-02-09 14:34:20 -08:00
David
129d720d8e Fix duplicate entity_ids in System Monitor (#12124)
* Fix duplicate entity_ids in System Monitor

This fix makes it so `_percent` is appended to the `entity_id` of the following 3 resources, in order to make the `entity_id` unique:
- disk_use_percent
- memory_use_percent
- swap_use_percent

* match entity_id to resource name

Match entity_id to resource name, to make resulting entity_id more predictable

* match entity_id to more resource names

match entity_id to more resource names

* Add unique_id property

* Revert "Add unique_id property"

This reverts commit c213ac360e0fa90ab1b9cfbd2161413f038a4ff1.
2018-02-09 14:10:16 -08:00
Eleftherios Chamakiotis
6174c1754b Fix for iTunes media player not updating artwork (#12089)
* Added timestamp at the end of the iTunes API URL from where HA retrieves the artwork, so that it's not cached, as the URL exposed by the API never changes

* Rearranged imports according to pylint

* Added content_id in media file URL instead of timestamp, according to Paulus' suggestion
2018-02-09 14:09:34 -08:00
luca-angemi
4c11a3461f Update owntracks.py (#12260) 2018-02-09 23:06:31 +01:00
Daniel Perna
0b947882ac Update pyhomematic to 0.1.39 (#12265)
* Update pyhomematic
2018-02-09 21:59:10 +01:00
ChristianKuehnel
2014e42e4e miflora - fix for exception handling bug (#12149)
* updated to development branch of miflora

* updated requirements_all.txt

* upgraded to version 0.3

* updated requirements_all.txt
2018-02-09 21:31:49 +01:00
Otto Winter
2ae0c5653e Fix source code using Windows newline (#12248)
* 🚜 Fix usage of carriage return

* 🤝 Rebase and repeat

* 🚜 Fix file permissions
2018-02-09 08:11:47 +01:00
Pascal Vizeli
e4874fd7c7 Update aiohttp 2.3.10 / yarl 1.1.0 (#12244)
* Update aiohttp 2.3.10 / yarl 1.1.0

* Update setup.py

* Update package_constraints.txt

* Update google.py

* Update static.py
2018-02-08 20:57:05 -08:00
Jon Maddox
18d027a10d Add Service Schema to Broadlink Switch (#12253)
* add service schema to ensure single values are wrapped into a list

Co-Authored-By: Paulus Schoutsen <paulus@paulusschoutsen.nl>

* 💐
2018-02-08 19:37:17 -08:00
ChristianKuehnel
b08294386b added more debug logging for sensor.alpha_vantage (#12249)
* added more debug logging for sensor.alpha_vantage

* fixed typo in log statement, more fine grained logging

* Capitalized first character in log statement

* replaced quotes as proposed by @OttoWinter
2018-02-09 00:14:49 +01:00
Anders Melchiorsen
acb521330c Add explicit first-time config for new purge_keep_days default (#12246) 2018-02-08 09:44:19 -08:00
cdce8p
231b62d043 Fix cover service description (#12243)
Parameter for `set_cover_tilt_position` is `tilt_position` not `position`.
2018-02-08 16:09:42 +01:00
Eu
905bb36e6a Added password mode to input_text (obscure content of text box) (#11849)
* Round values to one decimal

Temperature detection range: -20 - 60 Deg.C ( + / - 0.3 Deg.C )
Humidity detection range: 0 - 100pct RH ( + / - 0.3pct )
Atmospheric pressure detection range: 30 - 110KPa ( + / - 120Pa )

* Add password mode option

Hide the content of the input_text field

* Revert "Round values to one decimal"

This reverts commit a3124a6aaa2261eff558e2bd37a3eda57d1aac71.

* Added test for mode option

* Added newline (lint)
2018-02-08 12:29:33 +01:00
mkfink
25cbc8317f Force update support for mqtt binary sensor (#12092) 2018-02-08 12:28:12 +01:00
Anders Melchiorsen
6265d1b747 Avoid influxdb filling connection pool (#12182)
* Add a processing queue to influxdb

* Updates after reviews

* Remove lint

* Move retry loop to thread class

* Move constant calculation out of loop

* Deprecate retry_queue_limit
2018-02-08 12:25:26 +01:00
Thijs de Jong
702b1be985 Set tahoma cover update interval to default (#12232)
revert 35f35050ff158b423dc437c66bdea5ebcbabc009#diff-c65eb52376398392f1395f8127364078
2018-02-08 12:20:51 +01:00
Diogo Gomes
15368d4ca1 [SMALL PATCH] Sql sensor (#12242)
* Initial Commit

* Passed all checks

* Make DB_URL required

* addresses review comments from @fabaff

* unused variable

* return nothing
2018-02-08 12:17:54 +01:00
Paulus Schoutsen
5601fbdc7a Entity layer cleanup (#12237)
* Simplify entity update

* Split entity platform from entity component

* Decouple entity platform from entity component

* Always include unit of measurement again

* Lint

* Fix test
2018-02-08 12:16:51 +01:00
Sergey Isachenko
8523933605 Fixes for tesla. New sensors. (#12225)
* fixes #11970

* long line fix
2018-02-07 23:34:26 -08:00
Diogo Gomes
0300229085 SQL sensor (#12142)
* Initial Commit

* Passed all checks

* Make DB_URL required

* addresses review comments from @fabaff

* unused variable
2018-02-07 23:32:39 -08:00
Sergey Isachenko
d0ffb1bc52 librouteros version bump (#12227) 2018-02-07 23:15:02 -08:00
Andrey
2b9bb7963d Update min js=latest version (#12091) 2018-02-07 23:14:31 -08:00
Anders Melchiorsen
945606238c Allow zero purge_interval to disable recorder purge (#12220) 2018-02-07 22:59:09 -08:00
Anders Melchiorsen
aa9b5e6ea5 Return of entity_id in template platforms (#12234) 2018-02-07 22:46:14 -08:00
Phil Elson
9d5dee574a Specify the minimum python version in the setup.py. (#12144)
* Specify the minimum python version in the setup.py.

* Used the minimum python version defined in homeassistant.const.
2018-02-07 12:38:06 -08:00
Marc Egli
ea35ffbc81 Add wake on lan capability to philips TV (#12065)
* Add wake on lan capability to philips TV

* Update requirements_all.txt

* Fix line length issues.

* Replace wake on lan with turn on script for philips TV

* rerun requirements script
2018-02-07 09:35:08 -08:00
Kevin Siml
d05a1e35fc Update pushsafer.py (#11466)
* Update pushsafer.py

Now you can setup your pushsafer notification, and change the following parameters:
sound, vibration, icon, devices (targets), icon/led color, url, url title, time2live, picture

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* fix lint
2018-02-07 17:23:10 +01:00
Phil Elson
5ba02c531e Catch concurrent.futures.CancelledError in websocket code. (#12150)
* Catch concurrent.futures.CancelledError in websocket code.

* Added a comment about the use of futures.CancelledError
2018-02-06 21:30:18 -08:00
Boyi C
7e246e4680 Fix logger bug on Windows: path contains '\'. (#12197)
* Fix logger bug on Windows: path contains '\'.

* update

* Update __init__.py
2018-02-06 12:56:31 -08:00
kennedyshead
bd29cd2ba2 Fixes according to review from @MartinHjelmare Thank you. (#12171) 2018-02-06 21:27:35 +01:00
Sebastian Muszynski
cee57aab24 Xiaomi MiIO Light: Brightness mapping improved (#12203)
* Mapping ([1,100] <-> [1,255]) of the brightness improved.

* The cast to int isn't needed for python3.
2018-02-06 19:59:49 +01:00
Jerad Meisner
a2916a9c47 Fix Xeoma camera platform to allow different admin/viewer credentials (#12161) 2018-02-06 10:47:38 -08:00
Conrad Juhl Andersen
49c7b422f2 Add Xiaomi Universal IR Remote (Chuangmi IR) (#11891)
* First version of remote xiaomi-miio

* added to coveragerc

* fixed pylint error

* misc fixes and input validation

* address syssi's requests except device and async_service_handler

* forgot to run linter

* implemented async_service_handler

* fixed delay == None, honor timeout given by user, pythonic compare of None

* Added some whitespace for readability, added error message to turn_on and turn_off, fixed services.yaml examples

* fixed pylint errors

* readd pass for readability

* fixed small stuff

* Use RemoteDevice, Make send_command non-async

* Ready code for next version of python-miio (Support for pronto hex codes)

* cast command_optional to int, better input validation, fixed index out of bounds error.

* revert code now in python-miio

* ready for python-miio 0.3.5

* Removed unneccary return statements

* require 0.3.5

* Rebase and update requirements_all.txt
2018-02-06 19:47:24 +01:00
Thibault Cohen
a1d586c793 Fix clear playlist in Volumio component (#12173) 2018-02-06 10:46:44 -08:00
Russell Cloran
c7dad113d9 zha: Add support for XBee radios (#12205)
* zha: Add support for xbee radios

* Lint
2018-02-06 10:46:28 -08:00
Dan Nixon
844337ca42 Properly handle thresholds of zero (#12175)
Explicitly test for thresholds to be None rather than truth value
testing (which for number types returns False for zero values).
2018-02-06 10:32:56 -08:00
lance36
0fd17a7c35 Much nicer icon (#12212)
mdi:robot-vacuum will be renamed mdi:roomba 
https://github.com/Templarian/MaterialDesign/issues/2368
2018-02-06 18:52:55 +01:00
Sean Dague
6f74b672a3 Make waterfurnace recovery more robust (#12202)
This makes waterfurnace recovery more robust by catching any
understood exceptions by the library, and always doing another login.
2018-02-06 12:12:35 +01:00
Russell Cloran
f58e5f442d zha: Update to bellows 0.5.0+zigpy (#12187) 2018-02-05 16:05:19 -08:00
tadly
98b47cecbd Upgrade wakeonlan to 1.0.0 (#12190) 2018-02-05 16:04:31 -08:00
Richard Lucas
e7a0759e1c Add support for Alexa.StepSpeaker (#12183) 2018-02-05 16:02:08 -08:00
William Scanlon
bdaf9cfae2 Bump pyeconet version to fix JSONDecodeError (#12204) 2018-02-05 15:59:17 -08:00
hawk259
4f0776de13 Binary Sensor Template: Add icon_template and entity_picture_template support (#12158)
* Binary Sensor Template: Add icon_template and entity_picture_template support

* fix white space

* Added else logging and return state
2018-02-05 23:30:56 +01:00
Rene Nulsch
323fe87b57 Change attributes in new Mercedes Me component (#12147)
* Fix wrong component doc URL

* Change attributes to lowercase snakecase

* pylint fix

* Remove test comments
2018-02-05 23:29:19 +01:00
Fabian Affolter
c72460ccf0 Upgrade Sphinx to 1.6.7 (#12200) 2018-02-05 22:11:20 +01:00
Fabian Affolter
49343c9b02 Replace Gitter with Discord (#12199) 2018-02-05 21:25:37 +01:00
Joe Lu
e35d4f0a2c Canary live stream (#11949)
* Added support for Canary live stream view

* Updated requirements

* - Fixed lint error

* Addressed PR comment

* - Disabled polling for Canary camera as suggested in PR comment
- Live session is now renewed every time camera is retrieved and min time between session renewal is 90 seconds
2018-02-05 14:02:43 +01:00
tbergo
86e89b7c26 Upgrade pytouchline to 0.7 (#12179) 2018-02-05 09:33:07 +01:00
Thibault Cohen
44cfd2999c fix ecobee is_aux_heat_on property (#12186) 2018-02-05 09:21:20 +01:00
Tod Schmidt
f5030d9ebf Services (small_pr)(fix): Added missing return on data template error (#12184)
* Added return on data template error

* Rebased so not sure why spelling errors returned...
2018-02-05 09:19:56 +01:00
Sebastian Muszynski
137933a774 python-miio version bumped. Fixes all xiaomi_miio components. (Closes: #12017, Closes: #11948, Closes: #11200) (#12188) 2018-02-05 09:14:09 +01:00
Fabian Affolter
905a994972 Upgrade schiene to 0.21 (#12176) 2018-02-04 21:33:41 +01:00
Dan Nixon
ec201f3458 Move TP-Link socket LED state setting to update() (#12170)
* Add error handling to TP-LInk LED state set

Handles errors when setting the LED state of TP-Link sockets.

If the socket is unavailable then the raised exception will cause the
compoent to not be added to HA.

* Move LED state setting out of __init__
2018-02-04 19:20:06 +01:00
akloeckner
cff4f8ec9a add delay_arrival (#12169)
This adds the delay_arrival field from the schiene interface.
This field sometimes explains an ontime=false with delay=0...
2018-02-04 18:30:03 +01:00
Fabian Affolter
64cbfdfd77 Upgrade influxdb to 5.0.0 (#12156)
* Upgrade influxdb to 5.0.0

* UPdate sensor as well
2018-02-04 18:23:26 +01:00
kennedyshead
8fe339d2a8 Tests for samsungtv (#11933)
* Testing samsungtv

* Remove samsungtv from .coveragerc
2018-02-03 13:09:16 -05:00
Diogo Gomes
c209c10887 [Mediaroom media_player] Follow up on PR #11864 (#12155)
* addresses @MartinHjelmare on #11864

* as requested by @MartinHjelmare
2018-02-03 17:58:34 +01:00
Diogo Gomes
b33d89326f Panasonic viera new services (#11963)
* Implemented play_media

Panasonic Viera TV has a full blown Web Browser that can play any media

* media stop

* format checks

* added SUPPORT_*

* bump version

* Tks @rytilahti

* one too many
2018-02-03 11:51:34 -05:00
Per Osbäck
1aca6f922f update python-openzwave to 4.1.3 (#12057)
* update python-openzwave to 4.1.0

* 0.4.1.3
2018-02-03 11:08:48 -05:00
ErnstEeldert
9b0dbf3fbe Adding xy_color attribute support to deconz lights (#12106) 2018-02-03 17:08:00 +01:00
ruohan.chen
4ac9e7edf4 fix generic_thermostat bug when restore state from HA start up (#12134)
* fix generic_thermostat bug when restore state from HA start up

if you don't set "initial_operation_mode" in config, you will get
`self._enabled = True` when init GenericThermostat. And then you will
miss the `if self._current_operation != STATE_OFF` statement and the
self._enabled still keep `True`. That's the problem

* add a test to describe the restore case
2018-02-03 16:59:19 +01:00
Fabian Affolter
c144a3339f Upgrade TwitterAPI to 2.4.8 (#12148) 2018-02-03 16:56:35 +01:00
Fabian Affolter
acc767cdb1 Upgrade mutagen to 1.40.0 (#12152) 2018-02-03 16:55:19 +01:00
Diogo Gomes
880f18a37e Mediaroom (#11864)
* make port mapping optional

* dependencies + improvements

* Added bytes and packets sensors from IGD

* flake8 check

* new sensor with upnp counters

* checks

* whitespaces in blank line

* requirements update

* added sensor.upnp to .coveragerc

* downgrade miniupnpc

Latest version of miniupnpc is 2.0, but pypi only has 1.9

Fortunately it is enough

* revert to non async

miniupnpc will do network calls, so this component can’t be moved to
coroutine

* hof hof

forgot to remove import ot asyncio

* Add baudrate option

* merge

* Added Mediaroom media_player component

* Updated header

Works with MEO and VDF set-top boxes in Portugal

* formatting

* Development Checklist (done)

* fix formatting according to houndci-bot

* more format fixing (tks houndci-bot)

* more fixes

* too much cleanup...

* too much

* pylint check

* Initial commit

Basic configuration testing

* flake8 and lint
2018-02-03 08:29:55 -05:00
kennedyshead
f7c9787418 Add Melissa (HVAC/climate) component (#11503)
* Adding component melissa

* Adding sensor component melissa

* Adding Melissa climate component

* Testing component

* Tests for Climate component

* Testing Melissa sensor

* Fixing review Thank you @rytilahti
2018-02-03 03:17:01 +01:00
Nigel Rook
c204a7c787 Tado fixes (#11294)
* Fix tado overlay end state

Previously, when tado ended an overlay state itself, say because a timer
expired or a scheduled temperature change ocurred, the tado climate
component would not return to Smart Schedule mode. This change fixes
that issue

* Correct tado state after multiple rapid updates

Previosuly, making two changes to tado climate within 10 seconds, for
example setting operation mode to Tado mode, then changing the
temperature, would leave the entity showing the incorrect state for up
to a minute.

This change forces an unthrottled update after setting the climate
state, which fixes the issue

* Fix comment formatting
2018-02-02 17:28:54 -08:00
Ville Skyttä
2cbab48e1b Update flake8-docstrings to 1.0.3 (#12136) 2018-02-02 17:22:44 -08:00
Anthony Arnaud
86daec8c59 Fix #11875 Ubus broken since upgrade to 0 57 (#12141) 2018-02-02 17:22:29 -08:00
Anthony Arnaud
0f879a6c60 Fix #8475 device tracker ubus tracks unauthenticated and unassociated devices (#12140) 2018-02-02 17:22:14 -08:00
led-spb
a3e36e6c66 Adding information about current TV channel to WebOS media player (#11339)
* Added Channel attribute to webos media pplayer

* webostv: Current TV channel display as media_title

* Added displaying information about the current TV channel for WebOS platform

* Fixed PEP8 requirements
2018-02-02 23:54:54 +01:00
Thibault Cohen
730e0a0094 Update volumio component (#12045) 2018-02-02 23:12:54 +01:00
Ville Skyttä
13ec8b143d Spelling fixes (#12138) 2018-02-02 22:35:34 +01:00
Rene Nulsch
ed2d54ab45 Add Mercedes me component (#11743)
* Add Mercedes me component

* pump api version to 0.1.2

* Add Mercedes me component

* pump api version to 0.1.2

* clean up code

* Code cleanup

* Remove unneeded return statement

* Return statements added again

* Implement requested changes

* Rework component, move data load to component

* lint

* remove debug logging

* Change RainCloud comments, change from track_utc_time to track_time_interval

* Final cleanup for version 1
2018-02-02 10:56:58 -05:00
Marc Khouri
72c35468b3 Remove asyncio.test_utils to fix tests in Docker/Python 3.7 (#12102)
The module `asyncio.test_utils` has been removed from Python in the 3.7 branch, because it was intended to be a private module for internal testing of asyncio. For more information, see the upstream bug report at https://bugs.python.org/issue32273 and the upstream PR at https://github.com/python/cpython/pull/4785.

For this commit, I have migrated the small amount of functionality that was being used from the `asyncio.test_utils` directly into the `RunThreadsafeTests` Class. To see the original `asyncio.test_utils.TestCase` class, which I pulled some functionality from, please see: https://github.com/python/cpython/blob/3.6/Lib/asyncio/test_utils.py#L440

Note: In addition to being broken in 3.7, this test case also seems to be broken in Python 3.6.4 when using Docker. This PR fixes the test when run in docker.

To reproduce: `./script/test_docker -- tests/util/test_async.py`
failing output (prior to this commit):

```
... trimmed ...
py36 runtests: PYTHONHASHSEED='3262989550'
py36 runtests: commands[0] | py.test --timeout=9 --duration=10 --cov --cov-report= tests/util/test_async.py
Test session starts (platform: linux, Python 3.6.4, pytest 3.3.1, pytest-sugar 0.9.0)
rootdir: /usr/src/app, inifile: setup.cfg
plugins: timeout-1.2.1, sugar-0.9.0, cov-2.5.1, aiohttp-0.3.0
timeout: 9.0s method: signal

―――――――――――――――――― ERROR collecting tests/util/test_async.py ――――――――――――――――――――――――
ImportError while importing test module '/usr/src/app/tests/util/test_async.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/util/test_async.py:3: in <module>
from asyncio import test_utils
/usr/local/lib/python3.6/asyncio/test_utils.py:36: in <module>
from test import support
E ImportError: cannot import name 'support'
```
2018-02-02 14:59:05 +00:00
Eleftherios Chamakiotis
87c0fd98c7 Add support for "off" function to iTunes (#12109)
fixes #7614
2018-02-02 14:54:47 +00:00
Rene Nulsch
1d2e930900 OpenALPR Cloud API - transfer image in body of POST request (#12112)
* Send image in body of POST request

* Fix tests

* Implement requested change
2018-02-02 14:19:13 +01:00
Paul Annekov
ad24cbddcc fixed wrong check for valid range of 'rgb' values (#12132) 2018-02-02 14:02:11 +01:00
nordlead2005
65f22b09ae Dark sky precip accumulation (#12127)
* Added DarkSky Precipitation Accumulation as an hourly forecast field

* fixed spacing
2018-02-02 10:23:27 +01:00
hawk259
569f7e2fea Adds SUPPORT_TARGET_TEMPERATURE_HIGH and SUPPORT_TARGET_TEMPERATURE_LOW support (#12110)
Fixes: [Issue 12048]
2018-02-02 10:11:13 +01:00
Daniel Høyer Iversen
12dc0db856 except vol.MultipleInvalid in Broadlink #11795 (#12107)
* except vol.MultipleInvalid in Broadlink #11795

* typo
2018-02-02 09:05:54 +01:00
Marius
6d5a87afb6 Fixes away_mode error on startup (#12121)
* Fixes away_mode error on startup

* Updated based on feedback
2018-02-02 09:05:19 +01:00
Timmo
30ad591a59 Downgrade Sonarr and Radarr 'Host is not avaliable' errors to warnings (#12119) 2018-02-01 20:57:33 +01:00
Alok Saboo
be37bb14b7 Update jinja2 to 2.10 (#12118) 2018-02-01 19:21:15 +01:00
Craig J. Ward
53a99dc9fa Goalfeed channel (#12086)
* fix event channel name

* I guess accidentally added timeout here too.
2018-02-01 11:24:02 +01:00
jodur
2f07ffc4e4 added media_stop (#12100)
* added media_stop

VLC was missing the media_stop. The pause was present, but starting the same file result in resuming the file instead of start over new

* Corrected style issues

Style issues and added Support Flag to Support VLC

* fixed other style issues

* remove trailing whitespace
2018-02-01 09:49:39 +01:00
Philip Kleimeyer
8991690d53 update tahoma api to version 0.0.11 (#12099) 2018-02-01 08:15:13 +01:00
c727
764343dbf8 Fix detection of mobile browsers (#12075)
* Fix detection of mobile browsers

* Move break

* Add Mobile browsers to list

`Mobile Safari` is covered by iOS and `Opera Mini` does not support es6
... And Edge doesn't even work on desktop for me...
2018-01-31 10:44:33 -08:00
Philip Kleimeyer
e11e066684 updated sensor name (#12084)
* updated sensor name

* Lint
2018-01-31 10:10:35 -08:00
Phil Elson
40af9f2676 Correct use of middleware async handling. (#12078) 2018-01-31 09:04:32 -08:00
Fabian Affolter
424fe95ce4 Upgrade keyring to 11.0.0 (#12082)
* Upgrade keyring to 11.0.0

* Address the removal of 'keyring.__version__'
2018-01-31 09:03:20 -08:00
John Mihalic
81a6178931 Squeezebox Fix duplicate server from discovery (#12063)
* Fix duplicate server from discovery

* Use hass.data instead of global

* Simplify
2018-01-31 15:32:08 +01:00
escoand
e9508405bc Add conditions to forecast (#12074)
* add conditions to forecast chart

* Fix pylint issues
2018-01-31 13:05:15 +01:00
Gerben Meijer
6ae3fa40cf Set flux default stop time to dusk (#12062)
This is more in line with how one would expect light temperature
transitions to take place, but still allows for a user defined
stop_time.
2018-01-31 12:00:47 +01:00
Taylor Peet
434d2afbfc Influx import improvements (#11988)
* Influx import improvements

* fix line length issues

* fixing pylint spaces

* Added refined except clause

* Fix progress bar and exclude issues

* fix travis lint too many blank lines

* Minor changes
2018-01-31 11:39:15 +01:00
Ville Skyttä
0376cc0917 Handle more file closing using context manager (#11942) 2018-01-31 11:30:48 +01:00
escoand
4cb1f93019 fixed timestamp problem in firefox (#12073) 2018-01-31 11:26:35 +01:00
Craig J. Ward
ebfb380449 fix event channel name (#12077) 2018-01-30 21:46:47 -05:00
Marius
3e41422caa Fix demo platform support (#12070)
* Fixing demo platform to use support_flags

* Fixed tests as well

* Moved humidity low / high as always available based on defaults

* Updated demo platform to show more combinations
2018-01-30 14:59:43 -08:00
Ville Skyttä
cab6c694c5 Flake8 bugbear fixes (#12072)
* Don't use mutable argument defaults (bugbear B006)

* Use callable(x) instead of hasattr(x, '__call__') (bugbear B004)

* Remove/mark unused loop control variables (bugbear B007)

* Fix stripping protocol from kodi host name (bugbear B005)

* Fix plant daily history add default date (bugbear B008)
2018-01-30 14:44:05 -08:00
Kane610
37034a7450 Deconz use entity registry (#12067)
* Support for entity registry

* Not everything is a sensor...
2018-01-30 14:42:24 -08:00
Anders Melchiorsen
990fbdf3ca Unique ID for LIFX lights (#12064) 2018-01-30 14:40:44 -08:00
Pierre Ståhl
dfd2d631ae Publish errors on the event bus (#11964)
* Publish errors on the event bus

* Add block till done to test.

* Update test_system_log.py

* Remove old logger handlers
2018-01-30 11:25:58 -05:00
Alex Osadchyy
12182d6e49 Bumped up pymochad requirement to 0.2.0 as a fix for #11928 (#12014)
* Bumped up pymochad requirement to 0.2.0 as a fix for #11928

* requirements_all.txt updated to match pymochad requirements
2018-01-30 05:13:30 -08:00
Anders Melchiorsen
d7017f2138 Prepare for recorder purge to be active by default (#11976) 2018-01-30 12:41:33 +01:00
Paulus Schoutsen
ec1c395f09 Extract requirements (#12051) 2018-01-30 12:30:47 +01:00
Joe Lu
71cb4df817 Return all attributes that are not None in base lock entity class (#12049)
* Return all attributes that are not None in base lock entity class

* Update __init__.py
2018-01-30 12:20:20 +01:00
Paulus Schoutsen
e51427b284 Entity registry (#11979)
* Entity#unique_id defaults to None

* Initial commit entity registry

* Clean up unique_id property

* Lint

* Add tests to entity component

* Lint

* Restore some unique ids

* Spelling

* Remove use of IP address for unique ID

* Add tests

* Add tests

* Fix tests

* Add some docs

* Add one more test

* Fix new test…
2018-01-30 10:39:39 +01:00
Phil Kates
8e441ba03b Refactor Google Assistant query_device (#12022)
* google_assistant: Refactor query_device

The previous code had issues where domains could break out and end up
with weird brightness values and we weren't enforcing the `on` and
`oneline` keys in the response.

* google_assistant: Add media_player to query test
2018-01-30 01:19:24 -08:00
freol35241
5b1c51bdf6 Handling of payload not for this entity. (#11836)
* Handling of payload not for this entity.

The update state-method should not be called if the payload is not intended for this entity.

* Fixing linter errors

* Adding warning for case when no matching payload is found
2018-01-30 10:18:45 +01:00
Phil Frost
8624799c45 Refactor alexa smart_home tests (#12044)
* Refactor alexa smart_home tests

The previous tests had a lot of copy pasta due to a lack of expressions
for higher-level assertions. I'm hoping this makes it more reasonable to
extend all interfaces to support properties.

* Lint
2018-01-29 20:33:39 -08:00
Paulus Schoutsen
1aaf49d0c1 Merge pull request #12047 from home-assistant/release-0-62-1
0.62.1
2018-01-29 16:35:59 -08:00
Fabian Affolter
10263230f7 Upgrade astral to 1.5 (#12042) 2018-01-29 16:08:01 -08:00
Paulus Schoutsen
6f84fa4ce5 Bump frontend to 20180130.0 2018-01-29 16:06:00 -08:00
Anders Melchiorsen
a1c0544e35 Upgrade pyharmony to 1.0.20 (#12043) 2018-01-29 16:04:04 -08:00
c727
a59d26b1fa Fix 404 for Hass.io panel using frontend dev (#12039)
* Fix 404 for Hass.io panel using frontend dev

* Hound
2018-01-29 16:04:03 -08:00
Rene Nulsch
170a0c9888 Error handling, in case no connections are available (#12010)
* Error handling, in case no connections are available

* Fix elif to if
2018-01-29 16:04:03 -08:00
smoldaner
e084a260c6 Fix parameter escaping (#12008)
From rfc3986: The characters slash ("/") and question mark ("?") may represent data within the query component

See https://tools.ietf.org/html/rfc3986#section-3.4
2018-01-29 16:04:03 -08:00
Frantz
8709a397f6 Set default values for Daikin devices that don't support fan direction and fan speed features (#12000) 2018-01-29 16:04:02 -08:00
Ville Skyttä
9fed3acc90 Fix asuswrt AttributeError on neigh for unknown device (#11960) 2018-01-29 16:04:02 -08:00
tschmidty69
0713dbc7a3 Snips - (fix/change) remove response when intent not handled (#11929)
* Remove snips endSession response on unknownIntent

* Removed snips_response for unknown and error.
2018-01-29 16:04:01 -08:00
Anders Melchiorsen
5609b42863 Upgrade pyharmony to 1.0.20 (#12043) 2018-01-29 15:54:49 -08:00
Paulus Schoutsen
24c6285567 Bump frontend to 20180130.0 2018-01-29 15:51:43 -08:00
Paulus Schoutsen
5bdbf3dfc0 Version bump to 0.62.1 2018-01-29 15:40:08 -08:00
smoldaner
6d59dad1ce Fix parameter escaping (#12008)
From rfc3986: The characters slash ("/") and question mark ("?") may represent data within the query component

See https://tools.ietf.org/html/rfc3986#section-3.4
2018-01-29 15:02:26 -08:00
Frantz
99c6a10b99 Set default values for Daikin devices that don't support fan direction and fan speed features (#12000) 2018-01-29 14:56:55 -08:00
kennedyshead
7ad870c4ff Online state for samsungtv is jumping when TV is idle (#11998)
* Set timeout to offline

* Have to rewrite to use ping instead.
2018-01-29 14:55:39 -08:00
Rene Nulsch
89e0b26b73 Error handling, in case no connections are available (#12010)
* Error handling, in case no connections are available

* Fix elif to if
2018-01-29 14:49:38 -08:00
Otto Winter
8dcfd35b8b Spelling fixes (#12041)
* Spelling fixes

*Lots* of them.

* Spelling breaking changes

* Fix lint errors
2018-01-29 23:37:19 +01:00
Otto Winter
38fd9b65bf Fix MQTT cover availability subscription (#12036) 2018-01-29 23:19:08 +01:00
c727
105522f03f Fix 404 for Hass.io panel using frontend dev (#12039)
* Fix 404 for Hass.io panel using frontend dev

* Hound
2018-01-29 23:18:33 +01:00
akloeckner
8b9dc71cde sensor.deutsche_bahn: add only_direct option (#11999)
* sensor.deutsche_bahn: add only_direct option

This adds the `only_direct` option to the HA interface as provided by the schiene class.

* fix line length

as requested by @houndci-bot and @fabaff

* No line breaks needed
2018-01-29 23:17:58 +01:00
Dan Cinnamon
ff0fd71608 Bump upstream lib version. (#12021) 2018-01-29 12:35:13 +01:00
Andy Castille
12a53e2747 Fix DoorBird push notifications for installations with an API password (#12020) 2018-01-29 12:15:53 +01:00
Ville Skyttä
384f63dd1d Typing fixes (#12015)
* .gitignore: Add .mypy_cache

* Typing fixes
2018-01-29 00:24:08 -08:00
Ville Skyttä
78a3c01f27 Flake8 35 (#11972)
* Upgrade flake8 to 3.5

* Fix flake8 bare except errors

* Make flake8 and pylint cooperate
2018-01-29 00:23:53 -08:00
Jack Wilsdon
5426e5c875 emulated_hue: allow customization within emulated_hue configuration (#11981)
* emulated_hue: add entities configuration

* emulated_hue: update tests to include new entities attribute
2018-01-28 23:40:00 -08:00
Phil Kates
766875f702 alexa: Add media_player InputController support (#11946)
`media_player`s can support select_source so map that to an
InputController.

[1]: https://developer.amazon.com/docs/device-apis/alexa-inputcontroller.html
2018-01-28 22:22:04 -08:00
Phil Frost
7d6ef4445e Report states (#11973)
* Refactor Alexa Smart Home API

Having an object per interface will make it easier to support
properties.

Ideally, properties are reported in context in all responses. However
current implementation reports them only in response to a ReportState
request. This seems to work sufficiently. As long as the device is
opened in the Alexa app, Amazon will poll the device state every few
seconds with a ReportState request.

* Report properties for some Alexa interfaces

Fixes (mostly) #11874.

Other interfaces will need properties implemented as well.

Implementing properties for just PowerController seems sufficient to
eliminate the "There was a problem." error for any device that supports
it, even if other interfaces are supported. Of course the additional
properties will be reported incorrectly in the Alexa app.

Includes a minor bugfix: `reportable` was previously placed incorrectly
in the responses, so Amazon was ignoring it.
2018-01-28 17:00:34 -08:00
Phil Frost
84711aad90 Refactor Alexa Smart Home API (#12016)
Having an object per interface will make it easier to support
properties.

Ideally, properties are reported in context in all responses. However
current implementation reports them only in response to a ReportState
request. This seems to work sufficiently. As long as the device is
opened in the Alexa app, Amazon will poll the device state every few
seconds with a ReportState request.
2018-01-28 16:43:27 -08:00
Joe Lu
b3bf6c4be2 Fixed Canary temperature sensor and remapped air quality value (#11355)
* Fixed Canary temperature sensor and remapped air quality value

* Addressed review comment

* - Fixed canary tests and added more tests
- Removed py-canary requirements from tests

* Noop to trigger a build again

* - Removed py-canary requirements from tests

* Addressed PR comment

* - Updated tests
- Removed py-canary from gen_requirements_all.py

* - Fixed hound violation

* Added back py-canary to gen_requirements_all.py as it's still need in tests

* Added back py-canary to test requirements as it's still need in tests

* Address PR comment
2018-01-28 15:30:46 -08:00
Fabian Affolter
c7efe5b7dd Upgrade pyota to 2.0.4 (#11991) 2018-01-28 18:04:54 +01:00
Fabian Affolter
96f9a12541 Upgrade coinbase to 2.0.7 (#11992) 2018-01-28 18:04:40 +01:00
Kevin Goff
336bdb1889 Added support for hourly percent change in coinmarketcap component (#11996)
* Added support for hourly percent change (percent_change_1h)

* Fixed display of 1h percent change
2018-01-28 15:50:43 +01:00
Craig J. Ward
62d4f23833 Add Goalfeed platform (#11098)
* add goalfeed

* use pysher. begin auth

* auth!

* update params

* cleanup

* update library and gen requirements

* unused imports

* case-sensitive

* crazy train

* docstrings and some other fixes

* remove logging

* unused imports

* import in setup

* move import

* Update based on notes

* add timeout

* It's only a component

* Update docstrings
2018-01-28 14:04:40 +01:00
Emil Stjerneman
3c869c6ed6 Fix 11982 - uvc don't handle null as username (#11984) 2018-01-28 10:50:23 +01:00
Ville Skyttä
a3fc2c7fee Update panasonic_viera to 0.3 (#11989) 2018-01-28 09:16:06 +01:00
Ville Skyttä
2d3034be11 panasonic_viera: Set device name from discovery info (#11990) 2018-01-28 09:15:39 +01:00
MGWGIT
1419005082 Update xiaomi_aqara.py (#11969)
Sensor can measure temperature below -20, but maybe not so accurate, but no need to discard measurements.
2018-01-27 22:01:48 +01:00
Fabian Affolter
f43234b533 Bump dev to 0.63.0.dev0 (#11952) 2018-01-27 12:02:55 -08:00
Fabian Affolter
f08fd8182c Upgrade coinmarketcap to 4.2.1 (#11953) 2018-01-27 11:59:33 -08:00
Fabian Affolter
0c008663ad Upgrade sphinx-autodoc-typehints to 1.2.4 (#11954) 2018-01-27 11:59:19 -08:00
Fabian Affolter
63ae275182 Upgrade youtube_dl to 2018.01.21 (#11955) 2018-01-27 11:59:07 -08:00
Fabian Affolter
d8fde94763 Upgrade sqlalchemy to 1.2.2 (#11956) 2018-01-27 11:58:52 -08:00
Ville Skyttä
55ee8959ba Spelling fixes (#11940) 2018-01-27 11:58:27 -08:00
tschmidty69
94316f07a2 Snips - (fix/change) remove response when intent not handled (#11929)
* Remove snips endSession response on unknownIntent

* Removed snips_response for unknown and error.
2018-01-27 11:55:47 -08:00
Ville Skyttä
e750428e9d huawei_router: Fix documentation link (#11961) 2018-01-27 16:33:33 +01:00
Ville Skyttä
3af7c67bf1 Fix asuswrt AttributeError on neigh for unknown device (#11960) 2018-01-27 15:20:28 +01:00
Ville Skyttä
f1fc3c762a tests: Use assertEqual instead of deprecated assertEquals (#11943) 2018-01-27 12:18:02 +01:00
Ville Skyttä
b4d682ca75 Python 3.6 invalid escape sequence deprecation fixes (#11941)
https://docs.python.org/3/whatsnew/3.6.html#deprecated-python-behavior
2018-01-27 12:16:30 +01:00
Rene Nulsch
cad0bde95b Panel_Iframe - Allow relative urls in config (#11832)
* Panel_Iframe - Allow relative urls in config

* change regex to check for starting forward slash only

* Change error message and const name
2018-01-26 22:31:40 -08:00
Rene Nulsch
74b0740e1c Weblink - Allow relative urls in config (#11808)
* Allow relative url

* Allow absolute urls in config schema

* change after pylint build

* Add tests and change error message

* Change regex to check starting forward slash only

* Change error message and const name
2018-01-26 22:30:39 -08:00
Paulus Schoutsen
5bde72d490 Merge pull request #11921 from home-assistant/release-0-62
0.62
2018-01-26 21:07:57 -08:00
Daniel Perna
af69a307a8 Update pyhomematic to 0.1.38 (#11936) 2018-01-26 20:32:08 -08:00
Phil Frost
7bbef68b2a Implement Alexa temperature sensors (#11930) 2018-01-26 20:32:08 -08:00
Bas Schipper
abde8c40c9 Fixed rfxtrx binary_sensor KeyError on missing optional device_class (#11925)
* Fixed rfxtrx binary_sensor KeyError on missing optional device_class

* Fixed rfxtrx binary_sensor KeyError on missing optional device_class
2018-01-26 20:32:08 -08:00
Paulus Schoutsen
07b2f38046 Allow setting climate devices to AUTO mode via Google Assistant (#11923)
* Allow setting climate devices to AUTO mode via Google Assistant

* Remove cast to lower

* Clarify const name
2018-01-26 20:32:07 -08:00
kennedyshead
280c1601a2 fixes #11848 (#11915)
Adding tests to check the component after latest patch
2018-01-26 20:32:07 -08:00
Andrey
df24ecf395 Add "write" service to system_log (#11901)
* Add API to write error log

* Move write_error api to system_log.write service call

* Restore empty line
2018-01-26 20:32:06 -08:00
Daniel Perna
af5d0b3443 Update pyhomematic to 0.1.38 (#11936) 2018-01-26 21:41:43 +01:00
Robert Schütz
2b68bec428 check_config.py: allow colorlog==3.1. (#11927) 2018-01-26 10:43:55 -08:00
Phil Frost
ffcc41d6ef Implement Alexa temperature sensors (#11930) 2018-01-26 10:40:39 -08:00
kennedyshead
2d8ef36a6c fixes #11848 (#11915)
Adding tests to check the component after latest patch
2018-01-26 10:30:48 -08:00
Aaron Bach
5af7666a61 Adds allergy/disease sensor platform from Pollen.com (#11573)
* Base platform in place

* Logic in place

* Requirements and coverage

* Fixed some linting issues

* Small attribute reorganization

* Collaborator-requested changes round 1

* Updated documentation
2018-01-26 18:40:02 +01:00
Bas Schipper
bfe259f7a0 Fixed rfxtrx binary_sensor KeyError on missing optional device_class (#11925)
* Fixed rfxtrx binary_sensor KeyError on missing optional device_class

* Fixed rfxtrx binary_sensor KeyError on missing optional device_class
2018-01-26 13:45:02 +01:00
akloeckner
68d2851ecf Map media_stop to idle state (#11819)
adresses #11813
2018-01-26 12:57:54 +01:00
Andrey
8332d4e359 Add "write" service to system_log (#11901)
* Add API to write error log

* Move write_error api to system_log.write service call

* Restore empty line
2018-01-26 12:41:52 +01:00
Paulus Schoutsen
390b727869 Allow setting climate devices to AUTO mode via Google Assistant (#11923)
* Allow setting climate devices to AUTO mode via Google Assistant

* Remove cast to lower

* Clarify const name
2018-01-26 12:37:06 +01:00
Paulus Schoutsen
deb10a1c4d Update frontend to 20180126.0 2018-01-25 23:26:14 -08:00
Paulus Schoutsen
3d8e425113 Update frontend to 20180126.0 2018-01-25 23:26:02 -08:00
Paulus Schoutsen
a8ee11e732 Version 0.62 2018-01-25 23:17:07 -08:00
Nash Kaminski
748fff7ebc Allow separate command and state OIDs and payloads in SNMP switch (#11075)
* Allow separate command and state OIDs and payloads in SNMP switch

Follow PEP8 style properly

More PEP8 style fixes

Fully PEP8 compliant

* Fix pylint errors

* Remove comment to satisfy pylint

* Style changes/refactoring
2018-01-25 22:48:21 -08:00
Nolan Gilley
9a71717047 Add ERC20 tokens to etherscan.io sensor (#11916)
* upgrade python-etherscan-api

* add support for erc20 tokens
2018-01-25 21:08:08 -08:00
Phil Frost
920f9f132b Report scripts and groups as scenes to Alexa (#11900)
* Send Alexa Smart Home responses to debug log

* Report scripts and groups as scenes to Alexa

The Alexa API docs have a couple display categories that sound relevant
to scenes or scripts:

    ACTIVITY_TRIGGER: Describes a combination of devices set to a
    specific state, when the state change must occur in a specific
    order.  For example, a “watch Neflix” scene might require the: 1. TV
    to be powered on & 2. Input set to HDMI1.

    SCENE_TRIGGER: Describes a combination of devices set to a specific
    state, when the order of the state change is not important. For
    example a bedtime scene might include turning off lights and
    lowering the thermostat, but the order is unimportant.

Additionally, Alexa has a notion of scenes that support deactivation.
This is a natural fit for groups, and scripts with delays which can be
cancelled.

https://developer.amazon.com/docs/device-apis/alexa-discovery.html#display-categories

The mechanism to map entities to the Alexa Discovery response is
refactored since extending the data structures in MAPPING_COMPONENT to
implement supportsDeactivation would have added complication to what I
already found to be a confusing construct.
2018-01-25 21:06:57 -08:00
arcsur
3aa3130d05 Minor fix to configuration validation and related log line. (#11898) 2018-01-25 21:01:43 -08:00
David Fiel
caa16da5c5 Multi-Room Support for Greenwave Reality (#11364)
* Multi-Room Support for Greenwave Reality

* PEP8 Line Too Long

* Update requirements_all.txt

* Shared State Object

Shared State Object added, and implemented new function of greenwavereality to abstract complex runtimes.

* Update requirements_all.txt

* Lint issues

* Rewrite method to not trigger "Method could be a function"

* Remove unnecessary arguments for update call
2018-01-26 00:00:32 +01:00
Jerad Meisner
94e270f828 Added Xeoma camera platform (#11619)
* Added Xeoma camera platform

* Switch to dict.get() for optional config values with no default

* Minor changes
2018-01-25 23:48:38 +01:00
i-am-shodan
502ebd2a31 Improve foscam library exception support (#11701)
* Improve foscam library exception support

Catches foscam exceptions that otherwise pollute the log. Many of these exception can safely be ignored

* Fixed line length

Fixed line length

* Changed exception and log handling

changed logging and catched only the TypeError effecting the library

* Removed unused var

Removed var

* Fix remaining issue
2018-01-25 23:47:53 +01:00
Johannes Innerbichler
0db9c04f21 Iota wallet (#11398)
* worked on first version of IOTA wallet

* added sensor for IRI node

* added requirements

* ignored new component in test coverage

* changed length of line

* fixed linter issues

* changed requested changes

* moved attributes of IRI node

* change coverage definitions

* changed loading of platforms

* changed loading of platforms

* changed initial state of wallet sensor

* changed handling of config

* changed attribute handling for IOTA node sensor

* Follow the component style

* Fix ordering and docstring

* Fix pylint issue
2018-01-25 19:46:48 +01:00
Dan Cinnamon
72bb0e97e0 New venstar climate component (#11639)
* New venstar climate component

* Corrected items raised during the PR process.

* Corrected flak8 issues.

* Add support for venstar models without humidity control.

* Changed the idle operation mode to off.  Few other adjustments.

* Minor changes (log messages, sorting, etc.)
2018-01-25 18:34:53 +01:00
William Scanlon
5123487705 Update python-wink version and multiple wink fixes/updates. (#11833) 2018-01-25 11:31:38 -05:00
Paulus Schoutsen
3d9ff372fc Use API to discover Hue if no bridges specified (#11909)
* Use API to discover Hue if no bridges specified

* hide config file
2018-01-25 14:55:14 +01:00
Paulus Schoutsen
9123dfce6d Clarify emulated hue warning (#11910) 2018-01-25 11:20:37 +01:00
tschmidty69
27edbe5c0f Snips - (fix) removed endSession mqtt response on error and unknown intents (#11908)
* Remove snips endSession response on unknownIntent

* Removed snips_response for unknown and error.
2018-01-24 22:50:36 -08:00
tschmidty69
ffe832763d Pushbullet (fix) invalid keyword, added unittests (#11804)
* Fixed unittests

* revert requirements

* added pushbullet.py to requirements

* updated requirements
2018-01-24 21:06:35 +01:00
lich
becd94fe2f Add android option for linux_battery.py (#11852)
* Add android option for linux_battery.py

* Add system option for linux_battery.py, support android.
2018-01-24 13:51:39 +01:00
arcsur
a0a001db71 Bme680 (#11892)
* Added documentation reference to code

* Some code clean-ups suggested by @MartinHjelmare in PR#: 11695 after merging.

* fixed minor typo in docstring

* fixed another minor typo in same docstring...

* fixed another minor typo in same docstring...
2018-01-24 03:44:29 -08:00
Gregory Dosh
d65ac7421d device tracker - tomato https support (#11566)
* initial https support

* adding tests

* lint errors

* missing docstring

* fixing non-deterministic params

* fixing non-deterministic params

* Updating docstrings & added missing tests

* revert _LOGGER

* updating default port to reflect ssl/nonssl

* fixing docstrings for tests
2018-01-24 04:51:06 -05:00
Frantz
b43b542667 Handle Daikin AC adapters without fan mode and swing mode support (#11840)
* Handle daikin AC devices without FAN_MODE and SWING_MODE support

* Handle daikin AC devices without FAN_MODE and SWING_MODE support
2018-01-24 09:39:25 +01:00
Frantz
676c95ed2d [SMALL-PR] Don't make climate calls if feature is not supported (#11841)
* Don't make climate calls if feature is not supported

* Implemented suggested code review changes & cleanup

* Fix demo climate unit tests
2018-01-24 09:35:31 +01:00
Anders Melchiorsen
5b0a475197 Postpone "Z-wave not ready" warning (#11807)
* Release worker thread while waiting for Z-wave startup

* Increase zwave startup timeout

* Adjust test

* Use asyncio.sleep in _check_awaked

* Remove lint

* Name loop parameter
2018-01-24 09:27:58 +01:00
Sean Dague
4521d59bec Bump waterfurnace library to 0.3.0 (#11888)
Fixes in the library to handle transaction id which has to roll over
otherwise the server gets confused.
2018-01-24 08:24:54 +01:00
Rendili
8f083e17f8 Fix for hive aux_heat target temperature display (#11884) 2018-01-23 16:16:38 -08:00
Nolan Gilley
9a3895c79e upgrade ecobee (#11878) 2018-01-23 23:03:54 +01:00
Paul Annekov
eea7e2fa2d fixed async function called in a thread (#11882) 2018-01-23 22:44:07 +01:00
Phil Frost
990e076c2c Expose Alexa Smart Home via HTTP POST (#11859)
* Expose Alexa Smart Home via HTTP POST

Haaska uses the deprecated v2 Alexa Smart Home payload. Exposing the v3
implementation this way allows an easy path to upgrading Haaska and
reducing code duplication with Home Assistant Cloud.

* Expose Alexa Smart Home via HTTP POST

Haaska uses the deprecated v2 Alexa Smart Home payload. Exposing the v3
implementation this way allows an easy path to upgrading Haaska and
reducing code duplication with Home Assistant Cloud.
2018-01-23 10:45:28 -08:00
Sean Dague
73fa76d792 Add missing mock call for test_minimal_config (#11858)
In local testing py36 always fails on test_minimal_config on a wait
call that never completes. One difference between this test and others
in the class is the lack of a mock on `call`. With this added, the
test passes locally 100%.
2018-01-23 14:02:00 +01:00
Pascal Vizeli
6df1fae447 Hass.io panel v2 (#11860)
* Update hassio.py

* fix test

* Update test_hassio.py
2018-01-23 11:39:55 +01:00
Paul Annekov
3417c6ad8d Checking Xiaomi Aqara devices unavailability states (#11631)
* added unavailability tracker, updated sensor component

* change hass argument position according to position in binary_sensor

* added hass argument to binary_sensor, updated is_on(), it can be UNAVAILABLE now

* updated switch component to support unavailability feature

* updated light component to support unavailability feature

* updated cover component to support unavailability feature

* set _hass property

* added unavailability tracker, updated sensor component

* change hass argument position according to position in binary_sensor

* added hass argument to binary_sensor, updated is_on(), it can be UNAVAILABLE now

* updated switch component to support unavailability feature

* updated light component to support unavailability feature

* updated cover component to support unavailability feature

* set _hass property

* fixed error with wrong arguments number during callback call

* reset unavailability state on new message received from device

* use locks to fix race condition during managing _state property

* overriden state() method for some components to check for STATE_UNAVAILABLE and return it instead e.g. STATE_OFF

* fixed linter

* removed blank line

* use available() method instead of changing _state

* filter motion sensors 'heartbeat', was removed from PyXiaomiGateway

* remove self._hass, use self.hass set by HA on attach

* self.push_data now running in the event loop, use async_schedule_update_ha_state()

* merge fix

* removed accidentally added home-assistant-polymer

* bump PyXiaomiGateway version to 0.8.0

* bump PyXiaomiGateway to 0.8.0

* updated methods names and annotations
2018-01-23 10:22:43 +01:00
Phil Frost
95592d9283 Respond to Alexa scene activation correctly (#11869)
The API documentation[1] specifies that Alexa.SceneController Activate
must get a ActivationStarted response. Responding with just a `Response`
will elicit a "Hmm... $scene is not responding" from Alexa.

[1]: https://developer.amazon.com/docs/smarthome/provide-scenes-in-a-smart-home-skill.html
2018-01-23 00:01:18 -08:00
arcsur
09e3bf94eb BME680 Sensor Component (#11695)
* Adding BME680 Sensor Component

* Flake8 lint fixes

* PyLint fixes

* Fix for log line

* Updating requirements for testing

* Fix PyLint Log format errors and add to coveragerc ommisions as requires sensor connected

* Regenerated requirements_all.txt

* Added Pylint exception for import error of system specific library

* Refactored async_add_platform to move IO out to avoid heavy yield usage
2018-01-22 23:51:52 -08:00
Frantz
bc13c9db83 Allow exposing sensors as temperature or humidity 'climate' devices to Google Assistant (#11095)
* Allow exposing sensors as temperature or humidity as 'climate' to Google Assistant

* Fixed hound

* Fixed hound

* Handled correctly unit of measurement to fix humidity

* Fixed temperature conversion for Google climate components

* Fixed temperature conversion for Google climate components

* Fixed indentation

* Fixed hound

* Fixed tests

* Fixed conversion and unit tests

* Fix sync for custom unit temperature

* Implemented requested changes

* Fix hound

* Fix linting errors

* Added success tests for sensors as climate

* Fix lint errors
2018-01-22 23:23:33 -08:00
Paulus Schoutsen
183e0543b4 Clean up entity component (#11691)
* Clean up entity component

* Lint

* List -> Tuple

* Add Entity.async_remove back

* Unflake setting up group test
2018-01-22 22:54:41 -08:00
Sean Dague
d478517c51 Fix races on recorder test (#11857) 2018-01-22 15:21:56 +01:00
Pascal Vizeli
b224fd324d Fix new iframe panel url (#11850)
* Fix new iframe panel url

* fix tests
2018-01-22 14:45:48 +01:00
Oleksii Serdiuk
8c627e2b8b maxcube: Set MAX! Window Sensor's class to 'window' (#11799)
The sensors are meant to be put on windows to shut down the heating when
windows are open. Having 'window' device class instead of 'opening' is
much more logical here.
2018-01-22 12:32:27 +01:00
Marius
c8d26d99f0 Fix issues with generic thermostat (#11805)
* Fixes for #11757 #11798 #11763

* Adjustments based on feedback
2018-01-22 12:12:03 +01:00
kennedyshead
0f26ebe954 Use strict timeout when polling Samsung TV (Fix for #6375) (#11759) 2018-01-22 08:11:16 +00:00
andrewdolphin
5513ffc33c Change 'on' to 'heat' as fallback thermostat mode (#11377)
* Change 'on' to 'heat' as fallback thermostat mode

'on' isn't recognised as a mode by Google Assistant, rather is used as a method to return a thermostat to a previous mode. In the case where a thermostat doesn't support the standard google modes (e.g. A homematic radiator thermostat) this means the set_temperature doesn't get returned to the user on a request.

* Update test_google_assistant.py
2018-01-21 12:57:56 -08:00
William Scanlon
6a6ea263cf Fix Unifi direct errors caused by AP reboot. (#11835)
* Fix Unifi direct errors caused by AP reboot.

* Inverted logic in update
2018-01-21 18:13:28 +01:00
Teemu R
1a789a05db bump eq3bt version (#11834) 2018-01-21 11:45:20 +01:00
Fabian Affolter
47e31dc9ee Fixes for PEP257 (#11810)
* Fixes for PEP257

* More updates
2018-01-20 22:35:38 -08:00
Frantz
0100f87ff2 (Re)Enable Daikin autodiscovery (#11842) 2018-01-21 06:08:42 +01:00
Sean Dague
8c78a210ef Add waterfurnace platform (#11732)
Add waterfurnace platform

This adds support for waterfurnace geothermal systems. This is
implemented as a component as there will eventually be some active
control elements. This is not done as a climate platform because
geothermal systems work best when set at a constant temperature as
they are tuned to keep within 0.5 degrees F of a setpoint, and large
temperature shifts are slow and expensive.

This is done in the Data + Sensors model, with the Data component
having a regular update thread. That thread needs to call the read()
function at least every 30 seconds otherwise the underlying websocket
is closed by the server.
2018-01-20 16:51:59 -05:00
Sebastian Muszynski
dd81af4cd5 python-miio version bumped. Fixes all xiaomi_miio components. (Closes: #11768) (#11837) 2018-01-20 21:27:52 +01:00
Dan Nixon
2cfbd0dc1d Add missing availability schema to MQTT alarm panel (#11829)
* Add missing availability schema to MQTT alarm panel

* Add tests for default MQTT availability payloads
2018-01-20 17:11:04 +01:00
Filip Bednárik
a470cc212e Add more workday sensor countries and update holidays library to version 0.9.3 (#11826) 2018-01-20 17:09:05 +01:00
Michaël Arnauts
f7b129d790 Change telldus domain to download.telldus.com (#11825) 2018-01-20 17:07:45 +01:00
Jens Østergaard Nielsen
e02d5e7ff1 Ihc component and platforms (#10916)
* Added IHC platform

* Updated requirements for IHC platform

* Exclude IHC from test

* Correcting flake8 issues

* Fixing more flake8 issues

* Fixed flake8 issues

* Fixing pylint issues

* Fixed flake8 issues

* Changes from PR review.

* STATE_UNKNOWN changed to None

* Spelling mistake in comment

* Added IHC platform

* Updated requirements for IHC platform

* Exclude IHC from test

* Correcting flake8 issues

* Fixing more flake8 issues

* Fixed flake8 issues

* Fixing pylint issues

* Fixed flake8 issues

* Changes from PR review.

* STATE_UNKNOWN changed to None

* Spelling mistake in comment

* Updated requirements_all.txt with gen_requirements_app.py

* Pylint fix: No space allowed around keyword argument assignment

* PR review changes

* Moved auto setup from platforms to ihc component

* Do no auto setup if there are no IHC products found

* Changes from PR review
2018-01-20 16:29:50 +01:00
ChristianKuehnel
323992e224 MiFlora - use bluepy on linux systems (#11284)
* Updated bluepy to version 1.1.4 as some issues with the native code were fixed there.

* Miflora - Added support for bluepy backend.

* miflora - now using bluepy backend on linux platforms

* fixed pylint findings

* miflora now using bluepy as default bluetooth backend and gatttool as fallback

* fixed hound complaints

* fixed pylint warning

* updated requirements

* Update miflora.py
2018-01-20 08:50:25 +01:00
Spencer Oberstadt
f744467c5d bump roku version (#11816) 2018-01-19 21:56:56 -08:00
robhuls
7cbe017932 Nad (#11800)
* Update nad_receiver to 0.0.9

* Update nad_receiver to 0.0.9
2018-01-19 21:41:12 -08:00
Paulus Schoutsen
c1b0ab75e1 Update frontend to 20180119.0 2018-01-19 09:54:01 -08:00
Paulus Schoutsen
51c41ba4e3 Disable installing Telldus in Docker (#11806) 2018-01-19 09:47:45 -08:00
Lukas Barth
51dd9b6dde Fix recorder purge (#11802)
* Do proper largest-of query

* Fix error when event_id is NULL
2018-01-19 08:56:28 -08:00
Martin Rowan
d697e8e677 Correct inadvertent change to file permissions (#11755) 2018-01-19 16:28:47 +01:00
Paul Rabahy
d5df1c070d Make Google TTS secure (#11031)
* Make Google TTS secure

I noticed that my TTS queries were showing up in the log on my router, so I was curious if there was a way to make it secure. A quick search showed people using https instead of http (https://stackoverflow.com/questions/32053442/google-translate-tts-api-blocked), so I figure that should work. I am using hass.io, so I'm not actually sure how to test this, but its a pretty simple change.

* Fix the tts test.
2018-01-19 16:27:40 +02:00
Andrey
273db75248 Always load yr picture from https (#11796) 2018-01-19 13:06:34 +01:00
Andrey
5ef7a8d55a Fix sensibo function names (#11797) 2018-01-19 13:04:53 +01:00
starkillerOG
2ca4bde06a Hyperion: fix (#11793) 2018-01-19 10:50:12 +01:00
Daniel Høyer Iversen
4ceb13291f flux led version 0.20 (#11791) 2018-01-19 00:44:40 -08:00
Sebastian Muszynski
03a5d4e131 Additional attributes and services of the Xiaomi Air Purifier introduced (#11249)
* Attributes average_aqi and purify_volume introduced. Fixes https://github.com/syssi/xiaomi_airpurifier/issues/14.
New service light.xiaomi_miio_set_child_lock_{on,off} added. Fixes https://github.com/syssi/xiaomi_airpurifier/issues/13.

* Lazy loading of service descriptions.

* Merge conflict resolved.
2018-01-18 23:50:56 -08:00
Philip Kleimeyer
5de828d6e2 add generic rollershutter agian, was missing in last merge (#11788) 2018-01-18 23:47:35 -08:00
ChristianKuehnel
b84e551aea plant - check history for min_brightness (#9534)
* Added option to create a group for the plant and all of it's sensors so that they appear together in the UI

* fixed warnings from the hound

* added check for min_brightness over several days

* fixed hound complaints

* 1) added missing dependency on recorder
2) using group.Group instead of hass.states.async_set as requested by @pvizeli

* fixed pylint error in docstring

* changed the way the groups are created

* fixed requirements issue

* Changed the way the groups are implemented. This is proposal number 4...

* Data read from recorder only on startup.

We now only store one data point per day. If a recorder is configured, this data is initialized from the database. If not the list is empty on startup.

* added missing documentation

* fixed typo in comment

* removed group fature

* added group dependency since it's still needed

* fixed bug: now "None" is no longer added to the DailyHistory

* now also outputting unit of measurement if defined by the sensors

* removed iconss

* fixed line length

* Implemented changes requested in code reviews.

These changes affect the interface to the UI:
* renamed attribute for units of measurement to "unit_of_measurement_dict"
* renamed attribute for maximum in brightness history to "max_brightness"

* only loading the history if a brightness sensor was configured

* fixed testcase

* fixed stupid bug in check of brightness history

Also added test for this bug

* added missing docstring

* Fixed sporadic failure in test case.

Sometimes the component was created before the data was stored in the history. This lead to an empty history being read.

* removed unused import statement in testcase

* reverted change to test case

* Changed startup behavior of the component.

No failed tests after 20 local test runs.

* added missing docstring

* fixed tests

* added hass.start() to Setup
* fixed call parameters in constructor
* added time.sleep

* removed sleep

* fixed typo in variable name

* disabled loading from database as it's not stable at the moment and nobody knows why :(

* fixed flake8

* now using pytest.mark.skipif to skip test
2018-01-18 23:46:12 -08:00
Steaff
c48ef281ab Homematic ip tilt covers (#11650)
* add pyhomematic support for ip and tiltable covers

* use cached data in current_cover_tilt_position

* check for existance not for None

* reformatting

* check node for LEVEL_2
2018-01-18 23:20:05 -08:00
Sebastian Muszynski
b10fd172fd Service for setting a fixed scene of Xiaomi MIIO lights (#10819)
* Service for setting a fixed scene introduced.

Fixes https://github.com/syssi/philipslight/issues/6.
Fixes https://github.com/home-assistant/home-assistant/issues/10458.

* Service description added.

* Typo fixed.

* Error message updated and naming improved.

* Name ("scene") of the method parameter aligned.

* Hound error fixed: Spaces removed.

* async_setup_platform method simplified.

* Lazy loading of service descriptions.

* Unused import removed.
2018-01-18 22:52:30 -08:00
William Scanlon
314582ef0c Support for performance mode on Rheem water heaters. (#11786) 2018-01-18 22:37:24 -08:00
Fabian Affolter
b1fd9daf5f Fix typos (#11781) 2018-01-18 22:36:48 -08:00
Fabian Affolter
7fe2dafa04 Fix PEP8 and PEP257 issues (#11780) 2018-01-18 22:36:29 -08:00
tschmidty69
48619c9d7c Implemented event_data_template (new) (#11057)
* Implemented event_data_template

* The hound does not like my indentation

* Added passed variables to tests for event and svc template calls

* Moved recursive function to template.py

* Update template.py

* Update template.py

* Cleaned up service.py and fixed unit tests

* Blank lines

* Removed stray logger statement

* Blank lines again
2018-01-18 22:13:14 -08:00
tschmidty69
0e1cc05189 Snips: (change) Removed unknown intent speech response (#11776)
* Removed unknown intent speech response

* Fixed tests, doh!

* Woof
2018-01-18 22:01:04 -08:00
Anders Melchiorsen
ce9673b06d Limit service description loading to a single thread (#11733) 2018-01-18 21:59:03 -08:00
Kane610
a9634199e6 Axis discovery fails to save conf (#11769)
* Signal callback isnt JSON serializable so it has to be removed before saving to conf

* Remove filtered events list which is not a part of component configuration
2018-01-18 14:51:01 -08:00
karlkar
cf6f916ed4 Fix for Neato D3 and D5 (#11775) 2018-01-18 23:37:24 +01:00
Jean-Philippe Jodoin
8ca45acb4e Added support for TekSavvy bandwidth sensor (#11186)
* Added support for TekSavvy bandwidth sensor

* Variable name fix

* Units are Gigabytes and not Gigabits

* Change REST calls to use asyncio

* houndci violation fix

* pylint fix

* Fix for code review

* Import order asyncxxx:wq

* Tweak docstrings and log message
2018-01-18 23:15:13 +01:00
Fabian Affolter
23b2ca50e2 Update header and make it less verbose (#11774) 2018-01-18 23:04:18 +01:00
markferry
526405c83b Add a 'last' mode and attribute to min_max sensor (#11037)
* Add 'last' type to min/max sensor

Now supports types: min, max, mean, last
'last' is the most recently received value from all tracked entities.

* Min/max sensor 'last' type test

* Fix min/max sensor 'last' test
2018-01-18 23:03:41 +01:00
Conrad Juhl Andersen
536424b0c8 Owntracks: Use bluetooth_le as source_type if beacon was used for location change. (#11615)
* Use bluetooth_le source_type, if location was changed by beacon

* No reason to do nested ifs

* Added tests for source_type on owntracks

* Fixed The Hound

* Added test and fixed bug surfaced by test
2018-01-18 23:00:20 +01:00
Ioan Loosley
0859e38bd5 Unit should be mph as that is what the metoffices datapoint API returns (#11760) 2018-01-18 22:03:01 +01:00
Matthias Dötsch
46bbd78b23 Use localized forecast for openweathermap (#11770)
Use "detailed status" of forecast to get localized value
2018-01-18 21:59:50 +01:00
Fabian Affolter
5c474ec42d Update icon (fixes #11744) (#11758) 2018-01-18 21:48:21 +01:00
Alok Saboo
2df2f35423 Round off exchange rate (#11765) 2018-01-18 21:47:46 +01:00
Daniel Høyer Iversen
216075cc72 set default value for rfxtrx config (#11767) 2018-01-18 19:58:56 +01:00
Paulus Schoutsen
f5fba333d9 Upgrade netdisco (#11752) 2018-01-18 12:51:01 +01:00
Rene Nulsch
aad14b8b87 Xbox sensor - Extend error handling (#11637)
* Extend error handling fix #9016

* lint finding

* Implement requested changes

* Remove unneeded return statement
2018-01-17 21:26:23 -08:00
Kane610
8bcaf832ae Add deCONZ entities in a predicitive order (#11712)
* Make sure that entities names are created in a predicitive order

* Debug print for deconz config parameters

* Bump requirement to v25
2018-01-17 21:22:42 -08:00
Thijs de Jong
aac01cb096 Fix Tahoma device class (#11745)
* fix device class

* edit description
2018-01-17 21:20:23 -08:00
iliketoprogram14
e72fefa74d Fixed universal media player templated source_select bug (issue #10981) and corrected typo in test_universal (#11746) 2018-01-17 21:19:34 -08:00
karlkar
7617b8af52 Fix for None object access attempt (#11748)
* Fix NoneType access error

* Update lib dependencies

* Fix for line length
2018-01-17 21:10:15 -08:00
Martin Rowan
33fd9c7c8f Fix effects not appearing in UI due to missing attribute (#11738) 2018-01-17 22:00:46 +01:00
Pierre Ståhl
8703124c76 Add enable_output service to Yamaha platform (#11103)
* Add enable_output service to Yamaha platform

* Fix lint issues

* Fix review comment

* Check entity_ids instead of device
2018-01-17 19:34:21 +01:00
Pascal Vizeli
4ee2c311a7 Don't use None inside header (#11725) 2018-01-17 15:20:26 +01:00
Dan Nixon
020593d509 Override default name for TP-Link devices (#11710)
Fixes #11706

Corrects a bug introduced that prevents the names of TP-LInk devices
from being pulled from the devices themselves.
2018-01-17 00:52:32 -08:00
Åskar Andersson
1f118c4b84 Update mold_indicator.py (#11715) 2018-01-17 09:12:50 +01:00
Paulus Schoutsen
abbc6a2587 Merge branch 'master' into dev 2018-01-16 14:49:03 -08:00
Paulus Schoutsen
37eb6c90b6 Merge pull request #11716 from home-assistant/release-0-61-1
0.61.1
2018-01-16 14:33:12 -08:00
Lukas Barth
fc302186b2 Fix purge with MariaDB / MySQL (#11713) 2018-01-16 13:37:38 -08:00
Bob Anderson
903ca567c5 History order bugfix and opt-in option (#11686)
* make history view re-ordering optional and opt-in, also fix type bug

* use python false for default value

* whitespace cleanup
2018-01-16 13:37:37 -08:00
Daniel Høyer Iversen
fd75f157d6 Rfxtrx fix (#11678)
* fix voluptuous bug in rfxtrx

* fix voluptuous bug in rfxtrx

* fix voluptuous bug in rfxtrx
2018-01-16 13:37:37 -08:00
Anders Melchiorsen
f86224a64e Move several local services to their right domain (#11677)
* Move several local services to their right domain

* Fix lint
2018-01-16 13:37:37 -08:00
Russell Cloran
ed41252207 Fix zha color probe (#11670) 2018-01-16 13:37:36 -08:00
Paulus Schoutsen
6ec411b4bb Version bump to 0.61.1 2018-01-16 13:37:19 -08:00
Lukas Barth
5a26d4c039 Fix purge with MariaDB / MySQL (#11713) 2018-01-16 13:35:23 -08:00
Bob Anderson
94950cccc8 History order bugfix and opt-in option (#11686)
* make history view re-ordering optional and opt-in, also fix type bug

* use python false for default value

* whitespace cleanup
2018-01-16 11:48:10 -08:00
Sergey Isachenko
3a00077305 Tesla bug fix #11598 (#11707) 2018-01-16 17:34:41 +01:00
Wolf-Bastian Pöttner
4a82606ffb Feature/fritzdect errorhandling (#11490)
* Update to fritzhome 1.0.4

* Improved error handling, added autoreconnect on connection failure

* Move from STATE_UNKNOWN to None
2018-01-16 15:55:22 +01:00
Fabian Affolter
d5f63ebac4 Add attributes (#11698) 2018-01-16 12:32:08 +01:00
Åskar Andersson
dce079e711 fixed not to include spaces or dots in attribute names (#11694)
mold_indicator should be fixed not to include spaces or dots in attribute names

https://community.home-assistant.io/t/how-to-show-sensor-attribute-est-crit-temp-in-customize-template-and-extra-badge/39451
2018-01-16 10:59:20 +01:00
Fabian Affolter
632525f4d0 Enable probot move (#11690) 2018-01-16 09:25:13 +01:00
karlkar
98692523bf Added extra arguments to onvif platform config (#11680) 2018-01-16 09:23:48 +01:00
Anders Melchiorsen
87534692d0 Move several local services to their right domain (#11677)
* Move several local services to their right domain

* Fix lint
2018-01-15 14:53:56 -08:00
Daniel Høyer Iversen
a358174536 Rfxtrx fix (#11678)
* fix voluptuous bug in rfxtrx

* fix voluptuous bug in rfxtrx

* fix voluptuous bug in rfxtrx
2018-01-15 14:26:27 -08:00
Russell Cloran
ff32f90a29 Fix zha color probe (#11670) 2018-01-15 14:25:59 -08:00
Fabian Affolter
fb69620e49 Upgrade pylast to 2.1.0 (#11668) 2018-01-15 14:25:00 -08:00
Fabian Affolter
d219f244d2 Upgrade sqlalchemy to 1.2.1 (#11666) 2018-01-15 14:24:34 -08:00
Fabian Affolter
b0860ce5f0 Change line separator to LN (#11662) 2018-01-15 14:24:12 -08:00
Fabian Affolter
56a2c587ad Upgrade youtube_dl to 2018.01.14 (#11661) 2018-01-15 14:23:53 -08:00
Thom Troy
c43eceb2cb add temperature controls to eph-ember (#11400)
* add temperature controls to eph-ember

* fix linting
2018-01-15 23:13:48 +01:00
angel12
799e1f0469 Wemo Dimmer Support (#10882)
* Wemo Dimmer Support

Add support for the Wemo Dimmer Switch

* Add newline at end of file

Re: findings from hound

* Syntax for the hound

Sorry for the excess edits, new to python

* Change order of Models

Fixed order back to ABC order

* Changes as requested

I made the changes I was comfortable with at this point, the dimmer addition now very closely mirrors what is under the switch component, at least as far as the parts necessary for the dimmer.

Any changes past these with regards to the subscription registry / callback info is probably going to be over my head, but I will try to look deeper at them if required.

* Remove unnecessary lines

Removed self.schedule_update_ha_state() from turn off / turn on

* Remove update(self)

Removed update method

* Move subscription to async_added_to_hass

* Move subscription.
* Clean up.

* Wait until the job in the executor is done

* Run gen_requirements_all script

* Only update instance attributes via callback
2018-01-15 23:08:48 +01:00
Heiko Thiery
fdcf332a8a Add support for configuring jeelink RF parameters (#11620)
* add support for configuring jeelink ŔF parameters

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

* fix houndci-bot error

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
2018-01-15 22:49:17 +01:00
Ben
bf3329e9a9 update mypy commandline arguments (#11638) 2018-01-15 22:41:49 +01:00
Sean Dague
6b26154077 Add basic mychevy component (#11409)
* mychevy: added basic mychevy component

This implements a component using the mychevy library (which utilizes
selenium to webscrape the mychevy website for onstar for your
car). The architecture works by having a background thread doing
periodic polling of the website, and updating the sensors when new
data is found.

This requires rather more setup than most platforms, as you need
working selenium. Instructions will be provided on the component
list. All the sensors are spawned and coordinated from a single "hub"
as they are really just attributes of the same web scraping session.

* mychevy: only poll every 30 minutes

* mychevy: update sensors

* mychevy: better error handling

* mychevy: tweaking for refactor

* mychevy: bump version to handle odometer > 1000

* mychevy: great sensor reorg

* mychevy: add binary sensors

* mychevy: bump mychevy requirement

* mychevy: use dispatcher

Instead of directly modifying the sensors, this lets us use a
dispatcher to have sensors pull information from the car object when
there is a relevant update for them.

* mychevy: remove from coverage

* mychevy: dedicated constants for dispatch signals

This makes the dispatch signals dedicated topics, and fixes updating
the state on the sensors so that they are correctly updated.

* mychevy: updated with comments from martinhjelmare

* mychevy: set battery icon based with helper function

* Address additional review feedback

* Address additional review comments
2018-01-15 21:50:56 +01:00
covrig
5546ecd637 Round values to one decimal (#11673)
Temperature detection range: -20 - 60 Deg.C ( + / - 0.3 Deg.C )
Humidity detection range: 0 - 100pct RH ( + / - 0.3pct )
Atmospheric pressure detection range: 30 - 110KPa ( + / - 120Pa )
2018-01-15 20:40:12 +01:00
heydonms
079d4039a1 Add ability to specify a sender in the clicksend notification (#11046)
* Add ability to specify a sender in the clicksend notification

* Style fixes

* Fix remaining issue

* Add sender validation
2018-01-15 18:38:58 +01:00
Fabian Affolter
fc442361cd Bump release to 0.61.0 2018-01-15 13:27:54 +01:00
Fabian Affolter
1ed0c7d85d Bump dev to 0.62.0.dev0 (#11652) 2018-01-15 11:42:31 +01:00
Kane610
3979387c80 Add Deconz support for Zigbee green power devices like Hue Tap (#11455)
* Add support for Zigbee green power devices such as the Hue Tap

* Clarify that imported SWITCH is a DECONZ_REMOTE
2018-01-15 10:47:55 +01:00
Fabian Affolter
f86b645417 Merge branch 'master' into dev 2018-01-15 10:42:20 +01:00
Fabian Affolter
c3ff5de016 Merge pull request #11589 from home-assistant/release-0-61
0.61
2018-01-15 10:35:00 +01:00
Alok Saboo
9b15cfa5a5 Update Pyarlo to 0.1.2 (#11626) 2018-01-15 09:38:08 +01:00
Jesse Hills
7837b4893f Use kelvin/mireds correctly for setting iglo white (#11622)
* Use kelvin/mireds correctly for setting iglo white

* Update requirements_all.txt

* Fix line lengths
2018-01-15 09:38:07 +01:00
Thijs de Jong
d88edb0661 patch stop command (#11612) 2018-01-15 09:38:07 +01:00
Fabian Affolter
7a50450b92 Upgrade yarl to 0.18.0 (#11609) 2018-01-15 09:38:06 +01:00
Daniel Høyer Iversen
3afa4726bf Xiaomi lib upgrade (#11603)
* upgrade xiaomi lib

* xiaomi lib
2018-01-15 09:38:06 +01:00
Daniel Høyer Iversen
218e97d965 Bugfix and cleanup for Rfxtrx (#11600)
* rfxtrx clean up

* rfxtrx clean up

* rfxtrx clean up
2018-01-15 09:38:05 +01:00
Bob Anderson
8d19192c9c Concord232 alarm arm away fix (#11597)
* fix arming away cmd for concord232 client

* bump required version of concord232 to 0.15
2018-01-15 09:38:05 +01:00
tschmidty69
179d99381d Snips add say and say_actions services (new) (#11596)
* Added snips.say and snips.say_action services

* Added snips.say and snips.say_action services

* Merged services.yaml changes I missed

* added tests for new service configs

* Woof

* Woof Woof

* Changed attribute names to follow hass standards.

* updated test_snips with new attribute names
2018-01-15 09:38:04 +01:00
Adam Mills
b8dfa4c3d2 Fix state for trigger with forced updates (#11595) 2018-01-15 09:38:03 +01:00
tschmidty69
92bec562ab Pushbullet email support (fix) (#11590)
* Simplified push calls

* Cleaned up and added unittests

* Fixed email parameter

* Fixed email parameter
2018-01-15 09:38:03 +01:00
Thijs de Jong
1802c0a922 Fix Tahoma stop command for 2 types of shutters (#11588)
* add working stop command

This fixes the stop command for 2 types of roller shutters

* fix line too long

* fix indentation

* fix indentation
2018-01-15 09:38:02 +01:00
Pascal Vizeli
f2cc00cc64 Core support for hass.io calls & Bugfix check_config (#11571)
* Initial overwrites

* Add check_config function.

* Update hassio.py

* Address comments

* add hassio support

* add more tests

* revert core changes

* Address check_config

* Address comment with api_bool

* Bugfix check_config

* Update core.py

* Update test_core.py

* Update config.py

* Update hassio.py

* Update config.py

* Update test_config.py
2018-01-15 09:38:02 +01:00
Jack Fan
033e06868e Avoid returning empty media_image_url string (#11557)
This relates to issue
https://github.com/home-assistant/home-assistant/issues/11556
2018-01-15 09:37:57 +01:00
Fabian Affolter
688d706449 Upgrade coinmarketcap to 4.1.2 (#11634) 2018-01-14 22:31:47 +01:00
Pascal Vizeli
028597f774 Update CODEOWNERS 2018-01-14 15:03:39 +01:00
Lukas Barth
0550baaf4f Add templates to MQTT climate (#11623)
* Add templates

* Make pylint happy
2018-01-14 12:55:19 +01:00
Daniel Høyer Iversen
c33b171043 upgrade xiaomi lib (#11629) 2018-01-13 21:34:56 +01:00
Giuseppe
9d67d229fa Fixes and enhancements for the Tahoma platform (#11547)
* Strip off the RTS/IO ID from the entity ID

* Ignore exception thrown when the device does not provide an active state

* Send actions with a label for easier identification in the Tahoma log

* Linting

* Strip off the RTS/IO ID from the entity ID, take 2

As per suggestions, let HA do the standard initialization and assign
an appropriate entity_id, instead of overriding it with the lengthy
unique_id coming from the TaHoma devices.
2018-01-13 21:24:10 +01:00
starkillerOG
cdbf2f9293 Hyperion: Add brightness, HDMI and effect support (#11543)
* Hyperion: Add brightness, HDMI and effect support

- added brightness support to dim the hyperion light
- changed the "OFF" command to set the color to [0,0,0] after clearing all priorities.
  This is neccesary to keep the light turned off when an HDMI grabber is used for ambilight with hyperion.
- added HDMI ambilight mode recognition and control.
  by setting the "hdmi_priority" in your "configuration.yaml" file (defaults to 880), home assistant will now be able to recognize when the hyperion light is in HDMI ambilight mode and will change its icon to an HDMI symbol and set the status to ON.
Switching the hyperion light to HDMI ambilight mode can be done through the effect option (clears all priorities such that the HDMI grabber remains).
- added effect support for the default effects of hyperion, a custom list can be defined in the "configuration.yaml" file by using the "effect_list" option.

* Hyperion: Add brightness, HDMI and effect support

- added brightness support to dim the hyperion light
- changed the "OFF" command to set the color to [0,0,0] after clearing all priorities.
  This is neccesary to keep the light turned off when an HDMI grabber is used for ambilight with hyperion.
- added HDMI ambilight mode recognition and control.
  by setting the "hdmi_priority" in your "configuration.yaml" file (defaults to 880), home assistant will now be able to recognize when the hyperion light is in HDMI ambilight mode and will change its icon to an HDMI symbol and set the status to ON.
Switching the hyperion light to HDMI ambilight mode can be done through the effect option (clears all priorities such that the HDMI grabber remains).
- added effect support for the default effects of hyperion, a custom list can be defined in the "configuration.yaml" file by using the "effect_list" option.
- fixed some style issues with too long lines

* Hyperion: Add brightness, HDMI and effect support 

 - fixed some more indentation style issues

* Hyperion: Add brightness, HDMI and effect support 

- yet more fixed visuel indent issues

* Hyperion: Add brightness, HDMI and effect support 

- more visuel indents

* Hyperion: Add brightness, HDMI and effect support

- fixed invalid variable "A"

* Hyperion: Add brightness, HDMI and effect support

- remove unnececary brackets
- specify specific exceptions

* correct changing state holding attributes during a service method

Proccesed the comments of @MartinHjelmare: https://github.com/home-assistant/home-assistant/pull/11543#pullrequestreview-88328659

* indent correction

corrected tab instead of 4 spaces

* Hyperion: Add brightness, HDMI and effect support 

- changed 'none' to None
- renamed "self._skip_check" to "self._skip_update"

* Add brightness, HDMI and effect support 

changed checking if a list is empty from "list == []" to "not list"
2018-01-13 21:06:34 +01:00
Jesse Hills
5def6ebc3b Use kelvin/mireds correctly for setting iglo white (#11622)
* Use kelvin/mireds correctly for setting iglo white

* Update requirements_all.txt

* Fix line lengths
2018-01-13 20:07:39 +01:00
Alok Saboo
ea62deda59 Update Pyarlo to 0.1.2 (#11626) 2018-01-13 20:00:04 +01:00
Nicko van Someren
3e43f4e58e Adding support for Lutron covers (#11602)
* Adding support for Lutron Radio RA2 shades as cover components.

* Adding initial version of the Lutron shades component.

* Fixed line-length violation detected by Hound.
2018-01-13 19:11:20 +01:00
Jason Kölker
2e08766cb1 light/mqqt_json: allow brightness scaling (#11613) 2018-01-13 18:58:21 +01:00
Kees Schollaart
e476b9d225 Update Xiaomi Miio compontent broken URI (#11621) 2018-01-13 12:16:09 +01:00
Pascal Vizeli
b2b836d4c1 small sonos cleanup (#11607) 2018-01-13 09:59:50 +01:00
Thijs de Jong
5e81736f88 patch stop command (#11612) 2018-01-13 09:06:37 +01:00
Fabian Affolter
37427d052e Upgrad youtube_dl to 2017.12.31 (#11610) 2018-01-13 09:02:51 +01:00
Fabian Affolter
5656b0eb2c Upgrade keyring to 10.6.0 (#11608) 2018-01-13 09:02:25 +01:00
Fabian Affolter
b854cdb95b Upgrade yarl to 0.18.0 (#11609) 2018-01-13 09:01:05 +01:00
Daniel Høyer Iversen
be31a860d1 Xiaomi lib upgrade (#11603)
* upgrade xiaomi lib

* xiaomi lib
2018-01-12 13:35:32 -08:00
Daniel Høyer Iversen
0409192e64 Bugfix and cleanup for Rfxtrx (#11600)
* rfxtrx clean up

* rfxtrx clean up

* rfxtrx clean up
2018-01-12 11:52:53 -08:00
tschmidty69
c036141b37 Pushbullet email support (fix) (#11590)
* Simplified push calls

* Cleaned up and added unittests

* Fixed email parameter

* Fixed email parameter
2018-01-12 11:06:42 -08:00
tschmidty69
b8e4c2ff69 Snips add say and say_actions services (new) (#11596)
* Added snips.say and snips.say_action services

* Added snips.say and snips.say_action services

* Merged services.yaml changes I missed

* added tests for new service configs

* Woof

* Woof Woof

* Changed attribute names to follow hass standards.

* updated test_snips with new attribute names
2018-01-12 10:19:43 -08:00
Thijs de Jong
cc236529c4 Fix Tahoma stop command for 2 types of shutters (#11588)
* add working stop command

This fixes the stop command for 2 types of roller shutters

* fix line too long

* fix indentation

* fix indentation
2018-01-12 16:04:44 +01:00
Pascal Vizeli
dacd7cd8a4 Core support for hass.io calls & Bugfix check_config (#11571)
* Initial overwrites

* Add check_config function.

* Update hassio.py

* Address comments

* add hassio support

* add more tests

* revert core changes

* Address check_config

* Address comment with api_bool

* Bugfix check_config

* Update core.py

* Update test_core.py

* Update config.py

* Update hassio.py

* Update config.py

* Update test_config.py
2018-01-12 15:29:58 +01:00
Bob Anderson
8a301c6c59 Concord232 alarm arm away fix (#11597)
* fix arming away cmd for concord232 client

* bump required version of concord232 to 0.15
2018-01-12 08:45:01 +01:00
Adam Mills
6918993c75 Fix state for trigger with forced updates (#11595) 2018-01-11 22:06:09 -08:00
Jack Fan
88161cd5c9 Avoid returning empty media_image_url string (#11557)
This relates to issue
https://github.com/home-assistant/home-assistant/issues/11556
2018-01-11 20:14:37 -08:00
Paulus Schoutsen
4883036789 Update frontend 2018-01-11 15:50:50 -08:00
Andreas Björshammar
965bd8a2e0 Added support for enable/disable motion detection (#11583)
* Added support for enable/disable motion detection

* Changed name of variable for exception, lint error

* Moved motion_detection_enabled property to the other properties
2018-01-11 15:44:23 -08:00
Thijs de Jong
2224d05607 add velux roller shutter to tahoma (#11586)
With #11538 I forgot to add another type of Roller shutters that should be supported.
2018-01-11 15:43:31 -08:00
cgtobi
ed66c21035 Cast return values and add unit tests for the yahoo weather component. (#10699)
* Add unittest for yahoo weather component.

* Add requitements for tests.

* Update requirements.

* Revert "Update requirements."

This reverts commit 024b5cf8bf0d1bdfe927a117f5befb53c5a5cff4.

* Update requirements.

* Randomize sample data.

* Remove unnecessary methods.

* Remove dependency and replace with MockDependency.

* Add temporary fix for yahoo weather API issue.
2018-01-11 15:42:51 -08:00
Paulus Schoutsen
9384e2c963 Pr/11430 (#11587)
* Fix error when name is non-latin script

When the name is non-latin script (e.g. Japanese), slugify returns empty string and causes failure in a later stage. This commit fixes the issue by using default name.

* Add test
2018-01-11 15:26:48 -08:00
Bob Anderson
6af42b4372 Control ordering of display in history component (#11340)
* Make the order shown in the history component match the ordering given in the configuration of included entities (if any)

* return the sorted result

* optimize sorting.  since entities only appear once, we can break from a search on first find, and no copy of the list is needed
2018-01-11 15:21:23 -08:00
Laqoore
1235dae5b8 Changed device type of media player and cover to switch (#11483)
* Changed device type of media player and cover to switch

Covers and media players should not be of device type 'light'. Example: If user requests all lights to switch to off, covers are closed and media players are affected too.

* Fix test
2018-01-11 15:01:38 -08:00
Andrey
a35d05ac7e Remove aux_heat support from Sensibo now that UI supports on/off (#11579) 2018-01-11 23:25:15 +01:00
kennedyshead
6b103cc9b9 Fix for asuswrt, telnet not working and presence-detection for router mode (#11422)
* Fix for telnet mode
Fix for presence detection

closes #11349 #10231

* Optimisation when device is disconnected
2018-01-11 14:12:27 -08:00
Sean Wilson
a23f60315f Fix bluetooth tracker source (#11469)
* Add new sources for bluetooth and bluetooth_le trackers (rather than just using the generic 'gps' catch-all).

* Fix lint issues
2018-01-11 14:10:47 -08:00
Adam Mills
3bc6a7da32 Support OSRAM lights on ZHA (#11522) 2018-01-11 13:56:00 -08:00
hawk259
dc5b610ee5 Alarmdecoder add validation of the zone types (#11488)
* Alarmdecoder add validation of the zone types

* fix line length
2018-01-11 13:53:14 -08:00
Daniel Perna
7723db9e62 Update pyhomematic, support new devices (#11578) 2018-01-11 20:08:09 +01:00
Ulrich Dobramysl
cf612c3d5b Make the rpi_rf component thread-safe using an RLock (#11487)
* Make the rpi_rf component thread-safe

The previous implementation suffered from race conditions when two rpi_rf switches are triggered at the same time. This implementation uses an RLock to give one thread at a time exclusive access to the rfdevice object.

* cleanup

* fix lint
2018-01-11 13:47:05 +01:00
Josh Anderson
d2b6660881 Tado improvements - hot water zone sensors and climate precision (#11521)
* Add tado hot water zone sensors

* Set precision to match tado app/website
2018-01-11 10:49:41 +01:00
Dan Nixon
3972d1d4c6 Mark REST binary_sensor unavailable if request fails (#11506)
* Mark REST binary_sensor unavailable if request fails

* Add test suite for RESTful binary sensor
2018-01-11 10:48:15 +01:00
Anders Melchiorsen
5fda78cf91 Fix new squeezebox service descriptions for lazy loading (#11574) 2018-01-11 10:15:59 +01:00
randellhodges
60ce2b343d Tracking all groups to allow changing of existing groups (#11444)
* Tracking all groups to allow changing of existing groups

* Unit tests

* Fix flake8 warnings in test
2018-01-10 14:13:22 -08:00
Andrey
6cc285aea5 Add sensibo_assume_state service to Sensibo climate (#11567) 2018-01-10 14:04:35 -08:00
Pascal Vizeli
c5d5d57e9b Extend hass.io services / updater (#11549)
* Extend hass.io services

* Add warning for carfuly options with hass.io

* update tests

* finish tests

* remove update calls

* address comments

* address comments p2

* fix tests

* fix tests

* Use token also for proxy

* Add test for server_host

* Fix test

* Fix tests

* Add test for version

* Address comments
2018-01-10 19:48:31 +01:00
Thijs de Jong
02979db3d6 Add Velux Windows to Tahoma (#11538)
* Add Velux Windows to Tahoma

* fix linit

* add supported Tahoma devices by @glpatcern

* hound

* lint

* fix logging

* lint

* lint

* remove blank line after docstring

* changes based on notes by @armills

* fix logging
2018-01-10 09:41:16 -05:00
Paulus Schoutsen
0d06e8c1c9 Test tweaks (#11560)
* Fix is_allowed_path on OS X

* Move APNS2 inside func in test
2018-01-10 10:48:17 +01:00
Paulus Schoutsen
d793cfeb68 Update frontend to 20180110.0 2018-01-10 00:52:35 -08:00
Paulus Schoutsen
382a62346b Update frontend to 20180110.0 2018-01-10 00:52:12 -08:00
Anders Melchiorsen
9e0ca719ed Deprecate explicit entity_id in template platforms (#11123)
* Deprecate explicit entity_id in template platforms

* Use config validator for deprecation

* Fix copy/paste typos

* Also print the config value

* Add test for config validator

* Assert the module name that logged the message
2018-01-10 00:06:26 -08:00
Paulus Schoutsen
88b70e964c Remove execution file perm (#11563) 2018-01-09 23:55:14 -08:00
Andrea Campi
4dda842b16 Try to fix crashes after Hue refactoring (#11270)
* Try to fix crashes after Hue refactoring

Refs #11183

* Fix usage of dispatcher_send via helper.

* Address review feedback.
2018-01-10 08:05:04 +01:00
Nolan Gilley
3cba09c6f6 Coinbase.com sensor platform (#11036)
* coinbase sensors

use hass.data, load_platform

* add exchange rate sensors

dont pass complex object over event bus

* check for auth error
2018-01-10 07:47:22 +01:00
Fabian Affolter
c4bc42d527 Upgrade keyring to 10.3.2 (#11531) 2018-01-09 19:51:35 -08:00
Phil Kates
cf04a81f70 Fix error on entity_config missing (#11561)
If the `google_assistant` key exists in the config but has no
`entity_config` key under it you'll get an error.

```
  File "/Users/pkates/src/home-assistant/homeassistant/components/google_assistant/http.py", line 51, in is_exposed
    entity_config.get(entity.entity_id, {}).get(CONF_EXPOSE)
AttributeError: 'NoneType' object has no attribute 'get'
```
2018-01-09 19:47:24 -08:00
Eric Pignet
92014bf1d1 Add 2 media_player services and 1 custom service to Squeezebox platform (#10969)
* Add 2 media_player services and 1 custom service to Squeezebox platform

* Fix pylint error

* Remove apostrophe in example

* Split method into command and parameters

* Fix Lint error
2018-01-09 22:05:21 -05:00
cdce8p
cba55402b1 Improved test runtime (#11553)
* Remove redundent assert statements and cleanup

* Added 'get_date' function

* Replace 'freeze_time' with 'mock.patch'
* Tox in 185s (py35)

* Removed obsolete 'freeze_time' from test_updater
* Tox 162s (py35)

* Remove test requirement 'freezegun'

* Fixed flake8 errors

* Added 'mock.patch' for 'feedparser.parse'

* Made 'FUNCTION_PATH' a constant

* Remove debug statements.
2018-01-09 16:00:49 -08:00
Fabian Affolter
f56b3d8e9c Upgrade lightify to 1.0.6.1 (#11545) 2018-01-09 15:35:34 -08:00
Paulus Schoutsen
8313225b40 Move Google Assistant entity config out of customize (#11499)
* Move Google Assistant entity config out of customize

* CONF_ALIAS -> CONF_ALIASES

* Lint
2018-01-09 15:14:56 -08:00
Sean Wilson
13042d5557 ZoneMinder event sensor updates (#11369)
* Switch the ZoneMinder event sensor over to use the consoleEvents API, and add monitored_conditions for 'hour', 'day', 'week', 'month' and 'all'. 'all' is enabled by default to provide backward compatibility with the old behaviour.

* - Switch to new string formatting
- Remove redundant validator

* De-lint
2018-01-09 21:58:26 +01:00
Fabian Affolter
85858885c8 Upgrade Sphinx to 1.6.6 (#11534) 2018-01-09 15:30:54 +01:00
Fabian Affolter
10f48fbf6b Upgrade python-etherscan-api to 0.0.2 (#11535) 2018-01-09 15:30:36 +01:00
Fabian Affolter
8b267e3faf Upgrade numpy to 1.14.0 (#11542) 2018-01-09 15:30:00 +01:00
tschmidty69
13effee679 Snips: (fix) support new intentName format (#11509)
* support new intentName format

* Added tests for new and old format names

* pylint warning fixes
2018-01-08 13:00:21 -08:00
Cameron Llewellyn
903cda08b1 Insteon local update (#11088)
* trying to rework device discovery. now the main component will do the getlinked and pass it to the sub-components. no longer any config needed other than what is needed to connect to the hub. device names are no longer stored. core team told us to stop using configurator to ask for names. there should be a way to set names in hass...possibly this https://home-assistant.io/docs/configuration/customizing-devices/

* fix device types

* make device names just be the isnteon device id

* revert some config changes

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* update insteon client

* linting fixes

* Error Clean up

* Update to make requested changes

* more changes

* Finish requested changes to components

* Fixing Rebase Conflicts

* fix device types

* make device names just be the isnteon device id

* revert some config changes

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* Update insteon_local.py

* update insteon client

* linting fixes

* Error Clean up

* Update to make requested changes

* more changes

* Finish requested changes to components

* Update Insteon_Local for performance improvements

* Fix errors from get_linked

* Fix typo

* Requested changes

* Fix spacing

* Clean up

* Requested Changes
2018-01-08 18:18:10 +01:00
Yien Xu
e0e2f739ba Add options feature to Baidu TTS. (#11462)
* Add options feature to Baidu TTS.

Add options feature: supported_options() and default_options() added, get_tts_audio updated to accommodate options.

* Add options feature to Baidu TTS.

Add options feature: supported_options() and default_options() added, get_tts_audio updated to accommodate options.

* Fix style

* Fix style

Change the order of content of lists and dictionaries.

* Fix style

Changed order of imports, and fixed grammar errors.
2018-01-08 17:22:50 +01:00
Michael Kutý
0e710099e0 Support pushing all sensors and fix wrong metrics. (#11159)
For example all metrics with unit % match humidity.
This generate correct metrics like this
# HELP nut_ups_battery_charge sensor.nut_ups_battery_charge
# TYPE nut_ups_battery_charge gauge
nut_ups_battery_charge{entity="sensor.nut_ups_battery_charge",friendly_name="NUT UPS Battery Charge"} 98.0
nut_ups_battery_charge{entity="sensor.nut_ups_battery_charge_2",friendly_name="NUT UPS Battery Charge"} 97.0
2018-01-08 17:11:45 +01:00
timstanley1985
b1b0a2589e MQTT json attributes (#11439)
* MQTT json attributes

* Fix lint

* Amends following comments

* Fix lint

* Fix lint

* Add test

* Fix typo

* Amends following comments

* New tests

* Fix lint

* Fix tests
2018-01-08 17:07:39 +01:00
ChristianKuehnel
dff36b8087 Extension sensor alpha_vantage (#11427)
* Extended sensor alpha_vantage

* Improved error handling if symbol is not found. Now we add the symbols that were found,
* Added option to give names and currencies to symbols.
* Added support to read foreign exchange information.
* Icons are selected based on the currency (where MDI has a matching icon)

* added missing line at the end of the file...

* renamed variable as required by pylint

* Fix typos, ordering, and style
2018-01-08 16:58:34 +01:00
florianj1
46ad194097 Fix Kodi channels media type (#11505)
* Update kodi.py

* Update kodi.py

Fix code style
2018-01-08 16:57:50 +01:00
Alex Osadchyy
2ba9d825a0 Reconnect before mochad switch send command (#11296)
* Connection to mochad occasionally stalls on RPi and CM19A. Reconnect one switch send command.

* Formatting and exception hanling fixes

* Moved import inside the method. Logging outside the try-catch.

* Tailing whitespaces.

* MockDependency on pymochad in unit tests to resolve exceptions

* patch pymochad MochadException in unit tests to resolve exceptions

* patch pymochad MochadException in unit tests to resolve exceptions

* cleaned unused import

* lint issue fixed

* pylint issue fixed
2018-01-08 08:32:24 +01:00
Chris Cowart
8c0035c5b3 New features for Owntracks device_tracker (#11480)
* New features for Owntracks device_tracker

- Supporting a mapping of region names in OT to zones in HA, allowing
  separate namespaces in both applications. This is especially helpful
  if using one OT instance to update geofences for multiple homes.
- Creating a setting to ignore all location updates, allowing users to
  rely completely on enter and leave events. I have personally always
  used OT integrations with home automation this way and find it the
  most reliable.
- Allowing the OT topic to be overridden in configuration

* Fixing configuration of MQTT topic, related tests

* Tests for Owntracks events_only feature

* Tests for customizing mqtt topic, region mapping

* Fixing _parse and http for owntracks custom topic

* Making tests more thorough and cleaning up lint
2018-01-08 08:16:45 +01:00
Dan Nixon
c53fc94e84 Address missed review comments for Dark Sky weather (#11520)
See #11435
2018-01-07 19:54:27 -08:00
Paulus Schoutsen
bccd880395 Fix canary flaky test (#11519) 2018-01-07 15:05:19 -08:00
Anders Melchiorsen
8267a21bfe Lazy loading of service descriptions (#11479)
* Lazy loading of service descriptions

* Fix tests

* Load YAML in executor

* Return a copy of available services to allow mutations

* Remove lint

* Add zha/services.yaml

* Only cache descriptions for known services

* Remove lint

* Remove description loading during service registration

* Remove description parameter from async_register

* Test async_get_all_descriptions

* Remove lint

* Fix typos from multi-edit

* Remove unused arguments

* Remove unused import os

* Remove unused import os, part 2

* Remove unneeded coroutine decorator

* Only use executor for loading files

* Cleanups suggested in review

* Increase test coverage

* Fix races in existing tests
2018-01-07 14:54:16 -08:00
Dan Nixon
3cbd77f6ac Add Dark Sky weather component (#11435) 2018-01-07 13:59:32 -08:00
tschmidty69
4a6b5ba02b Snips (new) added speech response, parse snips/duration (#11513)
* Snips changed to using <username>:intentName instead of user_IDSTRING__intentName

* added response to snips

* blank line

* added unittests

* houndy

* sdtuff

* more stuff

* Update test_snips.py

* Update snips.py

* Split log tests to avoid dict ordering in py34

* Update test_snips.py

* Update test_snips.py

* still broken

* fixed tests

* fixed tests

* removed fix submitted in another PR
2018-01-07 13:42:08 -08:00
Julius Mittenzwei
efb83dde19 More tolerant KNX component if gateway cant be connected (#11511)
* Issue #11432: Do not stop initializing KNX when tunelling device cant be reached

*  Issue #11432: Mark devices as unavailable if gateway cant be connected
2018-01-07 13:39:14 -08:00
Julio Guerra
c20324793e timer: include the remaining time in the state attributes (#11510)
Add the amount of remaining time before a timer is finished in its state attributes, so that it is received when fetching a timer state.

In my particular case, it allows me to correctly implement a UI for a timer when it is paused and when the UI didn't received the pause state change (which happens when the UI is started after the pause). In this case, it is impossible to show the remaining amount of time before the timer ends.
2018-01-07 13:37:19 -08:00
Julian Kahnert
4496ee5af0 upgrade schiene to 0.20 (#11504) 2018-01-07 14:57:26 +01:00
Christopher Viel
e42c4859c2 Upgrade pywebpush to 1.5.0 (#11497)
This version includes a fix for the serialization errors that occurred
when updating push subscriptions.

Changes since version 1.3.0:
https://github.com/web-push-libs/pywebpush/compare/1.3.0...28d2b55f
2018-01-06 21:08:11 -08:00
Tom Waters
939d1b5ff6 Fix time functions would throw errors in python scripts (#11414)
* Fix time functions would throw errors in python scripts

* Added unit test for time.strptime, change variable name to satisfy lint

* Added docstring for time attribute wrapper method to satisfy lint

* Fixed line too long lint problem
2018-01-07 01:50:55 +01:00
Paulus Schoutsen
5c2cecde70 Clean up Alexa.intent and DialogFlow.intent (#11492)
* Clean up Alexa.intent

* Restructure dialogflow too

* Lint

* Lint
2018-01-07 01:39:32 +01:00
Fabian Affolter
c613585100 Add missing configuration variables (#11390)
* Add missing configuration variables

* Minor changes

* Sync platforms and other minor updates
2018-01-06 21:53:14 +01:00
Jesse Hills
3fbf09e7d9 Add new iGlo component (#11171)
* Add new iGlo component

* Missing comma
Add extra blank lines

* Dont change state in turn_on
Remove unused variables
Update before add

* Fixing some lint issues
2018-01-06 21:52:31 +01:00
Fabian Affolter
b22a26891e Upgrade pysnmp to 4.4.4 (#11485) 2018-01-06 19:54:15 +01:00
abondoe
a0df165011 Add Touchline climate platform (#10547)
* Add toucline platform

* Fix bugs suggested by houndci-bot

* Fix bugs suggested by houndci-bot

* Fix style based on comments and lint

* Remove target temperature

* Fix unexpected EOF

* Fix unexpected EOF

* Fix wrongfully named numberOfDevices variable

* Add target temperature

* Update requirements_all.txt

* Change after review

* Add supported features
* Remove update in constructor
* Set member variables to none in constructor

* Minor changes
2018-01-06 11:23:24 +01:00
Fabian Affolter
f6307a1523 Upgrade yarl to 0.17.0 (#11478) 2018-01-06 09:42:09 +01:00
Paulus Schoutsen
ff9688bb7a Fix vultr tests (#11477) 2018-01-05 16:34:03 -08:00
Fabian Affolter
c714658384 Upgrade alpha_vantage to 1.8.0 (#11476) 2018-01-05 16:05:51 -08:00
Fabian Affolter
f21914d1f3 Upgrade psutil to 5.4.3 (#11468) 2018-01-05 14:30:12 -08:00
hawk259
417c193c0d AlarmDecoder remove icon function as BinarySensorDevice handles it correctly now (#11467)
* remove icon function as BinarySensorDevice handles it correctly now

* removing _type, not used
2018-01-05 14:29:57 -08:00
Christopher Viel
455c629f47 Don't duplicate html5 registrations (#11451)
* Don't duplicate html5 registrations

If a registration is posted and another registration with the same
endpoint URL exists, update that one instead. That way, we preserve
the device name that has been configured. The previous behavior used to
append 'unnamed device' registrations over and over, leading to
multiple copies of the same registration. The endpoint URL is unique per
service worker so it is safe to update matching registrations.

* Refactor html5 registration view to not write json in the event loop
2018-01-05 14:29:27 -08:00
Paulus Schoutsen
01896786fb Merge branch 'master' into dev 2018-01-05 13:10:29 -08:00
Paulus Schoutsen
c526fcd40f Merge pull request #11470 from home-assistant/release-0-60-1
0.60.1
2018-01-05 12:55:13 -08:00
Paulus Schoutsen
8b57777ce9 Alexa to not use customize for entity config (#11461)
* Alexa to not use customize for entity config

* Test Alexa entity config

* Improve tests

* Fix test
2018-01-05 12:33:22 -08:00
Matt N
b61197196e iOS 10 should be served javascript_version:es5 (#11387)
* iOS 10 should be served javascript_version:es5

Fixes #11234

* Update min Safari version to 12
2018-01-05 11:29:20 -08:00
Pascal Vizeli
e0a1b87296 Don't block on sevice call for alexa (#11358)
* Don't block on sevice call for alexa

* fix tests
2018-01-05 11:29:19 -08:00
Greg Laabs
d3ed6d5242 Fix leak sensors always showing Unknown until Wet (#11313)
Leak sensors were using the "wet" node as a negative node, which prevented them from ever gettng a Dry status unless the user pressed the button on the hardware after every Hass reboot.

This change ignores the Wet node, as it is just always the exact inverse of the Dry node. We don't need to watch both.
2018-01-05 11:29:19 -08:00
Bob Anderson
5d6455415e Fix unpredictable entity names in concord232 binary_sensor (#11292) 2018-01-05 11:29:18 -08:00
maxlaverse
a27b37be59 Fix allday events in custom_calendars (#11272) 2018-01-05 11:29:18 -08:00
Zio Tibia
f6a67d99e4 Fix handling zero values for state_on/state_off (#11264) 2018-01-05 11:29:17 -08:00
CTLS
486263fff7 Fix inverted sensors on the concord232 binary sensor component (#11261)
* Fix inverted sensors on the concord232 binary sensor component

* Changed from == Tripped to != Normal
2018-01-05 11:29:17 -08:00
Andrea Campi
5a469f4d4b Support multiple Hue bridges with lights of the same id (#11259)
* Improve support for multiple Hue bridges with lights that have the same id.

The old code pre-refactoring kept a per-bridge list of lights in a closure; my refactoring moved that to hass.data, which is convenient but caused them to conflict with each other.

Fixes #11183

* Update test_hue.py
2018-01-05 11:29:16 -08:00
Pascal Vizeli
889eef78e4 Bugfix homematic available modus (#11256) 2018-01-05 11:29:16 -08:00
Greg Laabs
794cfb7976 Fix detection of if a negative node is in use (#11255)
* Fix detection of if a negative node is in use

Fix a problem where every negative node gets detected as in-use. Code was not checking the correct property.

* Allow protected access
2018-01-05 11:29:15 -08:00
Daniel Watkins
9055922153 Fix webostv select source (#11227)
* Fix reuse of variable name

This should fix #11224.

* Add tests for LgWebOSDevice.select_source
2018-01-05 11:29:15 -08:00
Janne Grunau
2330268842 homematic: add username and password to interface config schema (#11214)
Fixes #11191, the json-rpc name resolving method requires user account
and password.
2018-01-05 11:29:15 -08:00
maxlaverse
e81d17dae0 Fix webdav calendar schema (#11185) 2018-01-05 11:29:14 -08:00
Ben Randall
5820bab9b1 Fix async IO in Sesame lock component. (#11054)
* Call update on Sesame devices to cache initial state

* Switch to using async_add_devices

* Fix line length

* Fix Lint errors

* Fix more Lint errors

* Cache pysesame properties

* Updates from CR feedback
2018-01-05 11:29:14 -08:00
Paulus Schoutsen
3a00c3de64 Version bump to 0.60.1 2018-01-05 11:28:39 -08:00
Matt N
71fb7a6ef6 iOS 10 should be served javascript_version:es5 (#11387)
* iOS 10 should be served javascript_version:es5

Fixes #11234

* Update min Safari version to 12
2018-01-05 11:28:03 -08:00
Daniel Høyer Iversen
65d841c3a6 Update PULL_REQUEST_TEMPLATE.md (#11465)
* Update PULL_REQUEST_TEMPLATE.md

* Add period
2018-01-05 18:31:41 +01:00
William Scanlon
5236b720ab Catch everything when calling to OctoPrint API to fix #10557 (#11457) 2018-01-05 18:07:09 +01:00
Thibault Cohen
ebbdce1f42 Update hydroquebec component to use hass httpsession (#11412)
* Update hydroquebec component to use hass httpsession

* Remove blank line
2018-01-05 10:22:40 +01:00
cdce8p
1490ccf7fb Updated gitignore file (#11452) 2018-01-05 00:03:32 -08:00
cdce8p
642e9c53ba Input Boolean - Deleted 'DEFAULT_INITIAL' (#11453) 2018-01-05 00:03:00 -08:00
cdce8p
1e9e6927eb Input Select - Added service description (#11456) 2018-01-05 00:02:10 -08:00
Paulus Schoutsen
b7c7041873 Add some tests to the cloud component (#11460) 2018-01-04 21:40:18 -08:00
Thijs de Jong
35f35050ff Set tahoma cover scan interval to 60 seconds (#11447)
* Increase tahoma scan interval to 60

* import timedelta

* fix lint
2018-01-05 01:02:31 +01:00
PhracturedBlue
6cb02128b4 Reconnect to alarmdecoder on disconnect (#11383)
* Reconnect to alarmdecoder on disconnect

* Use track_point_in_time instead of call_later

* use alarmdecoder 1.13.2 which has a more robust reconnection fix
2018-01-04 20:10:56 +01:00
Marius
3436676de2 Updated generic thermostat to respect operation_mode and added away mode (#11445)
* Updated generic thermostat to respect operation_mode and added away mode

* Updated tests to include away mode and corrected init problem for sensor state
Added more tests to improve coverage and corrected again lint errors
Fixed new test by moving to correct package
Fixed bug not restoring away mode on restart

* Added support for idle on interface through state

* Added back initial_operation_mode and modified away_temp to be only one for now

* Fixed houndci-bot errors

* Added back check for None on restore temperature

* Fixed failing tests as well

* Removed unused definitions from tests

* Added use case for no initial temperature and no previously saved temperature
2018-01-04 19:05:11 +01:00
Frantz
04de22613c Added new climate component from Daikin (#10983)
* Added Daikin climate component

* Fixed tox & hound

* Place up the REQUIREMENTS var

* Update .coveragerc

* Removed unused customization

* Prevent setting invalid operation state

* Fixed hound

* Small refactor according to code review

* Fixed latest code review comments

* Used host instead of ip_address

* No real change

* No real change

* Fixed lint errors

* More pylint fixes

* Shush Hound

* Applied suggested changes for temperature & humidity settings

* Fixed hound

* Fixed upper case texts

* Fixed hound

* Fixed hound

* Fixed hound

* Removed humidity since even the device has the feature it cant be set from API

* Code review requested changes

* Fixed hound

* Fixed hound

* Trigger update after adding device

* Added Daikin sensors

* Fixed hound

* Fixed hound

* Fixed travis

* Fixed hound

* Fixed hound

* Fixed travis

* Fixed coverage decrease issue

* Do less API calls and fixed Travis failures

* Distributed code from platform to climate and sensor componenets

* Rename sensor state to device_attribute

* Fixed hound

* Updated requirements

* Simplified code

* Implemented requested changes

* Forgot one change

* Don't allow customizing temperature unit and take it from hass (FOR NOW)

* Additional code review changes applied

* Condensed import even more

* Simplify condition check

* Reordered imports

* Disabled autodiscovery FOR NOW :(

* Give more suggestive names to sensors
2018-01-04 11:05:27 +01:00
Paulus Schoutsen
2cf5acdfd2 Google Assistant -> Google Actions (#11442) 2018-01-03 17:26:58 -08:00
Andrey
4512a972d1 Climate: fix missing "|" (#11441)
* Add on/off supported feature to climate

* Lint

* Fix missing |

* lint
2018-01-04 02:26:11 +02:00
cdce8p
65df6f0013 Fix CONF_FRIENDLY_NAME (#11438) 2018-01-03 23:52:36 +01:00
Andrey
eb00e54eba Add on/off supported feature to climate (#11379)
* Add on/off supported feature to climate

* Lint
2018-01-03 23:10:54 +01:00
Steve Easley
ec700c2cd6 Fix errors in zigbee push state (#11386)
* Fix errors in zigbee push state

* Fix formatting

* Added comment
2018-01-03 12:48:36 -08:00
Daniel Claes
75a39352ff fix: hmip-etrv-2 now working with homeassistant (#11175)
* fix: hmip-etrv-2 now working with homeassistant (see also pull request at pyhomematic)

* fix linting issue and typo

* address comment @pvizeli

* Only use cached data in current operation mode

* fix linting issue
2018-01-03 19:36:25 +01:00
Ryan McLean
36c7fbe06a Plex api update (#11423)
* Updated plexapi to 3.0.5

* Removed removed server obj that was being used for the media URL generation as .url() is available in self._session
seasons() no longer exists -> renamed to season()
season() returns obj not list so corrected
season.index returns int, cast to str to zerofill

* Fixed Linting
2018-01-03 19:28:43 +01:00
Dave Finlay
bb2191b2b0 Add support for the renaming of Yamaha Receiver Zones via configuration file. Added a test to cover the change, plus previously untested options. (#11402) 2018-01-03 19:25:16 +01:00
Paulus Schoutsen
f314b6cb6c Cloud Updates (#11404)
* Verify stored keys on startup

* Handle Google Assistant messages

* Fix tests

* Don't verify expiration when getting claims

* Remove email based check

* Lint

* Lint

* Lint
2018-01-03 19:16:59 +01:00
Trevor Joynson
86e1d0f952 Account for User-Agent being non-existent, causing a TypeError (#11064)
* Account for User-Agent being non-existent, causing a TypeError

* Actually fix case of no user-agent with last resort

* Return es5 as last resort

* Update __init__.py

* Update __init__.py
2018-01-02 16:42:41 -08:00
Anders Melchiorsen
02c3ea1917 Silence redundant warnings about slow setup (#11352)
* Downgrade slow domain setup warning

* Revert "Downgrade slow domain setup warning"

This reverts commit 64472c006bb553c6bb75a024384361adad50d565.

* Remove warning for entity components

* Remove lint

* Fix original test with extra call
2018-01-02 12:16:32 -08:00
tomaszduda23
0a67195529 Fixing OpenWeatherMap Sensor. Current weather is 'unknown' if forecast: false. It was reported as #8640. (#11417) 2018-01-02 20:54:06 +01:00
Anders Melchiorsen
feb70b47df Performance optimization of TP-Link switch (#11416) 2018-01-02 19:31:33 +01:00
Lukas Barth
909f613324 Do not purge the most recent state for an entity (#11039)
* Protect states that are the most recent states of their entity

* Also protect events

* Some documentation

* Fix SQL
2018-01-01 18:43:10 -08:00
Dan Nixon
f0bf7b0def More support for availability reporting on MQTT components (#11336)
* Abstract MQTT availability from individual components

- Moved availability topic and payloads to MQTT base schema.
- Updated components that already report availability:
  - Switch
  - Binary sensor
  - Cover

* Add availability reporting to additional MQTT components

- Light
- JSON light
- Template light
- Lock
- Fan
- HVAC
- Sensor
- Vacuum
- Alarm control panel

* Annotate MQTT platform coroutines
2018-01-01 18:32:29 -08:00
Marius
541707c3e7 Removed status block to allow https://github.com/home-assistant/home-assistant-polymer/pull/766 with no impact (#11345) 2018-01-01 18:22:27 -08:00
Mitko Masarliev
add89d6973 Notify webos timeout error fix (#11027)
* use smaller icon

* add timeout option

* remove default icon, remove timeout option

* add image again
2018-01-01 18:19:49 -08:00
NotoriousBDG
e2cec9b3ae Move IMAP Email Content body to an attribute (#11096)
* Move IMAP Email Content body to an attribute

* Fix variable names
2018-01-01 18:09:40 -08:00
Paulus Schoutsen
0f914b4c20 Update frontend to 20180102.0 2018-01-01 17:20:27 -08:00
Paulus Schoutsen
1b4be0460c Log exceptions that happen during service call (#11394)
* Log exceptions that happen during service call

* Lint
2018-01-01 15:32:39 -08:00
Greg Dowling
cb899a9465 Bump pywemo to fix request include problems. (#11401) 2018-01-01 15:32:26 -08:00
Otto Winter
b362017206 Upgrade pychromecast to 1.0.3 (#11410) 2018-01-01 14:52:36 -08:00
Paulus Schoutsen
6e63a4ed8a Fix broken tests (#11395)
* Do not leave remember the milk config file behind

* Fix exception in service causing service timeout

* Change max service timeout to 9 to catch services timing out

* Fix Google Sync service test

* Update and pin test requirements
2018-01-01 14:30:09 -08:00
Kane610
b9c852392c Add deCONZ component (#10321)
* Base implementation of component, no sensors yet

* Added senor files

* First fully working chain of sensors and binary sensors going from hardware in to hass

* Clean up

* Clean up

* Added light platform

* Turning lights on and off and set brightness now works

* Pydeconz is now a proper pypi package
Stop sessions when Home Assistant is shutting down
Use a simpler websocket client

* Updated pydocstrings
Followed recommendations from pylint and flake8

* Clean up

* Updated requirements_all.txt

* Updated Codeowners to include deconz.py
Also re-added the Axis component since it had gotten removed

* Bump requirement

* Bumped to v2
Reran script/gen_requirements

* Removed global DECONZ since it wasn't relevant any more

* Username and password is only relevant in the context of getting a API key

* Add support for additional sensors

* Added support for groups

* Moved import of component library to inside of methods

* Moved the need for device id to library

* Bump pydeconz to v5

* Add support for colored lights

* Pylint and flake8 import improvements

* DATA_DECONZ TO DECONZ_DATA

* Add support for transition time

* Add support for flash

* Bump to v7

* ZHASwitch devices will now only generate events by default, instead of being a sensor entity

* Clean up

* Add battery sensor when device signals through an event

* Third-party library communicates with service

* Add support for effect colorloop

* Bump to pydeconz v8

* Same domain everywhere

* Clean up

* Updated requirements_all

* Generated API key will now be stored in a config file

* Change battery sensor to register to callback since library now supports multiple callbacks
Move DeconzEvent to hub
Bump to v9

* Improve entity attributes

* Change end of battery name to battery level
No need for static icon variable when using battery level helper

* Bump requirement to v10

* Improve pydocstring for DeconzEvent
Rename TYPE_AS_EVENT to CONF_TYPE_AS_EVENT

* Allow separate brightness to override RGB brightness

* Expose device.reachable in entity available property

* Bump requirement to 11 (it goes up to 11!)

* Pylint comment

* Binary sensors don't have unit of measurement

* Removed service to generate API key in favor of just generating it as a last resort of no API key is specified in configuration.yaml or deconz.conf

* Replace clear text to attribute definitions

* Use more constants

* Bump requirements to v12

* Color temp requires xy color support

* Only ZHASwitch should be an event

* Bump requirements to v13

* Added effect_list property

* Add attribute to battery sensor to easy find event id

* Bump requirements to v14

* Fix hound comment

* Bumped requirements_all information to v14

* Add service to configure devices on deCONZ

* Add initial support for scenes

* Bump requirements to v15

* Fix review comments

* Python doc string improvement

* Improve setup and error handling during setup

* Changed how to evaluate light features

* Remove 'ghost' events by not triggering updates if the signal originates from a config event
Bump requirement to v17

* Fix pylint issue by moving scene ownership in to groups in requirement pydeconz
Bump requirement to v18

* Added configurator option to register to deCONZ when unlocking gateway through settings
Bump requirement to v20

* Improve async configurator

* No user interaction for deconz.conf

* No file management in event loop

* Improve readability of load platform

* Fewer entity attributes

* Use values() instead of items() for dicts where applicable

* Do one add devices per platform

* Clean up of unused attributes

* Make sure that discovery info is not None

* Only register configure service and shutdown service when deconz has been setup properly

* Move description

* Fix lines longer than 80

* Moved deconz services to a separate file and moved hub to deconz/__init__.py

* Remove option to configure switch as entity

* Moved DeconzEvent to sensor since it is only Switch buttonpress that will be sent as event

* Added support for automatic discovery of deconz
Thanks to Kroimon for adding support to netdisco

* Use markup for configuration description

* Fix coveragerc

* Remove deCONZ support from Hue component

* Improved docstrings and readability

* Remove unnecessary extra name for storing in hass.data, using domain instead

* Improve readability by renaming all async methods
Bump to v21 - improved async naming on methods

* Fix first line not being in imperative mood

* Added logo to configurator
Let deconz.conf be visible since it will be the main config for the component after initial setup

* Removed bridge_type from new unit tests as part of removing deconz support from hue component

* Capitalize first letters of Battery Level

* Properly update state of sensor as well as reachable and battery
Bump dependency to v22

* Fix flake8 Multi-line docstring closing quotes should be on a separate line

* Fix martinhjelmares comments

Bump dependency to v23
Use only HASS aiohttp session
Change when to use 'deconz' or domain or deconz data
Clean up unused logger defines
Remove unnecessary return values
Fix faulty references to component documentation
Move callback registration to after entity has been initialized by HASS
Less inception style on pydocs ;)
Simplify loading platforms by using a for loop
Added voluptous schema for service
Yaml file is for deconz only, no need to have the domain present
Remove domain constraint when creating event title
2018-01-01 17:08:13 +01:00
Jeroen ter Heerdt
976a0fe38c Adding support for Egardia / Woonveilig version GATE-03 (#11397) 2018-01-01 02:10:52 +01:00
Paulus Schoutsen
fc8b25a71f Clean up Google Assistant (#11375)
* Clean up Google Assistant

* Fix tests
2017-12-31 15:04:49 -08:00
Dan Nixon
fcbf7abdaa Reverts unit conversions in TP-Link bulb (#11381)
Reverts energy and power unit conversions added in #10979 as they break
early devices.

A proper fix should be implemented in the pyhs100 library which should
return common units across all devices/firmwares.
2017-12-31 15:58:22 +01:00
ChristianKuehnel
7759ab6919 Remember the Milk - updating and completing tasks (#11069)
* Remember the Milk - updating and completing tasks

Added new feature so that tasks can be updated and completed.
For this feature a task id must be set when creating the task.

* fixed hould complaints

* fixed review comments by @MartinHjelmare

* removed unnecessary check as proposed by @MartinHjelmare
2017-12-29 19:20:36 +01:00
William Scanlon
3fd620198e Support for EcoNet water heaters (#11260)
* Support for EcoNet water heaters.

* Fixed requested changes.

* Added logging when temp or operation mode are None

* More fixes from PR review.

* Updated pyeconet version to fix natural gas water heater error. Last PR review fix.
2017-12-29 19:05:58 +01:00
Pascal Vizeli
49bc95549b Don't block on sevice call for alexa (#11358)
* Don't block on sevice call for alexa

* fix tests
2017-12-29 09:44:06 -08:00
Thibault Cohen
ba0f7a4101 Fido component use now asyncio (#11244)
* Fido component use now asyncio

* Fix comments

* Fix comments 2

* Fix assertion for test error

* Update to pyfido 2.1.0
2017-12-29 18:33:11 +01:00
tschmidty69
4914ad1dd9 Ping device tracker now respects interval_seconds (#11348)
* Ping device tracker now respects interval_seconds
2017-12-29 16:18:39 +01:00
Dan Nixon
f07a4684e0 Fix RGB template ordering in MQTT Light (#11362)
* Use different colour channel intensities in tests

Uses a different value for each colour channel in MQTT light tests to
properly differentiate between colour channels.

* Correct ordering of RGB channels in MQTT light
2017-12-29 15:28:20 +01:00
Paulus Schoutsen
cfd78f7b02 Add HTTP endpoint for resending email confirmation (#11354) 2017-12-29 14:46:10 +01:00
Dan Nixon
2a2e6b6334 Correct units used in TP-Link energy monioring (#10979)
* Correct units used in TP-Link energy monioring

- Energy is measured in kWh for swtches
- Power is reported in mW for bulbs
- Energy is reported in Wh for bulbs

* TP-Ling energy: store units in attribute names

Stores the unit in the attrbute names for TP-Link devices that support
energy monitoring.
2017-12-29 13:13:15 +01:00
Fabian Affolter
b635637541 Upgrade youtube_dl to 2017.12.28 (#11357) 2017-12-29 10:16:18 +01:00
Fabian Affolter
a7ebba6863 Upgrade python-telegram-bot to 9.0.0 (#11341) 2017-12-29 10:08:14 +01:00
Fabian Affolter
1f8acb49bc Upgrade mypy to 0.560 (#11334) 2017-12-29 10:07:25 +01:00
Fabian Affolter
5a4bca9780 Upgrade sqlalchemy to 1.2.0 (#11333) 2017-12-29 10:07:04 +01:00
Fabian Affolter
d7e52d8014 Upgrade pyowm to 2.8.0 (#11332) 2017-12-29 10:06:52 +01:00
Fabian Affolter
391a8901c8 Upgrade fuzzywuzzy to 0.16.0 (#11331) 2017-12-29 10:06:39 +01:00
Fabian Affolter
b98e03b5bc Upgrade aiohttp to 2.3.7 (#11329) 2017-12-29 10:06:25 +01:00
Andy Castille
6b586c268a DoorBird feature update (#11193)
* Allow disabling the DoorBird camera live view

* Support for push notifications from DoorBird devices

* use DoorBirdPy 0.1.1 instead of 0.1.0

* Fix lint errors in DoorBird binary sensor

* Change DoorBird push notifications from binary sensor to event

* Remove DoorBird camera options

* use DoorBirdPy 0.1.2 to fix history image urls

* clean up doorbird event code and remove unused doorbird camera imports

* use async for doorbird doorbell events

* Minor changes

* Update file header

* Fix my mess

* Fix docstring
2017-12-29 10:05:45 +01:00
goldminenine
9a34e7174c Update modbus.py (#11238)
Support of MODBUS RTU over TCP ethernet mode. See more description here:  https://www.eltima.com/modbus-over-ethernet/
2017-12-29 09:19:34 +01:00
Fabian Affolter
3203849b60 Move data instance to setup (#11350) 2017-12-29 09:03:03 +01:00
Thom Troy
2e582a4597 pass stops_at to get_station_by_name (#11304) 2017-12-28 22:37:51 +01:00
Gregory Benner
5d38eec37d Sochain cryptocurrency sensor (#11335)
* add required files

* add sochain sensor

* add missing schema

* end first sentence with a period to make travis happy

* upgrade to python-sochain-api 0.0.2 and use asyncio

* add missing _LOGGER and fix long line

* move object setup to async_setup_platform

* rename chainSo variable to chainso
2017-12-28 21:39:24 +01:00
Dan Nixon
a6c7fe04da Add default names and validation for TP-Link devices (#11346)
Adds missing platform schema for TP-Link smart sockets and adds default
names for smart sockets and bulbs.
2017-12-28 21:22:46 +01:00
Jeroen ter Heerdt
966ab20f26 Remove need for separate EgardiaServer setup (#11344)
* Removing need for separate Egardiaserver setup

* Fixing linting errors

* Updating egardia component based on review

* Updating egardia component based on review

* Updating egardia component based on review

* Removed return False twice based on review
2017-12-28 20:20:44 +01:00
Matt Schmitt
b2e9dc5c8f Additional device classes for binary sensors (#11280)
* Add additional device classes for binary sensor
2017-12-28 18:55:22 +01:00
Lukas Barth
fc3a8e4e79 Merge pull request #10535 from broox/nuheat
Adding a Nuheat Thermostat component
2017-12-28 09:14:27 +01:00
Derek Brooks
00352d41a7 remove return value as requested 2017-12-27 18:20:12 -08:00
Derek Brooks
29c26e0015 fix bad nuheat component test 2017-12-27 13:06:04 -08:00
Derek Brooks
63d9bd4a9c test resume program service 2017-12-27 12:42:56 -08:00
Bob Igo
cb23549af6 closes #11314 by not restricting the voice to anything but a string (#11326) 2017-12-27 19:49:06 +01:00
Rene Nulsch
e5cc5a58e1 Bugfix for HA Issue 7292, 9412 - switch to gamertag to receive ssl image url (#11315) 2017-12-27 09:24:37 +01:00
Greg Laabs
aa8db784d5 Fix leak sensors always showing Unknown until Wet (#11313)
Leak sensors were using the "wet" node as a negative node, which prevented them from ever gettng a Dry status unless the user pressed the button on the hardware after every Hass reboot.

This change ignores the Wet node, as it is just always the exact inverse of the Dry node. We don't need to watch both.
2017-12-27 09:23:21 +01:00
Fabian Affolter
d68d4d1129 Upgrade alpha_vantage to 1.6.0 (#11307) 2017-12-27 09:21:28 +01:00
Fabian Affolter
8d32e883bd Upgrade youtube_dl to 2017.12.23 (#11308) 2017-12-27 09:21:07 +01:00
Fabian Affolter
7826b9aa72 Upgrade python-digitalocean to 1.13.2 (#11311) 2017-12-27 09:20:44 +01:00
Fabian Affolter
e91d47db96 Upgrade distro to 1.2.0 (#11312) 2017-12-27 09:20:08 +01:00
Fabian Affolter
e92e433805 Upgrade yahooweather to 0.10 (#11309) 2017-12-27 09:19:46 +01:00
Fabian Affolter
40e1d35268 Upgrade luftdaten to 0.1.3 (#11316) 2017-12-27 09:19:02 +01:00
Fabian Affolter
af6c39f4d1 Upgrade pysnmp to 4.4.3 (#11317) 2017-12-27 09:17:43 +01:00
Fabian Affolter
5be949f00f Upgrade aiohttp_cors to 0.6.0 (#11310) 2017-12-27 09:17:03 +01:00
Mitko Masarliev
169459b57f Fix for track_new_devices BC (#11202)
* BC fix

* more tests

* inline if change

* inline if change
2017-12-26 14:49:24 -08:00
Conrad Juhl Andersen
05926b1994 xiaomi_aqara: Fix covers never being closed (#11319)
Bug in equality testing
2017-12-26 23:35:48 +01:00
awkwardDuck
54b4142530 Fix typo in bitcoin.py component for mined blocks. (#11318) 2017-12-26 22:02:59 +01:00
Derek Brooks
f0244d7982 add a bit more test coverage 2017-12-26 11:12:28 -08:00
Paulus Schoutsen
7a600ea064 Add heartbeat to websocket connections (#11298) 2017-12-26 10:59:41 +01:00
Greg Laabs
d687bc073e Huge ISY994 platform cleanup, fixes support for 5.0.10 firmware (#11243)
* Huge ISY994 platform cleanup, fixes support for 5.0.10 firmware

# * No more globals - store on hass.data
# * Parent ISY994 component handles categorizing nodes in to Hass components, rather than each individual domain filtering all nodes themselves
# * Remove hidden string, replace with ignore string. Hidden should be done via the customize block; ignore fully prevents the node from getting a Hass entity
# * Removed a few unused methods in the ISYDevice class
# * Cleaned up the hostname parsing
# * Removed broken logic in the fan Program component. It was setting properties that have no setters
# * Added the missing SUPPORTED_FEATURES to the fan component to indicate that it can set speed
# * Added better error handling and a log warning when an ISY994 program entity fails to initialize
# * Cleaned up a few instances of unecessarily complicated logic paths, and other cases of unnecessary logic that is already handled by base classes

* Use `super()` instead of explicit base class calls

* Move `hass` argument to first position

* Use str.format instead of string addition

* Move program structure building and validation to component

Removes the need for a bunch of duplicate exception handling in each individual platform

* Fix climate nodes, fix climate names, add config to disable climate

Sensor platform was crashing when the ISY reported climate nodes. Logic has been fixed. Also added a config option to prevent climate sensors from getting imported from the ISY. Also replace the underscore from climate node names with spaces so they default to friendly names.

* Space missing in error message

* Fix string comparison to use `==`

* Explicitly check for attributes rather than catch AttributeError

Also removes two stray debug lines

* Remove null checks on hass.data, as they are always null at this point
2017-12-26 09:26:37 +01:00
Mike Megally
a59b02b6b4 Removed error log used as debug (#11301)
An error was being logged to display debug info. Removed it
2017-12-25 20:49:02 +01:00
Frantz
14919082a3 Better error handling (#11297)
* Better error handling

* Fixed hound
2017-12-25 17:46:42 +01:00
Bob Anderson
802a95eac5 Fix unpredictable entity names in concord232 binary_sensor (#11292) 2017-12-25 13:26:22 +01:00
Michael Irigoyen
a44181fd35 Add Chime status and control to Alarm Decoder component (#11271)
* Enable more alarm decoder attributes, including chime status and ready status

* Expose chime service in the alarm decoder component

* Fix line length linting issue

* Fix spacing lint issue

* Update PR based on reviewer requests

* Update based on linting catches

* Fix descriptions include from async to sync
2017-12-25 11:34:07 +01:00
PhracturedBlue
b280a791a6 Store raw state of RF sensors from alarmdecoder (#10841)
* Store raw state of RF sensors from alarmdecoder

* Fix resync.  Fix issue with RFID not being truly optional

* Breakdown RF attributes per bit

* Preserve import style
2017-12-25 10:52:33 +01:00
Jordy
7269070d97 Added rainsensor (#11023)
* Added rainsensor

Added rainsensor

* Added to coverage ignore

* Fixed issues

* script\gen_requirements_all.py

script\gen_requirements_all.py

* Gen requirements

* requirements

* requirements

* Fix docstring

* Fix log message

* Revert change
2017-12-25 10:07:17 +01:00
Phil Kates
94ac0b5ed8 alexa: Add handling for covers (#11242)
* alexa: Add handling for covers

Covers don't support either cover.turn_on or homeassistant.turn_on so
use cover.[open|close]_cover.

* alexa: Add tests for covers
2017-12-24 15:05:56 -08:00
Derek Brooks
8ef8dbc868 pleasin the hound 2017-12-24 11:15:50 -07:00
Derek Brooks
7de3c62846 register nuheat_resume_program service 2017-12-24 11:10:22 -07:00
Derek Brooks
fb90dab471 add ability to change the Nuheat thermostat hold mode 2017-12-24 10:09:27 -07:00
Derek Brooks
419ec7f7a7 bump to python-nuheat 0.3.0 2017-12-24 09:43:56 -07:00
Derek Brooks
bdf64ccbbb Merge branch 'dev' into nuheat 2017-12-24 09:40:21 -07:00
Ryan McLean
3fa45375d9 Plex refactor (#11235)
* Cleaned up '_clear_media()'

* Moved media Type to new method

* renamed "clear_media()' to ' clear_media_details()'
reset 'app_name' (Library Name) in clear_media_details
moved thumbs to '_set_media_image()'

* Moved playback info into setmedia type as it was just used for the next anyway

* Moved library name & image download to only happen if session and player active as else no point anyway

* Fixed Linting issue

* Some tweaks to clean up unintended complexity

* Removed redundant declarations

* Fixed whitespace

* Revert "Fixed whitespace"

This reverts commit 0985445c478f42090d0ea9945b8ebc974ab983dc.

* Revert "Removed redundant declarations"

This reverts commit 6f9d5a85b03efffb4bca44613bcc45c3a71677cc.
2017-12-24 11:18:31 -05:00
Aaron Bach
5566ea8c81 Adds support for disabled Tiles and automatic session renewal (#11172)
* Adds support for disabled Tiles and automatic session renewal

* Updated requirements

* Collaborator-requested changes

* Collaborator-requested changes
2017-12-24 01:19:04 +01:00
Andrea Campi
8c303bf48c Support multiple Hue bridges with lights of the same id (#11259)
* Improve support for multiple Hue bridges with lights that have the same id.

The old code pre-refactoring kept a per-bridge list of lights in a closure; my refactoring moved that to hass.data, which is convenient but caused them to conflict with each other.

Fixes #11183

* Update test_hue.py
2017-12-24 01:12:54 +01:00
David Fiel
8683d75aa1 Greenwave Reality (TCP Connected) Lighting Component (#11282)
* Create greenwave.py

* Update .coveragerc

* Update requirements_all.txt

* Update greenwave.py

Line too long

* Update greenwave.py

* Update requirements_all.txt

* Update greenwave.py

* Update greenwave.py

* fix style
2017-12-24 01:11:45 +01:00
Andrey Kupreychik
4f5d7cea11 Added password for GPS logger endpoint (#11245)
* Added password for GPS logger endpoint

* Fixed lint error

* Update gpslogger.py

* fix lint

* fix import
2017-12-24 00:15:06 +01:00
Andrey
ab9ffc4f05 Report Sensibo as off when it is off (#11281) 2017-12-23 11:10:54 +01:00
Paulus Schoutsen
6e2bfcfe65 Update frontend to 20171223.0 2017-12-22 21:31:31 -08:00
Andrey
240098dd7e Change manifest path to /states as this is the path / actually sets. (#11274) 2017-12-22 21:05:15 -08:00
Daniel Watkins
353bb62687 Fix webostv select source (#11227)
* Fix reuse of variable name

This should fix #11224.

* Add tests for LgWebOSDevice.select_source
2017-12-22 18:38:00 +01:00
maxlaverse
46df91ff45 Fix allday events in custom_calendars (#11272) 2017-12-22 14:08:34 +01:00
Ben Randall
295caeb065 Fix async IO in Sesame lock component. (#11054)
* Call update on Sesame devices to cache initial state

* Switch to using async_add_devices

* Fix line length

* Fix Lint errors

* Fix more Lint errors

* Cache pysesame properties

* Updates from CR feedback
2017-12-22 10:28:51 +01:00
Egor Tsinko
eeb309aea1 Functinality to save/restore snapshots for monoprice platform (#10296)
* added functionality to save/restore snapshots to monoprice platform

* renamed monoprice_snapshot, monoprice_restore to snapshot, restore

This is to simplify refactoring of snapshot/restore functionality for monoprice, snapcast and sonos in the future
2017-12-22 10:26:34 +01:00
Pascal Vizeli
9e0a765801 Revert "Backup configuration files before overwriting" (#11269)
* Revert "Adding MotionIP to BinarySensors for HMIP-SMI (#11268)"

This reverts commit c94cc34a8f.

* Revert "Bugfix: 10509 - http is hard coded in plex sensor (#11072)"

This reverts commit 901d4b5489.

* Revert "Fix handling zero values for state_on/state_off (#11264)"

This reverts commit 2e4e3a42cc.

* Revert "Fix inverted sensors on the concord232 binary sensor component (#11261)"

This reverts commit b866687cd7.

* Revert "Proper Steam game names and small fixes (#11182)"

This reverts commit 7faa94046c.

* Revert "Bugfix homematic available modus (#11256)"

This reverts commit 1d579587c1.

* Revert "Fix detection of if a negative node is in use (#11255)"

This reverts commit b28bfad496.

* Revert "added myself to become code owner for miflora and plant (#11251)"

This reverts commit e0682044f0.

* Revert "Add workaround for running tox on Windows platforms (#11188)"

This reverts commit 81f1a65fae.

* Revert "Upgrade to new miflora version 0.2.0 (#11250)"

This reverts commit 8efc4b5ba9.

* Revert "homematic: add username and password to interface config schema (#11214)"

This reverts commit b4e2537de3.

* Revert "Backup configuration files before overwriting (#11216)"

This reverts commit 90e25a6dfb.
2017-12-21 22:33:37 +01:00
schnoetz
c94cc34a8f Adding MotionIP to BinarySensors for HMIP-SMI (#11268)
* Adding MotionIP to BinarySensors for HMIP-SMI

My HmIP-SMI (Homematic IP Motion Sensor) only shows "ILLUMINATION" and no MOTION, because the binary values are not recognized. The "old" homematic-motion detectors are working well showing motion, too. 
I found out that "MotionIP" was missing at the binary_sensors - after adding "Motion" and "Motion Detection Activated" are shown.

* Removed trailing blanks

removed trailing blanks from my previous change
2017-12-21 21:46:42 +01:00
Ryan McLean
901d4b5489 Bugfix: 10509 - http is hard coded in plex sensor (#11072)
* Fix for sensor no ssl

* Line length Fixes

* Removed unneeded schema extensions

* Removed unrequired variable

* Added defaults for SSL & SSL Verify

* Moved Defaults to Variables

Corrected SSL Defaults to match the other Defaults style

* Fixed Typo

* Removed option to disable verify ssl

* Removed unused import

* Removed unused CONST

* Fixed error handling

* Cleanup of unneeded vars & logging

* Fix for linting
2017-12-21 10:24:57 -05:00
Zio Tibia
2e4e3a42cc Fix handling zero values for state_on/state_off (#11264) 2017-12-21 14:24:19 +01:00
CTLS
b866687cd7 Fix inverted sensors on the concord232 binary sensor component (#11261)
* Fix inverted sensors on the concord232 binary sensor component

* Changed from == Tripped to != Normal
2017-12-21 06:29:42 +01:00
Frank Wickström
7faa94046c Proper Steam game names and small fixes (#11182)
* Use constant for offline state

* Use constant for no game name

* Rename trade and play constant their proper names

Trade and Play are not the correct names for the states. For instance
Play might be seens as the user is actually is playing, which is not
correct as there is no such state is returned from the Steam API.
Just having "trade" does not say much about what is happening and
might be misintepreted that the user is currently trading, which is not
correct either.

We instead use the names from the underlying library for naming the
states [1]

[1] 2e518ad84f/steam/user.py (L109)

* Get the proper game name if no extra info is given from the api

The third `current_game` parameter that was used before hold
extra information about the game that is being played. This might
contain the game name, it might also be empty. The correct way to
get the game name is to fetch it from the API depending on the
game id that might be returned in the `current_game` attribute if
the user is playing a game.

To not break existing implementations we keep the functionality
to first go with the extra information and only then fetch the proper
game name.

* Refactor getting game name to its own function

This cleans up the code and removed "ugly" else statements
from the sensor and makes the game fetching easier to read.

* Let state constant values be lower snake case

* Return None instead of 'None' when no current game exists

* Initialize steam app list only once to benefit form caching

* Return None as state attributes if no current game is present
2017-12-20 22:32:33 -05:00
Pascal Vizeli
1d579587c1 Bugfix homematic available modus (#11256) 2017-12-20 23:59:11 +01:00
Greg Laabs
b28bfad496 Fix detection of if a negative node is in use (#11255)
* Fix detection of if a negative node is in use

Fix a problem where every negative node gets detected as in-use. Code was not checking the correct property.

* Allow protected access
2017-12-20 23:58:22 +01:00
ChristianKuehnel
e0682044f0 added myself to become code owner for miflora and plant (#11251) 2017-12-20 12:11:56 +01:00
Ben Randall
81f1a65fae Add workaround for running tox on Windows platforms (#11188)
* Add workaround for running tox on Windows platforms

* Remove install_command override
2017-12-20 11:50:31 +01:00
ChristianKuehnel
8efc4b5ba9 Upgrade to new miflora version 0.2.0 (#11250) 2017-12-20 11:35:03 +01:00
Janne Grunau
b4e2537de3 homematic: add username and password to interface config schema (#11214)
Fixes #11191, the json-rpc name resolving method requires user account
and password.
2017-12-20 00:38:59 +01:00
Charles Garwood
90e25a6dfb Backup configuration files before overwriting (#11216)
* Backup configuration files before overwriting

* Changed timestamp format from epoch to iso8601 (minus punctuation)
2017-12-19 17:55:24 +01:00
Dan Chen
3d90855ca6 Bump python-miio version (#11232) 2017-12-19 08:22:13 +01:00
Dan Nixon
200c927087 Extend Threshold binary sensor to support ranges (#11110)
* Extend Threshold binary sensor to support ranges

- Adds support for ranges
- Threshold type (lower, upper, range) is defined by supplied
  thresholds (lower, upper)
- Adds verbose status/position relative to threshold as attribute
  (position)

* Minor changes (ordering, names, etc.)

* Update name

* Update name
2017-12-19 01:52:19 +01:00
markferry
ef22a6e18d Fix statistics sensor mean and median when only one sample is available. (#11180)
* Fix statistics sensor mean and median when only one sample is available.

With only one data point stddev and variance throw an exception.
This would clear the (valid) mean and median calculations.

Separate the try..catch blocks for one-or-more and two-or-more stats so
that this doesn't happen.

Test this with a new sampling_size_1 test.

* test_statistics trivial whitespace fix
2017-12-18 21:21:27 +01:00
Thibault Maekelbergh
061395d2f8 Add Discogs Sensor platform (#10957)
* Add Discogs Sensor platform

* Add discogs module to requirements_all

* Fix wrong style var name

* PR Feedback (scan interval, mod. docstring)

* Added sensor.discogs to coveragerc

* Use SERVER_SOFTWARE helper for UA-String

* Don't setup platform if token is invalid

* Fix trailing whitespace for Hound CI

* Move client setup to setup()
2017-12-18 19:10:54 +01:00
Khole
05258ea4bf Hive Component Release Two (#11053)
* Add boost functionality to climate devices

* Update boost target temperature rounding

* Update with Colour Bulb Support

* colour bulb fix

* Requirements Update and colorsys import

* Add RGB Attribute - ATTR_RGB_COLOR

* Hive release-2

* add boost support for hive climate platform

* Colour Bulb - Varible update

* Boost - Tox error

* Convert colour to color

* Correct over indentation

* update version to 0.2.9 pyhiveapi

* Updated pyhiveapi to version 2.10 and altertered turn_n on fuction to 1 call

* Update climate doc string

* Update to is_aux_heat_on

* update to is_aux_heat_on
2017-12-18 18:15:41 +01:00
Thibault Cohen
8742ce035a Hydroquebec component use now asyncio (#10795)
* Hydroquebec component use now asyncio

* Add tests

* Improve coverage

* fix tests

* Remove useless try/except and associated tests
2017-12-17 22:11:48 +01:00
maxlaverse
0664bf31a2 Fix webdav calendar schema (#11185) 2017-12-17 20:53:40 +01:00
Fabian Affolter
0ec1ff642d Bump dev to 0.61.0.dev0 2017-12-17 16:29:36 +01:00
Fabian Affolter
cd44824233 Merge branch 'master' into dev 2017-12-17 16:24:52 +01:00
Fabian Affolter
79240a0d47 Merge pull request #11153 from home-assistant/release-0-60
0.60
2017-12-17 15:44:41 +01:00
Brad Dixon
c03d04d826 Revbump to SoCo 0.13 and add support for Night Sound and Speech Enhancement. (#10765)
Sonos Playbar and Playbase devices support Night Sound and Speech Enhancement
effects when playing from sources such as a TV. Adds a new service "sonos_set_option"
whichs accepts boolean options to control these audio features.
2017-12-17 13:09:48 +01:00
Brad Dixon
dfb8b5a3c1 Revbump to SoCo 0.13 and add support for Night Sound and Speech Enhancement. (#10765)
Sonos Playbar and Playbase devices support Night Sound and Speech Enhancement
effects when playing from sources such as a TV. Adds a new service "sonos_set_option"
whichs accepts boolean options to control these audio features.
2017-12-17 13:08:35 +01:00
Mike Megally
432304be82 Remove logging (#11173)
An error was being log that seems more like debug info
2017-12-17 13:07:23 +01:00
PhracturedBlue
294d8171a2 convert alarmdecoder interface from async to sync (#11168)
* convert alarmdecoder interface from async to sync

* Convert he rest of alarmdecoder rom async to sync

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py
2017-12-17 13:07:23 +01:00
Pascal Vizeli
a46ddcf6dd Add install mode to homematic (#11164) 2017-12-17 13:07:23 +01:00
Paulus Schoutsen
5ca006cc9c Don't connect to cloud if subscription expired (#11163)
* Final touch for cloud component

* Fix test
2017-12-17 13:07:23 +01:00
Adam Mills
564ed26aeb Perform logbook filtering on the worker thread (#11161) 2017-12-17 13:07:22 +01:00
Pascal Vizeli
5860267410 Resolve hostnames (#11160) 2017-12-17 13:07:22 +01:00
Pascal Vizeli
ec9638f4d1 Homematic next (#11156)
* Cleanup logic & New gen of HomeMatic

* fix lint

* cleanup

* fix coverage

* cleanup

* name consistenc

* fix lint

* Rename ip

* cleanup wrong property

* fix bug

* handle callback better

* fix lint

* Running now
2017-12-17 13:07:22 +01:00
Matthew Treinish
7db8bbf385 Fix X10 commands for mochad light turn on (#11146)
* Fix X10 commands for mochad light turn on

This commit attempts to address issues that a lot of people are having
with the x10 light component. Originally this was written to use the
xdim (extended dim) X10 command. However, not every X10 dimmer device
supports the xdim command. Additionally, it turns out the number of
dim/brighness levels the X10 device supports is device specific and
there is no way to detect this (given the mostly 1 way nature of X10)

To address these issues, this commit removes the usage of xdim and
instead relies on using the 'on' command and the 'dim' command. This
should work on all x10 light devices. In an attempt to address the
different dim/brightness levels supported by different devices this
commit also adds a new optional config value, 'brightness_levels', to
specify if it's either 32, 64, or 256. By default 32 levels are used
as this is the normal case and what is documented by mochad.

Fixes #8943

* make code more readable

* fix style

* fix lint

* fix tests
2017-12-17 13:07:22 +01:00
Przemek Więch
024f1d4882 Try multiple methods of getting data in asuswrt. (#11140)
* Try multiple methods of getting data in asuswrt.

Solves #11108 and potentially #8112.

* fix style

* fix lint
2017-12-17 12:46:47 +01:00
PhracturedBlue
3375261f51 convert alarmdecoder interface from async to sync (#11168)
* convert alarmdecoder interface from async to sync

* Convert he rest of alarmdecoder rom async to sync

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py

* Update alarmdecoder.py
2017-12-17 00:52:59 +01:00
Matthew Treinish
640d58f0a8 Fix X10 commands for mochad light turn on (#11146)
* Fix X10 commands for mochad light turn on

This commit attempts to address issues that a lot of people are having
with the x10 light component. Originally this was written to use the
xdim (extended dim) X10 command. However, not every X10 dimmer device
supports the xdim command. Additionally, it turns out the number of
dim/brighness levels the X10 device supports is device specific and
there is no way to detect this (given the mostly 1 way nature of X10)

To address these issues, this commit removes the usage of xdim and
instead relies on using the 'on' command and the 'dim' command. This
should work on all x10 light devices. In an attempt to address the
different dim/brightness levels supported by different devices this
commit also adds a new optional config value, 'brightness_levels', to
specify if it's either 32, 64, or 256. By default 32 levels are used
as this is the normal case and what is documented by mochad.

Fixes #8943

* make code more readable

* fix style

* fix lint

* fix tests
2017-12-17 00:52:40 +01:00
Mike Megally
793b8b8ad3 Remove logging (#11173)
An error was being log that seems more like debug info
2017-12-16 22:29:40 +01:00
Pascal Vizeli
39af43eb5c Add install mode to homematic (#11164) 2017-12-16 14:22:23 +01:00
Paulus Schoutsen
b56675a7bb Don't connect to cloud if subscription expired (#11163)
* Final touch for cloud component

* Fix test
2017-12-16 00:42:25 -08:00
Adam Mills
c4d71e934d Perform logbook filtering on the worker thread (#11161) 2017-12-16 00:04:27 -08:00
Paulus Schoutsen
f4d7bbd044 Update frontend 2017-12-15 23:36:04 -08:00
Paulus Schoutsen
3d5d90241f Update frontend 2017-12-15 23:35:37 -08:00
Pascal Vizeli
a7c8e202aa Resolve hostnames (#11160) 2017-12-15 22:54:54 +01:00
Pascal Vizeli
a63658d583 Homematic next (#11156)
* Cleanup logic & New gen of HomeMatic

* fix lint

* cleanup

* fix coverage

* cleanup

* name consistenc

* fix lint

* Rename ip

* cleanup wrong property

* fix bug

* handle callback better

* fix lint

* Running now
2017-12-15 21:22:36 +01:00
Fabian Affolter
ca81180e6d Bump release to 0.60.0 2017-12-15 10:06:06 +01:00
Daniel Perna
de4c8adca2 Upgrade Homematic (#11149)
* Update pyhomematic

* Update pyhomematic
2017-12-15 00:34:27 +01:00
Paulus Schoutsen
823e260c2a Disable html5 notify dependency (#11135) 2017-12-14 00:15:25 -08:00
Greg Laabs
1c8b5838cd ISY994 sensor improvements (#10805)
* Fire events for ISY994 control events

This allows hass to react directly to Insteon button presses (on switches and remotes), including presses, double-presses, and long holds

* Move change event subscription to after entity is added to hass

The event handler method requires `self.hass` to exist, which doesn't have a value until the async_added_to_hass method is called. Should eliminate a race condition.

* Overhaul binary sensors in ISY994 to be functional "out of the box"

We now smash all of the subnodes from the ISY994 in to one Hass binary_sensor, and automatically support both paradigms of state reporting that Insteon sensors can do. Sometimes a single node's state represents the sensor's state, other times two nodes are used and only "ON" events are sent from each. The logic between the two forunately do not conflict so we can support both without knowing which mode the device is in.

This also allows us to handle the heartbeat functionality that certain sensors have - we simply store the timestamp of the heartbeat as an attribute on the sensor device. It defaults to Unknown on bootup if and only if the device supports heartbeats, due to the presence of subnode 4.

* Parse the binary sensor device class from the ISY's device "type"

Now we automatically know which sensors are moisture, motion, and openings! (We also reverse the moisture sensor state, because Insteon reports ON for dry on the primary node.)

* Code review tweaks

The one material change here is that the event subscribers were moved to the `async_added_to_hass` method, as the handlers depend on things that only exist after the entity has been added.

* Handle cases where a sensor's state is unknown

When the ISY first boots up, if a battery-powered sensor has not reported in yet (due to heartbeat or a change in state), the state is unknown until it does.

* Clean up from code review

Fix coroutine await, remove unnecessary exception check, and return None when state is unknown

* Unknown value from PyISY is now -inf rather than -1

* Move heartbeat handling to a separate sensor

Now all heartbeat-compatible sensors will have a separate `binary_sensor` device that represents the battery state (on = dead)

* Add support for Unknown state, which is being added in next PyISY 

PyISY will report unknown states as the number "-inf". This is implemented in the base ISY994 component, but subcomponents that override the `state` method needed some extra logic to handle it as well.

* Change a couple try blocks to explicit None checks

* Bump PyISY to 1.1.0, now that it has been published!

* Remove -inf checking from base component

The implementation of the -inf checking was improved in another branch which has been merged in to this branch already.

* Restrict negative-node and heartbeat support to known compatible types

Not all Insteon sensors use the same subnode IDs for the same things, so we need to use different logic depending on device type. Negative node and heartbeat support is now only used for leak sensors and open/close sensors.

* Use new style string formatting

* Add binary sensor detection for pre-5.x firmware

Meant to do this originally; writing documentation revealed that this requirement was missed!
2017-12-13 20:14:56 -08:00
BryanJacobs
3473ef63af Allow using more than one keyboard remote (#11061)
* Allow using more than one keyboard remote

This sets up one thread per keyboard remote, listening for events.

* Remove enclosing block in keyboard_remote

* Remove unnecessary semantic check for keyboard_remote
2017-12-13 20:07:23 -08:00
Michael Pollett
2cced1dac3 set default utc offset to 0 (#11114) 2017-12-13 20:03:41 -08:00
Adam Mills
b5d3a4736b Add problem device class (#11130) 2017-12-13 20:02:24 -08:00
Andrea Campi
e627544479 Always consume the no_throttle keyword argument. (#11126)
The current code relies on the assumption that the first invocation will never specify no_throttle=True.
However that puts us in a pickle when writing unit tests: if we had a fictitious:

  def setup_platform():
    update()

  @Throttle(MIN_TIME_BETWEEN_SCANS)
  def update():
    pass

Then given multiple tests, the second and some of subsequent tests would be throttled (depending on timing).
But we also can't change that code to call `update(no_throttle=True)' because that's not currently accepted.

This diff shouldn't change the visibile behavior of any component, but allows this extra flexibility.
2017-12-13 20:01:59 -08:00
Andrea Campi
d547345f90 Skip HASS emulated Hue bridges from detection. (#11128)
When refactoring the Hue support we lost a check for HASS bridges; restore that.
2017-12-13 20:00:30 -08:00
Nolan Gilley
4ec3289f9c update pyripple (#11122) 2017-12-13 21:21:14 +01:00
Philipp Schmitt
638dd25aff Add media position properties (#10076)
* Add media progress information

* Remove unnecessary comments

* Remove datetime import

* Remove pysonyavr dependency

* Fix doc syntax (D205)

* Lint fix: no-else-return

* Don't attempt to set media progress info if program is None

* Fix Python 3.4 compatibility

* Explicitely depend on pyteleloisirs

* Only update remaining play time when it changed

* Fix floot state table
2017-12-13 10:58:49 +01:00
Ryan McLean
37efd5a5cd Fixed typo in automation.py (#11116) 2017-12-13 10:17:12 +01:00
Paulus Schoutsen
168065b9bc Update Warrant (#11101)
* Update Warrant

* Lint
2017-12-12 21:12:41 -08:00
Eitan Mosenkis
95cd2035b6 Fix incorrect comment. (#11111) 2017-12-13 00:04:42 +01:00
Dan Nixon
aeba81e193 Report availability for TP-Link smart bulbs (#10976) 2017-12-12 17:18:46 +01:00
Pierre Ståhl
c7e327ea87 Bump pyatv to 0.3.9 (#11104) 2017-12-12 16:52:39 +01:00
Fabian Affolter
ed06b8cead Use luftdaten module (#10970)
* Use luftdaten module

* Refactoring

* Check meta data

* Make name consistent

* Remove try block
2017-12-12 08:09:47 +01:00
Jan Almeroth
a79c7ee217 Bump pymusiccast to version 0.1.6 (#11091) 2017-12-11 22:29:52 +01:00
Pascal Vizeli
6bf23f9167 Update tellcore-net to 0.4 (#11087)
* Update tellcore-net to 0.4

* Update requirements_all.txt
2017-12-11 18:32:48 +01:00
Fabian Affolter
1b3963299d Upgrade shodan to 1.7.7 (#11084) 2017-12-11 16:44:14 +01:00
Fabian Affolter
c461a7c7e2 Upgrade youtube_dl to 2017.12.10 (#11080) 2017-12-11 13:53:01 +01:00
Fabian Affolter
0cfff13be1 Upgrade psutil to 5.4.2 (#11083) 2017-12-11 13:52:43 +01:00
Fabian Affolter
0245189670 Upgrade yarl to 0.16.0 (#11078) 2017-12-11 13:52:22 +01:00
Fabian Affolter
7777d5811f Upgrade aiohttp to 2.3.6 (#11079) 2017-12-11 13:50:55 +01:00
Pascal Vizeli
7259cc878e Allow tradfri to read the available state of the device (#11056)
* Allow tradfri to read the available state of the device

* Update tradfri.py
2017-12-11 11:34:48 +01:00
Erik Eriksson
a4214afddb Volvo on call: Optional use of Scandinavian miles. Also add average fuel consumption property (#11051) 2017-12-10 13:57:44 -08:00
uchagani
b078f6c342 add custom bypass status to total connect (#11042)
* add custom bypass status to total connect

* remove logger line
2017-12-10 16:02:12 -05:00
Andrea Campi
81974885ee Refactor hue to split bridge support from light platform (#10691)
* Introduce a new Hue component that knows how to talk to a Hue bridge, but doesn't actually set up lights.

* Refactor the hue lights platform to use the HueBridge class from the hue component.

* Reimplement support for multiple bridges

* Auto discover bridges.

* Provide some migration support by showing a persistent notification.

* Address most feedback from code review.

* Call load_platform from inside HueBridge.setup passing the bridge id.

Not only this looks nicer, but it also nicely solves additional bridges being added after initial setup (e.g. pairing a second bridge should work now, I believe it required a restart before).

* Add a unit test for hue_activate_scene

* Address feedback from code review.

* After feedback from @andrey-git I was able to find a way to not import phue in tests, yay!

* Inject a mock phue in a couple of places
2017-12-10 10:15:01 -08:00
Adde Lovein
b2c5a9f5fe Add GPS coords to meraki (#10998) 2017-12-10 09:47:14 -08:00
maxlaverse
04cb893d10 Add a caldav calendar component (#10842)
* Add caldav component

* Code review - 1

* Code review - 2

* Sort imports
2017-12-10 17:44:28 +01:00
perfalk
3b228c78c0 Added support for cover in tellstick (#10858)
* Added support for cover in tellstick

* Fixed comments from PR

* Fixed comments from PR

* Address comments
2017-12-10 17:35:10 +01:00
tringler
4e91e6d103 This change fixes the error OSError: [WinError 193] on Windows debuggers (i.e. PyCharm) (#11034) 2017-12-09 16:58:52 -08:00
Paulus Schoutsen
cb4e886a4f Make notify.html5 depend on config (#11052) 2017-12-09 13:14:16 -08:00
GreenTurtwig
bee80c5b79 Add support for Logitech UE Smart Radios. (#10077)
* Add support for Logitech UE Smart Radios.

* Removed full stops to please Hound's line limit.

* Updated with requested changes.

* Fix Pylint Flake8 problem.

* Updated with requested changes.
2017-12-09 20:01:23 +01:00
Andrey Kupreychik
4479761131 Added force_update for REST sensor (#11016)
* Added force_update for REST sensor

* Linting error
2017-12-09 08:18:45 +01:00
Andrey
20f1e1609f In dev mode expose only relevant sources (#11026) 2017-12-08 17:25:16 -08:00
Matthew Treinish
1f1115f631 Serialize mochad requests (#11029)
All mochad devices are sharing a single socket interface. When multiple
threads are issuing requests to the mochad daemon at the same time the
write read cycle might get crossed between the threads. This is normally
not an issue for 1-way X10 devices because as long as the request issued
successfully and data is read over the socket then we know as much as
mochad will tell us (since there is no ACK from the request for most
X10 devices). However, where it does matter is on the device __init__()
because we're relying on the mochad daemon's internal state to take an
educated guess at the device's state to intialize things with. When
there are multiple devices being initialized at the same time the wires
can get crossed between and the wrong device state may be read.

To address this potential issue this commit adds locking using a
semaphore around all pairs of send_cmd() and read_data() (which is what
pymochad.device.Device.get_status() does internally) calls to the mochad
controller to ensure we're only ever dealing with a single request at a
time.

Fixes mtreinish/pymochad#4
2017-12-08 09:18:52 -08:00
Andrey
f7c2ec19ef Change default js version to auto (#10999) 2017-12-08 09:16:26 -08:00
tschmidty69
fed7bd9473 Update snips to listen on new mqtt topic and utilize rawValue (#11020)
* Updated snips to listen on new mqtt topic and use rawValue if value not present in slot

* Too late at night

* Trying to make minor changes via web

* Update test_snips.py

* Update __init__.py

* Updated wrong branch cause I'm a monkey
2017-12-08 09:16:08 -08:00
Anders Melchiorsen
4d6070e33a Support LIFX Mini products (#10996)
* Support new LIFX products

* Remove lint
2017-12-08 08:43:37 -08:00
Anders Melchiorsen
0a7e6ac222 Ignore Sonos players with unknown hostnames (#11013) 2017-12-08 12:01:10 +01:00
Joe Lu
f892c3394b Add support for Canary component and platforms (#10306)
* Add Canary component

* Made some change to how canary data is updated and stored

* Updated to use py-canary:0.1.2

* Addressed flake8 warnings

* Import canary API locally

* Import canary API locally again

* Addressed pylint errors

* Updated requirements_all.txt

* Fixed incorrect unit of measurement for air quality sensor

* Added tests for Canary component and sensors

* Updated canary component to handle exception better when initializing

* Fixed tests

* Fixed tests again

* Addressed review comments

* Fixed houndci error

* Addressed comment about camera force update

* Addressed comment regarding timeout when fetching camera image

* Updated to use py-canary==0.2.2

* Increased update frequency to 30 seconds

* Added support for Canary alarm control panel

* Address review comments

* Fixed houndci error

* Fixed lint errors

* Updated test to only test setup component / platform

* Fixed flake error

* Fixed failing test

* Uptake py-canary:0.2.3

* canary.alarm_control_panel DISARM is now mapped to canary PRIVACY mode

* Fixed failing tests

* Removed unnecessary methods

* Removed polling in canary camera component and update camera info when getting camera image

* Added more tests to cover Canary sensors

* Address review comments

* Addressed review comment in tests

* Fixed pylint errors

* Excluded canary alarm_control_panel and camera from coverage calculation
2017-12-08 10:40:45 +01:00
Marcus Schmidt
929d49ed6f Shuffle support in Sonos (#10875)
* initial commit of shuffle option for sonos

* added test

* Small adjustments to adhere to review requests

* Removed unnessesary setting of variable. Use shuffle state from soco instead
2017-12-07 14:44:06 -05:00
Lewis Juggins
3c1f8cd882 Handle OSError when forcibly turning off media_player.samsungtv (#10997) 2017-12-07 16:30:51 +00:00
Jeroen ter Heerdt
f21da7cfdc Fix Egardia alarm status shown as unknown after restart (#11010) 2017-12-07 12:39:34 +01:00
Alan Fischer
39d33c97ff Added Vera scenes (#10424)
* Added Vera scenes

* Fixed flake8 issues

* Fixed comments

* Moved vera to use hass.data

* Made requested changes
2017-12-07 07:47:19 +01:00
Derek Brooks
3193e825d5 remove nuheat away functionality. :( 2017-12-06 22:34:13 -06:00
Derek Brooks
c262a387dc add supported_features functionality 2017-12-06 22:24:54 -06:00
Derek Brooks
36d5fff8e0 address feedback on log lines 2017-12-06 21:52:44 -06:00
Derek Brooks
72aa722c33 Merge branch 'dev' into nuheat 2017-12-06 21:49:13 -06:00
Richard Leurs
c952f2e18a Ensure Docker script files uses LF line endings to support Docker for Windows. (#10067) 2017-12-06 15:00:58 +01:00
Daniel Watkins
0fc7f37185 webostv: Ensure source exists before use (#10959)
In a case where either (a) an incorrect source name is used, or (b) the
TV isn't currently queryable (e.g. it's off), we get tracebacks because
we assume the source that we are being asked to select exists in
self._source_list.

This makes the lookup code a little more rugged, and adds in a warning
message (in place of the current exception).
2017-12-06 14:48:17 +01:00
Pascal Vizeli
9cff6c7e6a Update tradfri.py (#10991) 2017-12-06 12:44:41 +01:00
Mitko Masarliev
e66268dffe Meraki AP Device tracker (#10971)
* Device tracker for meraki AP

* styles fix

* fix again

* again

* and again :)

* fix hide if away

* docs and optimization

* tests and fixes

* styles

* styles

* styles

* styles

* styles fix. Hope last

* clear track new

* changes

* fix accuracy error and requested changes

* remove meraki from .coveragerc

* tests and minor changes

* remove location
2017-12-06 09:24:20 +01:00
Paulus Schoutsen
c13b510ba3 Update frontend to 20171206.0 2017-12-05 23:40:31 -08:00
Dan Nixon
5f4baa67dc Allow disabling the LEDs on TP-Link smart plugs (#10980) 2017-12-06 08:38:27 +01:00
Paulus Schoutsen
1db7e2c9d6 Merge branch 'master' into dev 2017-12-05 23:36:08 -08:00
Paulus Schoutsen
fa324dce9c Merge pull request #10990 from home-assistant/release-0-59-2
0.59.2
2017-12-05 22:17:27 -08:00
Paulus Schoutsen
56c694b477 Revert pychromecast update (#10989)
* Revert pychromecast update

* Update cast.py
2017-12-05 22:11:23 -08:00
Craig J. Ward
3f764f1981 Reload closest store on api menu request (#10962)
* reload closest store on api request

* revert change from debugging
2017-12-05 22:11:22 -08:00
William Scanlon
63d6734612 Allow chime to work for wink siren/chime (#10961)
* Allow Wink siren/chimes to work

* Updated requirements_all.txt
2017-12-05 22:11:22 -08:00
Erik Eriksson
f9743c29cd Upgrade tellduslive library version (closes https://github.com/home-assistant/home-assistant/issues/10922) (#10950) 2017-12-05 22:11:22 -08:00
Mateusz Drab
bdb7a29586 Fix linksys_ap.py by inheriting DeviceScanner (#10947)
As per issue #8638, the class wasn't inheriting from DeviceScanner, this commit patches it up.
2017-12-05 22:11:21 -08:00
Andrey
22c36f0ad3 Require FF43 for latest js (#10941)
* Require FF43 for latest js

`Array.prototype.includes` added in Firefox 43

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

* Update __init__.py
2017-12-05 22:11:20 -08:00
Paulus Schoutsen
fd6373c7aa Version bump to 0.59.2 2017-12-05 22:10:47 -08:00
Andrey
87fe674c70 Require FF43 for latest js (#10941)
* Require FF43 for latest js

`Array.prototype.includes` added in Firefox 43

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

* Update __init__.py
2017-12-05 22:09:41 -08:00
Paulus Schoutsen
ddec566e10 Revert pychromecast update (#10989)
* Revert pychromecast update

* Update cast.py
2017-12-05 22:08:09 -08:00
William Scanlon
454d8535f8 Allow chime to work for wink siren/chime (#10961)
* Allow Wink siren/chimes to work

* Updated requirements_all.txt
2017-12-05 22:07:59 -08:00
Mitko Masarliev
8e4942088e Add option to set default hide if away for new devices (#10762)
* Option to change hide_if_away

* tests fix

* change new device defaults

* tests and requested changes

* fix assert
2017-12-05 21:56:43 -08:00
Adam Mills
3af527b1b5 Use new build path for dev translations (#10937) 2017-12-05 09:13:09 -05:00
ziotibia81
69d5738e47 Generic thermostat initial_operation_mode (#10690)
* Generic thermostat restore operation mode

* Test restore operation mode

* Fix trailing whitespace

* Fix line too long

* Fix test duplicate entity_id

* Fix test

* async_added_to_hass modify modify internal state

* Test inital_operation_mode

* More restore state tests

* Fix whitespace

* fix test_custom_setup_param

* Test "None" target temp
2017-12-05 15:00:33 +01:00
Menno Blom
379c10985b Add Ziggo Mediabox XL media_player (#10514)
* Add Ziggo Mediabox XL media_player

* Using pypi module ziggo-mediabox-xl now.

* Code review changes
2017-12-05 14:22:27 +01:00
Roman
821cf7135d Gearbest sensor (#10556)
* Added Gearbest Sensor

* Updated required files

* Fixed houndci-bout findings

* Fix tox lint errors

* Changed code according to review
Implemented library version 1.0.5

* Fixed houndci-bot findings

* Fixed tox lint issues

* Updated item schema to use has_at_least_one_key
Added conf constants

* Remove CONF_ constants and import them from homeassistant.const

* Removed CurrencyConverter from hass
Fixed couple of issues found by MartinHjelmare
2017-12-05 12:32:43 +01:00
Craig J. Ward
d986bdab98 Reload closest store on api menu request (#10962)
* reload closest store on api request

* revert change from debugging
2017-12-05 10:47:48 +01:00
Stefan Lehmann
53d9fd18b7 Add ADS component (#10142)
* add ads hub, light and switch

* add binary sensor prototype

* switch: use adsvar for connection

* fix some issues with binary sensor

* fix binary sensor

* fix all platforms

* use latest pyads

* fixed error with multiple binary sensors

* add sensor

* add ads sensor

* clean up after shutdown

* ads component with platforms switch, binary_sensor, light, sensor

add locking

poll sensors at startup

update state of ads switch and light

update ads requirements

remove update() from constructors on ads platforms

omit ads coverage

ads catch read error when polling

* add ads service

* add default settings for use_notify and poll_interval

* fix too long line

* Fix style issues

* no pydocstyle errors

* Send and receive native brightness data to ADS device to prevent issues with math.floor reducing brightness -1 at every switch

* Enable non dimmable lights

* remove setting of self._state in switch

* remove polling

* Revert "remove polling"

This reverts commit 7da420f82385a4a5c66a929af7025c00ed197e86.

* add service schema, add links to documentation

* fix naming, cleanup

* re-remove polling

* use async_added_to_hass for setup of callbacks

* fix comment.

* add callbacks for changed values

* use async_add_job for creating device notifications

* set should_poll to False for all platforms

* change should_poll to property

* add service description to services.yaml

* add for brigthness not being None

* put ads component in package

* Remove whitespace

* omit ads package
2017-12-05 09:44:22 +01:00
Mateusz Drab
38a1f06d14 Fix linksys_ap.py by inheriting DeviceScanner (#10947)
As per issue #8638, the class wasn't inheriting from DeviceScanner, this commit patches it up.
2017-12-04 18:58:52 +01:00
Paul Annekov
2e2d0f48fb don't ignore voltage data if sensor data changed (#10925) 2017-12-04 17:26:41 +01:00
Erik Eriksson
4652b8aea1 Upgrade tellduslive library version (closes https://github.com/home-assistant/home-assistant/issues/10922) (#10950) 2017-12-04 17:26:07 +01:00
dasos
ef1cbd3aea Tado ignore invalid devices (#10927)
* Ignore devices without temperatures

* Typo

* Linting

* Removing return false

* Another typo. :(

* Spelling received correctly
2017-12-04 14:55:04 +01:00
drop table USERS; --
31cedf83c7 Export climate status and target temperature to Prometheus (#10919)
* Export climate metrics to Prometheus.

This adds climate_state and temperature_c metrics for each climate
device.

* Add more climate states to state_as_number
2017-12-04 13:39:26 +01:00
Nicolas Bougues
19a97580fc Set percent unit for battery level so that history displays properly; edited variable name for consistency (#10932) 2017-12-04 08:34:42 +01:00
Dan Nixon
17f3cf0389 Report availability of TP-Link smart sockets (#10933)
* Report availability of TP-Link smart sockets

* Changes according to our style guide
2017-12-04 08:33:22 +01:00
Paulus Schoutsen
4e02300cbc Merge remote-tracking branch 'origin/master' into dev 2017-12-03 20:15:34 -08:00
Paulus Schoutsen
015cdd155c Merge pull request #10936 from home-assistant/release-0-59-1
0.59.1
2017-12-03 20:08:04 -08:00
Craig J. Ward
d4e603cc6a Dominos no order fix (#10935)
* check for none

* fix error from no store being set

* typo

* Lint

* fix default as per notes. Lint fix and make closest store None not False

* update default
2017-12-03 19:36:49 -08:00
Paulus Schoutsen
7ae374e11f Update frontend to 20171204.0 (#10934) 2017-12-03 19:36:49 -08:00
Will Boyce
292b403dc3 fix ios component config generation (#10923)
Fixes: #19020
2017-12-03 19:36:49 -08:00
Daniel Perna
b815898ddb Fix Notifications for Android TV (#10798)
* Fixed icon path, added dynamic icon

* Addressing requested changes

* Using DEFAULT_ICON

* Using CONF_ICON from const

* Getting hass_frontend path via import

* Lint

* Using embedded 1px transparent icon

* woof -.-

* Lint
2017-12-03 19:36:48 -08:00
Paulus Schoutsen
b1855f1d1d Version bump to 0.59.1 2017-12-03 19:36:41 -08:00
Craig J. Ward
bd6a17a3a5 Dominos no order fix (#10935)
* check for none

* fix error from no store being set

* typo

* Lint

* fix default as per notes. Lint fix and make closest store None not False

* update default
2017-12-03 19:34:58 -08:00
Paulus Schoutsen
29fad3fa3c Update frontend to 20171204.0 (#10934) 2017-12-03 17:59:58 -08:00
Paulus Schoutsen
0c43466225 Update coveragerc (#10931)
* Sort coveragerc

* Add climate.honeywell and vacuum.xiaomi_miio to coveragerc
2017-12-03 16:42:18 -08:00
Daniel Perna
0d6c95ac44 Fix Notifications for Android TV (#10798)
* Fixed icon path, added dynamic icon

* Addressing requested changes

* Using DEFAULT_ICON

* Using CONF_ICON from const

* Getting hass_frontend path via import

* Lint

* Using embedded 1px transparent icon

* woof -.-

* Lint
2017-12-03 15:08:10 -08:00
Will Boyce
6776e942d7 fix ios component config generation (#10923)
Fixes: #19020
2017-12-03 14:59:22 -08:00
Brent Hughes
879e32f670 Add Min and Event Count Metrics To Prometheus (#10530)
* Added min and Events sensor types to prometheus

* Updated prometheus client and fixed invalid swith state

* Added metric to count number of times an automation is triggered

* Removed assumption that may not apply to everybody

* Fixed tests

* Updated requirements_test_all

* Fixed unit tests
2017-12-03 23:39:54 +01:00
Oliver
3a246df544 Don't repeat getting receiver name on each update / pushed to denonavr 0.5.5 (#10915) 2017-12-03 21:51:32 +01:00
Fabian Affolter
9577525b0b Add Alpha Vantage sensor (#10873)
* Add Alpha Vantage sensor

* Remove data object

* Remove unused vars and change return

* Fix typo
2017-12-03 21:34:59 +01:00
Touliloup
6b410d8076 Correction of Samsung Power OFF behaviour (#10907)
* Correction of Samsung Power OFF behaviour

Addition of a delay after powering OFF a Samsung TV, this avoid status
update from powering the TV back ON.
Deletion of update() return statement, return value not used.

* Rename self._end_of_power_off_command into self._end_of_power_off

* Removal of unused line break in Samsung TV component
2017-12-03 18:34:45 +01:00
Ludovico de Nittis
9e82433a3e Add iAlarm support (#10878)
* Add iAlarm support

* Minor fixes to iAlarm

* Rename ialarmpanel to ialarm and add a check for the host value

* corrections in the value validation of ialarm

* add a missing period on ialarm
2017-12-03 16:48:12 +01:00
Erik Eriksson
8ceaa72ba3 Update eliqonline.py (#10914)
Channel id is now required (change in API)
2017-12-03 16:48:07 +01:00
Fabian Affolter
fce994ea76 Bump dev to 0.60.0.dev0 (#10912) 2017-12-03 16:47:21 +01:00
Nicko van Someren
4390fed168 Unpacking RESTful sensor JSON results into attributes. (#10753)
* Added support for extracting JSON attributes from RESTful values

Setting the json_attributes configuration option to true on the
RESTful sensor will cause the result of the REST request to be parsed
as a JSON string and if successful the resulting dictionary will be
used for the attributes of the sensor.

* Added support for extracting JSON attributes from RESTful values

Setting the json_attributes configuration option to true on the
RESTful sensor will cause the result of the REST request to be parsed
as a JSON string and if successful the resulting dictionary will be
used for the attributes of the sensor.

* Added requirement that RESTful JSON results used as attributes must be
objects, not lists.

* Expanded test coverage to test REFTful JSON attributes with and
without a value template.

* Added support for extracting JSON attributes from RESTful values

Setting the json_attributes configuration option to true on the
RESTful sensor will cause the result of the REST request to be parsed
as a JSON string and if successful the resulting dictionary will be
used for the attributes of the sensor.

* Added requirement that RESTful JSON results used as attributes must be
objects, not lists.

* Expanded test coverage to test REFTful JSON attributes with and
without a value template.

* sensor.envirophat: add missing requirement (#7451)

Adding requirements that is not explicitly pulled in by the library
that manages the Enviro pHAT.

* PyPI Openzwave (#7415)

* Remove default zwave config path

PYOZW now has much more comprehensive default handling for the config
path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in
the same place we were looking, plus _many_ more. It will certainly do a
much better job of finding the config files than we will (and will be
updated as the library is changed, so we don't end up chasing it). The
getConfig() method has been there for a while, but was subsntially
improved recently.

This change simply leaves the config_path as None if it is not
specified, which will trigger the default handling in PYOZW.

* Install python-openzwave from PyPI

As of version 0.4, python-openzwave supports installation from PyPI,
which means we can use our 'normal' dependency management tooling to
install it. Yay.

This uses the default 'embed' build (which goes and downloads
statically sources to avoid having to compile anything locally). Check
out the python-openzwave readme for more details.

* Add python-openzwave deps to .travis.yml

Python OpenZwave require the libudev headers to build. This adds the
libudev-dev package to Travis runs via the 'apt' addon for Travis.

Thanks to @MartinHjelmare for this fix.

* Update docker build for PyPI openzwave

Now that PYOZW can be install from PyPI, the docker image build process
can be simplified to remove the explicit compilation of PYOZW.

* Add datadog component (#7158)

* Add datadog component

* Improve test_invalid_config datadog test

* Use assert_setup_component for test setup

* Fix object type for default KNX port

#7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue...

* Added support for extracting JSON attributes from RESTful values

Setting the json_attributes configuration option to true on the
RESTful sensor will cause the result of the REST request to be parsed
as a JSON string and if successful the resulting dictionary will be
used for the attributes of the sensor.

* Added requirement that RESTful JSON results used as attributes must be
objects, not lists.

* Expanded test coverage to test REFTful JSON attributes with and
without a value template.

* Added support for extracting JSON attributes from RESTful values

Setting the json_attributes configuration option to true on the
RESTful sensor will cause the result of the REST request to be parsed
as a JSON string and if successful the resulting dictionary will be
used for the attributes of the sensor.

* Added requirement that RESTful JSON results used as attributes must be
objects, not lists.

* Expanded test coverage to test REFTful JSON attributes with and
without a value template.

* Added support for extracting JSON attributes from RESTful values

Setting the json_attributes configuration option to true on the
RESTful sensor will cause the result of the REST request to be parsed
as a JSON string and if successful the resulting dictionary will be
used for the attributes of the sensor.

* Added requirement that RESTful JSON results used as attributes must be
objects, not lists.

* Expanded test coverage to test REFTful JSON attributes with and
without a value template.

* Fixed breaks cause by manual upstream merge.

* Added one extra blank line to make PyLint happy.

* Switched json_attributes to be a list of keys rather than a boolean.

The value of json_attributes can now be either a comma sepaated list
of key names or a YAML list of key names. Only matching keys in a
retuned JSON dictionary will be mapped to sensor attributes.

Updated test cases to handle json_attributes being a list.

Also fixed two minor issues arrising from manual merge with 0.58 master.

* Added an explicit default value to the json_attributes config entry.

* Removed self.update() from __init__() body.

* Expended unit tests for error cases of json_attributes processing.

* Align quotes
2017-12-03 16:30:25 +01:00
Paolo Bonzini
0f8e48c26d More declarative timeout syntax for manual alarm control panel. (#10738)
More declarative timeout syntax for manual alarm control panel
2017-12-03 13:52:31 +01:00
Fabian Affolter
2d556486bf Merge branch 'master' into dev 2017-12-03 13:28:25 +01:00
Fabian Affolter
850a20a626 Merge pull request #10898 from home-assistant/release-0-59
0.59
2017-12-03 13:24:22 +01:00
John Arild Berentsen
68dc0d4d99 Bugfix #10902 (#10904) 2017-12-03 10:09:44 +01:00
PhracturedBlue
58e66c947b Fix issues from review of ecobee weather component (#10903)
* Fix issues from review

* Don't use STATE_UNKNOWN
2017-12-03 10:09:40 +01:00
John Arild Berentsen
29f47d58bc Bugfix #10902 (#10904) 2017-12-03 00:15:57 +01:00
PhracturedBlue
8947052405 Fix issues from review of ecobee weather component (#10903)
* Fix issues from review

* Don't use STATE_UNKNOWN
2017-12-02 22:44:55 +01:00
raymccarthy
475b7896e2 Pybotvac multi (#10843)
* Update requirements_all.txt

* Update neato.py
2017-12-02 15:44:24 +01:00
PhracturedBlue
b2a2cb3fd8 Update ecobee version to fix stack-trace issue (#10894) 2017-12-02 07:56:35 +02:00
Fabian Affolter
462a438f89 Version bump to 0.59.0 2017-12-02 01:09:43 +01:00
Andrey
4ebc52ab52 Reload groups after saving a change via config API (#10877) 2017-12-01 12:53:46 -08:00
Andrey
8afeef2f36 Serve latest extra_html in dev mode (#10863) 2017-12-01 12:53:15 -08:00
Adam Cooper
c2525782aa Refactored WHOIS sensor to resolve assumed key errors (#10662)
* Refactored WHOIS sensor to resolve assumed key errors

Altered it to now set an attribute key and value only if the attribute
is present in the WHOIS response. This prevents assumed keys (registrar)
from raising a KeyError on WHOIS lookups that don't contain registrar
information (onet.pl, wp.pl, for example).

* Removed non-used self._data

* WHOIS sensor now creates a new local attributes dict and overrides

* Corrected typos, refactored error cases to clear state adn attributes

* Resolved double return and refactored error logging
2017-12-01 11:36:15 -05:00
Pascal Vizeli
bc4de4e769 Fix tests (#10891) 2017-12-01 15:49:56 +01:00
Fabian Affolter
9f324205cb Upgrade yarl to 0.15.0 (#10888) 2017-12-01 13:37:14 +01:00
Fabian Affolter
fff85ab392 Upgrade youtube_dl to 2017.11.26 (#10890) 2017-12-01 12:38:46 +01:00
Jeroen ter Heerdt
29f4b73230 Microsoft Text-to-speech: Fixing missing en-gb support bug (#10429)
* Fixing missing en-gb support bug

* Microsoft TTS adding support for rate, volume, pitch and contour.

* Microsoft TTS fixing support for jp-jp.

* Fixing linting error on line 67

* make impossible things possible 🎉
2017-12-01 12:38:20 +01:00
PhracturedBlue
606fa34792 Create ecobee weather platform (#10869)
* Create ecobee weather component

* Update requirements_all for ecobee

* Fix missed lint issue
2017-12-01 12:30:45 +01:00
Teemu R
7b452208b6 Xiaomi Vacuum: remove deprecated calls (#10839)
* vacuum.xiaomi_miio: read dnd status properly instead of using imprecise dnd flag from vacuum_state

* vacuum.xiaomi_miio: use miio package instead of mirobo

* check only that wanted calls have taken place, ignore order of calls

* Fix linting issues

* Remove empty line after docstring
2017-12-01 12:28:59 +01:00
Fabian Affolter
493de295ac Upgrade schiene to 0.19 (#10887) 2017-12-01 12:26:15 +01:00
Fabian Affolter
d2106c40e1 Upgrade fastdotcom to 0.0.3 (#10886) 2017-12-01 12:25:54 +01:00
Fabian Affolter
9a0a5b7867 Upgrade aiohttp to 2.3.5 (#10889) 2017-12-01 12:22:28 +01:00
Paulus Schoutsen
d8003c4d87 Update frontend to 20171130.0 2017-11-30 20:46:21 -08:00
Pascal Vizeli
f7380dc927 tellstick fix DEPENDENCIES and update tellcore-net (#10859)
* Update requirements_all.txt

* Update tellstick.py

* Fix DEPENDENCIES

* Update requirements_all.txt

* fix format

* fix lint

* fix lint

* Update tellstick.py

* update tellcore-net

* update tellcore-net

* besser validate
2017-11-30 21:13:18 +01:00
Pascal Vizeli
ea6ca9252c Bugfix trigger state with multible entities (#10857)
* Bugfix trigger state with multible entities

* Fix numeric state

* fix lint

* fix dict

* fix unsub

* fix logic

* fix name

* fix new logic

* add test for state

* add numeric state test for unsub

* add test for multible entities

* Update numeric_state.py

* Update numeric_state.py

* Update state.py

* Fix logic for triple match

* Add clear to numeric state

* clear for state trigger
2017-11-30 21:03:52 +01:00
Fabian Affolter
bfc61c268a Upgrade distro to 1.1.0 (#10850) 2017-11-30 15:58:50 +01:00
Julius Mittenzwei
1c227bc0d9 Revert "KNX: Added config option for broadcasting current time to KNX bus. (#10654)" (#10874)
This reverts commit cadd797200.

As discussed within #10708 we should chose a different implementation. Therefore we should revert this change to avoid a breaking change.
2017-11-30 15:52:57 +01:00
Aaron Bach
bb870a688d Updated codeowner for Tile device tracker (#10861) 2017-11-29 19:13:31 +01:00
Fabian Affolter
40a98d56fa Upgrade mutagen to 1.39 (#10851) 2017-11-29 11:04:28 +01:00
Lukas Barth
373508693a Climate component: add supported_features (#10658)
* Implement supported_features for the climate component

* Test supported features

* Convert generic thermostat to supported features

* Max / min temperature are not features

* Fix lint

* Min / max humidity are not features

* Linting

* Remove current temperature / humidity

* Move c-hacker-style constants to boring integers. Booo!

* Refactor all the climate platforms to use the new supported_features

* Force all climate platforms to implement supported_features

* Fix mistakes

* Adapt hive platform

* Move flags into a constant

* Calm the hound
2017-11-29 11:01:28 +01:00
Daniel Perna
59fa4f18e4 Upgrade HomeMatic, add devices (#10845) 2017-11-28 23:16:47 -08:00
Per Osbäck
253d5aea6e add support for multiple execution per execute request (#10844) 2017-11-28 23:16:29 -08:00
Andrey
99ea2c17a1 Add useragent-based detection of JS version (#10776)
* Add useragent-based detection of JS version

* Keep es5 as default meanwhile

* Update test
2017-11-28 22:53:12 -08:00
Erik Eriksson
7ab15c0e79 Tellduslive: Use magic constants for battery level. Also, the previous formula for battery level was wrong. (#10788) 2017-11-28 15:32:36 +01:00
Matt Schmitt
4e4d4365a0 Add device class for low battery (#10829) 2017-11-28 15:25:32 +01:00
Cameron Bulock
1f82bb033d Ecobee set humidity level (#10780)
* Add the ability to set humidity levels on ecobee thermostats

* use the latest version of python-ecobee-api

* Lint fixes
2017-11-28 10:39:30 +01:00
Julius Mittenzwei
cadd797200 KNX: Added config option for broadcasting current time to KNX bus. (#10654) 2017-11-27 23:15:57 -08:00
Fredrik Erlandsson
6df5e712f7 Tellduslive update with support for auto config and Local api (#10435)
* Add support for local api connection found in TellStick Znet Lite/Pro.
Added auto discovery support for all TelldusLive devices,
changed authentication method. Breaking change!
Upgraded tellduslive dependency
Update CODEOWNERS.

* Close any open configurator when configuration done

* Add support for Telldus Local API via config (#2)

* Updated dependency (addresses issue raised by @rasmusbe in https://github.com/home-assistant/home-assistant/pull/10435#issuecomment-344719714)

* Fix requested changes
2017-11-27 23:13:30 -08:00
Zach
282e37ef14 Changing handling for google_assistant groups to treat them as lights. (#10111)
* Fixed aliases warning message

* Fixed test cases

* Changing handling for google_assistant groups to treat them as lights - amending to include user info.

* Enable brightness, RGB, etc for groups in Google Assistant

* Revert color/hue/temp settings

* Change servce from light to homeassistant

* Fixed config_units

* Convert from light to switch

* Change group to switch

* Update tests to switch instead of light for group
2017-11-27 21:43:01 -08:00
Odin Ugedal
0668fba7bd Add support for logarithm in templates (#10824)
* Add support for logarithm in templates

This adds a 'log' filter that takes the logarithm of the given value,
with an optional base number. The base defaults to 'e' - the natural
logarithm

* Remove usage of log10 in template filter 'log'

* Add logarithm as a global

This makes it possible to write:
'{{ log(4, 2) }}'
2017-11-27 21:29:01 -08:00
Dan Ferrante
27270b49b4 upgrade somecomfort to 0.5.0 (#10834)
* upgrading somecomfort to 0.5.0

* upgrade somecomfort to 0.5.0 in requirements files
2017-11-27 21:09:04 -08:00
Andrey
8c5d6ee9c3 Fix for Sensibo with missing temperature (#10801)
* Fix for sensibo woth missing temperature

* Use new temperatureUnit API field
2017-11-27 21:05:43 -08:00
chocomega
934c19445d Fixed Yeelight's color temperature conversion to RGB (#10831) 2017-11-27 20:54:56 -08:00
Stephen Yeargin
72251e0375 Fix "recently pair device" (#10832)
Noticed a minor grammar mistake.
2017-11-27 20:54:18 -08:00
Diogo Gomes
b1e2275b47 Add debug (#10828) 2017-11-27 21:25:00 +01:00
Maciej Sokołowski
af1bde6619 Single LEDs in Blinkt support (#10581)
* Single LEDs in Blinkt support

* Review remarks
2017-11-27 21:14:03 +01:00
Per Osbäck
2daea92379 make RGB values consistent as int. fixes #10766 (#10782)
* make RGB consitant as int. fixes #10766

* fix rounding and only change for hex convertion
2017-11-27 11:31:35 +01:00
zhujisheng
6cd9ca018a Add tts.baidu platform (#10724)
* Add tts.baidu platform

* Update baidu.py

* changed to sync

get_engine and get_tts_audio changed to sync.
2017-11-27 10:13:25 +01:00
Rasmus
eb282b3bb3 Added sensor types from telldus server src (#10787)
Added from https://github.com/telldus/tellstick-server/blob/master/telldus/src/telldus/Device.py
2017-11-27 10:11:00 +01:00
Paulus Schoutsen
fe0a9529ed Cloud cognito switch (#10823)
* Allow email based cognito instance

* Fix quitting Home Assistant while reconnecting

* Lint
2017-11-27 10:09:17 +01:00
Paulus Schoutsen
1b7a64412d Bump frontend to 20171127.0 2017-11-26 17:48:11 -08:00
Fabian Affolter
a187bd5455 Add missing docstring (#10812)
* Add missing docstring

* Revert isort change
2017-11-26 21:12:47 +01:00
Paulus Schoutsen
3e962808e6 Bump frontend to 20171126.0 2017-11-25 21:54:51 -08:00
bcl1713
3d5a9b5e91 Add away_mode_name to arlo alarm control panel (#10796)
* Update arlo.py

Include variables for custom away mode specification

* fixed line too long style problem

* fix trailing white space

* fix sending away mode command
2017-11-26 01:13:14 +01:00
Milan V
ba43218a73 Fix WUnderground error handling, rework entity methods (#10295)
* WUnderground sensor error handling and sensor class rework

* WUnderground error handling, avoid long state, tests

* Wunderground - add handling ValueError exception on parsing

* Changes to address review comments - part 1

* Tests lint

* Changes to address review comments - part 2
2017-11-25 15:19:52 -05:00
Andrey
d8bf15a2f5 system_log improvements (#10709)
* system_log improvements

* Don't use ModuleNotFoundError which is 3.6+

* Don't use FrameSummary which was added in 3.5

* Don't trace stack for exception logs

* Handle test error in Python 3.4
2017-11-25 16:22:41 +02:00
Marcelo Moreira de Mello
dbbbe1ceef Load Ring camera only with Ring Protect plan activated (#10739)
* Added ability to only load Ring camera
if the Ring Protect plan is activated.

* Fixed notification for all invalid cameras

* Fixed attribute name

* Using asyncio for persistent notifications
2017-11-25 12:15:12 +01:00
uchagani
2817f03378 Fixes #10773: Demo Alarm Broken (#10777)
* Fixes #10773: Demo Alarm Broken

* Added test for platform setup

* Remove unused import

* Lint fix

* Rework assert to work with python 3.5
2017-11-24 20:30:57 -08:00
Paulus Schoutsen
fcc164c31e Fix scene description formatting. (#10785) 2017-11-24 15:52:59 -08:00
uchagani
65d5b64d8d Bump total-connect-client version (#10769) 2017-11-25 00:21:31 +01:00
Rendili
f6547ec157 Update CODEOWNERS with hive Component / Platforms (#10775) 2017-11-24 16:31:37 +01:00
Nathan Henrie
61cddaa441 Make shell_command async (#10741)
* Make shell_command async

Use `asyncio.subprocess` instead of `subprocess` to make the
`shell_command` component async.

Was able to migrate over existing component and tests without too many
drastic changes.

Retrieving stdout and stderr paves the way for possibly using these in
future feature enhancements.

* Remove trailing comma

* Fix lint errors

* Try to get rid of syntaxerror

* Ignore spurious pylint error
2017-11-23 17:28:31 -08:00
Bart S
b03c024f74 Fix name collision when using multiple Hue bridges (#10486)
* Fix name collision when using multiple Hue bridges

See https://github.com/home-assistant/home-assistant/issues/9393

* Use new style of string formatting

* Removed creating of "All Hue Lights" group
2017-11-23 17:26:36 -08:00
Craig J. Ward
1a7522a594 Add Dominos Pizza platform (#10379)
* add dominos service

* change require

* dump to log

* component fixes

* clean-up use updated library

* remove unnecessary import

* fix hound errors

* more lint fixes

* Coverage rc

* update requirements

* cleanup as per notes

* missing message

* linting...

* schema validation and reducing requests

* fixlint

* spacing

* unused variable

* fix docstrings

* update req

* notes updates, pypi package, front-end panel

* stale import

* fix constant name

* docstrings

* fix library import

* lint fixes

* pylint bug

* remove built-in panel

* Make synchronous

* unused import and use throttle

* Handle exceptions properly and update client

* Import exceptions properly

* unused import

* remove bloat from start-up, readability fixes from notes, retrieve menu on request, not on startup

* whitespace on blank line
2017-11-23 17:21:24 -08:00
Jan Losinski
d0b9f08bf2 InfluxDB send retry after IOError (#10263)
* Implement data write retry for InfluxDB

This adds an optional max_retries parameter to the InfluxDB component
to specify if and how often the component should try to send the data
if the connection failed due to an IOError.

The sending will be scheduled for a retry in 20 seconds as often as the
user specified. This can be handy for flaky getwork connections between
the DB and Homeassistant or outages like daily DSL reconnects.

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Add unittest for influx write retries

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Add RetryOnError as helper decorator in util

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Add unittests for RetryOnError

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Use RetryOnError decorator in InfluxDB

This replaces the scheduling logic in the InfluxDB component with the
RetryOnError decorator from homeassistant.util

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Make the linters happy

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Implement a queue limit for the retry decorator.

This adds a queue limit to the RetryOnError handler. It limits the
number of calls waiting for be retried. If this number is exceeded,
every new call will discard the oldest one in the queue.

* influxdb: Add the retry queue limit option.

* Make the linter happy.

* Make pylint happy

* Log exception of dropped retry

* Move RetryOnError decorator to influxdb component.

* Fix bug in logging usage

* Fix imports

* Add newlines at the end of files.

* Remove blank line

* Remove blank line
2017-11-23 16:58:18 -08:00
Marcelo Moreira de Mello
3dd49b2b95 Protect sensitive information for Amcrest cameras (#10569)
*  Creates a AmcresHub object to protect some private attributes on the logs

* Uses hass.data to pass AmcrestHub to components

* Prefer constants

* Removed serializer since it's using hass.data and simplified camera entity constructor

* small cleanup
2017-11-23 16:38:53 -08:00
braddparker
3ef9c99003 Google assistant climate mode fix (#10726)
* Changed supported climate modes lookup to be case insensitive by forcing to lower-case

* Fixed style errors. (Blank line and line too long)
2017-11-23 12:57:30 -08:00
cgtobi
47183ce02e Temporarily fix yahoo weather API issue and add unit test. (#10737)
* Temporarily fix yahoo weather API issue and add unit test.

* Add test data.
2017-11-23 12:45:56 -08:00
Rendili
f2dea4615f New Hive Component / Platforms (#9804)
* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms

* Changes

* Changes

* Changes

* changes

* Updates

* Updates

* Updates

* Updates

* Updates

* Updates

* Sensor code updates

* Sensor code updates

* Move sensors to binary sensors

* Quack

* Updates - Removed climate related sensors

* sensor fix

* binary_sensor updates

* New Hive Component / Platforms

* New Hive Component / Platforms

* New Hive Component / Platforms
2017-11-23 13:10:23 +01:00
Ted Drain
b4635db5ac Add fan and reduce I/O calls in radiotherm (#10437)
* Added fan support.  Reduced number of calls to the thermostat to a minimum

* Move temp rounding to config schema

* Fixed pep8 errors

* Fix for review comments.

* removed unneeded if block

* Added missing precision attr back

* Fixed pylint errors

* Code review fixes.  Fan support by model number.

* Defined circulate state
2017-11-22 21:59:49 +01:00
Andy Castille
b668b19543 Use new DoorBirdPy (v0.1.0) (#10734)
* Use new DoorBirdPy (v0.1.0)

* Update requirements_all for DoorBirdPy 0.1.0
2017-11-22 11:40:15 +01:00
Lewis Juggins
cfb1853bbd Update pytradfri to 4.1.0 (#10521) 2017-11-22 09:37:20 +00:00
Sven-Hendrik Haase
b784d80973 Add transmission rate (#10740)
* Add transmission rate

* Rename transmission rate attributes to shorter names
2017-11-22 08:39:45 +01:00
Guillaume Rischard
2084ad2164 Optimised images. Saved 80 KB out of 656 KB. 12.3% overall (up to 32.1% per file) (#10735) 2017-11-21 21:19:13 -08:00
Bryan York
9c77f5f5a9 Fix unit conversion for Sensibo A/C units (#10692)
* Fix unit conversion for Sensibo A/C units

When the Sensibo component was released, there was a provision to not convert the temperature units unless "nativeTemperatureUnit" was returned with the API. I'm not sure if the API changed on Sensibo's side, but I do not get this key passed back with API requests.

This causes my current temperature to be returned in CELSIUS instead of FAHRENHEIT.

Removing this fixes it, and I can confirm the units are shown properly now.

* Update adding comment showing temperature is always in C
2017-11-21 20:48:36 +02:00
Otto Winter
8a750eba68 Bump pychromecast to 1.0.2 (#10728)
Fixes home-assistant/home-assistant#9965
2017-11-21 09:04:44 -08:00
bigwoof
5dbd554a10 Adding Queue count sensor (#10723)
Adding another sensor to output the numeber of items in the SABnabd queue.  This is an alternative to displaying filesize, just a preference thing, as it is more meaningfull for me the way I use SABnzdb. 

Note this is my first time coding on github and I have no idea if I am doing things right, I assume that all I needed to do is add a couple of lines to the sensors available and also another line as to what to extract from the SABnzdb API, in this case I have called the sensor "queue_count" and it gets the value from the noofslots_total which as I understand - each slot is a separate download item. 

hope I did this correctly - also I don't have a separate instance of home assistant running for testing so I have no way to test this code (and I don't know how I would switch to the dev channel either).  As I said I am a newb!
2017-11-21 15:35:23 +01:00
Sebastian Muszynski
d0296561f6 python-miio version bumped for improved device support. (#10720) 2017-11-21 09:23:39 +01:00
Paulus Schoutsen
db212cfb00 Fix tests 2017-11-20 22:38:12 -08:00
Paulus Schoutsen
6db5afe597 Update frontend to 20171121.1 2017-11-20 22:00:48 -08:00
Alok Saboo
2ba83655bb Add presence device_class (#10705) 2017-11-20 21:45:00 -08:00
Paulus Schoutsen
6e27e73474 Shopping list: add item HTTP API (#10674)
* Shopping list: add item HTTP API

* Fix order of decorators
2017-11-20 21:44:22 -08:00
Paulus Schoutsen
f0fe8cb2fe Merge branch 'master' into dev 2017-11-20 21:36:30 -08:00
Paulus Schoutsen
3d9f03d4f1 Merge pull request #10716 from home-assistant/release-0-58-1
0.58.1
2017-11-20 21:32:12 -08:00
Egor Tsinko
235707d31c Fix for time_date sensor (#10694)
* fix to time_date sensor

* cleaned up the code and added unit tests

* fixed lint errors
2017-11-20 20:58:28 -08:00
Thibault Cohen
8cb87d5e64 Handle the new version of HydroQuebec website (#10682)
* Handle the new version of HydroQuebec website

* Update requirements_all.txt
2017-11-20 20:58:27 -08:00
Anders Melchiorsen
4cb0e4b3c2 Properly initialize Harmony remote (#10665)
The delay_secs variable was not initialized if discovery was active and no
matching configuration block existed (i.e. override was None).
2017-11-20 20:58:27 -08:00
Lukas Barth
2ba5f1f45e Fix yweather (#10661) 2017-11-20 20:58:26 -08:00
Paulus Schoutsen
d7f9be9640 Version bump to 0.58.1 2017-11-20 20:50:12 -08:00
Paulus Schoutsen
34f06e8eef Bump frontend to 20171121.0 2017-11-20 20:49:58 -08:00
Paulus Schoutsen
efd45549e4 Bump frontend to 20171121.0 2017-11-20 20:48:52 -08:00
Paulus Schoutsen
34a4db57db Fix conversation (#10686)
* Fix conversation

* Lint
2017-11-20 20:26:36 -08:00
uchagani
e62ef067cc Add Arm Custom Bypass to alarm_control_panel (#10697) 2017-11-20 18:34:21 +01:00
Thibault Cohen
df37cb11fa Handle the new version of HydroQuebec website (#10682)
* Handle the new version of HydroQuebec website

* Update requirements_all.txt
2017-11-20 18:02:05 +01:00
Paulus Schoutsen
857d6b5b49 index.html improvements (#10696) 2017-11-20 15:16:36 +01:00
Paulus Schoutsen
62a740ba22 Convert configurator to use markdown (#10668) 2017-11-20 14:11:55 +01:00
Markus Nigbur
a83e741dc7 Refactored to new global json saving and loading (#10677)
* Refactored to new global json saving and loading

* Fixed emulated_hue tests

* Removed unnecassary error handling

* Added missing newline

* Remove unused imports

* Fixed linting error

* Moved _load_json wrapper out of the config class
2017-11-19 19:47:55 -08:00
Egor Tsinko
7695ca2c8b Fix for time_date sensor (#10694)
* fix to time_date sensor

* cleaned up the code and added unit tests

* fixed lint errors
2017-11-19 19:41:30 -08:00
Paulus Schoutsen
3f5c748560 Reorganize lint travis builds (#10670)
* tox cleanup

* 1 tox step

* Revert pytest sugar changes

* Tox: make pylint its own task

* Bump Travis to 30 minutes timeout
2017-11-19 17:39:24 -08:00
PeteBa
fb32cc39e1 Populate measurement state field for HA states like home/not_home (#9833) 2017-11-19 23:49:49 +01:00
Philip Kleimeyer
b548116f9b Tahoma platform for Somfy Covers and Sensors (#10652)
Tahoma platform for Somfy Covers and Sensors
2017-11-19 21:35:13 +01:00
PeteBa
2031b2803f Include unit_of_measurement as InfluxDb field (#9790) 2017-11-19 21:30:47 +01:00
Fabian Affolter
50775ce509 Bump dev to 0.59.0.dev0 (#10675) 2017-11-19 14:37:07 +01:00
Anders Melchiorsen
709df1e844 Properly initialize Harmony remote (#10665)
The delay_secs variable was not initialized if discovery was active and no
matching configuration block existed (i.e. override was None).
2017-11-19 05:20:31 +01:00
Giel Janssens
09d826edf4 Netatmo httperror403 fix (#10659)
* Update lnetatmo

* updated zip

* updated zip
2017-11-18 14:36:01 -08:00
Lukas Barth
086f64b06c Fix yweather (#10661) 2017-11-18 14:33:18 -08:00
frittes
6ad62a2ccb Added cycles config option to LaMetric notifications (#10656)
* Added cycles config option to lametric.py

Added cycles config option, changed display_time to lifetime, code cleanup

* Update lametric.py

* Update lametric.py
2017-11-18 21:12:16 +01:00
Charles Garwood
92fe9aadc8 Change some warnings to info (#10386) 2017-11-18 20:04:09 +01:00
Derek Brooks
a9feafd571 add nuheat to coverage reports 2017-11-18 10:26:36 -06:00
Derek Brooks
e1d1cf76ca Add Facebook Notification tests (#10642)
* test the facebook notification component

* respond to hound feedback

* remove unnecessary line breaks

* parse_qs not needed with requests_mock

* remove facebook notifier from .coveragerc
2017-11-17 21:12:36 -08:00
Robbie Trencheny
1317297191 Implement entity and domain exclude/include for Alexa (#10647)
* Implement entity and domain exclude/include for Alexa

* Switch to using generate_filter

* Use proper domain for turn on/off calls except for groups where we must use the generic homeassistant.turn_on/off

* travis fixes

* Untangle

* Lint
2017-11-17 21:10:24 -08:00
Pierre Ståhl
64a393b377 Bump pyatv to 0.3.8 (#10643)
Fixes AirPlay issues on newer versions of tvOS.
2017-11-18 00:00:15 +01:00
Aaron Bach
3ad64b0a66 Fixes AirVisual bug regarding incorrect location data (#10054)
* Fixes AirVisual bug regarding incorrect location data

* Owner-requested changes
2017-11-17 21:11:05 +01:00
William Scanlon
2664ca498e Support for Unifi direct access device tracker (No unifi controller software) (#10097) 2017-11-17 14:47:40 -05:00
Giel Janssens
5b44e83c0f Update lnetatmo (#10631) 2017-11-17 10:31:08 -08:00
Cezar Sá Espinola
b8b4e32758 Make MQTT reconnection logic more resilient and fix race condition (#10133) 2017-11-17 10:29:23 -08:00
Robbie Trencheny
2b60fca08d Alexa improvements (#10632)
* Initial scene support

* Initial fan support

* ordering

* Initial lock support

* Scenes cant be deactivated; Correct the scene display category

* Initial input_boolean support

* Support customization of Alexa discovered entities

* Initial media player support

* Add input_boolean to tests

* Add play/pause/stop/next/previous to media player

* Add missing functions and pylint

* Set manufacturerName to Home Assistant since the value is displayed in app

* Add scene test

* Add fan tests

* Add lock test

* Fix volume logic

* Add volume tests

* settup -> setup

* Remove unused variable

* Set required scene description as per docs

* Allow setting scene category (ACTIVITY_TRIGGER/SCENE_TRIGGER)

* Add alert, automation and group support/tests

* Change display categories to match docs

* simplify down the display category props into a single prop which can be used on any entity

* Fix tests to expect proper display categories

* Add cover support

* sort things

* Use generic homeassistant domain for turn on/off
2017-11-17 09:14:22 -08:00
Andrey
f43092c563 Print entity type in "too slow" warnings (#10641)
* Update entity.py

* Update entity.py
2017-11-17 17:36:18 +01:00
Lukas Barth
68d2076b56 Restore target temperature for generic thermostat (#10635)
* Restore target temp for generic thermostat

* Fix lint
2017-11-17 17:32:58 +01:00
cgtobi
be5f0fb3ac Add hddtemp sensor device even if unreachable. (#10623)
* Add hddtemp sensor device even if unreachable.

* Removed old commented code.

* Move unit detection logic into update.
2017-11-17 09:21:27 -05:00
Milan V
e9b691173a Change generic thermostat - any toggle device as heater switch (#10597)
* Change generic thermostat - any toggle device as heater

* Heater switch state method

* Tests

* Debug log, lint

* Debug code remove, cleanup

* Change generic thermostat to control heating on mode change Off -> Auto

* Fix typo

* Review fixes, tests

* Merge and fix tests
2017-11-17 12:47:54 +01:00
Alok Saboo
2a77883146 Added unit_of_measurement to Currencylayer (#10598)
* Added unit_of_measurement to Currencylayer

* Updated based on comments

* Remove quote from name
2017-11-17 08:58:46 +01:00
Derek Brooks
a3c6211c04 python 3.5 seems to not like assert_called_once() 2017-11-13 23:20:16 -06:00
Derek Brooks
afcb0b8767 fix up some docstrings 2017-11-13 23:13:04 -06:00
Derek Brooks
c0c439c549 that int() casting was redundant 2017-11-13 22:45:29 -06:00
Derek Brooks
959f6386b4 shorten that long line 2017-11-13 22:43:11 -06:00
Derek Brooks
f1fe8e95ba clean up a couple away temperature settings 2017-11-13 22:40:18 -06:00
Derek Brooks
6892033556 remove that unused constant 2017-11-13 12:31:15 -06:00
Derek Brooks
766893253a make sure is_away_mode_on supports user-defined minimum away temps 2017-11-13 12:28:09 -06:00
Derek Brooks
ef5edb95ba Update home/auto hold mode to be consistent with current documentation 2017-11-13 11:38:08 -06:00
Derek Brooks
f21b9988e9 allow for the configuring of a minimum away temperature 2017-11-13 11:00:33 -06:00
Derek Brooks
7859b76429 kill target_temperature_low and high. They don't make sense here 2017-11-13 10:35:48 -06:00
Derek Brooks
2c44e4fb12 address initial houndbot suggestions 2017-11-11 16:47:12 -06:00
Derek Brooks
9b373901fa add documentation links 2017-11-11 16:31:35 -06:00
Derek Brooks
37be81c20c add ability to resume program... and add in a forgotten test 2017-11-11 16:21:14 -06:00
Derek Brooks
5fe2db228c bug fixes and linting 2017-11-11 10:18:32 -06:00
Derek Brooks
c91d52a587 first stab at the nuheat components 2017-11-11 00:22:37 -06:00
878 changed files with 40512 additions and 16497 deletions

View File

@@ -11,6 +11,9 @@ omit =
homeassistant/components/abode.py
homeassistant/components/*/abode.py
homeassistant/components/ads/__init__.py
homeassistant/components/*/ads.py
homeassistant/components/alarmdecoder.py
homeassistant/components/*/alarmdecoder.py
@@ -47,12 +50,20 @@ omit =
homeassistant/components/bloomsky.py
homeassistant/components/*/bloomsky.py
homeassistant/components/coinbase.py
homeassistant/components/sensor/coinbase.py
homeassistant/components/comfoconnect.py
homeassistant/components/*/comfoconnect.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
@@ -80,9 +91,15 @@ omit =
homeassistant/components/hdmi_cec.py
homeassistant/components/*/hdmi_cec.py
homeassistant/components/homematic.py
homeassistant/components/hive.py
homeassistant/components/*/hive.py
homeassistant/components/homematic/__init__.py
homeassistant/components/*/homematic.py
homeassistant/components/ihc/*
homeassistant/components/*/ihc.py
homeassistant/components/insteon_local.py
homeassistant/components/*/insteon_local.py
@@ -92,6 +109,9 @@ omit =
homeassistant/components/ios.py
homeassistant/components/*/ios.py
homeassistant/components/iota.py
homeassistant/components/*/iota.py
homeassistant/components/isy994.py
homeassistant/components/*/isy994.py
@@ -125,12 +145,18 @@ omit =
homeassistant/components/maxcube.py
homeassistant/components/*/maxcube.py
homeassistant/components/mercedesme.py
homeassistant/components/*/mercedesme.py
homeassistant/components/mochad.py
homeassistant/components/*/mochad.py
homeassistant/components/modbus.py
homeassistant/components/*/modbus.py
homeassistant/components/mychevy.py
homeassistant/components/*/mychevy.py
homeassistant/components/mysensors.py
homeassistant/components/*/mysensors.py
@@ -182,6 +208,9 @@ omit =
homeassistant/components/tado.py
homeassistant/components/*/tado.py
homeassistant/components/tahoma.py
homeassistant/components/*/tahoma.py
homeassistant/components/tellduslive.py
homeassistant/components/*/tellduslive.py
@@ -224,6 +253,9 @@ omit =
homeassistant/components/volvooncall.py
homeassistant/components/*/volvooncall.py
homeassistant/components/waterfurnace.py
homeassistant/components/*/waterfurnace.py
homeassistant/components/*/webostv.py
homeassistant/components/wemo.py
@@ -252,9 +284,14 @@ omit =
homeassistant/components/zoneminder.py
homeassistant/components/*/zoneminder.py
homeassistant/components/daikin.py
homeassistant/components/*/daikin.py
homeassistant/components/alarm_control_panel/alarmdotcom.py
homeassistant/components/alarm_control_panel/canary.py
homeassistant/components/alarm_control_panel/concord232.py
homeassistant/components/alarm_control_panel/egardia.py
homeassistant/components/alarm_control_panel/ialarm.py
homeassistant/components/alarm_control_panel/manual_mqtt.py
homeassistant/components/alarm_control_panel/nx584.py
homeassistant/components/alarm_control_panel/simplisafe.py
@@ -271,26 +308,33 @@ omit =
homeassistant/components/binary_sensor/rest.py
homeassistant/components/binary_sensor/tapsaff.py
homeassistant/components/browser.py
homeassistant/components/calendar/caldav.py
homeassistant/components/calendar/todoist.py
homeassistant/components/camera/bloomsky.py
homeassistant/components/camera/canary.py
homeassistant/components/camera/ffmpeg.py
homeassistant/components/camera/foscam.py
homeassistant/components/camera/mjpeg.py
homeassistant/components/camera/rpi_camera.py
homeassistant/components/camera/onvif.py
homeassistant/components/camera/ring.py
homeassistant/components/camera/rpi_camera.py
homeassistant/components/camera/synology.py
homeassistant/components/camera/xeoma.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
homeassistant/components/climate/heatmiser.py
homeassistant/components/climate/homematic.py
homeassistant/components/climate/honeywell.py
homeassistant/components/climate/knx.py
homeassistant/components/climate/oem.py
homeassistant/components/climate/proliphix.py
homeassistant/components/climate/radiotherm.py
homeassistant/components/climate/sensibo.py
homeassistant/components/climate/touchline.py
homeassistant/components/climate/venstar.py
homeassistant/components/cover/garadget.py
homeassistant/components/cover/homematic.py
homeassistant/components/cover/knx.py
@@ -300,7 +344,6 @@ omit =
homeassistant/components/cover/scsgate.py
homeassistant/components/device_tracker/actiontec.py
homeassistant/components/device_tracker/aruba.py
homeassistant/components/device_tracker/asuswrt.py
homeassistant/components/device_tracker/automatic.py
homeassistant/components/device_tracker/bbox.py
homeassistant/components/device_tracker/bluetooth_le_tracker.py
@@ -323,10 +366,10 @@ omit =
homeassistant/components/device_tracker/sky_hub.py
homeassistant/components/device_tracker/snmp.py
homeassistant/components/device_tracker/swisscom.py
homeassistant/components/device_tracker/thomson.py
homeassistant/components/device_tracker/tomato.py
homeassistant/components/device_tracker/tado.py
homeassistant/components/device_tracker/thomson.py
homeassistant/components/device_tracker/tile.py
homeassistant/components/device_tracker/tomato.py
homeassistant/components/device_tracker/tplink.py
homeassistant/components/device_tracker/trackr.py
homeassistant/components/device_tracker/ubus.py
@@ -337,6 +380,7 @@ omit =
homeassistant/components/fan/xiaomi_miio.py
homeassistant/components/feedreader.py
homeassistant/components/foursquare.py
homeassistant/components/goalfeed.py
homeassistant/components/ifttt.py
homeassistant/components/image_processing/dlib_face_detect.py
homeassistant/components/image_processing/dlib_face_identify.py
@@ -344,20 +388,22 @@ omit =
homeassistant/components/keyboard.py
homeassistant/components/keyboard_remote.py
homeassistant/components/light/avion.py
homeassistant/components/light/blinkt.py
homeassistant/components/light/blinksticklight.py
homeassistant/components/light/blinkt.py
homeassistant/components/light/decora.py
homeassistant/components/light/decora_wifi.py
homeassistant/components/light/flux_led.py
homeassistant/components/light/greenwave.py
homeassistant/components/light/hue.py
homeassistant/components/light/hyperion.py
homeassistant/components/light/iglo.py
homeassistant/components/light/lifx.py
homeassistant/components/light/lifx_legacy.py
homeassistant/components/light/limitlessled.py
homeassistant/components/light/mystrom.py
homeassistant/components/light/osramlightify.py
homeassistant/components/light/rpi_gpio_pwm.py
homeassistant/components/light/piglow.py
homeassistant/components/light/rpi_gpio_pwm.py
homeassistant/components/light/sensehat.py
homeassistant/components/light/tikteck.py
homeassistant/components/light/tplink.py
@@ -368,9 +414,9 @@ omit =
homeassistant/components/light/yeelightsunflower.py
homeassistant/components/light/zengge.py
homeassistant/components/lirc.py
homeassistant/components/lock/lockitron.py
homeassistant/components/lock/nello.py
homeassistant/components/lock/nuki.py
homeassistant/components/lock/lockitron.py
homeassistant/components/lock/sesame.py
homeassistant/components/media_extractor.py
homeassistant/components/media_player/anthemav.py
@@ -393,6 +439,7 @@ omit =
homeassistant/components/media_player/kodi.py
homeassistant/components/media_player/lg_netcast.py
homeassistant/components/media_player/liveboxplaytv.py
homeassistant/components/media_player/mediaroom.py
homeassistant/components/media_player/mpchc.py
homeassistant/components/media_player/mpd.py
homeassistant/components/media_player/nad.py
@@ -407,16 +454,17 @@ omit =
homeassistant/components/media_player/roku.py
homeassistant/components/media_player/russound_rio.py
homeassistant/components/media_player/russound_rnet.py
homeassistant/components/media_player/samsungtv.py
homeassistant/components/media_player/snapcast.py
homeassistant/components/media_player/sonos.py
homeassistant/components/media_player/spotify.py
homeassistant/components/media_player/squeezebox.py
homeassistant/components/media_player/ue_smart_radio.py
homeassistant/components/media_player/vizio.py
homeassistant/components/media_player/vlc.py
homeassistant/components/media_player/volumio.py
homeassistant/components/media_player/yamaha.py
homeassistant/components/media_player/yamaha_musiccast.py
homeassistant/components/media_player/ziggo_mediabox_xl.py
homeassistant/components/mycroft.py
homeassistant/components/notify/aws_lambda.py
homeassistant/components/notify/aws_sns.py
@@ -426,7 +474,6 @@ omit =
homeassistant/components/notify/clicksend.py
homeassistant/components/notify/clicksend_tts.py
homeassistant/components/notify/discord.py
homeassistant/components/notify/facebook.py
homeassistant/components/notify/free_mobile.py
homeassistant/components/notify/gntp.py
homeassistant/components/notify/group.py
@@ -459,12 +506,15 @@ omit =
homeassistant/components/notify/yessssms.py
homeassistant/components/nuimo_controller.py
homeassistant/components/prometheus.py
homeassistant/components/rainbird.py
homeassistant/components/remember_the_milk/__init__.py
homeassistant/components/remote/harmony.py
homeassistant/components/remote/itach.py
homeassistant/components/remote/xiaomi_miio.py
homeassistant/components/scene/hunterdouglas_powerview.py
homeassistant/components/scene/lifx_cloud.py
homeassistant/components/sensor/airvisual.py
homeassistant/components/sensor/alpha_vantage.py
homeassistant/components/sensor/arest.py
homeassistant/components/sensor/arwn.py
homeassistant/components/sensor/bbox.py
@@ -472,11 +522,12 @@ omit =
homeassistant/components/sensor/bitcoin.py
homeassistant/components/sensor/blockchain.py
homeassistant/components/sensor/bme280.py
homeassistant/components/sensor/bme680.py
homeassistant/components/sensor/bom.py
homeassistant/components/sensor/broadlink.py
homeassistant/components/sensor/buienradar.py
homeassistant/components/sensor/citybikes.py
homeassistant/components/sensor/cert_expiry.py
homeassistant/components/sensor/citybikes.py
homeassistant/components/sensor/comed_hourly_pricing.py
homeassistant/components/sensor/cpuspeed.py
homeassistant/components/sensor/crimereports.py
@@ -486,6 +537,7 @@ omit =
homeassistant/components/sensor/deluge.py
homeassistant/components/sensor/deutsche_bahn.py
homeassistant/components/sensor/dht.py
homeassistant/components/sensor/discogs.py
homeassistant/components/sensor/dnsip.py
homeassistant/components/sensor/dovado.py
homeassistant/components/sensor/dte_energy_bridge.py
@@ -499,11 +551,11 @@ omit =
homeassistant/components/sensor/etherscan.py
homeassistant/components/sensor/fastdotcom.py
homeassistant/components/sensor/fedex.py
homeassistant/components/sensor/fido.py
homeassistant/components/sensor/fitbit.py
homeassistant/components/sensor/fixer.py
homeassistant/components/sensor/fritzbox_callmonitor.py
homeassistant/components/sensor/fritzbox_netmonitor.py
homeassistant/components/sensor/gearbest.py
homeassistant/components/sensor/geizhals.py
homeassistant/components/sensor/gitter.py
homeassistant/components/sensor/glances.py
@@ -513,7 +565,6 @@ omit =
homeassistant/components/sensor/haveibeenpwned.py
homeassistant/components/sensor/hp_ilo.py
homeassistant/components/sensor/htu21d.py
homeassistant/components/sensor/hydroquebec.py
homeassistant/components/sensor/imap.py
homeassistant/components/sensor/imap_email_content.py
homeassistant/components/sensor/influxdb.py
@@ -546,11 +597,13 @@ omit =
homeassistant/components/sensor/pi_hole.py
homeassistant/components/sensor/plex.py
homeassistant/components/sensor/pocketcasts.py
homeassistant/components/sensor/pollen.py
homeassistant/components/sensor/pushbullet.py
homeassistant/components/sensor/pvoutput.py
homeassistant/components/sensor/pyload.py
homeassistant/components/sensor/qnap.py
homeassistant/components/sensor/radarr.py
homeassistant/components/sensor/rainbird.py
homeassistant/components/sensor/ripple.py
homeassistant/components/sensor/sabnzbd.py
homeassistant/components/sensor/scrape.py
@@ -561,6 +614,7 @@ omit =
homeassistant/components/sensor/skybeacon.py
homeassistant/components/sensor/sma.py
homeassistant/components/sensor/snmp.py
homeassistant/components/sensor/sochain.py
homeassistant/components/sensor/sonarr.py
homeassistant/components/sensor/speedtest.py
homeassistant/components/sensor/steam_online.py
@@ -572,6 +626,7 @@ omit =
homeassistant/components/sensor/sytadin.py
homeassistant/components/sensor/tank_utility.py
homeassistant/components/sensor/ted5000.py
homeassistant/components/sensor/teksavvy.py
homeassistant/components/sensor/temper.py
homeassistant/components/sensor/tibber.py
homeassistant/components/sensor/time_date.py
@@ -589,7 +644,6 @@ omit =
homeassistant/components/sensor/worldtidesinfo.py
homeassistant/components/sensor/worxlandroid.py
homeassistant/components/sensor/xbox_live.py
homeassistant/components/sensor/yweather.py
homeassistant/components/sensor/zamg.py
homeassistant/components/shiftr.py
homeassistant/components/spc.py
@@ -615,26 +669,27 @@ omit =
homeassistant/components/switch/rest.py
homeassistant/components/switch/rpi_rf.py
homeassistant/components/switch/snmp.py
homeassistant/components/switch/tplink.py
homeassistant/components/switch/telnet.py
homeassistant/components/switch/tplink.py
homeassistant/components/switch/transmission.py
homeassistant/components/switch/xiaomi_miio.py
homeassistant/components/telegram_bot/*
homeassistant/components/thingspeak.py
homeassistant/components/tts/amazon_polly.py
homeassistant/components/tts/baidu.py
homeassistant/components/tts/microsoft.py
homeassistant/components/tts/picotts.py
homeassistant/components/vacuum/mqtt.py
homeassistant/components/vacuum/roomba.py
homeassistant/components/vacuum/xiaomi_miio.py
homeassistant/components/weather/bom.py
homeassistant/components/weather/buienradar.py
homeassistant/components/weather/darksky.py
homeassistant/components/weather/metoffice.py
homeassistant/components/weather/openweathermap.py
homeassistant/components/weather/yweather.py
homeassistant/components/weather/zamg.py
homeassistant/components/zeroconf.py
homeassistant/components/zwave/util.py
homeassistant/components/vacuum/mqtt.py
[report]
# Regexes for lines to exclude from consideration

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Ensure Docker script files uses LF to support Docker for Windows.
setup_docker_prereqs eol=lf
/virtualization/Docker/scripts/* eol=lf

View File

@@ -11,6 +11,7 @@
```
## Checklist:
- [ ] The code change is tested and works locally.
If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [home-assistant.github.io](https://github.com/home-assistant/home-assistant.github.io)

13
.github/move.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# Configuration for move-issues - https://github.com/dessant/move-issues
# Delete the command comment. Ignored when the comment also contains other content
deleteCommand: true
# Close the source issue after moving
closeSourceIssue: true
# Lock the source issue after moving
lockSourceIssue: false
# Set custom aliases for targets
# aliases:
# r: repo
# or: owner/repo

8
.gitignore vendored
View File

@@ -16,7 +16,9 @@ Icon
# Thumbnails
._*
# IntelliJ IDEA
.idea
*.iml
# pytest
.cache
@@ -74,6 +76,7 @@ pip-selfcheck.json
venv
.venv
Pipfile*
share/*
# vimmy stuff
*.swp
@@ -96,4 +99,7 @@ docs/build
desktop.ini
/home-assistant.pyproj
/home-assistant.sln
/.vs/home-assistant/v14
/.vs/*
# mypy
/.mypy_cache/*

View File

@@ -8,18 +8,18 @@ matrix:
include:
- python: "3.4.2"
env: TOXENV=lint
- python: "3.4.2"
env: TOXENV=pylint
- python: "3.4.2"
env: TOXENV=py34
# - python: "3.5"
# env: TOXENV=typing
- python: "3.5"
- python: "3.5.3"
env: TOXENV=py35
- python: "3.6"
env: TOXENV=py36
# - python: "3.6-dev"
# env: TOXENV=py36
- python: "3.4.2"
env: TOXENV=requirements
# allow_failures:
# - python: "3.5"
# env: TOXENV=typing
@@ -29,5 +29,5 @@ cache:
- $HOME/.cache/pip
install: pip install -U tox coveralls
language: python
script: travis_wait tox
script: travis_wait 30 tox --develop
after_success: coveralls

View File

@@ -32,13 +32,16 @@ homeassistant/components/zone.py @home-assistant/core
# To monitor non-pypi additions
requirements_all.txt @andrey-git
# HomeAssistant 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
# Indiviudal components
homeassistant/components/hassio.py @home-assistant/hassio
# Individual components
homeassistant/components/alarm_control_panel/egardia.py @jeroenterheerdt
homeassistant/components/camera/yi.py @bachya
homeassistant/components/climate/ephember.py @ttroy50
@@ -46,15 +49,19 @@ homeassistant/components/climate/eq3btsmart.py @rytilahti
homeassistant/components/climate/sensibo.py @andrey-git
homeassistant/components/cover/template.py @PhracturedBlue
homeassistant/components/device_tracker/automatic.py @armills
homeassistant/components/device_tracker/tile.py @bachya
homeassistant/components/history_graph.py @andrey-git
homeassistant/components/light/tplink.py @rytilahti
homeassistant/components/light/yeelight.py @rytilahti
homeassistant/components/media_player/kodi.py @armills
homeassistant/components/media_player/monoprice.py @etsinko
homeassistant/components/media_player/yamaha_musiccast.py @jalmeroth
homeassistant/components/plant.py @ChristianKuehnel
homeassistant/components/sensor/airvisual.py @bachya
homeassistant/components/sensor/gearbest.py @HerrHofrat
homeassistant/components/sensor/irish_rail_transport.py @ttroy50
homeassistant/components/sensor/miflora.py @danielhiversen
homeassistant/components/sensor/miflora.py @danielhiversen @ChristianKuehnel
homeassistant/components/sensor/pollen.py @bachya
homeassistant/components/sensor/sytadin.py @gautric
homeassistant/components/sensor/tibber.py @danielhiversen
homeassistant/components/sensor/waqi.py @andrey-git
@@ -62,14 +69,22 @@ homeassistant/components/switch/rainmachine.py @bachya
homeassistant/components/switch/tplink.py @rytilahti
homeassistant/components/xiaomi_aqara.py @danielhiversen @syssi
homeassistant/components/*/axis.py @kane610
homeassistant/components/*/broadlink.py @danielhiversen
homeassistant/components/hive.py @Rendili @KJonline
homeassistant/components/*/hive.py @Rendili @KJonline
homeassistant/components/*/deconz.py @kane610
homeassistant/components/*/rfxtrx.py @danielhiversen
homeassistant/components/velux.py @Julius2342
homeassistant/components/*/velux.py @Julius2342
homeassistant/components/knx.py @Julius2342
homeassistant/components/*/knx.py @Julius2342
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/*/tradfri.py @ggravlingen
homeassistant/components/*/xiaomi_aqara.py @danielhiversen @syssi
homeassistant/components/*/xiaomi_miio.py @rytilahti @syssi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -2,5 +2,5 @@
<li><a href="https://home-assistant.io/">Homepage</a></li>
<li><a href="https://community.home-assistant.io">Community Forums</a></li>
<li><a href="https://github.com/home-assistant/home-assistant">GitHub</a></li>
<li><a href="https://gitter.im/home-assistant/home-assistant">Gitter</a></li>
<li><a href="https://discord.gg/c5DvZ4e">Discord</a></li>
</ul>

View File

@@ -182,7 +182,8 @@ def check_pid(pid_file: str) -> None:
"""Check that Home Assistant is not already running."""
# Check pid file
try:
pid = int(open(pid_file, 'r').readline())
with open(pid_file, 'r') as file:
pid = int(file.readline())
except IOError:
# PID File does not exist
return
@@ -204,7 +205,8 @@ def write_pid(pid_file: str) -> None:
"""Create a PID File."""
pid = os.getpid()
try:
open(pid_file, 'w').write(str(pid))
with open(pid_file, 'w') as file:
file.write(str(pid))
except IOError:
print('Fatal Error: Unable to write pid file {}'.format(pid_file))
sys.exit(1)
@@ -230,7 +232,7 @@ def closefds_osx(min_fd: int, max_fd: int) -> None:
def cmdline() -> List[str]:
"""Collect path and arguments to re-execute the current hass instance."""
if sys.argv[0].endswith(os.path.sep + '__main__.py'):
if os.path.basename(sys.argv[0]) == '__main__.py':
modulepath = os.path.dirname(sys.argv[0])
os.environ['PYTHONPATH'] = os.path.dirname(modulepath)
return [sys.executable] + [arg for arg in sys.argv if

View File

@@ -10,7 +10,6 @@ Component design guidelines:
import asyncio
import itertools as it
import logging
import os
import homeassistant.core as ha
import homeassistant.config as conf_util
@@ -111,11 +110,6 @@ def async_reload_core_config(hass):
@asyncio.coroutine
def async_setup(hass, config):
"""Set up general services related to Home Assistant."""
descriptions = yield from hass.async_add_job(
conf_util.load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml')
)
@asyncio.coroutine
def async_handle_turn_service(service):
"""Handle calls to homeassistant.turn_on/off."""
@@ -139,7 +133,7 @@ def async_setup(hass, config):
# have been processed. If a service does not exist it causes a 10
# second delay while we're blocking waiting for a response.
# But services can be registered on other HA instances that are
# listening to the bus too. So as a in between solution, we'll
# listening to the bus too. So as an in between solution, we'll
# block only if the service is defined in the current HA instance.
blocking = hass.services.has_service(domain, service.service)
@@ -155,14 +149,11 @@ def async_setup(hass, config):
yield from asyncio.wait(tasks, loop=hass.loop)
hass.services.async_register(
ha.DOMAIN, SERVICE_TURN_OFF, async_handle_turn_service,
descriptions[ha.DOMAIN][SERVICE_TURN_OFF])
ha.DOMAIN, SERVICE_TURN_OFF, async_handle_turn_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_TURN_ON, async_handle_turn_service,
descriptions[ha.DOMAIN][SERVICE_TURN_ON])
ha.DOMAIN, SERVICE_TURN_ON, async_handle_turn_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_TOGGLE, async_handle_turn_service,
descriptions[ha.DOMAIN][SERVICE_TOGGLE])
ha.DOMAIN, SERVICE_TOGGLE, async_handle_turn_service)
@asyncio.coroutine
def async_handle_core_service(call):
@@ -187,14 +178,11 @@ def async_setup(hass, config):
hass.async_add_job(hass.async_stop(RESTART_EXIT_CODE))
hass.services.async_register(
ha.DOMAIN, SERVICE_HOMEASSISTANT_STOP, async_handle_core_service,
descriptions[ha.DOMAIN][SERVICE_HOMEASSISTANT_STOP])
ha.DOMAIN, SERVICE_HOMEASSISTANT_STOP, async_handle_core_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_HOMEASSISTANT_RESTART, async_handle_core_service,
descriptions[ha.DOMAIN][SERVICE_HOMEASSISTANT_RESTART])
ha.DOMAIN, SERVICE_HOMEASSISTANT_RESTART, async_handle_core_service)
hass.services.async_register(
ha.DOMAIN, SERVICE_CHECK_CONFIG, async_handle_core_service,
descriptions[ha.DOMAIN][SERVICE_CHECK_CONFIG])
ha.DOMAIN, SERVICE_CHECK_CONFIG, async_handle_core_service)
@asyncio.coroutine
def async_handle_reload_config(call):
@@ -209,7 +197,6 @@ def async_setup(hass, config):
hass, conf.get(ha.DOMAIN) or {})
hass.services.async_register(
ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG, async_handle_reload_config,
descriptions[ha.DOMAIN][SERVICE_RELOAD_CORE_CONFIG])
ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG, async_handle_reload_config)
return True

View File

@@ -7,11 +7,9 @@ https://home-assistant.io/components/abode/
import asyncio
import logging
from functools import partial
from os import path
import voluptuous as vol
from homeassistant.config import load_yaml_config_file
from homeassistant.const import (
ATTR_ATTRIBUTION, ATTR_DATE, ATTR_TIME, ATTR_ENTITY_ID, CONF_USERNAME,
CONF_PASSWORD, CONF_EXCLUDE, CONF_NAME, CONF_LIGHTS,
@@ -188,22 +186,16 @@ def setup_hass_services(hass):
for device in target_devices:
device.trigger()
descriptions = load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml'))[DOMAIN]
hass.services.register(
DOMAIN, SERVICE_SETTINGS, change_setting,
descriptions.get(SERVICE_SETTINGS),
schema=CHANGE_SETTING_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_CAPTURE_IMAGE, capture_image,
descriptions.get(SERVICE_CAPTURE_IMAGE),
schema=CAPTURE_IMAGE_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_TRIGGER, trigger_quick_action,
descriptions.get(SERVICE_TRIGGER),
schema=TRIGGER_SCHEMA)

View File

@@ -0,0 +1,196 @@
"""
Support for Automation Device Specification (ADS).
For more details about this component, please refer to the documentation.
https://home-assistant.io/components/ads/
"""
import threading
import struct
import logging
import ctypes
from collections import namedtuple
import voluptuous as vol
from homeassistant.const import CONF_DEVICE, CONF_PORT, CONF_IP_ADDRESS, \
EVENT_HOMEASSISTANT_STOP
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyads==2.2.6']
_LOGGER = logging.getLogger(__name__)
DATA_ADS = 'data_ads'
# Supported Types
ADSTYPE_INT = 'int'
ADSTYPE_UINT = 'uint'
ADSTYPE_BYTE = 'byte'
ADSTYPE_BOOL = 'bool'
DOMAIN = 'ads'
CONF_ADS_VAR = 'adsvar'
CONF_ADS_VAR_BRIGHTNESS = 'adsvar_brightness'
CONF_ADS_TYPE = 'adstype'
CONF_ADS_FACTOR = 'factor'
CONF_ADS_VALUE = 'value'
SERVICE_WRITE_DATA_BY_NAME = 'write_data_by_name'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_DEVICE): cv.string,
vol.Required(CONF_PORT): cv.port,
vol.Optional(CONF_IP_ADDRESS): cv.string,
})
}, extra=vol.ALLOW_EXTRA)
SCHEMA_SERVICE_WRITE_DATA_BY_NAME = vol.Schema({
vol.Required(CONF_ADS_TYPE):
vol.In([ADSTYPE_INT, ADSTYPE_UINT, ADSTYPE_BYTE]),
vol.Required(CONF_ADS_VALUE): cv.match_all,
vol.Required(CONF_ADS_VAR): cv.string,
})
def setup(hass, config):
"""Set up the ADS component."""
import pyads
conf = config[DOMAIN]
net_id = conf.get(CONF_DEVICE)
ip_address = conf.get(CONF_IP_ADDRESS)
port = conf.get(CONF_PORT)
client = pyads.Connection(net_id, port, ip_address)
AdsHub.ADS_TYPEMAP = {
ADSTYPE_BOOL: pyads.PLCTYPE_BOOL,
ADSTYPE_BYTE: pyads.PLCTYPE_BYTE,
ADSTYPE_INT: pyads.PLCTYPE_INT,
ADSTYPE_UINT: pyads.PLCTYPE_UINT,
}
AdsHub.PLCTYPE_BOOL = pyads.PLCTYPE_BOOL
AdsHub.PLCTYPE_BYTE = pyads.PLCTYPE_BYTE
AdsHub.PLCTYPE_INT = pyads.PLCTYPE_INT
AdsHub.PLCTYPE_UINT = pyads.PLCTYPE_UINT
AdsHub.ADSError = pyads.ADSError
try:
ads = AdsHub(client)
except pyads.pyads.ADSError:
_LOGGER.error(
"Could not connect to ADS host (netid=%s, port=%s)", net_id, port)
return False
hass.data[DATA_ADS] = ads
hass.bus.listen(EVENT_HOMEASSISTANT_STOP, ads.shutdown)
def handle_write_data_by_name(call):
"""Write a value to the connected ADS device."""
ads_var = call.data.get(CONF_ADS_VAR)
ads_type = call.data.get(CONF_ADS_TYPE)
value = call.data.get(CONF_ADS_VALUE)
try:
ads.write_by_name(ads_var, value, ads.ADS_TYPEMAP[ads_type])
except pyads.ADSError as err:
_LOGGER.error(err)
hass.services.register(
DOMAIN, SERVICE_WRITE_DATA_BY_NAME, handle_write_data_by_name,
schema=SCHEMA_SERVICE_WRITE_DATA_BY_NAME)
return True
# Tuple to hold data needed for notification
NotificationItem = namedtuple(
'NotificationItem', 'hnotify huser name plc_datatype callback'
)
class AdsHub(object):
"""Representation of an ADS connection."""
def __init__(self, ads_client):
"""Initialize the ADS hub."""
self._client = ads_client
self._client.open()
# All ADS devices are registered here
self._devices = []
self._notification_items = {}
self._lock = threading.Lock()
def shutdown(self, *args, **kwargs):
"""Shutdown ADS connection."""
_LOGGER.debug("Shutting down ADS")
for notification_item in self._notification_items.values():
self._client.del_device_notification(
notification_item.hnotify,
notification_item.huser
)
_LOGGER.debug(
"Deleting device notification %d, %d",
notification_item.hnotify, notification_item.huser)
self._client.close()
def register_device(self, device):
"""Register a new device."""
self._devices.append(device)
def write_by_name(self, name, value, plc_datatype):
"""Write a value to the device."""
with self._lock:
return self._client.write_by_name(name, value, plc_datatype)
def read_by_name(self, name, plc_datatype):
"""Read a value from the device."""
with self._lock:
return self._client.read_by_name(name, plc_datatype)
def add_device_notification(self, name, plc_datatype, callback):
"""Add a notification to the ADS devices."""
from pyads import NotificationAttrib
attr = NotificationAttrib(ctypes.sizeof(plc_datatype))
with self._lock:
hnotify, huser = self._client.add_device_notification(
name, attr, self._device_notification_callback)
hnotify = int(hnotify)
_LOGGER.debug(
"Added device notification %d for variable %s", hnotify, name)
self._notification_items[hnotify] = NotificationItem(
hnotify, huser, name, plc_datatype, callback)
def _device_notification_callback(self, addr, notification, huser):
"""Handle device notifications."""
contents = notification.contents
hnotify = int(contents.hNotification)
_LOGGER.debug("Received notification %d", hnotify)
data = contents.data
try:
notification_item = self._notification_items[hnotify]
except KeyError:
_LOGGER.debug("Unknown device notification handle: %d", hnotify)
return
# Parse data to desired datatype
if notification_item.plc_datatype == self.PLCTYPE_BOOL:
value = bool(struct.unpack('<?', bytearray(data)[:1])[0])
elif notification_item.plc_datatype == self.PLCTYPE_INT:
value = struct.unpack('<h', bytearray(data)[:2])[0]
elif notification_item.plc_datatype == self.PLCTYPE_BYTE:
value = struct.unpack('<B', bytearray(data)[:1])[0]
elif notification_item.plc_datatype == self.PLCTYPE_UINT:
value = struct.unpack('<H', bytearray(data)[:2])[0]
else:
value = bytearray(data)
_LOGGER.warning("No callback available for this datatype")
notification_item.callback(notification_item.name, value)

View File

@@ -0,0 +1,15 @@
# Describes the format for available ADS services
write_data_by_name:
description: Write a value to the connected ADS device.
fields:
adsvar:
description: The name of the variable to write to.
example: '.global_var'
adstype:
description: The data type of the variable to write to.
example: 'int'
value:
description: The value to write to the variable.
example: 1

View File

@@ -7,15 +7,13 @@ https://home-assistant.io/components/alarm_control_panel/
import asyncio
from datetime import timedelta
import logging
import os
import voluptuous as vol
from homeassistant.const import (
ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER,
SERVICE_ALARM_DISARM, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_NIGHT)
from homeassistant.config import load_yaml_config_file
SERVICE_ALARM_ARM_NIGHT, SERVICE_ALARM_ARM_CUSTOM_BYPASS)
from homeassistant.loader import bind_hass
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv
@@ -33,6 +31,7 @@ SERVICE_TO_METHOD = {
SERVICE_ALARM_ARM_HOME: 'alarm_arm_home',
SERVICE_ALARM_ARM_AWAY: 'alarm_arm_away',
SERVICE_ALARM_ARM_NIGHT: 'alarm_arm_night',
SERVICE_ALARM_ARM_CUSTOM_BYPASS: 'alarm_arm_custom_bypass',
SERVICE_ALARM_TRIGGER: 'alarm_trigger'
}
@@ -107,6 +106,18 @@ def alarm_trigger(hass, code=None, entity_id=None):
hass.services.call(DOMAIN, SERVICE_ALARM_TRIGGER, data)
@bind_hass
def alarm_arm_custom_bypass(hass, code=None, entity_id=None):
"""Send the alarm the command for arm custom bypass."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_CUSTOM_BYPASS, data)
@asyncio.coroutine
def async_setup(hass, config):
"""Track states and offer events for sensors."""
@@ -135,14 +146,10 @@ def async_setup(hass, config):
if update_tasks:
yield from asyncio.wait(update_tasks, loop=hass.loop)
descriptions = yield from hass.async_add_job(
load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
for service in SERVICE_TO_METHOD:
hass.services.async_register(
DOMAIN, service, async_alarm_service_handler,
descriptions.get(service), schema=ALARM_SERVICE_SCHEMA)
schema=ALARM_SERVICE_SCHEMA)
return True
@@ -216,6 +223,17 @@ class AlarmControlPanel(Entity):
"""
return self.hass.async_add_job(self.alarm_trigger, code)
def alarm_arm_custom_bypass(self, code=None):
"""Send arm custom bypass command."""
raise NotImplementedError()
def async_alarm_arm_custom_bypass(self, code=None):
"""Send arm custom bypass command.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.async_add_job(self.alarm_arm_custom_bypass, code)
@property
def state_attributes(self):
"""Return the state attributes."""

View File

@@ -6,12 +6,12 @@ https://home-assistant.io/components/alarm_control_panel.abode/
"""
import logging
from homeassistant.components.abode import (
AbodeDevice, DOMAIN as ABODE_DOMAIN, CONF_ATTRIBUTION)
from homeassistant.components.alarm_control_panel import (AlarmControlPanel)
from homeassistant.const import (ATTR_ATTRIBUTION, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED)
from homeassistant.components.abode import CONF_ATTRIBUTION, AbodeDevice
from homeassistant.components.abode import DOMAIN as ABODE_DOMAIN
from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.const import (
ATTR_ATTRIBUTION, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED)
DEPENDENCIES = ['abode']
@@ -21,7 +21,7 @@ ICON = 'mdi:security'
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up a sensor for an Abode device."""
"""Set up an alarm control panel for an Abode device."""
data = hass.data[ABODE_DOMAIN]
alarm_devices = [AbodeAlarm(data, data.abode.get_alarm(), data.name)]
@@ -41,7 +41,7 @@ class AbodeAlarm(AbodeDevice, AlarmControlPanel):
@property
def icon(self):
"""Return icon."""
"""Return the icon."""
return ICON
@property
@@ -81,5 +81,5 @@ class AbodeAlarm(AbodeDevice, AlarmControlPanel):
ATTR_ATTRIBUTION: CONF_ATTRIBUTION,
'device_id': self._device.device_id,
'battery_backup': self._device.battery,
'cellular_backup': self._device.is_cellular
'cellular_backup': self._device.is_cellular,
}

View File

@@ -7,69 +7,86 @@ https://home-assistant.io/components/alarm_control_panel.alarmdecoder/
import asyncio
import logging
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarmdecoder import (DATA_AD,
SIGNAL_PANEL_MESSAGE)
from homeassistant.components.alarmdecoder import DATA_AD, SIGNAL_PANEL_MESSAGE
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN, STATE_ALARM_TRIGGERED)
ATTR_CODE, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['alarmdecoder']
SERVICE_ALARM_TOGGLE_CHIME = 'alarmdecoder_alarm_toggle_chime'
ALARM_TOGGLE_CHIME_SCHEMA = vol.Schema({
vol.Required(ATTR_CODE): cv.string,
})
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up for AlarmDecoder alarm panels."""
_LOGGER.debug("AlarmDecoderAlarmPanel: setup")
device = AlarmDecoderAlarmPanel()
add_devices([device])
device = AlarmDecoderAlarmPanel("Alarm Panel", hass)
def alarm_toggle_chime_handler(service):
"""Register toggle chime handler."""
code = service.data.get(ATTR_CODE)
device.alarm_toggle_chime(code)
async_add_devices([device])
return True
hass.services.register(
alarm.DOMAIN, SERVICE_ALARM_TOGGLE_CHIME, alarm_toggle_chime_handler,
schema=ALARM_TOGGLE_CHIME_SCHEMA)
class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
"""Representation of an AlarmDecoder-based alarm panel."""
def __init__(self, name, hass):
def __init__(self):
"""Initialize the alarm panel."""
self._display = ""
self._name = name
self._state = STATE_UNKNOWN
_LOGGER.debug("Setting up panel")
self._name = "Alarm Panel"
self._state = None
self._ac_power = None
self._backlight_on = None
self._battery_low = None
self._check_zone = None
self._chime = None
self._entry_delay_off = None
self._programming_mode = None
self._ready = None
self._zone_bypassed = None
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_PANEL_MESSAGE, self._message_callback)
self.hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_PANEL_MESSAGE, self._message_callback)
@callback
def _message_callback(self, message):
"""Handle received messages."""
if message.alarm_sounding or message.fire_alarm:
if self._state != STATE_ALARM_TRIGGERED:
self._state = STATE_ALARM_TRIGGERED
self.async_schedule_update_ha_state()
self._state = STATE_ALARM_TRIGGERED
elif message.armed_away:
if self._state != STATE_ALARM_ARMED_AWAY:
self._state = STATE_ALARM_ARMED_AWAY
self.async_schedule_update_ha_state()
self._state = STATE_ALARM_ARMED_AWAY
elif message.armed_home:
if self._state != STATE_ALARM_ARMED_HOME:
self._state = STATE_ALARM_ARMED_HOME
self.async_schedule_update_ha_state()
self._state = STATE_ALARM_ARMED_HOME
else:
if self._state != STATE_ALARM_DISARMED:
self._state = STATE_ALARM_DISARMED
self.async_schedule_update_ha_state()
self._state = STATE_ALARM_DISARMED
self._ac_power = message.ac_power
self._backlight_on = message.backlight_on
self._battery_low = message.battery_low
self._check_zone = message.check_zone
self._chime = message.chime_on
self._entry_delay_off = message.entry_delay_off
self._programming_mode = message.programming_mode
self._ready = message.ready
self._zone_bypassed = message.zone_bypassed
self.schedule_update_ha_state()
@property
def name(self):
@@ -91,26 +108,37 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
"""Return the state of the device."""
return self._state
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
@property
def device_state_attributes(self):
"""Return the state attributes."""
return {
'ac_power': self._ac_power,
'backlight_on': self._backlight_on,
'battery_low': self._battery_low,
'check_zone': self._check_zone,
'chime': self._chime,
'entry_delay_off': self._entry_delay_off,
'programming_mode': self._programming_mode,
'ready': self._ready,
'zone_bypassed': self._zone_bypassed,
}
def alarm_disarm(self, code=None):
"""Send disarm command."""
_LOGGER.debug("alarm_disarm: %s", code)
if code:
_LOGGER.debug("alarm_disarm: sending %s1", str(code))
self.hass.data[DATA_AD].send("{!s}1".format(code))
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
def alarm_arm_away(self, code=None):
"""Send arm away command."""
_LOGGER.debug("alarm_arm_away: %s", code)
if code:
_LOGGER.debug("alarm_arm_away: sending %s2", str(code))
self.hass.data[DATA_AD].send("{!s}2".format(code))
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
def alarm_arm_home(self, code=None):
"""Send arm home command."""
_LOGGER.debug("alarm_arm_home: %s", code)
if code:
_LOGGER.debug("alarm_arm_home: sending %s3", str(code))
self.hass.data[DATA_AD].send("{!s}3".format(code))
def alarm_toggle_chime(self, code=None):
"""Send toggle chime command."""
if code:
self.hass.data[DATA_AD].send("{!s}9".format(code))

View File

@@ -4,17 +4,18 @@ Interfaces with Alarm.com alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.alarmdotcom/
"""
import logging
import asyncio
import logging
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN, CONF_CODE,
CONF_NAME)
import homeassistant.helpers.config_validation as cv
CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyalarmdotcom==0.3.0']
@@ -44,7 +45,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class AlarmDotCom(alarm.AlarmControlPanel):
"""Represent an Alarm.com status."""
"""Representation of an Alarm.com status."""
def __init__(self, hass, name, code, username, password):
"""Initialize the Alarm.com status."""
@@ -57,10 +58,8 @@ class AlarmDotCom(alarm.AlarmControlPanel):
self._password = password
self._websession = async_get_clientsession(self._hass)
self._state = STATE_UNKNOWN
self._alarm = Alarmdotcom(username,
password,
self._websession,
hass.loop)
self._alarm = Alarmdotcom(
username, password, self._websession, hass.loop)
@asyncio.coroutine
def async_login(self):
@@ -80,7 +79,7 @@ class AlarmDotCom(alarm.AlarmControlPanel):
@property
def code_format(self):
"""One or more characters if code is defined."""
"""Return one or more characters if code is defined."""
return None if self._code is None else '.+'
@property
@@ -116,5 +115,5 @@ class AlarmDotCom(alarm.AlarmControlPanel):
"""Validate given code."""
check = self._code is None or code == self._code
if not check:
_LOGGER.warning('Wrong code entered.')
_LOGGER.warning("Wrong code entered")
return check

View File

@@ -22,6 +22,7 @@ _LOGGER = logging.getLogger(__name__)
ARMED = 'armed'
CONF_HOME_MODE_NAME = 'home_mode_name'
CONF_AWAY_MODE_NAME = 'away_mode_name'
DEPENDENCIES = ['arlo']
@@ -31,6 +32,7 @@ ICON = 'mdi:security'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_HOME_MODE_NAME, default=ARMED): cv.string,
vol.Optional(CONF_AWAY_MODE_NAME, default=ARMED): cv.string,
})
@@ -43,19 +45,22 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
return
home_mode_name = config.get(CONF_HOME_MODE_NAME)
away_mode_name = config.get(CONF_AWAY_MODE_NAME)
base_stations = []
for base_station in data.base_stations:
base_stations.append(ArloBaseStation(base_station, home_mode_name))
base_stations.append(ArloBaseStation(base_station, home_mode_name,
away_mode_name))
async_add_devices(base_stations, True)
class ArloBaseStation(AlarmControlPanel):
"""Representation of an Arlo Alarm Control Panel."""
def __init__(self, data, home_mode_name):
def __init__(self, data, home_mode_name, away_mode_name):
"""Initialize the alarm control panel."""
self._base_station = data
self._home_mode_name = home_mode_name
self._away_mode_name = away_mode_name
self._state = None
@property
@@ -89,8 +94,8 @@ class ArloBaseStation(AlarmControlPanel):
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
self._base_station.mode = ARMED
"""Send arm away command. Uses custom mode."""
self._base_station.mode = self._away_mode_name
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
@@ -118,4 +123,6 @@ class ArloBaseStation(AlarmControlPanel):
return STATE_ALARM_DISARMED
elif mode == self._home_mode_name:
return STATE_ALARM_ARMED_HOME
elif mode == self._away_mode_name:
return STATE_ALARM_ARMED_AWAY
return None

View File

@@ -0,0 +1,92 @@
"""
Support for Canary alarm.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.canary/
"""
import logging
from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.canary import DATA_CANARY
from homeassistant.const import STATE_ALARM_DISARMED, STATE_ALARM_ARMED_AWAY, \
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_ARMED_HOME
DEPENDENCIES = ['canary']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Canary alarms."""
data = hass.data[DATA_CANARY]
devices = []
for location in data.locations:
devices.append(CanaryAlarm(data, location.location_id))
add_devices(devices, True)
class CanaryAlarm(AlarmControlPanel):
"""Representation of a Canary alarm control panel."""
def __init__(self, data, location_id):
"""Initialize a Canary security camera."""
self._data = data
self._location_id = location_id
@property
def name(self):
"""Return the name of the alarm."""
location = self._data.get_location(self._location_id)
return location.name
@property
def state(self):
"""Return the state of the device."""
from canary.api import LOCATION_MODE_AWAY, LOCATION_MODE_HOME, \
LOCATION_MODE_NIGHT
location = self._data.get_location(self._location_id)
if location.is_private:
return STATE_ALARM_DISARMED
mode = location.mode
if mode.name == LOCATION_MODE_AWAY:
return STATE_ALARM_ARMED_AWAY
elif mode.name == LOCATION_MODE_HOME:
return STATE_ALARM_ARMED_HOME
elif mode.name == LOCATION_MODE_NIGHT:
return STATE_ALARM_ARMED_NIGHT
else:
return None
@property
def device_state_attributes(self):
"""Return the state attributes."""
location = self._data.get_location(self._location_id)
return {
'private': location.is_private
}
def alarm_disarm(self, code=None):
"""Send disarm command."""
location = self._data.get_location(self._location_id)
self._data.set_location_mode(self._location_id, location.mode.name,
True)
def alarm_arm_home(self, code=None):
"""Send arm home command."""
from canary.api import LOCATION_MODE_HOME
self._data.set_location_mode(self._location_id, LOCATION_MODE_HOME)
def alarm_arm_away(self, code=None):
"""Send arm away command."""
from canary.api import LOCATION_MODE_AWAY
self._data.set_location_mode(self._location_id, LOCATION_MODE_AWAY)
def alarm_arm_night(self, code=None):
"""Send arm night command."""
from canary.api import LOCATION_MODE_NIGHT
self._data.set_location_mode(self._location_id, LOCATION_MODE_NIGHT)

View File

@@ -18,7 +18,7 @@ from homeassistant.const import (
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['concord232==0.14']
REQUIREMENTS = ['concord232==0.15']
_LOGGER = logging.getLogger(__name__)
@@ -29,9 +29,9 @@ DEFAULT_PORT = 5007
SCAN_INTERVAL = timedelta(seconds=1)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
})
@@ -47,7 +47,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
add_devices([Concord232Alarm(hass, url, name)])
except requests.exceptions.ConnectionError as ex:
_LOGGER.error("Unable to connect to Concord232: %s", str(ex))
return False
return
class Concord232Alarm(alarm.AlarmControlPanel):
@@ -107,7 +107,7 @@ class Concord232Alarm(alarm.AlarmControlPanel):
newstate = STATE_ALARM_ARMED_AWAY
if not newstate == self._state:
_LOGGER.info("State Change from %s to %s", self._state, newstate)
_LOGGER.info("State change from %s to %s", self._state, newstate)
self._state = newstate
return self._state
@@ -121,4 +121,4 @@ class Concord232Alarm(alarm.AlarmControlPanel):
def alarm_arm_away(self, code=None):
"""Send arm away command."""
self._alarm.arm('auto')
self._alarm.arm('away')

View File

@@ -4,27 +4,45 @@ Demo platform that has two fake alarm control panels.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
import datetime
import homeassistant.components.alarm_control_panel.manual as manual
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_TRIGGERED, CONF_PENDING_TIME)
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_CUSTOM_BYPASS,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, CONF_DELAY_TIME,
CONF_PENDING_TIME, CONF_TRIGGER_TIME)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Demo alarm control panel platform."""
add_devices([
manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10, False, {
manual.ManualAlarm(hass, 'Alarm', '1234', None, False, {
STATE_ALARM_ARMED_AWAY: {
CONF_PENDING_TIME: 5
CONF_DELAY_TIME: datetime.timedelta(seconds=0),
CONF_PENDING_TIME: datetime.timedelta(seconds=5),
CONF_TRIGGER_TIME: datetime.timedelta(seconds=10),
},
STATE_ALARM_ARMED_HOME: {
CONF_PENDING_TIME: 5
CONF_DELAY_TIME: datetime.timedelta(seconds=0),
CONF_PENDING_TIME: datetime.timedelta(seconds=5),
CONF_TRIGGER_TIME: datetime.timedelta(seconds=10),
},
STATE_ALARM_ARMED_NIGHT: {
CONF_PENDING_TIME: 5
CONF_DELAY_TIME: datetime.timedelta(seconds=0),
CONF_PENDING_TIME: datetime.timedelta(seconds=5),
CONF_TRIGGER_TIME: datetime.timedelta(seconds=10),
},
STATE_ALARM_DISARMED: {
CONF_DELAY_TIME: datetime.timedelta(seconds=0),
CONF_TRIGGER_TIME: datetime.timedelta(seconds=10),
},
STATE_ALARM_ARMED_CUSTOM_BYPASS: {
CONF_DELAY_TIME: datetime.timedelta(seconds=0),
CONF_PENDING_TIME: datetime.timedelta(seconds=5),
CONF_TRIGGER_TIME: datetime.timedelta(seconds=10),
},
STATE_ALARM_TRIGGERED: {
CONF_PENDING_TIME: 5
CONF_PENDING_TIME: datetime.timedelta(seconds=5),
},
}),
])

View File

@@ -10,15 +10,15 @@ import requests
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.exceptions as exc
import homeassistant.helpers.config_validation as cv
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_PORT, CONF_HOST, CONF_PASSWORD, CONF_USERNAME, STATE_UNKNOWN,
CONF_NAME, STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_TRIGGERED)
CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_UNKNOWN)
import homeassistant.exceptions as exc
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pythonegardia==1.0.22']
REQUIREMENTS = ['pythonegardia==1.0.26']
_LOGGER = logging.getLogger(__name__)
@@ -26,12 +26,15 @@ CONF_REPORT_SERVER_CODES = 'report_server_codes'
CONF_REPORT_SERVER_ENABLED = 'report_server_enabled'
CONF_REPORT_SERVER_PORT = 'report_server_port'
CONF_REPORT_SERVER_CODES_IGNORE = 'ignore'
CONF_VERSION = 'version'
DEFAULT_NAME = 'Egardia'
DEFAULT_PORT = 80
DEFAULT_REPORT_SERVER_ENABLED = False
DEFAULT_REPORT_SERVER_PORT = 52010
DEFAULT_VERSION = 'GATE-01'
DOMAIN = 'egardia'
D_EGARDIASRV = 'egardiaserver'
NOTIFICATION_ID = 'egardia_notification'
NOTIFICATION_TITLE = 'Egardia'
@@ -49,6 +52,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_REPORT_SERVER_CODES): vol.All(cv.ensure_list),
@@ -62,6 +66,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Egardia platform."""
from pythonegardia import egardiadevice
from pythonegardia import egardiaserver
name = config.get(CONF_NAME)
username = config.get(CONF_USERNAME)
@@ -71,41 +76,59 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
rs_enabled = config.get(CONF_REPORT_SERVER_ENABLED)
rs_port = config.get(CONF_REPORT_SERVER_PORT)
rs_codes = config.get(CONF_REPORT_SERVER_CODES)
version = config.get(CONF_VERSION)
try:
egardiasystem = egardiadevice.EgardiaDevice(
host, port, username, password, '')
host, port, username, password, '', version)
except requests.exceptions.RequestException:
raise exc.PlatformNotReady()
except egardiadevice.UnauthorizedError:
_LOGGER.error("Unable to authorize. Wrong password or username")
return False
return
add_devices([EgardiaAlarm(
name, egardiasystem, hass, rs_enabled, rs_port, rs_codes)], True)
eg_dev = EgardiaAlarm(
name, egardiasystem, rs_enabled, rs_codes)
if rs_enabled:
# Set up the egardia server
_LOGGER.info("Setting up EgardiaServer")
try:
if D_EGARDIASRV not in hass.data:
server = egardiaserver.EgardiaServer('', rs_port)
bound = server.bind()
if not bound:
raise IOError(
"Binding error occurred while starting EgardiaServer")
hass.data[D_EGARDIASRV] = server
server.start()
except IOError:
return
hass.data[D_EGARDIASRV].register_callback(eg_dev.handle_status_event)
def handle_stop_event(event):
"""Call function for Home Assistant stop event."""
hass.data[D_EGARDIASRV].stop()
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, handle_stop_event)
add_devices([eg_dev], True)
class EgardiaAlarm(alarm.AlarmControlPanel):
"""Representation of a Egardia alarm."""
def __init__(self, name, egardiasystem, hass, rs_enabled=False,
rs_port=None, rs_codes=None):
"""Initialize object."""
def __init__(self, name, egardiasystem, rs_enabled=False, rs_codes=None):
"""Initialize the Egardia alarm."""
self._name = name
self._egardiasystem = egardiasystem
self._status = STATE_UNKNOWN
self._status = None
self._rs_enabled = rs_enabled
self._rs_port = rs_port
self._hass = hass
if rs_codes is not None:
self._rs_codes = rs_codes[0]
else:
self._rs_codes = rs_codes
if self._rs_enabled:
self.listen_to_system_status()
@property
def name(self):
"""Return the name of the device."""
@@ -116,17 +139,20 @@ class EgardiaAlarm(alarm.AlarmControlPanel):
"""Return the state of the device."""
return self._status
def handle_system_status_event(self, event):
"""Handle egardia_system_status_event."""
if event.data.get('status') is not None:
statuscode = event.data.get('status')
@property
def should_poll(self):
"""Poll if no report server is enabled."""
if not self._rs_enabled:
return True
return False
def handle_status_event(self, event):
"""Handle the Egardia system status event."""
statuscode = event.get('status')
if statuscode is not None:
status = self.lookupstatusfromcode(statuscode)
self.parsestatus(status)
def listen_to_system_status(self):
"""Subscribe to egardia_system_status event."""
self._hass.bus.listen(
'egardia_system_status', self.handle_system_status_event)
self.schedule_update_ha_state()
def lookupstatusfromcode(self, statuscode):
"""Look at the rs_codes and returns the status from the code."""
@@ -161,9 +187,8 @@ class EgardiaAlarm(alarm.AlarmControlPanel):
def update(self):
"""Update the alarm status."""
if not self._rs_enabled:
status = self._egardiasystem.getstate()
self.parsestatus(status)
status = self._egardiasystem.getstate()
self.parsestatus(status)
def alarm_disarm(self, code=None):
"""Send disarm command."""

View File

@@ -6,7 +6,6 @@ https://home-assistant.io/components/alarm_control_panel.envisalink/
"""
import asyncio
import logging
import os
import voluptuous as vol
@@ -14,7 +13,6 @@ from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.helpers.config_validation as cv
from homeassistant.config import load_yaml_config_file
from homeassistant.components.envisalink import (
DATA_EVL, EnvisalinkDevice, PARTITION_SCHEMA, CONF_CODE, CONF_PANIC,
CONF_PARTITIONNAME, SIGNAL_KEYPAD_UPDATE, SIGNAL_PARTITION_UPDATE)
@@ -69,14 +67,9 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
for device in target_devices:
device.async_alarm_keypress(keypress)
# Register Envisalink specific services
descriptions = yield from hass.async_add_job(
load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
hass.services.async_register(
alarm.DOMAIN, SERVICE_ALARM_KEYPRESS, alarm_keypress_handler,
descriptions.get(SERVICE_ALARM_KEYPRESS), schema=ALARM_KEYPRESS_SCHEMA)
schema=ALARM_KEYPRESS_SCHEMA)
return True

View File

@@ -0,0 +1,107 @@
"""
Interfaces with iAlarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.ialarm/
"""
import logging
import voluptuous as vol
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)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyialarm==0.2']
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'iAlarm'
def no_application_protocol(value):
"""Validate that value is without the application protocol."""
protocol_separator = "://"
if not value or protocol_separator in value:
raise vol.Invalid(
'Invalid host, {} is not allowed'.format(protocol_separator))
return value
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): vol.All(cv.string, no_application_protocol),
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up an iAlarm control panel."""
name = config.get(CONF_NAME)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
host = config.get(CONF_HOST)
url = 'http://{}'.format(host)
ialarm = IAlarmPanel(name, username, password, url)
add_devices([ialarm], True)
class IAlarmPanel(alarm.AlarmControlPanel):
"""Representation of an iAlarm status."""
def __init__(self, name, username, password, url):
"""Initialize the iAlarm status."""
from pyialarm import IAlarm
self._name = name
self._username = username
self._password = password
self._url = url
self._state = None
self._client = IAlarm(username, password, url)
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def state(self):
"""Return the state of the device."""
return self._state
def update(self):
"""Return the state of the device."""
status = self._client.get_status()
_LOGGER.debug('iAlarm status: %s', status)
if status:
status = int(status)
if status == self._client.DISARMED:
state = STATE_ALARM_DISARMED
elif status == self._client.ARMED_AWAY:
state = STATE_ALARM_ARMED_AWAY
elif status == self._client.ARMED_STAY:
state = STATE_ALARM_ARMED_HOME
else:
state = None
self._state = state
def alarm_disarm(self, code=None):
"""Send disarm command."""
self._client.disarm()
def alarm_arm_away(self, code=None):
"""Send arm away command."""
self._client.arm_away()
def alarm_arm_home(self, code=None):
"""Send arm home command."""
self._client.arm_stay()

View File

@@ -11,28 +11,48 @@ import logging
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.util.dt as dt_util
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED,
CONF_PLATFORM, CONF_NAME, CONF_CODE, CONF_PENDING_TIME, CONF_TRIGGER_TIME,
CONF_DISARM_AFTER_TRIGGER)
CONF_CODE, CONF_DELAY_TIME, CONF_DISARM_AFTER_TRIGGER, CONF_NAME,
CONF_PENDING_TIME, CONF_PLATFORM, CONF_TRIGGER_TIME,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_CUSTOM_BYPASS,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED,
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_point_in_time
import homeassistant.util.dt as dt_util
_LOGGER = logging.getLogger(__name__)
CONF_CODE_TEMPLATE = 'code_template'
DEFAULT_ALARM_NAME = 'HA Alarm'
DEFAULT_PENDING_TIME = 60
DEFAULT_TRIGGER_TIME = 120
DEFAULT_DELAY_TIME = datetime.timedelta(seconds=0)
DEFAULT_PENDING_TIME = datetime.timedelta(seconds=60)
DEFAULT_TRIGGER_TIME = datetime.timedelta(seconds=120)
DEFAULT_DISARM_AFTER_TRIGGER = False
SUPPORTED_PENDING_STATES = [STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_TRIGGERED]
SUPPORTED_STATES = [STATE_ALARM_DISARMED, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_TRIGGERED]
SUPPORTED_PRETRIGGER_STATES = [state for state in SUPPORTED_STATES
if state != STATE_ALARM_TRIGGERED]
SUPPORTED_PENDING_STATES = [state for state in SUPPORTED_STATES
if state != STATE_ALARM_DISARMED]
ATTR_PRE_PENDING_STATE = 'pre_pending_state'
ATTR_POST_PENDING_STATE = 'post_pending_state'
def _state_validator(config):
"""Validate the state."""
config = copy.deepcopy(config)
for state in SUPPORTED_PRETRIGGER_STATES:
if CONF_DELAY_TIME not in config[state]:
config[state][CONF_DELAY_TIME] = config[CONF_DELAY_TIME]
if CONF_TRIGGER_TIME not in config[state]:
config[state][CONF_TRIGGER_TIME] = config[CONF_TRIGGER_TIME]
for state in SUPPORTED_PENDING_STATES:
if CONF_PENDING_TIME not in config[state]:
config[state][CONF_PENDING_TIME] = config[CONF_PENDING_TIME]
@@ -40,30 +60,47 @@ def _state_validator(config):
return config
STATE_SETTING_SCHEMA = vol.Schema({
vol.Optional(CONF_PENDING_TIME):
vol.All(vol.Coerce(int), vol.Range(min=0))
})
def _state_schema(state):
"""Validate the state."""
schema = {}
if state in SUPPORTED_PRETRIGGER_STATES:
schema[vol.Optional(CONF_DELAY_TIME)] = vol.All(
cv.time_period, cv.positive_timedelta)
schema[vol.Optional(CONF_TRIGGER_TIME)] = vol.All(
cv.time_period, cv.positive_timedelta)
if state in SUPPORTED_PENDING_STATES:
schema[vol.Optional(CONF_PENDING_TIME)] = vol.All(
cv.time_period, cv.positive_timedelta)
return vol.Schema(schema)
PLATFORM_SCHEMA = vol.Schema(vol.All({
vol.Required(CONF_PLATFORM): 'manual',
vol.Optional(CONF_NAME, default=DEFAULT_ALARM_NAME): cv.string,
vol.Optional(CONF_CODE): cv.string,
vol.Exclusive(CONF_CODE, 'code validation'): cv.string,
vol.Exclusive(CONF_CODE_TEMPLATE, 'code validation'): cv.template,
vol.Optional(CONF_DELAY_TIME, default=DEFAULT_DELAY_TIME):
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_PENDING_TIME, default=DEFAULT_PENDING_TIME):
vol.All(vol.Coerce(int), vol.Range(min=0)),
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_TRIGGER_TIME, default=DEFAULT_TRIGGER_TIME):
vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_DISARM_AFTER_TRIGGER,
default=DEFAULT_DISARM_AFTER_TRIGGER): cv.boolean,
vol.Optional(STATE_ALARM_ARMED_AWAY, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_ARMED_HOME, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_ARMED_NIGHT, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_TRIGGERED, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_ARMED_AWAY, default={}):
_state_schema(STATE_ALARM_ARMED_AWAY),
vol.Optional(STATE_ALARM_ARMED_HOME, default={}):
_state_schema(STATE_ALARM_ARMED_HOME),
vol.Optional(STATE_ALARM_ARMED_NIGHT, default={}):
_state_schema(STATE_ALARM_ARMED_NIGHT),
vol.Optional(STATE_ALARM_ARMED_CUSTOM_BYPASS, default={}):
_state_schema(STATE_ALARM_ARMED_CUSTOM_BYPASS),
vol.Optional(STATE_ALARM_DISARMED, default={}):
_state_schema(STATE_ALARM_DISARMED),
vol.Optional(STATE_ALARM_TRIGGERED, default={}):
_state_schema(STATE_ALARM_TRIGGERED),
}, _state_validator))
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the manual alarm platform."""
@@ -71,8 +108,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
hass,
config[CONF_NAME],
config.get(CONF_CODE),
config.get(CONF_PENDING_TIME, DEFAULT_PENDING_TIME),
config.get(CONF_TRIGGER_TIME, DEFAULT_TRIGGER_TIME),
config.get(CONF_CODE_TEMPLATE),
config.get(CONF_DISARM_AFTER_TRIGGER, DEFAULT_DISARM_AFTER_TRIGGER),
config
)])
@@ -83,31 +119,41 @@ class ManualAlarm(alarm.AlarmControlPanel):
Representation of an alarm status.
When armed, will be pending for 'pending_time', after that armed.
When triggered, will be pending for 'trigger_time'. After that will be
triggered for 'trigger_time', after that we return to the previous state
or disarm if `disarm_after_trigger` is true.
When triggered, will be pending for the triggering state's 'delay_time'
plus the triggered state's 'pending_time'.
After that will be triggered for 'trigger_time', after that we return to
the previous state or disarm if `disarm_after_trigger` is true.
A trigger_time of zero disables the alarm_trigger service.
"""
def __init__(self, hass, name, code, pending_time, trigger_time,
def __init__(self, hass, name, code, code_template,
disarm_after_trigger, config):
"""Init the manual alarm panel."""
self._state = STATE_ALARM_DISARMED
self._hass = hass
self._name = name
self._code = str(code) if code else None
self._trigger_time = datetime.timedelta(seconds=trigger_time)
if code_template:
self._code = code_template
self._code.hass = hass
else:
self._code = code or None
self._disarm_after_trigger = disarm_after_trigger
self._pre_trigger_state = self._state
self._previous_state = self._state
self._state_ts = None
self._pending_time_by_state = {}
for state in SUPPORTED_PENDING_STATES:
self._pending_time_by_state[state] = datetime.timedelta(
seconds=config[state][CONF_PENDING_TIME])
self._delay_time_by_state = {
state: config[state][CONF_DELAY_TIME]
for state in SUPPORTED_PRETRIGGER_STATES}
self._trigger_time_by_state = {
state: config[state][CONF_TRIGGER_TIME]
for state in SUPPORTED_PRETRIGGER_STATES}
self._pending_time_by_state = {
state: config[state][CONF_PENDING_TIME]
for state in SUPPORTED_PENDING_STATES}
@property
def should_poll(self):
"""Return the plling state."""
"""Return the polling state."""
return False
@property
@@ -118,15 +164,16 @@ class ManualAlarm(alarm.AlarmControlPanel):
@property
def state(self):
"""Return the state of the device."""
if self._state == STATE_ALARM_TRIGGERED and self._trigger_time:
if self._state == STATE_ALARM_TRIGGERED:
if self._within_pending_time(self._state):
return STATE_ALARM_PENDING
elif (self._state_ts + self._pending_time_by_state[self._state] +
self._trigger_time) < dt_util.utcnow():
trigger_time = self._trigger_time_by_state[self._previous_state]
if (self._state_ts + self._pending_time(self._state) +
trigger_time) < dt_util.utcnow():
if self._disarm_after_trigger:
return STATE_ALARM_DISARMED
else:
self._state = self._pre_trigger_state
self._state = self._previous_state
return self._state
if self._state in SUPPORTED_PENDING_STATES and \
@@ -135,13 +182,28 @@ class ManualAlarm(alarm.AlarmControlPanel):
return self._state
def _within_pending_time(self, state):
@property
def _active_state(self):
"""Get the current state."""
if self.state == STATE_ALARM_PENDING:
return self._previous_state
else:
return self._state
def _pending_time(self, state):
"""Get the pending time."""
pending_time = self._pending_time_by_state[state]
return self._state_ts + pending_time > dt_util.utcnow()
if state == STATE_ALARM_TRIGGERED:
pending_time += self._delay_time_by_state[self._previous_state]
return pending_time
def _within_pending_time(self, state):
"""Get if the action is in the pending time window."""
return self._state_ts + self._pending_time(state) > dt_util.utcnow()
@property
def code_format(self):
"""One or more characters."""
"""Return one or more characters."""
return None if self._code is None else '.+'
def alarm_disarm(self, code=None):
@@ -174,27 +236,44 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._update_state(STATE_ALARM_ARMED_NIGHT)
def alarm_trigger(self, code=None):
"""Send alarm trigger command. No code needed."""
self._pre_trigger_state = self._state
def alarm_arm_custom_bypass(self, code=None):
"""Send arm custom bypass command."""
if not self._validate_code(code, STATE_ALARM_ARMED_CUSTOM_BYPASS):
return
self._update_state(STATE_ALARM_ARMED_CUSTOM_BYPASS)
def alarm_trigger(self, code=None):
"""
Send alarm trigger command.
No code needed, a trigger time of zero for the current state
disables the alarm.
"""
if not self._trigger_time_by_state[self._active_state]:
return
self._update_state(STATE_ALARM_TRIGGERED)
def _update_state(self, state):
"""Update the state."""
if self._state == state:
return
self._previous_state = self._state
self._state = state
self._state_ts = dt_util.utcnow()
self.schedule_update_ha_state()
pending_time = self._pending_time_by_state[state]
if state == STATE_ALARM_TRIGGERED and self._trigger_time:
pending_time = self._pending_time(state)
if state == STATE_ALARM_TRIGGERED:
track_point_in_time(
self._hass, self.async_update_ha_state,
self._state_ts + pending_time)
trigger_time = self._trigger_time_by_state[self._previous_state]
track_point_in_time(
self._hass, self.async_update_ha_state,
self._state_ts + self._trigger_time + pending_time)
self._state_ts + pending_time + trigger_time)
elif state in SUPPORTED_PENDING_STATES and pending_time:
track_point_in_time(
self._hass, self.async_update_ha_state,
@@ -202,7 +281,14 @@ class ManualAlarm(alarm.AlarmControlPanel):
def _validate_code(self, code, state):
"""Validate given code."""
check = self._code is None or code == self._code
if self._code is None:
return True
if isinstance(self._code, str):
alarm_code = self._code
else:
alarm_code = self._code.render(from_state=self._state,
to_state=state)
check = not alarm_code or code == alarm_code
if not check:
_LOGGER.warning("Invalid code given for %s", state)
return check
@@ -213,6 +299,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
state_attr = {}
if self.state == STATE_ALARM_PENDING:
state_attr[ATTR_PRE_PENDING_STATE] = self._previous_state
state_attr[ATTR_POST_PENDING_STATE] = self._state
return state_attr

View File

@@ -16,8 +16,8 @@ import homeassistant.util.dt as dt_util
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED,
CONF_PLATFORM, CONF_NAME, CONF_CODE, CONF_PENDING_TIME, CONF_TRIGGER_TIME,
CONF_DISARM_AFTER_TRIGGER)
CONF_PLATFORM, CONF_NAME, CONF_CODE, CONF_DELAY_TIME, CONF_PENDING_TIME,
CONF_TRIGGER_TIME, CONF_DISARM_AFTER_TRIGGER)
import homeassistant.components.mqtt as mqtt
from homeassistant.helpers.event import async_track_state_change
@@ -26,28 +26,47 @@ from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_point_in_time
_LOGGER = logging.getLogger(__name__)
CONF_CODE_TEMPLATE = 'code_template'
CONF_PAYLOAD_DISARM = 'payload_disarm'
CONF_PAYLOAD_ARM_HOME = 'payload_arm_home'
CONF_PAYLOAD_ARM_AWAY = 'payload_arm_away'
CONF_PAYLOAD_ARM_NIGHT = 'payload_arm_night'
DEFAULT_ALARM_NAME = 'HA Alarm'
DEFAULT_PENDING_TIME = 60
DEFAULT_TRIGGER_TIME = 120
DEFAULT_DELAY_TIME = datetime.timedelta(seconds=0)
DEFAULT_PENDING_TIME = datetime.timedelta(seconds=60)
DEFAULT_TRIGGER_TIME = datetime.timedelta(seconds=120)
DEFAULT_DISARM_AFTER_TRIGGER = False
DEFAULT_ARM_AWAY = 'ARM_AWAY'
DEFAULT_ARM_HOME = 'ARM_HOME'
DEFAULT_ARM_NIGHT = 'ARM_NIGHT'
DEFAULT_DISARM = 'DISARM'
SUPPORTED_PENDING_STATES = [STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_TRIGGERED]
SUPPORTED_STATES = [STATE_ALARM_DISARMED, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_TRIGGERED]
SUPPORTED_PRETRIGGER_STATES = [state for state in SUPPORTED_STATES
if state != STATE_ALARM_TRIGGERED]
SUPPORTED_PENDING_STATES = [state for state in SUPPORTED_STATES
if state != STATE_ALARM_DISARMED]
ATTR_PRE_PENDING_STATE = 'pre_pending_state'
ATTR_POST_PENDING_STATE = 'post_pending_state'
def _state_validator(config):
"""Validate the state."""
config = copy.deepcopy(config)
for state in SUPPORTED_PRETRIGGER_STATES:
if CONF_DELAY_TIME not in config[state]:
config[state][CONF_DELAY_TIME] = config[CONF_DELAY_TIME]
if CONF_TRIGGER_TIME not in config[state]:
config[state][CONF_TRIGGER_TIME] = config[CONF_TRIGGER_TIME]
for state in SUPPORTED_PENDING_STATES:
if CONF_PENDING_TIME not in config[state]:
config[state][CONF_PENDING_TIME] = config[CONF_PENDING_TIME]
@@ -55,27 +74,45 @@ def _state_validator(config):
return config
STATE_SETTING_SCHEMA = vol.Schema({
vol.Optional(CONF_PENDING_TIME):
vol.All(vol.Coerce(int), vol.Range(min=0))
})
def _state_schema(state):
"""Validate the state."""
schema = {}
if state in SUPPORTED_PRETRIGGER_STATES:
schema[vol.Optional(CONF_DELAY_TIME)] = vol.All(
cv.time_period, cv.positive_timedelta)
schema[vol.Optional(CONF_TRIGGER_TIME)] = vol.All(
cv.time_period, cv.positive_timedelta)
if state in SUPPORTED_PENDING_STATES:
schema[vol.Optional(CONF_PENDING_TIME)] = vol.All(
cv.time_period, cv.positive_timedelta)
return vol.Schema(schema)
DEPENDENCIES = ['mqtt']
PLATFORM_SCHEMA = vol.Schema(vol.All(mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
vol.Required(CONF_PLATFORM): 'manual_mqtt',
vol.Optional(CONF_NAME, default=DEFAULT_ALARM_NAME): cv.string,
vol.Optional(CONF_CODE): cv.string,
vol.Exclusive(CONF_CODE, 'code validation'): cv.string,
vol.Exclusive(CONF_CODE_TEMPLATE, 'code validation'): cv.template,
vol.Optional(CONF_DELAY_TIME, default=DEFAULT_DELAY_TIME):
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_PENDING_TIME, default=DEFAULT_PENDING_TIME):
vol.All(vol.Coerce(int), vol.Range(min=0)),
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_TRIGGER_TIME, default=DEFAULT_TRIGGER_TIME):
vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_DISARM_AFTER_TRIGGER,
default=DEFAULT_DISARM_AFTER_TRIGGER): cv.boolean,
vol.Optional(STATE_ALARM_ARMED_AWAY, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_ARMED_HOME, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_ARMED_NIGHT, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_TRIGGERED, default={}): STATE_SETTING_SCHEMA,
vol.Optional(STATE_ALARM_ARMED_AWAY, default={}):
_state_schema(STATE_ALARM_ARMED_AWAY),
vol.Optional(STATE_ALARM_ARMED_HOME, default={}):
_state_schema(STATE_ALARM_ARMED_HOME),
vol.Optional(STATE_ALARM_ARMED_NIGHT, default={}):
_state_schema(STATE_ALARM_ARMED_NIGHT),
vol.Optional(STATE_ALARM_DISARMED, default={}):
_state_schema(STATE_ALARM_DISARMED),
vol.Optional(STATE_ALARM_TRIGGERED, default={}):
_state_schema(STATE_ALARM_TRIGGERED),
vol.Required(mqtt.CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Required(mqtt.CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
@@ -84,8 +121,6 @@ PLATFORM_SCHEMA = vol.Schema(vol.All(mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string,
}), _state_validator))
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the manual MQTT alarm platform."""
@@ -93,8 +128,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
hass,
config[CONF_NAME],
config.get(CONF_CODE),
config.get(CONF_PENDING_TIME, DEFAULT_PENDING_TIME),
config.get(CONF_TRIGGER_TIME, DEFAULT_TRIGGER_TIME),
config.get(CONF_CODE_TEMPLATE),
config.get(CONF_DISARM_AFTER_TRIGGER, DEFAULT_DISARM_AFTER_TRIGGER),
config.get(mqtt.CONF_STATE_TOPIC),
config.get(mqtt.CONF_COMMAND_TOPIC),
@@ -111,31 +145,39 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
Representation of an alarm status.
When armed, will be pending for 'pending_time', after that armed.
When triggered, will be pending for 'trigger_time'. After that will be
triggered for 'trigger_time', after that we return to the previous state
or disarm if `disarm_after_trigger` is true.
When triggered, will be pending for the triggering state's 'delay_time'
plus the triggered state's 'pending_time'.
After that will be triggered for 'trigger_time', after that we return to
the previous state or disarm if `disarm_after_trigger` is true.
A trigger_time of zero disables the alarm_trigger service.
"""
def __init__(self, hass, name, code, pending_time,
trigger_time, disarm_after_trigger,
state_topic, command_topic, qos,
payload_disarm, payload_arm_home, payload_arm_away,
payload_arm_night, config):
def __init__(self, hass, name, code, code_template, disarm_after_trigger,
state_topic, command_topic, qos, payload_disarm,
payload_arm_home, payload_arm_away, payload_arm_night,
config):
"""Init the manual MQTT alarm panel."""
self._state = STATE_ALARM_DISARMED
self._hass = hass
self._name = name
self._code = str(code) if code else None
self._pending_time = datetime.timedelta(seconds=pending_time)
self._trigger_time = datetime.timedelta(seconds=trigger_time)
if code_template:
self._code = code_template
self._code.hass = hass
else:
self._code = code or None
self._disarm_after_trigger = disarm_after_trigger
self._pre_trigger_state = self._state
self._previous_state = self._state
self._state_ts = None
self._pending_time_by_state = {}
for state in SUPPORTED_PENDING_STATES:
self._pending_time_by_state[state] = datetime.timedelta(
seconds=config[state][CONF_PENDING_TIME])
self._delay_time_by_state = {
state: config[state][CONF_DELAY_TIME]
for state in SUPPORTED_PRETRIGGER_STATES}
self._trigger_time_by_state = {
state: config[state][CONF_TRIGGER_TIME]
for state in SUPPORTED_PRETRIGGER_STATES}
self._pending_time_by_state = {
state: config[state][CONF_PENDING_TIME]
for state in SUPPORTED_PENDING_STATES}
self._state_topic = state_topic
self._command_topic = command_topic
@@ -158,15 +200,16 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
@property
def state(self):
"""Return the state of the device."""
if self._state == STATE_ALARM_TRIGGERED and self._trigger_time:
if self._state == STATE_ALARM_TRIGGERED:
if self._within_pending_time(self._state):
return STATE_ALARM_PENDING
elif (self._state_ts + self._pending_time_by_state[self._state] +
self._trigger_time) < dt_util.utcnow():
trigger_time = self._trigger_time_by_state[self._previous_state]
if (self._state_ts + self._pending_time(self._state) +
trigger_time) < dt_util.utcnow():
if self._disarm_after_trigger:
return STATE_ALARM_DISARMED
else:
self._state = self._pre_trigger_state
self._state = self._previous_state
return self._state
if self._state in SUPPORTED_PENDING_STATES and \
@@ -175,13 +218,28 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
return self._state
def _within_pending_time(self, state):
@property
def _active_state(self):
"""Get the current state."""
if self.state == STATE_ALARM_PENDING:
return self._previous_state
else:
return self._state
def _pending_time(self, state):
"""Get the pending time."""
pending_time = self._pending_time_by_state[state]
return self._state_ts + pending_time > dt_util.utcnow()
if state == STATE_ALARM_TRIGGERED:
pending_time += self._delay_time_by_state[self._previous_state]
return pending_time
def _within_pending_time(self, state):
"""Get if the action is in the pending time window."""
return self._state_ts + self._pending_time(state) > dt_util.utcnow()
@property
def code_format(self):
"""One or more characters."""
"""Return one or more characters."""
return None if self._code is None else '.+'
def alarm_disarm(self, code=None):
@@ -215,26 +273,36 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
self._update_state(STATE_ALARM_ARMED_NIGHT)
def alarm_trigger(self, code=None):
"""Send alarm trigger command. No code needed."""
self._pre_trigger_state = self._state
"""
Send alarm trigger command.
No code needed, a trigger time of zero for the current state
disables the alarm.
"""
if not self._trigger_time_by_state[self._active_state]:
return
self._update_state(STATE_ALARM_TRIGGERED)
def _update_state(self, state):
"""Update the state."""
if self._state == state:
return
self._previous_state = self._state
self._state = state
self._state_ts = dt_util.utcnow()
self.schedule_update_ha_state()
pending_time = self._pending_time_by_state[state]
if state == STATE_ALARM_TRIGGERED and self._trigger_time:
pending_time = self._pending_time(state)
if state == STATE_ALARM_TRIGGERED:
track_point_in_time(
self._hass, self.async_update_ha_state,
self._state_ts + pending_time)
trigger_time = self._trigger_time_by_state[self._previous_state]
track_point_in_time(
self._hass, self.async_update_ha_state,
self._state_ts + self._trigger_time + pending_time)
self._state_ts + pending_time + trigger_time)
elif state in SUPPORTED_PENDING_STATES and pending_time:
track_point_in_time(
self._hass, self.async_update_ha_state,
@@ -242,7 +310,14 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
def _validate_code(self, code, state):
"""Validate given code."""
check = self._code is None or code == self._code
if self._code is None:
return True
if isinstance(self._code, str):
alarm_code = self._code
else:
alarm_code = self._code.render(from_state=self._state,
to_state=state)
check = not alarm_code or code == alarm_code
if not check:
_LOGGER.warning("Invalid code given for %s", state)
return check
@@ -253,12 +328,13 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
state_attr = {}
if self.state == STATE_ALARM_PENDING:
state_attr[ATTR_PRE_PENDING_STATE] = self._previous_state
state_attr[ATTR_POST_PENDING_STATE] = self._state
return state_attr
def async_added_to_hass(self):
"""Subscribe mqtt events.
"""Subscribe to MQTT events.
This method must be run in the event loop and returns a coroutine.
"""
@@ -287,5 +363,5 @@ class ManualMQTTAlarm(alarm.AlarmControlPanel):
@asyncio.coroutine
def _async_state_changed_listener(self, entity_id, old_state, new_state):
"""Publish state change to MQTT."""
mqtt.async_publish(self.hass, self._state_topic, new_state.state,
self._qos, True)
mqtt.async_publish(
self.hass, self._state_topic, new_state.state, self._qos, True)

View File

@@ -17,7 +17,9 @@ from homeassistant.const import (
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN,
CONF_NAME, CONF_CODE)
from homeassistant.components.mqtt import (
CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS)
CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC, CONF_COMMAND_TOPIC,
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS,
MqttAvailability)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
@@ -40,7 +42,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string,
vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string,
})
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@asyncio.coroutine
@@ -54,15 +56,21 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
config.get(CONF_PAYLOAD_DISARM),
config.get(CONF_PAYLOAD_ARM_HOME),
config.get(CONF_PAYLOAD_ARM_AWAY),
config.get(CONF_CODE))])
config.get(CONF_CODE),
config.get(CONF_AVAILABILITY_TOPIC),
config.get(CONF_PAYLOAD_AVAILABLE),
config.get(CONF_PAYLOAD_NOT_AVAILABLE))])
class MqttAlarm(alarm.AlarmControlPanel):
class MqttAlarm(MqttAvailability, alarm.AlarmControlPanel):
"""Representation of a MQTT alarm status."""
def __init__(self, name, state_topic, command_topic, qos, payload_disarm,
payload_arm_home, payload_arm_away, code):
payload_arm_home, payload_arm_away, code, availability_topic,
payload_available, payload_not_available):
"""Init the MQTT Alarm Control Panel."""
super().__init__(availability_topic, qos, payload_available,
payload_not_available)
self._state = STATE_UNKNOWN
self._name = name
self._state_topic = state_topic
@@ -73,11 +81,11 @@ class MqttAlarm(alarm.AlarmControlPanel):
self._payload_arm_away = payload_arm_away
self._code = code
@asyncio.coroutine
def async_added_to_hass(self):
"""Subscribe mqtt events.
"""Subscribe mqtt events."""
yield from super().async_added_to_hass()
This method must be run in the event loop and returns a coroutine.
"""
@callback
def message_received(topic, payload, qos):
"""Run when new MQTT message has been received."""
@@ -89,7 +97,7 @@ class MqttAlarm(alarm.AlarmControlPanel):
self._state = payload
self.async_schedule_update_ha_state()
return mqtt.async_subscribe(
yield from mqtt.async_subscribe(
self.hass, self._state_topic, message_received, self._qos)
@property

View File

@@ -12,8 +12,8 @@ import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN, CONF_NAME, CONF_HOST, CONF_PORT)
CONF_HOST, CONF_NAME, CONF_PORT, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pynx584==0.4']
@@ -25,14 +25,14 @@ DEFAULT_NAME = 'NX584'
DEFAULT_PORT = 5007
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the nx584 platform."""
"""Set up the NX584 platform."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
@@ -88,7 +88,7 @@ class NX584Alarm(alarm.AlarmControlPanel):
self._state = STATE_UNKNOWN
zones = []
except IndexError:
_LOGGER.error("nx584 reports no partitions")
_LOGGER.error("NX584 reports no partitions")
self._state = STATE_UNKNOWN
zones = []

View File

@@ -8,9 +8,8 @@ import asyncio
import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.satel_integra import (CONF_ARM_HOME_MODE,
DATA_SATEL,
SIGNAL_PANEL_MESSAGE)
from homeassistant.components.satel_integra import (
CONF_ARM_HOME_MODE, DATA_SATEL, SIGNAL_PANEL_MESSAGE)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
@@ -21,12 +20,12 @@ DEPENDENCIES = ['satel_integra']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up for AlarmDecoder alarm panels."""
"""Set up for Satel Integra alarm panels."""
if not discovery_info:
return
device = SatelIntegraAlarmPanel("Alarm Panel",
discovery_info.get(CONF_ARM_HOME_MODE))
device = SatelIntegraAlarmPanel(
"Alarm Panel", discovery_info.get(CONF_ARM_HOME_MODE))
async_add_devices([device])
@@ -47,7 +46,7 @@ class SatelIntegraAlarmPanel(alarm.AlarmControlPanel):
@callback
def _message_callback(self, message):
"""Handle received messages."""
if message != self._state:
self._state = message
self.async_schedule_update_ha_state()
@@ -90,5 +89,5 @@ class SatelIntegraAlarmPanel(alarm.AlarmControlPanel):
def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
if code:
yield from self.hass.data[DATA_SATEL].arm(code,
self._arm_home_mode)
yield from self.hass.data[DATA_SATEL].arm(
code, self._arm_home_mode)

View File

@@ -59,3 +59,13 @@ envisalink_alarm_keypress:
keypress:
description: 'String to send to the alarm panel (1-6 characters).'
example: '*71'
alarmdecoder_alarm_toggle_chime:
description: Send the alarm the toggle chime command.
fields:
entity_id:
description: Name of the alarm control panel to trigger.
example: 'alarm_control_panel.downstairs'
code:
description: A required code to toggle the alarm control panel chime with.
example: 1234

View File

@@ -11,9 +11,9 @@ import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, STATE_UNKNOWN, CONF_CODE, CONF_NAME,
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY,
EVENT_HOMEASSISTANT_STOP)
CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_UNKNOWN)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['simplisafe-python==1.0.5']
@@ -22,6 +22,7 @@ _LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'SimpliSafe'
DOMAIN = 'simplisafe'
NOTIFICATION_ID = 'simplisafe_notification'
NOTIFICATION_TITLE = 'SimpliSafe Setup'
@@ -65,7 +66,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class SimpliSafeAlarm(alarm.AlarmControlPanel):
"""Representation a SimpliSafe alarm."""
"""Representation of a SimpliSafe alarm."""
def __init__(self, simplisafe, name, code):
"""Initialize the SimpliSafe alarm."""
@@ -82,7 +83,7 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
@property
def code_format(self):
"""One or more characters if code is defined."""
"""Return one or more characters if code is defined."""
return None if self._code is None else '.+'
@property
@@ -103,12 +104,12 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
def device_state_attributes(self):
"""Return the state attributes."""
return {
'temperature': self.simplisafe.temperature(),
'alarm': self.simplisafe.alarm(),
'co': self.simplisafe.carbon_monoxide(),
'fire': self.simplisafe.fire(),
'alarm': self.simplisafe.alarm(),
'flood': self.simplisafe.flood(),
'last_event': self.simplisafe.last_event(),
'flood': self.simplisafe.flood()
'temperature': self.simplisafe.temperature(),
}
def update(self):

View File

@@ -9,26 +9,27 @@ import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.spc import (
SpcWebGateway, ATTR_DISCOVER_AREAS, DATA_API, DATA_REGISTRY)
ATTR_DISCOVER_AREAS, DATA_API, DATA_REGISTRY, SpcWebGateway)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN)
_LOGGER = logging.getLogger(__name__)
SPC_AREA_MODE_TO_STATE = {'0': STATE_ALARM_DISARMED,
'1': STATE_ALARM_ARMED_HOME,
'3': STATE_ALARM_ARMED_AWAY}
SPC_AREA_MODE_TO_STATE = {
'0': STATE_ALARM_DISARMED,
'1': STATE_ALARM_ARMED_HOME,
'3': STATE_ALARM_ARMED_AWAY,
}
def _get_alarm_state(spc_mode):
"""Get the alarm state."""
return SPC_AREA_MODE_TO_STATE.get(spc_mode, STATE_UNKNOWN)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the SPC alarm control panel platform."""
if (discovery_info is None or
discovery_info[ATTR_DISCOVER_AREAS] is None):
@@ -42,7 +43,7 @@ def async_setup_platform(hass, config, async_add_devices,
class SpcAlarm(alarm.AlarmControlPanel):
"""Represents the SPC alarm panel."""
"""Representation of the SPC alarm panel."""
def __init__(self, api, area):
"""Initialize the SPC alarm panel."""
@@ -57,7 +58,7 @@ class SpcAlarm(alarm.AlarmControlPanel):
@asyncio.coroutine
def async_added_to_hass(self):
"""Calbback for init handlers."""
"""Call for adding new entities."""
self.hass.data[DATA_REGISTRY].register_alarm_device(
self._area_id, self)

View File

@@ -14,9 +14,11 @@ from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED,
STATE_ALARM_ARMING, STATE_ALARM_DISARMING, STATE_UNKNOWN, CONF_NAME)
STATE_ALARM_ARMING, STATE_ALARM_DISARMING, STATE_UNKNOWN, CONF_NAME,
STATE_ALARM_ARMED_CUSTOM_BYPASS)
REQUIREMENTS = ['total_connect_client==0.13']
REQUIREMENTS = ['total_connect_client==0.16']
_LOGGER = logging.getLogger(__name__)
@@ -76,6 +78,8 @@ class TotalConnect(alarm.AlarmControlPanel):
state = STATE_ALARM_ARMED_AWAY
elif status == self._client.ARMED_STAY_NIGHT:
state = STATE_ALARM_ARMED_NIGHT
elif status == self._client.ARMED_CUSTOM_BYPASS:
state = STATE_ALARM_ARMED_CUSTOM_BYPASS
elif status == self._client.ARMING:
state = STATE_ALARM_ARMING
elif status == self._client.DISARMING:

View File

@@ -8,8 +8,8 @@ import logging
from time import sleep
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.verisure import CONF_ALARM, CONF_CODE_DIGITS
from homeassistant.components.verisure import HUB as hub
from homeassistant.components.verisure import (CONF_ALARM, CONF_CODE_DIGITS)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN)
@@ -43,7 +43,7 @@ class VerisureAlarm(alarm.AlarmControlPanel):
"""Representation of a Verisure alarm status."""
def __init__(self):
"""Initalize the Verisure alarm panel."""
"""Initialize the Verisure alarm panel."""
self._state = STATE_UNKNOWN
self._digits = hub.config.get(CONF_CODE_DIGITS)
self._changed_by = None

View File

@@ -8,11 +8,10 @@ import asyncio
import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.const import (STATE_UNKNOWN,
STATE_ALARM_DISARMED,
STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY)
from homeassistant.components.wink import WinkDevice, DOMAIN
from homeassistant.components.wink import DOMAIN, WinkDevice
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN)
_LOGGER = logging.getLogger(__name__)
@@ -41,7 +40,7 @@ class WinkCameraDevice(WinkDevice, alarm.AlarmControlPanel):
@asyncio.coroutine
def async_added_to_hass(self):
"""Callback when entity is added to hass."""
"""Call when entity is added to hass."""
self.hass.data[DOMAIN]['entities']['alarm_control_panel'].append(self)
@property

View File

@@ -4,18 +4,18 @@ Support for AlarmDecoder devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/alarmdecoder/
"""
import asyncio
import logging
from datetime import timedelta
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.core import callback
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.discovery import load_platform
from homeassistant.util import dt as dt_util
from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA
REQUIREMENTS = ['alarmdecoder==0.12.3']
REQUIREMENTS = ['alarmdecoder==1.13.2']
_LOGGER = logging.getLogger(__name__)
@@ -32,6 +32,7 @@ CONF_DEVICE_TYPE = 'type'
CONF_PANEL_DISPLAY = 'panel_display'
CONF_ZONE_NAME = 'name'
CONF_ZONE_TYPE = 'type'
CONF_ZONE_RFID = 'rfid'
CONF_ZONES = 'zones'
DEFAULT_DEVICE_TYPE = 'socket'
@@ -51,6 +52,7 @@ SIGNAL_PANEL_DISARM = 'alarmdecoder.panel_disarm'
SIGNAL_ZONE_FAULT = 'alarmdecoder.zone_fault'
SIGNAL_ZONE_RESTORE = 'alarmdecoder.zone_restore'
SIGNAL_RFX_MESSAGE = 'alarmdecoder.rfx_message'
DEVICE_SOCKET_SCHEMA = vol.Schema({
vol.Required(CONF_DEVICE_TYPE): 'socket',
@@ -67,13 +69,15 @@ DEVICE_USB_SCHEMA = vol.Schema({
ZONE_SCHEMA = vol.Schema({
vol.Required(CONF_ZONE_NAME): cv.string,
vol.Optional(CONF_ZONE_TYPE, default=DEFAULT_ZONE_TYPE): cv.string})
vol.Optional(CONF_ZONE_TYPE,
default=DEFAULT_ZONE_TYPE): vol.Any(DEVICE_CLASSES_SCHEMA),
vol.Optional(CONF_ZONE_RFID): cv.string})
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_DEVICE): vol.Any(DEVICE_SOCKET_SCHEMA,
DEVICE_SERIAL_SCHEMA,
DEVICE_USB_SCHEMA),
vol.Required(CONF_DEVICE): vol.Any(
DEVICE_SOCKET_SCHEMA, DEVICE_SERIAL_SCHEMA,
DEVICE_USB_SCHEMA),
vol.Optional(CONF_PANEL_DISPLAY,
default=DEFAULT_PANEL_DISPLAY): cv.boolean,
vol.Optional(CONF_ZONES): {vol.Coerce(int): ZONE_SCHEMA},
@@ -81,14 +85,14 @@ CONFIG_SCHEMA = vol.Schema({
}, extra=vol.ALLOW_EXTRA)
@asyncio.coroutine
def async_setup(hass, config):
def setup(hass, config):
"""Set up for the AlarmDecoder devices."""
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice)
conf = config.get(DOMAIN)
restart = False
device = conf.get(CONF_DEVICE)
display = conf.get(CONF_PANEL_DISPLAY)
zones = conf.get(CONF_ZONES)
@@ -99,32 +103,55 @@ def async_setup(hass, config):
path = DEFAULT_DEVICE_PATH
baud = DEFAULT_DEVICE_BAUD
sync_connect = asyncio.Future(loop=hass.loop)
def handle_open(device):
"""Handle the successful connection."""
_LOGGER.info("Established a connection with the alarmdecoder")
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder)
sync_connect.set_result(True)
@callback
def stop_alarmdecoder(event):
"""Handle the shutdown of AlarmDecoder."""
_LOGGER.debug("Shutting down alarmdecoder")
nonlocal restart
restart = False
controller.close()
@callback
def open_connection(now=None):
"""Open a connection to AlarmDecoder."""
from alarmdecoder.util import NoDeviceError
nonlocal restart
try:
controller.open(baud)
except NoDeviceError:
_LOGGER.debug("Failed to connect. Retrying in 5 seconds")
hass.helpers.event.track_point_in_time(
open_connection, dt_util.utcnow() + timedelta(seconds=5))
return
_LOGGER.debug("Established a connection with the alarmdecoder")
restart = True
def handle_closed_connection(event):
"""Restart after unexpected loss of connection."""
nonlocal restart
if not restart:
return
restart = False
_LOGGER.warning("AlarmDecoder unexpectedly lost connection.")
hass.add_job(open_connection)
def handle_message(sender, message):
"""Handle message from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message)
hass.helpers.dispatcher.dispatcher_send(
SIGNAL_PANEL_MESSAGE, message)
def handle_rfx_message(sender, message):
"""Handle RFX message from AlarmDecoder."""
hass.helpers.dispatcher.dispatcher_send(
SIGNAL_RFX_MESSAGE, message)
def zone_fault_callback(sender, zone):
"""Handle zone fault from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone)
hass.helpers.dispatcher.dispatcher_send(
SIGNAL_ZONE_FAULT, zone)
def zone_restore_callback(sender, zone):
"""Handle zone restore from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_RESTORE, zone)
hass.helpers.dispatcher.dispatcher_send(
SIGNAL_ZONE_RESTORE, zone)
controller = False
if device_type == 'socket':
@@ -139,30 +166,25 @@ def async_setup(hass, config):
AlarmDecoder(USBDevice.find())
return False
controller.on_open += handle_open
controller.on_message += handle_message
controller.on_rfx_message += handle_rfx_message
controller.on_zone_fault += zone_fault_callback
controller.on_zone_restore += zone_restore_callback
controller.on_close += handle_closed_connection
hass.data[DATA_AD] = controller
controller.open(baud)
open_connection()
result = yield from sync_connect
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder)
if not result:
return False
hass.async_add_job(
async_load_platform(hass, 'alarm_control_panel', DOMAIN, conf,
config))
load_platform(hass, 'alarm_control_panel', DOMAIN, conf, config)
if zones:
hass.async_add_job(async_load_platform(
hass, 'binary_sensor', DOMAIN, {CONF_ZONES: zones}, config))
load_platform(
hass, 'binary_sensor', DOMAIN, {CONF_ZONES: zones}, config)
if display:
hass.async_add_job(async_load_platform(
hass, 'sensor', DOMAIN, conf, config))
load_platform(hass, 'sensor', DOMAIN, conf, config)
return True

View File

@@ -7,12 +7,10 @@ https://home-assistant.io/components/alert/
import asyncio
from datetime import datetime, timedelta
import logging
import os
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.config import load_yaml_config_file
from homeassistant.const import (
CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE, STATE_ON, STATE_OFF,
SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE, ATTR_ENTITY_ID)
@@ -129,22 +127,16 @@ def async_setup(hass, config):
alert[CONF_NOTIFIERS], alert[CONF_CAN_ACK])
all_alerts[entity.entity_id] = entity
# Read descriptions
descriptions = yield from hass.async_add_job(
load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
descriptions = descriptions.get(DOMAIN, {})
# Setup service calls
hass.services.async_register(
DOMAIN, SERVICE_TURN_OFF, async_handle_alert_service,
descriptions.get(SERVICE_TURN_OFF), schema=ALERT_SERVICE_SCHEMA)
schema=ALERT_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_TURN_ON, async_handle_alert_service,
descriptions.get(SERVICE_TURN_ON), schema=ALERT_SERVICE_SCHEMA)
schema=ALERT_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_TOGGLE, async_handle_alert_service,
descriptions.get(SERVICE_TOGGLE), schema=ALERT_SERVICE_SCHEMA)
schema=ALERT_SERVICE_SCHEMA)
tasks = [alert.async_update_ha_state() for alert in all_alerts.values()]
if tasks:
@@ -285,7 +277,7 @@ class Alert(ToggleEntity):
yield from self.async_update_ha_state()
@asyncio.coroutine
def async_toggle(self):
def async_toggle(self, **kwargs):
"""Async toggle alert."""
if self._ack:
return self.async_turn_on()

View File

@@ -10,18 +10,33 @@ import logging
import voluptuous as vol
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import entityfilter
from . import flash_briefings, intent, smart_home
from .const import (
DOMAIN, CONF_UID, CONF_TITLE, CONF_AUDIO, CONF_TEXT, CONF_DISPLAY_URL)
from . import flash_briefings, intent
CONF_AUDIO, CONF_DISPLAY_URL, CONF_TEXT, CONF_TITLE, CONF_UID, DOMAIN,
CONF_FILTER, CONF_ENTITY_CONFIG)
_LOGGER = logging.getLogger(__name__)
CONF_FLASH_BRIEFINGS = 'flash_briefings'
CONF_SMART_HOME = 'smart_home'
DEPENDENCIES = ['http']
CONF_FLASH_BRIEFINGS = 'flash_briefings'
ALEXA_ENTITY_SCHEMA = vol.Schema({
vol.Optional(smart_home.CONF_DESCRIPTION): cv.string,
vol.Optional(smart_home.CONF_DISPLAY_CATEGORIES): cv.string,
vol.Optional(smart_home.CONF_NAME): cv.string,
})
SMART_HOME_SCHEMA = vol.Schema({
vol.Optional(
CONF_FILTER,
default=lambda: entityfilter.generate_filter([], [], [], [])
): entityfilter.FILTER_SCHEMA,
vol.Optional(CONF_ENTITY_CONFIG): {cv.entity_id: ALEXA_ENTITY_SCHEMA}
})
CONFIG_SCHEMA = vol.Schema({
DOMAIN: {
@@ -33,7 +48,10 @@ CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_TEXT, default=""): cv.template,
vol.Optional(CONF_DISPLAY_URL): cv.template,
}]),
}
},
# vol.Optional here would mean we couldn't distinguish between an empty
# smart_home: and none at all.
CONF_SMART_HOME: vol.Any(SMART_HOME_SCHEMA, None),
}
}, extra=vol.ALLOW_EXTRA)
@@ -49,4 +67,12 @@ def async_setup(hass, config):
if flash_briefings_config:
flash_briefings.async_setup(hass, flash_briefings_config)
try:
smart_home_config = config[CONF_SMART_HOME]
except KeyError:
pass
else:
smart_home_config = smart_home_config or SMART_HOME_SCHEMA({})
smart_home.async_setup(hass, smart_home_config)
return True

View File

@@ -8,6 +8,9 @@ CONF_AUDIO = 'audio'
CONF_TEXT = 'text'
CONF_DISPLAY_URL = 'display_url'
CONF_FILTER = 'filter'
CONF_ENTITY_CONFIG = 'entity_config'
ATTR_UID = 'uid'
ATTR_UPDATE_DATE = 'updateDate'
ATTR_TITLE_TEXT = 'titleText'

View File

@@ -5,19 +5,18 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/alexa/
"""
import copy
import logging
from datetime import datetime
import logging
import uuid
from homeassistant.components import http
from homeassistant.core import callback
from homeassistant.helpers import template
from homeassistant.components import http
from .const import (
CONF_UID, CONF_TITLE, CONF_AUDIO, CONF_TEXT, CONF_DISPLAY_URL, ATTR_UID,
ATTR_UPDATE_DATE, ATTR_TITLE_TEXT, ATTR_STREAM_URL, ATTR_MAIN_TEXT,
ATTR_REDIRECTION_URL, DATE_FORMAT)
ATTR_MAIN_TEXT, ATTR_REDIRECTION_URL, ATTR_STREAM_URL, ATTR_TITLE_TEXT,
ATTR_UID, ATTR_UPDATE_DATE, CONF_AUDIO, CONF_DISPLAY_URL, CONF_TEXT,
CONF_TITLE, CONF_UID, DATE_FORMAT)
_LOGGER = logging.getLogger(__name__)
@@ -46,11 +45,11 @@ class AlexaFlashBriefingView(http.HomeAssistantView):
@callback
def get(self, request, briefing_id):
"""Handle Alexa Flash Briefing request."""
_LOGGER.debug('Received Alexa flash briefing request for: %s',
_LOGGER.debug("Received Alexa flash briefing request for: %s",
briefing_id)
if self.flash_briefings.get(briefing_id) is None:
err = 'No configured Alexa flash briefing was found for: %s'
err = "No configured Alexa flash briefing was found for: %s"
_LOGGER.error(err, briefing_id)
return b'', 404

View File

@@ -3,29 +3,31 @@ Support for Alexa skill service end point.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/alexa/
"""
import asyncio
import enum
import logging
from homeassistant.core import callback
from homeassistant.const import HTTP_BAD_REQUEST
from homeassistant.helpers import intent
from homeassistant.components import http
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import intent
from homeassistant.util.decorator import Registry
from .const import DOMAIN, SYN_RESOLUTION_MATCH
INTENTS_API_ENDPOINT = '/api/alexa'
_LOGGER = logging.getLogger(__name__)
HANDLERS = Registry()
INTENTS_API_ENDPOINT = '/api/alexa'
class SpeechType(enum.Enum):
"""The Alexa speech types."""
plaintext = "PlainText"
ssml = "SSML"
plaintext = 'PlainText'
ssml = 'SSML'
SPEECH_MAPPINGS = {
@@ -37,8 +39,8 @@ SPEECH_MAPPINGS = {
class CardType(enum.Enum):
"""The Alexa card types."""
simple = "Simple"
link_account = "LinkAccount"
simple = 'Simple'
link_account = 'LinkAccount'
@callback
@@ -47,6 +49,10 @@ def async_setup(hass):
hass.http.register_view(AlexaIntentsView)
class UnknownRequest(HomeAssistantError):
"""When an unknown Alexa request is passed in."""
class AlexaIntentsView(http.HomeAssistantView):
"""Handle Alexa requests."""
@@ -57,71 +63,114 @@ class AlexaIntentsView(http.HomeAssistantView):
def post(self, request):
"""Handle Alexa."""
hass = request.app['hass']
data = yield from request.json()
message = yield from request.json()
_LOGGER.debug('Received Alexa request: %s', data)
req = data.get('request')
if req is None:
_LOGGER.error('Received invalid data from Alexa: %s', data)
return self.json_message('Expected request value not received',
HTTP_BAD_REQUEST)
req_type = req['type']
if req_type == 'SessionEndedRequest':
return None
alexa_intent_info = req.get('intent')
alexa_response = AlexaResponse(hass, alexa_intent_info)
if req_type != 'IntentRequest' and req_type != 'LaunchRequest':
_LOGGER.warning('Received unsupported request: %s', req_type)
return self.json_message(
'Received unsupported request: {}'.format(req_type),
HTTP_BAD_REQUEST)
if req_type == 'LaunchRequest':
intent_name = data.get('session', {}) \
.get('application', {}) \
.get('applicationId')
else:
intent_name = alexa_intent_info['name']
_LOGGER.debug("Received Alexa request: %s", message)
try:
intent_response = yield from intent.async_handle(
hass, DOMAIN, intent_name,
{key: {'value': value} for key, value
in alexa_response.variables.items()})
response = yield from async_handle_message(hass, message)
return b'' if response is None else self.json(response)
except UnknownRequest as err:
_LOGGER.warning(str(err))
return self.json(intent_error_response(
hass, message, str(err)))
except intent.UnknownIntent as err:
_LOGGER.warning('Received unknown intent %s', intent_name)
alexa_response.add_speech(
SpeechType.plaintext,
"This intent is not yet configured within Home Assistant.")
return self.json(alexa_response)
_LOGGER.warning(str(err))
return self.json(intent_error_response(
hass, message,
"This intent is not yet configured within Home Assistant."))
except intent.InvalidSlotInfo as err:
_LOGGER.error('Received invalid slot data from Alexa: %s', err)
return self.json_message('Invalid slot data received',
HTTP_BAD_REQUEST)
except intent.IntentError:
_LOGGER.exception('Error handling request for %s', intent_name)
return self.json_message('Error handling intent', HTTP_BAD_REQUEST)
_LOGGER.error("Received invalid slot data from Alexa: %s", err)
return self.json(intent_error_response(
hass, message,
"Invalid slot information received for this intent."))
for intent_speech, alexa_speech in SPEECH_MAPPINGS.items():
if intent_speech in intent_response.speech:
alexa_response.add_speech(
alexa_speech,
intent_response.speech[intent_speech]['speech'])
break
except intent.IntentError as err:
_LOGGER.exception(str(err))
return self.json(intent_error_response(
hass, message, "Error handling intent."))
if 'simple' in intent_response.card:
alexa_response.add_card(
CardType.simple, intent_response.card['simple']['title'],
intent_response.card['simple']['content'])
return self.json(alexa_response)
def intent_error_response(hass, message, error):
"""Return an Alexa response that will speak the error message."""
alexa_intent_info = message.get('request').get('intent')
alexa_response = AlexaResponse(hass, alexa_intent_info)
alexa_response.add_speech(SpeechType.plaintext, error)
return alexa_response.as_dict()
@asyncio.coroutine
def async_handle_message(hass, message):
"""Handle an Alexa intent.
Raises:
- UnknownRequest
- intent.UnknownIntent
- intent.InvalidSlotInfo
- intent.IntentError
"""
req = message.get('request')
req_type = req['type']
handler = HANDLERS.get(req_type)
if not handler:
raise UnknownRequest('Received unknown request {}'.format(req_type))
return (yield from handler(hass, message))
@HANDLERS.register('SessionEndedRequest')
@asyncio.coroutine
def async_handle_session_end(hass, message):
"""Handle a session end request."""
return None
@HANDLERS.register('IntentRequest')
@HANDLERS.register('LaunchRequest')
@asyncio.coroutine
def async_handle_intent(hass, message):
"""Handle an intent request.
Raises:
- intent.UnknownIntent
- intent.InvalidSlotInfo
- intent.IntentError
"""
req = message.get('request')
alexa_intent_info = req.get('intent')
alexa_response = AlexaResponse(hass, alexa_intent_info)
if req['type'] == 'LaunchRequest':
intent_name = message.get('session', {}) \
.get('application', {}) \
.get('applicationId')
else:
intent_name = alexa_intent_info['name']
intent_response = yield from intent.async_handle(
hass, DOMAIN, intent_name,
{key: {'value': value} for key, value
in alexa_response.variables.items()})
for intent_speech, alexa_speech in SPEECH_MAPPINGS.items():
if intent_speech in intent_response.speech:
alexa_response.add_speech(
alexa_speech,
intent_response.speech[intent_speech]['speech'])
break
if 'simple' in intent_response.card:
alexa_response.add_card(
CardType.simple, intent_response.card['simple']['title'],
intent_response.card['simple']['content'])
return alexa_response.as_dict()
def resolve_slot_synonyms(key, request):

File diff suppressed because it is too large Load Diff

View File

@@ -89,6 +89,7 @@ def setup(hass, config):
"""Set up the Amcrest IP Camera component."""
from amcrest import AmcrestCamera
hass.data[DATA_AMCREST] = {}
amcrest_cams = config[DOMAIN]
for device in amcrest_cams:
@@ -126,22 +127,34 @@ def setup(hass, config):
else:
authentication = None
hass.data[DATA_AMCREST][name] = AmcrestDevice(
camera, name, authentication, ffmpeg_arguments, stream_source,
resolution)
discovery.load_platform(
hass, 'camera', DOMAIN, {
'device': camera,
CONF_AUTHENTICATION: authentication,
CONF_FFMPEG_ARGUMENTS: ffmpeg_arguments,
CONF_NAME: name,
CONF_RESOLUTION: resolution,
CONF_STREAM_SOURCE: stream_source,
}, config)
if sensors:
discovery.load_platform(
hass, 'sensor', DOMAIN, {
'device': camera,
CONF_NAME: name,
CONF_SENSORS: sensors,
}, config)
return True
class AmcrestDevice(object):
"""Representation of a base Amcrest discovery device."""
def __init__(self, camera, name, authentication, ffmpeg_arguments,
stream_source, resolution):
"""Initialize the entity."""
self.device = camera
self.name = name
self.authentication = authentication
self.ffmpeg_arguments = ffmpeg_arguments
self.stream_source = stream_source
self.resolution = resolution

View File

@@ -251,7 +251,7 @@ class AndroidIPCamEntity(Entity):
"""The Android device running IP Webcam."""
def __init__(self, host, ipcam):
"""Initialize the data oject."""
"""Initialize the data object."""
self._host = host
self._ipcam = ipcam

View File

@@ -66,7 +66,7 @@ class APCUPSdData(object):
"""
def __init__(self, host, port):
"""Initialize the data oject."""
"""Initialize the data object."""
from apcaccess import status
self._host = host
self._port = port

View File

@@ -24,6 +24,7 @@ from homeassistant.const import (
__version__)
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.state import AsyncTrackStates
from homeassistant.helpers.service import async_get_all_descriptions
from homeassistant.helpers import template
from homeassistant.components.http import HomeAssistantView
@@ -293,10 +294,11 @@ class APIServicesView(HomeAssistantView):
url = URL_API_SERVICES
name = "api:services"
@ha.callback
@asyncio.coroutine
def get(self, request):
"""Get registered services."""
return self.json(async_services_json(request.app['hass']))
services = yield from async_services_json(request.app['hass'])
return self.json(services)
class APIDomainServicesView(HomeAssistantView):
@@ -355,10 +357,12 @@ class APITemplateView(HomeAssistantView):
HTTP_BAD_REQUEST)
@asyncio.coroutine
def async_services_json(hass):
"""Generate services data to JSONify."""
descriptions = yield from async_get_all_descriptions(hass)
return [{"domain": key, "services": value}
for key, value in hass.services.async_services().items()]
for key, value in descriptions.items()]
def async_events_json(hass):

View File

@@ -4,21 +4,20 @@ Support for Apple TV.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/apple_tv/
"""
import os
import asyncio
import logging
from typing import Sequence, TypeVar, Union
import voluptuous as vol
from typing import Union, TypeVar, Sequence
from homeassistant.const import (CONF_HOST, CONF_NAME, ATTR_ENTITY_ID)
from homeassistant.config import load_yaml_config_file
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers import discovery
from homeassistant.components.discovery import SERVICE_APPLE_TV
from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST, CONF_NAME
from homeassistant.helpers import discovery
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyatv==0.3.8']
REQUIREMENTS = ['pyatv==0.3.9']
_LOGGER = logging.getLogger(__name__)
@@ -61,9 +60,9 @@ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.All(ensure_list, [vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_LOGIN_ID): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_CREDENTIALS, default=None): cv.string,
vol.Optional(CONF_START_OFF, default=False): cv.boolean
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_START_OFF, default=False): cv.boolean,
})])
}, extra=vol.ALLOW_EXTRA)
@@ -142,7 +141,7 @@ def async_setup(hass, config):
@asyncio.coroutine
def async_service_handler(service):
"""Handler for service calls."""
"""Handle service calls."""
entity_ids = service.data.get(ATTR_ENTITY_ID)
if service.service == SERVICE_SCAN:
@@ -169,7 +168,7 @@ def async_setup(hass, config):
@asyncio.coroutine
def atv_discovered(service, info):
"""Setup an Apple TV that was auto discovered."""
"""Set up an Apple TV that was auto discovered."""
yield from _setup_atv(hass, {
CONF_NAME: info['name'],
CONF_HOST: info['host'],
@@ -183,18 +182,12 @@ def async_setup(hass, config):
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
descriptions = yield from hass.async_add_job(
load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
hass.services.async_register(
DOMAIN, SERVICE_SCAN, async_service_handler,
descriptions.get(SERVICE_SCAN),
schema=APPLE_TV_SCAN_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_AUTHENTICATE, async_service_handler,
descriptions.get(SERVICE_AUTHENTICATE),
schema=APPLE_TV_AUTHENTICATE_SCHEMA)
return True
@@ -202,7 +195,7 @@ def async_setup(hass, config):
@asyncio.coroutine
def _setup_atv(hass, atv_config):
"""Setup an Apple TV."""
"""Set up an Apple TV."""
import pyatv
name = atv_config.get(CONF_NAME)
host = atv_config.get(CONF_HOST)
@@ -253,7 +246,7 @@ class AppleTVPowerManager:
@property
def turned_on(self):
"""If device is on or off."""
"""Return true if device is on or off."""
return self._is_on
def set_power_on(self, value):

View File

@@ -12,7 +12,7 @@ from requests.exceptions import HTTPError, ConnectTimeout
from homeassistant.helpers import config_validation as cv
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
REQUIREMENTS = ['pyarlo==0.1.0']
REQUIREMENTS = ['pyarlo==0.1.2']
_LOGGER = logging.getLogger(__name__)
@@ -47,7 +47,7 @@ def setup(hass, config):
return False
hass.data[DATA_ARLO] = arlo
except (ConnectTimeout, HTTPError) as ex:
_LOGGER.error("Unable to connect to Netgar Arlo: %s", str(ex))
_LOGGER.error("Unable to connect to Netgear Arlo: %s", str(ex))
hass.components.persistent_notification.create(
'Error: {}<br />'
'You will need to restart hass after fixing.'

View File

@@ -1,34 +1,34 @@
"""Support for Asterisk Voicemail interface."""
"""
Support for Asterisk Voicemail interface.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/asterisk_mbox/
"""
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.const import (CONF_HOST,
CONF_PORT, CONF_PASSWORD)
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import (async_dispatcher_connect,
async_dispatcher_send)
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import (
async_dispatcher_connect, async_dispatcher_send)
REQUIREMENTS = ['asterisk_mbox==0.4.0']
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
SIGNAL_MESSAGE_REQUEST = 'asterisk_mbox.message_request'
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'asterisk_mbox'
_LOGGER = logging.getLogger(__name__)
SIGNAL_MESSAGE_REQUEST = 'asterisk_mbox.message_request'
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORT): int,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_PORT): int,
}),
}, extra=vol.ALLOW_EXTRA)
@@ -43,7 +43,7 @@ def setup(hass, config):
hass.data[DOMAIN] = AsteriskData(hass, host, port, password)
discovery.load_platform(hass, "mailbox", DOMAIN, {}, config)
discovery.load_platform(hass, 'mailbox', DOMAIN, {}, config)
return True
@@ -68,15 +68,14 @@ class AsteriskData(object):
from asterisk_mbox.commands import CMD_MESSAGE_LIST
if command == CMD_MESSAGE_LIST:
_LOGGER.info("AsteriskVM sent updated message list")
self.messages = sorted(msg,
key=lambda item: item['info']['origtime'],
reverse=True)
async_dispatcher_send(self.hass, SIGNAL_MESSAGE_UPDATE,
self.messages)
_LOGGER.debug("AsteriskVM sent updated message list")
self.messages = sorted(
msg, key=lambda item: item['info']['origtime'], reverse=True)
async_dispatcher_send(
self.hass, SIGNAL_MESSAGE_UPDATE, self.messages)
@callback
def _request_messages(self):
"""Handle changes to the mailbox."""
_LOGGER.info("Requesting message list")
_LOGGER.debug("Requesting message list")
self.client.messages()

View File

@@ -7,14 +7,12 @@ https://home-assistant.io/components/automation/
import asyncio
from functools import partial
import logging
import os
import voluptuous as vol
from homeassistant.setup import async_prepare_setup_platform
from homeassistant.core import CoreState
from homeassistant.loader import bind_hass
from homeassistant import config as conf_util
from homeassistant.const import (
ATTR_ENTITY_ID, CONF_PLATFORM, STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF,
SERVICE_TOGGLE, SERVICE_RELOAD, EVENT_HOMEASSISTANT_START, CONF_ID)
@@ -166,11 +164,6 @@ def async_setup(hass, config):
yield from _async_process_config(hass, config, component)
descriptions = yield from hass.async_add_job(
conf_util.load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml')
)
@asyncio.coroutine
def trigger_service_handler(service_call):
"""Handle automation triggers."""
@@ -216,20 +209,20 @@ def async_setup(hass, config):
hass.services.async_register(
DOMAIN, SERVICE_TRIGGER, trigger_service_handler,
descriptions.get(SERVICE_TRIGGER), schema=TRIGGER_SERVICE_SCHEMA)
schema=TRIGGER_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_RELOAD, reload_service_handler,
descriptions.get(SERVICE_RELOAD), schema=RELOAD_SERVICE_SCHEMA)
schema=RELOAD_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_TOGGLE, toggle_service_handler,
descriptions.get(SERVICE_TOGGLE), schema=SERVICE_SCHEMA)
schema=SERVICE_SCHEMA)
for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF):
hass.services.async_register(
DOMAIN, service, turn_onoff_service_handler,
descriptions.get(service), schema=SERVICE_SCHEMA)
schema=SERVICE_SCHEMA)
return True
@@ -345,10 +338,9 @@ class AutomationEntity(ToggleEntity):
yield from self.async_update_ha_state()
@asyncio.coroutine
def async_remove(self):
"""Remove automation from HASS."""
def async_will_remove_from_hass(self):
"""Remove listeners when removing automation from HASS."""
yield from self.async_turn_off()
yield from super().async_remove()
@asyncio.coroutine
def async_enable(self):

View File

@@ -37,8 +37,8 @@ def async_trigger(hass, config, action):
above = config.get(CONF_ABOVE)
time_delta = config.get(CONF_FOR)
value_template = config.get(CONF_VALUE_TEMPLATE)
async_remove_track_same = None
already_triggered = False
unsub_track_same = {}
entities_triggered = set()
if value_template is not None:
value_template.hass = hass
@@ -63,8 +63,6 @@ def async_trigger(hass, config, action):
@callback
def state_automation_listener(entity, from_s, to_s):
"""Listen for state changes and calls action."""
nonlocal already_triggered, async_remove_track_same
@callback
def call_action():
"""Call action with right context."""
@@ -81,16 +79,18 @@ def async_trigger(hass, config, action):
matching = check_numeric_state(entity, from_s, to_s)
if matching and not already_triggered:
if not matching:
entities_triggered.discard(entity)
elif entity not in entities_triggered:
entities_triggered.add(entity)
if time_delta:
async_remove_track_same = async_track_same_state(
unsub_track_same[entity] = async_track_same_state(
hass, time_delta, call_action, entity_ids=entity_id,
async_check_same_func=check_numeric_state)
else:
call_action()
already_triggered = matching
unsub = async_track_state_change(
hass, entity_id, state_automation_listener)
@@ -98,7 +98,8 @@ def async_trigger(hass, config, action):
def async_remove():
"""Remove state listeners async."""
unsub()
if async_remove_track_same:
async_remove_track_same() # pylint: disable=not-callable
for async_remove in unsub_track_same.values():
async_remove()
unsub_track_same.clear()
return async_remove

View File

@@ -35,13 +35,11 @@ def async_trigger(hass, config, action):
to_state = config.get(CONF_TO, MATCH_ALL)
time_delta = config.get(CONF_FOR)
match_all = (from_state == MATCH_ALL and to_state == MATCH_ALL)
async_remove_track_same = None
unsub_track_same = {}
@callback
def state_automation_listener(entity, from_s, to_s):
"""Listen for state changes and calls action."""
nonlocal async_remove_track_same
@callback
def call_action():
"""Call action with right context."""
@@ -57,14 +55,14 @@ def async_trigger(hass, config, action):
# Ignore changes to state attributes if from/to is in use
if (not match_all and from_s is not None and to_s is not None and
from_s.last_changed == to_s.last_changed):
from_s.state == to_s.state):
return
if not time_delta:
call_action()
return
async_remove_track_same = async_track_same_state(
unsub_track_same[entity] = async_track_same_state(
hass, time_delta, call_action,
lambda _, _2, to_state: to_state.state == to_s.state,
entity_ids=entity_id)
@@ -76,7 +74,8 @@ def async_trigger(hass, config, action):
def async_remove():
"""Remove state listeners async."""
unsub()
if async_remove_track_same:
async_remove_track_same() # pylint: disable=not-callable
for async_remove in unsub_track_same.values():
async_remove()
unsub_track_same.clear()
return async_remove

View File

@@ -4,25 +4,20 @@ Support for Axis devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/axis/
"""
import json
import logging
import os
import voluptuous as vol
from homeassistant.components.discovery import SERVICE_AXIS
from homeassistant.config import load_yaml_config_file
from homeassistant.const import (ATTR_LOCATION, ATTR_TRIPPED,
CONF_EVENT, CONF_HOST, CONF_INCLUDE,
CONF_NAME, CONF_PASSWORD, CONF_PORT,
CONF_TRIGGER_TIME, CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP)
from homeassistant.const import (
ATTR_LOCATION, ATTR_TRIPPED, 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']
@@ -83,10 +78,10 @@ def request_configuration(hass, config, name, host, serialnumber):
configurator = hass.components.configurator
def configuration_callback(callback_data):
"""Called when config is submitted."""
"""Call when configuration is submitted."""
if CONF_INCLUDE not in callback_data:
configurator.notify_errors(request_id,
"Functionality mandatory.")
configurator.notify_errors(
request_id, "Functionality mandatory.")
return False
callback_data[CONF_INCLUDE] = callback_data[CONF_INCLUDE].split()
@@ -98,18 +93,20 @@ def request_configuration(hass, config, name, host, serialnumber):
try:
device_config = DEVICE_SCHEMA(callback_data)
except vol.Invalid:
configurator.notify_errors(request_id,
"Bad input, please check spelling.")
configurator.notify_errors(
request_id, "Bad input, please check spelling.")
return False
if setup_device(hass, config, device_config):
config_file = _read_config(hass)
del device_config['events']
del device_config['signal']
config_file = load_json(hass.config.path(CONFIG_FILE))
config_file[serialnumber] = dict(device_config)
_write_config(hass, config_file)
save_json(hass.config.path(CONFIG_FILE), config_file)
configurator.request_done(request_id)
else:
configurator.notify_errors(request_id,
"Failed to register, please try again.")
configurator.notify_errors(
request_id, "Failed to register, please try again.")
return False
title = '{} ({})'.format(name, host)
@@ -147,7 +144,7 @@ def request_configuration(hass, config, name, host, serialnumber):
def setup(hass, config):
"""Common setup for Axis devices."""
"""Set up for Axis devices."""
def _shutdown(call): # pylint: disable=unused-argument
"""Stop the event stream on shutdown."""
for serialnumber, device in AXIS_DEVICES.items():
@@ -157,13 +154,13 @@ def setup(hass, config):
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
def axis_device_discovered(service, discovery_info):
"""Called when axis devices has been found."""
"""Call when axis devices has been found."""
host = discovery_info[CONF_HOST]
name = discovery_info['hostname']
serialnumber = discovery_info['properties']['macaddress']
if serialnumber not in AXIS_DEVICES:
config_file = _read_config(hass)
config_file = load_json(hass.config.path(CONFIG_FILE))
if serialnumber in config_file:
# Device config previously saved to file
try:
@@ -173,8 +170,8 @@ def setup(hass, config):
_LOGGER.error("Bad data from %s. %s", CONFIG_FILE, err)
return False
if not setup_device(hass, config, device_config):
_LOGGER.error("Couldn\'t set up %s",
device_config[CONF_NAME])
_LOGGER.error(
"Couldn't set up %s", device_config[CONF_NAME])
else:
# New device, create configuration request for UI
request_configuration(hass, config, name, host, serialnumber)
@@ -193,11 +190,7 @@ def setup(hass, config):
if CONF_NAME not in device_config:
device_config[CONF_NAME] = device
if not setup_device(hass, config, device_config):
_LOGGER.error("Couldn\'t set up %s", device_config[CONF_NAME])
# Services to communicate with device.
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
_LOGGER.error("Couldn't set up %s", device_config[CONF_NAME])
def vapix_service(call):
"""Service to send a message."""
@@ -209,24 +202,21 @@ def setup(hass, config):
call.data[SERVICE_PARAM])
hass.bus.fire(SERVICE_VAPIX_CALL_RESPONSE, response)
return True
_LOGGER.info("Couldn\'t find device %s", call.data[CONF_NAME])
_LOGGER.info("Couldn't find device %s", call.data[CONF_NAME])
return False
# Register service with Home Assistant.
hass.services.register(DOMAIN,
SERVICE_VAPIX_CALL,
vapix_service,
descriptions[DOMAIN][SERVICE_VAPIX_CALL],
schema=SERVICE_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_VAPIX_CALL, vapix_service, schema=SERVICE_SCHEMA)
return True
def setup_device(hass, config, device_config):
"""Set up device."""
"""Set up an Axis device."""
from axis import AxisDevice
def signal_callback(action, event):
"""Callback to configure events when initialized on event stream."""
"""Call to configure events when initialized on event stream."""
if action == 'add':
event_config = {
CONF_EVENT: event,
@@ -235,11 +225,8 @@ def setup_device(hass, config, device_config):
CONF_TRIGGER_TIME: device_config[CONF_TRIGGER_TIME]
}
component = event.event_platform
discovery.load_platform(hass,
component,
DOMAIN,
event_config,
config)
discovery.load_platform(
hass, component, DOMAIN, event_config, config)
event_types = list(filter(lambda x: x in device_config[CONF_INCLUDE],
EVENT_TYPES))
@@ -250,7 +237,7 @@ def setup_device(hass, config, device_config):
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])
_LOGGER.error("Couldn't connect to %s", device_config[CONF_HOST])
return False
for component in device_config[CONF_INCLUDE]:
@@ -262,11 +249,8 @@ def setup_device(hass, config, device_config):
CONF_USERNAME: device_config[CONF_USERNAME],
CONF_PASSWORD: device_config[CONF_PASSWORD]
}
discovery.load_platform(hass,
component,
DOMAIN,
camera_config,
config)
discovery.load_platform(
hass, component, DOMAIN, camera_config, config)
AXIS_DEVICES[device.serial_number] = device
if event_types:
@@ -274,34 +258,15 @@ def setup_device(hass, config, device_config):
return True
def _read_config(hass):
"""Read Axis config."""
path = hass.config.path(CONFIG_FILE)
if not os.path.isfile(path):
return {}
with open(path) as f_handle:
# Guard against empty file
return json.loads(f_handle.read() or '{}')
def _write_config(hass, config):
"""Write Axis config."""
data = json.dumps(config)
with open(hass.config.path(CONFIG_FILE), 'w', encoding='utf-8') as outfile:
outfile.write(data)
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._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
@@ -322,7 +287,7 @@ class AxisDeviceEvent(Entity):
@property
def should_poll(self):
"""No polling needed."""
"""Return the polling state. No polling needed."""
return False
@property

View File

@@ -20,22 +20,28 @@ SCAN_INTERVAL = timedelta(seconds=30)
ENTITY_ID_FORMAT = DOMAIN + '.{}'
DEVICE_CLASSES = [
'cold', # On means cold (or too cold)
'connectivity', # On means connection present, Off = no connection
'gas', # CO, CO2, etc.
'heat', # On means hot (or too hot)
'light', # Lightness threshold
'moisture', # Specifically a wetness sensor
'motion', # Motion sensor
'moving', # On means moving, Off means stopped
'occupancy', # On means occupied, Off means not occupied
'opening', # Door, window, etc.
'battery', # On means low, Off means normal
'cold', # On means cold, Off means normal
'connectivity', # On means connected, Off means disconnected
'door', # On means open, Off means closed
'garage_door', # On means open, Off means closed
'gas', # On means gas detected, Off means no gas (clear)
'heat', # On means hot, Off means normal
'light', # On means light detected, Off means no light
'moisture', # On means wet, Off means dry
'motion', # On means motion detected, Off means no motion (clear)
'moving', # On means moving, Off means not moving (stopped)
'occupancy', # On means occupied, Off means not occupied (clear)
'opening', # On means open, Off means closed
'plug', # On means plugged in, Off means unplugged
'power', # Power, over-current, etc
'safety', # Generic on=unsafe, off=safe
'smoke', # Smoke detector
'sound', # On means sound detected, Off means no sound
'power', # On means power detected, Off means no power
'presence', # On means home, Off means away
'problem', # On means problem detected, Off means no problem (OK)
'safety', # On means unsafe, Off means safe
'smoke', # On means smoke detected, Off means no smoke (clear)
'sound', # On means sound detected, Off means no sound (clear)
'vibration', # On means vibration detected, Off means no vibration
'window', # On means open, Off means closed
]
DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(DEVICE_CLASSES))

View File

@@ -0,0 +1,84 @@
"""
Support for ADS binary sensors.
For more details about this platform, please refer to the documentation.
https://home-assistant.io/components/binary_sensor.ads/
"""
import asyncio
import logging
import voluptuous as vol
from homeassistant.components.ads import CONF_ADS_VAR, DATA_ADS
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'ADS binary sensor'
DEPENDENCIES = ['ads']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Binary Sensor platform for ADS."""
ads_hub = hass.data.get(DATA_ADS)
ads_var = config.get(CONF_ADS_VAR)
name = config.get(CONF_NAME)
device_class = config.get(CONF_DEVICE_CLASS)
ads_sensor = AdsBinarySensor(ads_hub, name, ads_var, device_class)
add_devices([ads_sensor])
class AdsBinarySensor(BinarySensorDevice):
"""Representation of ADS binary sensors."""
def __init__(self, ads_hub, name, ads_var, device_class):
"""Initialize ADS binary sensor."""
self._name = name
self._state = False
self._device_class = device_class or 'moving'
self._ads_hub = ads_hub
self.ads_var = ads_var
@asyncio.coroutine
def async_added_to_hass(self):
"""Register device notification."""
def update(name, value):
"""Handle device notifications."""
_LOGGER.debug('Variable %s changed its value to %d', name, value)
self._state = value
self.schedule_update_ha_state()
self.hass.async_add_job(
self._ads_hub.add_device_notification,
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update)
@property
def name(self):
"""Return the default name of the binary sensor."""
return self._name
@property
def device_class(self):
"""Return the device class."""
return self._device_class
@property
def is_on(self):
"""Return if the binary sensor is on."""
return self._state
@property
def should_poll(self):
"""Return False because entity pushes its state to HA."""
return False

View File

@@ -7,39 +7,41 @@ https://home-assistant.io/components/binary_sensor.alarmdecoder/
import asyncio
import logging
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.alarmdecoder import (ZONE_SCHEMA,
CONF_ZONES,
CONF_ZONE_NAME,
CONF_ZONE_TYPE,
SIGNAL_ZONE_FAULT,
SIGNAL_ZONE_RESTORE)
from homeassistant.components.alarmdecoder import (
ZONE_SCHEMA, CONF_ZONES, CONF_ZONE_NAME, CONF_ZONE_TYPE,
CONF_ZONE_RFID, SIGNAL_ZONE_FAULT, SIGNAL_ZONE_RESTORE,
SIGNAL_RFX_MESSAGE)
DEPENDENCIES = ['alarmdecoder']
_LOGGER = logging.getLogger(__name__)
ATTR_RF_BIT0 = 'rf_bit0'
ATTR_RF_LOW_BAT = 'rf_low_battery'
ATTR_RF_SUPERVISED = 'rf_supervised'
ATTR_RF_BIT3 = 'rf_bit3'
ATTR_RF_LOOP3 = 'rf_loop3'
ATTR_RF_LOOP2 = 'rf_loop2'
ATTR_RF_LOOP4 = 'rf_loop4'
ATTR_RF_LOOP1 = 'rf_loop1'
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the AlarmDecoder binary sensor devices."""
configured_zones = discovery_info[CONF_ZONES]
devices = []
for zone_num in configured_zones:
device_config_data = ZONE_SCHEMA(configured_zones[zone_num])
zone_type = device_config_data[CONF_ZONE_TYPE]
zone_name = device_config_data[CONF_ZONE_NAME]
zone_rfid = device_config_data.get(CONF_ZONE_RFID)
device = AlarmDecoderBinarySensor(
hass, zone_num, zone_name, zone_type)
zone_num, zone_name, zone_type, zone_rfid)
devices.append(device)
async_add_devices(devices)
add_devices(devices)
return True
@@ -47,46 +49,52 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class AlarmDecoderBinarySensor(BinarySensorDevice):
"""Representation of an AlarmDecoder binary sensor."""
def __init__(self, hass, zone_number, zone_name, zone_type):
def __init__(self, zone_number, zone_name, zone_type, zone_rfid):
"""Initialize the binary_sensor."""
self._zone_number = zone_number
self._zone_type = zone_type
self._state = 0
self._state = None
self._name = zone_name
self._type = zone_type
_LOGGER.debug("Setup up zone: %s", self._name)
self._rfid = zone_rfid
self._rfstate = None
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_FAULT, self._fault_callback)
self.hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_ZONE_FAULT, self._fault_callback)
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_RESTORE, self._restore_callback)
self.hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_ZONE_RESTORE, self._restore_callback)
self.hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_RFX_MESSAGE, self._rfx_message_callback)
@property
def name(self):
"""Return the name of the entity."""
return self._name
@property
def icon(self):
"""Icon for device by its type."""
if "window" in self._name.lower():
return "mdi:window-open" if self.is_on else "mdi:window-closed"
if self._type == 'smoke':
return "mdi:fire"
return None
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def device_state_attributes(self):
"""Return the state attributes."""
attr = {}
if self._rfid and self._rfstate is not None:
attr[ATTR_RF_BIT0] = True if self._rfstate & 0x01 else False
attr[ATTR_RF_LOW_BAT] = True if self._rfstate & 0x02 else False
attr[ATTR_RF_SUPERVISED] = True if self._rfstate & 0x04 else False
attr[ATTR_RF_BIT3] = True if self._rfstate & 0x08 else False
attr[ATTR_RF_LOOP3] = True if self._rfstate & 0x10 else False
attr[ATTR_RF_LOOP2] = True if self._rfstate & 0x20 else False
attr[ATTR_RF_LOOP4] = True if self._rfstate & 0x40 else False
attr[ATTR_RF_LOOP1] = True if self._rfstate & 0x80 else False
return attr
@property
def is_on(self):
"""Return true if sensor is on."""
@@ -97,16 +105,20 @@ class AlarmDecoderBinarySensor(BinarySensorDevice):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return self._zone_type
@callback
def _fault_callback(self, zone):
"""Update the zone's state, if needed."""
if zone is None or int(zone) == self._zone_number:
self._state = 1
self.async_schedule_update_ha_state()
self.schedule_update_ha_state()
@callback
def _restore_callback(self, zone):
"""Update the zone's state, if needed."""
if zone is None or int(zone) == self._zone_number:
self._state = 0
self.async_schedule_update_ha_state()
self.schedule_update_ha_state()
def _rfx_message_callback(self, message):
"""Update RF state."""
if self._rfid and message and message.serial_number == self._rfid:
self._rfstate = message.value
self.schedule_update_ha_state()

View File

@@ -4,13 +4,12 @@ Support for Axis binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.axis/
"""
import logging
from datetime import timedelta
import logging
from homeassistant.components.binary_sensor import (BinarySensorDevice)
from homeassistant.components.axis import (AxisDeviceEvent)
from homeassistant.const import (CONF_TRIGGER_TIME)
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.util.dt import utcnow
@@ -20,7 +19,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Axis device event."""
"""Set up the Axis binary devices."""
add_devices([AxisBinarySensor(hass, discovery_info)], True)
@@ -28,7 +27,7 @@ class AxisBinarySensor(AxisDeviceEvent, BinarySensorDevice):
"""Representation of a binary Axis event."""
def __init__(self, hass, event_config):
"""Initialize the binary sensor."""
"""Initialize the Axis binary sensor."""
self.hass = hass
self._state = False
self._delay = event_config[CONF_TRIGGER_TIME]
@@ -56,7 +55,7 @@ class AxisBinarySensor(AxisDeviceEvent, BinarySensorDevice):
# 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.",
_LOGGER.debug("%s called delayed (%s sec) update",
self._name, self._delay)
self.schedule_update_ha_state()
self._timer = None

View File

@@ -50,7 +50,6 @@ class BloomSkySensor(BinarySensorDevice):
self._device_id = device['DeviceID']
self._sensor_name = sensor_name
self._name = '{} {}'.format(device['DeviceName'], sensor_name)
self._unique_id = 'bloomsky_binary_sensor {}'.format(self._name)
self._state = None
@property
@@ -58,11 +57,6 @@ class BloomSkySensor(BinarySensorDevice):
"""Return the name of the BloomSky device and this sensor."""
return self._name
@property
def unique_id(self):
"""Return the unique ID for this sensor."""
return self._unique_id
@property
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""

13
homeassistant/components/binary_sensor/concord232.py Executable file → Normal file
View File

@@ -15,7 +15,7 @@ from homeassistant.components.binary_sensor import (
from homeassistant.const import (CONF_HOST, CONF_PORT)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['concord232==0.14']
REQUIREMENTS = ['concord232==0.15']
_LOGGER = logging.getLogger(__name__)
@@ -53,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
sensors = []
try:
_LOGGER.debug("Initializing Client")
_LOGGER.debug("Initializing client")
client = concord232_client.Client('http://{}:{}'.format(host, port))
client.zones = client.list_zones()
client.last_zone_update = datetime.datetime.now()
@@ -62,6 +62,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
_LOGGER.error("Unable to connect to Concord232: %s", str(ex))
return False
# The order of zones returned by client.list_zones() can vary.
# When the zones are not named, this can result in the same entity
# name mapping to different sensors in an unpredictable way. Sort
# the zones by zone number to prevent this.
client.zones.sort(key=lambda zone: zone['number'])
for zone in client.zones:
_LOGGER.info("Loading Zone found: %s", zone['name'])
if zone['number'] not in exclude:
@@ -118,7 +125,7 @@ class Concord232ZoneSensor(BinarySensorDevice):
def is_on(self):
"""Return true if the binary sensor is on."""
# True means "faulted" or "open" or "abnormal state"
return bool(self._zone['state'] == 'Normal')
return bool(self._zone['state'] != 'Normal')
def update(self):
"""Get updated stats from API."""

View File

@@ -0,0 +1,102 @@
"""
Support for deCONZ binary sensor.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.deconz/
"""
import asyncio
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.deconz import DOMAIN as DECONZ_DATA
from homeassistant.const import ATTR_BATTERY_LEVEL
from homeassistant.core import callback
DEPENDENCIES = ['deconz']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the deCONZ binary sensor."""
if discovery_info is None:
return
from pydeconz.sensor import DECONZ_BINARY_SENSOR
sensors = hass.data[DECONZ_DATA].sensors
entities = []
for key in sorted(sensors.keys(), key=int):
sensor = sensors[key]
if sensor and sensor.type in DECONZ_BINARY_SENSOR:
entities.append(DeconzBinarySensor(sensor))
async_add_devices(entities, True)
class DeconzBinarySensor(BinarySensorDevice):
"""Representation of a binary sensor."""
def __init__(self, sensor):
"""Set up sensor and add update callback to get data from websocket."""
self._sensor = sensor
@asyncio.coroutine
def async_added_to_hass(self):
"""Subscribe sensors events."""
self._sensor.register_async_callback(self.async_update_callback)
@callback
def async_update_callback(self, reason):
"""Update the sensor's state.
If reason is that state is updated,
or reachable has changed or battery has changed.
"""
if reason['state'] or \
'reachable' in reason['attr'] or \
'battery' in reason['attr']:
self.async_schedule_update_ha_state()
@property
def is_on(self):
"""Return true if sensor is on."""
return self._sensor.is_tripped
@property
def name(self):
"""Return the name of the sensor."""
return self._sensor.name
@property
def unique_id(self):
"""Return a unique identifier for this sensor."""
return self._sensor.uniqueid
@property
def device_class(self):
"""Return the class of the sensor."""
return self._sensor.sensor_class
@property
def icon(self):
"""Return the icon to use in the frontend."""
return self._sensor.sensor_icon
@property
def available(self):
"""Return True if sensor is available."""
return self._sensor.reachable
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def device_state_attributes(self):
"""Return the state attributes of the sensor."""
from pydeconz.sensor import PRESENCE
attr = {
ATTR_BATTERY_LEVEL: self._sensor.battery,
}
if self._sensor.type == PRESENCE:
attr['dark'] = self._sensor.dark
return attr

View File

@@ -1,60 +0,0 @@
"""Support for reading binary states from a DoorBird video doorbell."""
from datetime import timedelta
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.doorbird import DOMAIN as DOORBIRD_DOMAIN
from homeassistant.util import Throttle
DEPENDENCIES = ['doorbird']
_LOGGER = logging.getLogger(__name__)
_MIN_UPDATE_INTERVAL = timedelta(milliseconds=250)
SENSOR_TYPES = {
"doorbell": {
"name": "Doorbell Ringing",
"icon": {
True: "bell-ring",
False: "bell",
None: "bell-outline"
}
}
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the DoorBird binary sensor component."""
device = hass.data.get(DOORBIRD_DOMAIN)
add_devices([DoorBirdBinarySensor(device, "doorbell")], True)
class DoorBirdBinarySensor(BinarySensorDevice):
"""A binary sensor of a DoorBird device."""
def __init__(self, device, sensor_type):
"""Initialize a binary sensor on a DoorBird device."""
self._device = device
self._sensor_type = sensor_type
self._state = None
@property
def name(self):
"""Get the name of the sensor."""
return SENSOR_TYPES[self._sensor_type]["name"]
@property
def icon(self):
"""Get an icon to display."""
state_icon = SENSOR_TYPES[self._sensor_type]["icon"][self._state]
return "mdi:{}".format(state_icon)
@property
def is_on(self):
"""Get the state of the binary sensor."""
return self._state
@Throttle(_MIN_UPDATE_INTERVAL)
def update(self):
"""Pull the latest value from the device."""
self._state = self._device.doorbell_state()

View File

@@ -50,11 +50,6 @@ class EcobeeBinarySensor(BinarySensorDevice):
"""Return the status of the sensor."""
return self._state == 'true'
@property
def unique_id(self):
"""Return the unique ID of this sensor."""
return "binary_sensor_ecobee_{}_{}".format(self._name, self.index)
@property
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""

View File

@@ -48,7 +48,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the FFmpeg binary moition sensor."""
"""Set up the FFmpeg binary motion sensor."""
manager = hass.data[DATA_FFMPEG]
if not manager.async_run_test(config.get(CONF_INPUT)):

View File

@@ -238,6 +238,5 @@ class FlicButton(BinarySensorDevice):
import pyflic
if connection_status == pyflic.ConnectionStatus.Disconnected:
_LOGGER.info("Button (%s) disconnected. Reason: %s",
self.address, disconnect_reason)
self.remove()
_LOGGER.warning("Button (%s) disconnected. Reason: %s",
self.address, disconnect_reason)

View File

@@ -118,7 +118,7 @@ class HikvisionData(object):
"""Hikvision device event stream object."""
def __init__(self, hass, url, port, name, username, password):
"""Initialize the data oject."""
"""Initialize the data object."""
from pyhik.hikvision import HikCamera
self._url = url
self._port = port
@@ -212,7 +212,7 @@ class HikvisionBinarySensor(BinarySensorDevice):
@property
def unique_id(self):
"""Return an unique ID."""
return '{}.{}'.format(self.__class__, self._id)
return self._id
@property
def is_on(self):

View File

@@ -0,0 +1,63 @@
"""
Support for the Hive devices.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.hive/
"""
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.hive import DATA_HIVE
DEPENDENCIES = ['hive']
DEVICETYPE_DEVICE_CLASS = {'motionsensor': 'motion',
'contactsensor': 'opening'}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Hive sensor devices."""
if discovery_info is None:
return
session = hass.data.get(DATA_HIVE)
add_devices([HiveBinarySensorEntity(session, discovery_info)])
class HiveBinarySensorEntity(BinarySensorDevice):
"""Representation of a Hive binary sensor."""
def __init__(self, hivesession, hivedevice):
"""Initialize the hive sensor."""
self.node_id = hivedevice["Hive_NodeID"]
self.node_name = hivedevice["Hive_NodeName"]
self.device_type = hivedevice["HA_DeviceType"]
self.node_device_type = hivedevice["Hive_DeviceType"]
self.session = hivesession
self.data_updatesource = '{}.{}'.format(self.device_type,
self.node_id)
self.session.entities.append(self)
def handle_update(self, updatesource):
"""Handle the new update request."""
if '{}.{}'.format(self.device_type, self.node_id) not in updatesource:
self.schedule_update_ha_state()
@property
def device_class(self):
"""Return the class of this sensor."""
return DEVICETYPE_DEVICE_CLASS.get(self.node_device_type)
@property
def name(self):
"""Return the name of the binary sensor."""
return self.node_name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self.session.sensor.get_state(self.node_id,
self.node_device_type)
def update(self):
"""Update all Node data from Hive."""
self.session.core.update_data(self.node_id)

View File

@@ -25,6 +25,7 @@ SENSOR_TYPES_CLASS = {
'RemoteMotion': None,
'WeatherSensor': None,
'TiltSensor': None,
'PresenceIP': 'motion',
}

View File

@@ -0,0 +1,96 @@
"""IHC binary sensor platform.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.ihc/
"""
from xml.etree.ElementTree import Element
import voluptuous as vol
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA)
from homeassistant.components.ihc import (
validate_name, IHC_DATA, IHC_CONTROLLER, IHC_INFO)
from homeassistant.components.ihc.const import CONF_INVERTING
from homeassistant.components.ihc.ihcdevice import IHCDevice
from homeassistant.const import (
CONF_NAME, CONF_TYPE, CONF_ID, CONF_BINARY_SENSORS)
import homeassistant.helpers.config_validation as cv
DEPENDENCIES = ['ihc']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_BINARY_SENSORS, default=[]):
vol.All(cv.ensure_list, [
vol.All({
vol.Required(CONF_ID): cv.positive_int,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_TYPE, default=None): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_INVERTING, default=False): cv.boolean,
}, validate_name)
])
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the IHC binary sensor platform."""
ihc_controller = hass.data[IHC_DATA][IHC_CONTROLLER]
info = hass.data[IHC_DATA][IHC_INFO]
devices = []
if discovery_info:
for name, device in discovery_info.items():
ihc_id = device['ihc_id']
product_cfg = device['product_cfg']
product = device['product']
sensor = IHCBinarySensor(ihc_controller, name, ihc_id, info,
product_cfg[CONF_TYPE],
product_cfg[CONF_INVERTING],
product)
devices.append(sensor)
else:
binary_sensors = config[CONF_BINARY_SENSORS]
for sensor_cfg in binary_sensors:
ihc_id = sensor_cfg[CONF_ID]
name = sensor_cfg[CONF_NAME]
sensor_type = sensor_cfg[CONF_TYPE]
inverting = sensor_cfg[CONF_INVERTING]
sensor = IHCBinarySensor(ihc_controller, name, ihc_id, info,
sensor_type, inverting)
devices.append(sensor)
add_devices(devices)
class IHCBinarySensor(IHCDevice, BinarySensorDevice):
"""IHC Binary Sensor.
The associated IHC resource can be any in or output from a IHC product
or function block, but it must be a boolean ON/OFF resources.
"""
def __init__(self, ihc_controller, name, ihc_id: int, info: bool,
sensor_type: str, inverting: bool,
product: Element=None) -> None:
"""Initialize the IHC binary sensor."""
super().__init__(ihc_controller, name, ihc_id, info, product)
self._state = None
self._sensor_type = sensor_type
self.inverting = inverting
@property
def device_class(self):
"""Return the class of this sensor."""
return self._sensor_type
@property
def is_on(self):
"""Return true if the binary sensor is on/open."""
return self._state
def on_ihc_change(self, ihc_id, value):
"""IHC resource has changed."""
if self.inverting:
self._state = not value
else:
self._state = value
self.schedule_update_ha_state()

View File

@@ -83,5 +83,5 @@ class InsteonPLMBinarySensorDevice(BinarySensorDevice):
@callback
def async_binarysensor_update(self, message):
"""Receive notification from transport that new data exists."""
_LOGGER.info("Received update calback from PLM for %s", self._address)
_LOGGER.info("Received update callback from PLM for %s", self._address)
self._hass.async_add_job(self.async_update_ha_state())

View File

@@ -4,67 +4,364 @@ Support for ISY994 binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.isy994/
"""
import asyncio
import logging
from datetime import timedelta
from typing import Callable # noqa
from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorDevice, DOMAIN
import homeassistant.components.isy994 as isy
from homeassistant.components.isy994 import (ISY994_NODES, ISY994_PROGRAMS,
ISYDevice)
from homeassistant.const import STATE_ON, STATE_OFF
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.util import dt as dt_util
_LOGGER = logging.getLogger(__name__)
VALUE_TO_STATE = {
False: STATE_OFF,
True: STATE_ON,
ISY_DEVICE_TYPES = {
'moisture': ['16.8', '16.13', '16.14'],
'opening': ['16.9', '16.6', '16.7', '16.2', '16.17', '16.20', '16.21'],
'motion': ['16.1', '16.4', '16.5', '16.3']
}
UOM = ['2', '78']
STATES = [STATE_OFF, STATE_ON, 'true', 'false']
# pylint: disable=unused-argument
def setup_platform(hass, config: ConfigType,
add_devices: Callable[[list], None], discovery_info=None):
"""Set up the ISY994 binary sensor platform."""
if isy.ISY is None or not isy.ISY.connected:
_LOGGER.error("A connection has not been made to the ISY controller")
return False
devices = []
devices_by_nid = {}
child_nodes = []
for node in isy.filter_nodes(isy.SENSOR_NODES, units=UOM,
states=STATES):
devices.append(ISYBinarySensorDevice(node))
for program in isy.PROGRAMS.get(DOMAIN, []):
try:
status = program[isy.KEY_STATUS]
except (KeyError, AssertionError):
pass
for node in hass.data[ISY994_NODES][DOMAIN]:
if node.parent_node is None:
device = ISYBinarySensorDevice(node)
devices.append(device)
devices_by_nid[node.nid] = device
else:
devices.append(ISYBinarySensorProgram(program.name, status))
# We'll process the child nodes last, to ensure all parent nodes
# have been processed
child_nodes.append(node)
for node in child_nodes:
try:
parent_device = devices_by_nid[node.parent_node.nid]
except KeyError:
_LOGGER.error("Node %s has a parent node %s, but no device "
"was created for the parent. Skipping.",
node.nid, node.parent_nid)
else:
device_type = _detect_device_type(node)
subnode_id = int(node.nid[-1])
if device_type == 'opening':
# Door/window sensors use an optional "negative" node
if subnode_id == 4:
# Subnode 4 is the heartbeat node, which we will represent
# as a separate binary_sensor
device = ISYBinarySensorHeartbeat(node, parent_device)
parent_device.add_heartbeat_device(device)
devices.append(device)
elif subnode_id == 2:
parent_device.add_negative_node(node)
elif device_type == 'moisture':
# Moisture nodes have a subnode 2, but we ignore it because
# it's just the inverse of the primary node.
if subnode_id == 4:
# Heartbeat node
device = ISYBinarySensorHeartbeat(node, parent_device)
parent_device.add_heartbeat_device(device)
devices.append(device)
else:
# We don't yet have any special logic for other sensor types,
# so add the nodes as individual devices
device = ISYBinarySensorDevice(node)
devices.append(device)
for name, status, _ in hass.data[ISY994_PROGRAMS][DOMAIN]:
devices.append(ISYBinarySensorProgram(name, status))
add_devices(devices)
class ISYBinarySensorDevice(isy.ISYDevice, BinarySensorDevice):
"""Representation of an ISY994 binary sensor device."""
def _detect_device_type(node) -> str:
try:
device_type = node.type
except AttributeError:
# The type attribute didn't exist in the ISY's API response
return None
split_type = device_type.split('.')
for device_class, ids in ISY_DEVICE_TYPES.items():
if '{}.{}'.format(split_type[0], split_type[1]) in ids:
return device_class
return None
def _is_val_unknown(val):
"""Determine if a number value represents UNKNOWN from PyISY."""
return val == -1*float('inf')
class ISYBinarySensorDevice(ISYDevice, BinarySensorDevice):
"""Representation of an ISY994 binary sensor device.
Often times, a single device is represented by multiple nodes in the ISY,
allowing for different nuances in how those devices report their on and
off events. This class turns those multiple nodes in to a single Hass
entity and handles both ways that ISY binary sensors can work.
"""
def __init__(self, node) -> None:
"""Initialize the ISY994 binary sensor device."""
isy.ISYDevice.__init__(self, node)
super().__init__(node)
self._negative_node = None
self._heartbeat_device = None
self._device_class_from_type = _detect_device_type(self._node)
# pylint: disable=protected-access
if _is_val_unknown(self._node.status._val):
self._computed_state = None
else:
self._computed_state = bool(self._node.status._val)
@asyncio.coroutine
def async_added_to_hass(self) -> None:
"""Subscribe to the node and subnode event emitters."""
yield from super().async_added_to_hass()
self._node.controlEvents.subscribe(self._positive_node_control_handler)
if self._negative_node is not None:
self._negative_node.controlEvents.subscribe(
self._negative_node_control_handler)
def add_heartbeat_device(self, device) -> None:
"""Register a heartbeat device for this sensor.
The heartbeat node beats on its own, but we can gain a little
reliability by considering any node activity for this sensor
to be a heartbeat as well.
"""
self._heartbeat_device = device
def _heartbeat(self) -> None:
"""Send a heartbeat to our heartbeat device, if we have one."""
if self._heartbeat_device is not None:
self._heartbeat_device.heartbeat()
def add_negative_node(self, child) -> None:
"""Add a negative node to this binary sensor device.
The negative node is a node that can receive the 'off' events
for the sensor, depending on device configuration and type.
"""
self._negative_node = child
# pylint: disable=protected-access
if not _is_val_unknown(self._negative_node.status._val):
# If the negative node has a value, it means the negative node is
# in use for this device. Therefore, we cannot determine the state
# of the sensor until we receive our first ON event.
self._computed_state = None
def _negative_node_control_handler(self, event: object) -> None:
"""Handle an "On" control event from the "negative" node."""
if event == 'DON':
_LOGGER.debug("Sensor %s turning Off via the Negative node "
"sending a DON command", self.name)
self._computed_state = False
self.schedule_update_ha_state()
self._heartbeat()
def _positive_node_control_handler(self, event: object) -> None:
"""Handle On and Off control event coming from the primary node.
Depending on device configuration, sometimes only On events
will come to this node, with the negative node representing Off
events
"""
if event == 'DON':
_LOGGER.debug("Sensor %s turning On via the Primary node "
"sending a DON command", self.name)
self._computed_state = True
self.schedule_update_ha_state()
self._heartbeat()
if event == 'DOF':
_LOGGER.debug("Sensor %s turning Off via the Primary node "
"sending a DOF command", self.name)
self._computed_state = False
self.schedule_update_ha_state()
self._heartbeat()
# pylint: disable=unused-argument
def on_update(self, event: object) -> None:
"""Ignore primary node status updates.
We listen directly to the Control events on all nodes for this
device.
"""
pass
@property
def value(self) -> object:
"""Get the current value of the device.
Insteon leak sensors set their primary node to On when the state is
DRY, not WET, so we invert the binary state if the user indicates
that it is a moisture sensor.
"""
if self._computed_state is None:
# Do this first so we don't invert None on moisture sensors
return None
if self.device_class == 'moisture':
return not self._computed_state
return self._computed_state
@property
def is_on(self) -> bool:
"""Get whether the ISY994 binary sensor device is on.
Note: This method will return false if the current state is UNKNOWN
"""
return bool(self.value)
@property
def state(self):
"""Return the state of the binary sensor."""
if self._computed_state is None:
return None
return STATE_ON if self.is_on else STATE_OFF
@property
def device_class(self) -> str:
"""Return the class of this device.
This was discovered by parsing the device type code during init
"""
return self._device_class_from_type
class ISYBinarySensorHeartbeat(ISYDevice, BinarySensorDevice):
"""Representation of the battery state of an ISY994 sensor."""
def __init__(self, node, parent_device) -> None:
"""Initialize the ISY994 binary sensor device."""
super().__init__(node)
self._computed_state = None
self._parent_device = parent_device
self._heartbeat_timer = None
@asyncio.coroutine
def async_added_to_hass(self) -> None:
"""Subscribe to the node and subnode event emitters."""
yield from super().async_added_to_hass()
self._node.controlEvents.subscribe(
self._heartbeat_node_control_handler)
# Start the timer on bootup, so we can change from UNKNOWN to ON
self._restart_timer()
def _heartbeat_node_control_handler(self, event: object) -> None:
"""Update the heartbeat timestamp when an On event is sent."""
if event == 'DON':
self.heartbeat()
def heartbeat(self):
"""Mark the device as online, and restart the 25 hour timer.
This gets called when the heartbeat node beats, but also when the
parent sensor sends any events, as we can trust that to mean the device
is online. This mitigates the risk of false positives due to a single
missed heartbeat event.
"""
self._computed_state = False
self._restart_timer()
self.schedule_update_ha_state()
def _restart_timer(self):
"""Restart the 25 hour timer."""
try:
self._heartbeat_timer()
self._heartbeat_timer = None
except TypeError:
# No heartbeat timer is active
pass
# pylint: disable=unused-argument
@callback
def timer_elapsed(now) -> None:
"""Heartbeat missed; set state to indicate dead battery."""
self._computed_state = True
self._heartbeat_timer = None
self.schedule_update_ha_state()
point_in_time = dt_util.utcnow() + timedelta(hours=25)
_LOGGER.debug("Timer starting. Now: %s Then: %s",
dt_util.utcnow(), point_in_time)
self._heartbeat_timer = async_track_point_in_utc_time(
self.hass, timer_elapsed, point_in_time)
# pylint: disable=unused-argument
def on_update(self, event: object) -> None:
"""Ignore node status updates.
We listen directly to the Control events for this device.
"""
pass
@property
def value(self) -> object:
"""Get the current value of this sensor."""
return self._computed_state
@property
def is_on(self) -> bool:
"""Get whether the ISY994 binary sensor device is on.
Note: This method will return false if the current state is UNKNOWN
"""
return bool(self.value)
@property
def state(self):
"""Return the state of the binary sensor."""
if self._computed_state is None:
return None
return STATE_ON if self.is_on else STATE_OFF
@property
def device_class(self) -> str:
"""Get the class of this device."""
return 'battery'
@property
def device_state_attributes(self):
"""Get the state attributes for the device."""
attr = super().device_state_attributes
attr['parent_entity_id'] = self._parent_device.entity_id
return attr
class ISYBinarySensorProgram(ISYDevice, BinarySensorDevice):
"""Representation of an ISY994 binary sensor program.
This does not need all of the subnode logic in the device version of binary
sensors.
"""
def __init__(self, name, node) -> None:
"""Initialize the ISY994 binary sensor program."""
super().__init__(node)
self._name = name
@property
def is_on(self) -> bool:
"""Get whether the ISY994 binary sensor device is on."""
return bool(self.value)
class ISYBinarySensorProgram(ISYBinarySensorDevice):
"""Representation of an ISY994 binary sensor program."""
def __init__(self, name, node) -> None:
"""Initialize the ISY994 binary sensor program."""
ISYBinarySensorDevice.__init__(self, node)
self._name = name

View File

@@ -5,12 +5,13 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.knx/
"""
import asyncio
import voluptuous as vol
from homeassistant.components.knx import DATA_KNX, ATTR_DISCOVER_DEVICES, \
KNXAutomation
from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, \
BinarySensorDevice
from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.components.knx import (
ATTR_DISCOVER_DEVICES, DATA_KNX, KNXAutomation)
from homeassistant.const import CONF_NAME
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
@@ -53,20 +54,16 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up binary sensor(s) for KNX platform."""
if DATA_KNX not in hass.data \
or not hass.data[DATA_KNX].initialized:
return False
if DATA_KNX not in hass.data or not hass.data[DATA_KNX].initialized:
return
if discovery_info is not None:
async_add_devices_discovery(hass, discovery_info, async_add_devices)
else:
async_add_devices_config(hass, config, async_add_devices)
return True
@callback
def async_add_devices_discovery(hass, discovery_info, async_add_devices):
@@ -80,7 +77,7 @@ def async_add_devices_discovery(hass, discovery_info, async_add_devices):
@callback
def async_add_devices_config(hass, config, async_add_devices):
"""Set up binary senor for KNX platform configured within plattform."""
"""Set up binary senor for KNX platform configured within platform."""
name = config.get(CONF_NAME)
import xknx
binary_sensor = xknx.devices.BinarySensor(
@@ -108,7 +105,7 @@ class KNXBinarySensor(BinarySensorDevice):
"""Representation of a KNX binary sensor."""
def __init__(self, hass, device):
"""Initialization of KNXBinarySensor."""
"""Initialize of KNX binary sensor."""
self.device = device
self.hass = hass
self.async_register_callbacks()
@@ -119,7 +116,7 @@ class KNXBinarySensor(BinarySensorDevice):
"""Register callbacks to update hass after device was changed."""
@asyncio.coroutine
def after_update_callback(device):
"""Callback after device was updated."""
"""Call after device was updated."""
# pylint: disable=unused-argument
yield from self.async_update_ha_state()
self.device.register_device_updated_cb(after_update_callback)
@@ -129,6 +126,11 @@ class KNXBinarySensor(BinarySensorDevice):
"""Return the name of the KNX device."""
return self.device.name
@property
def available(self):
"""Return True if entity is available."""
return self.hass.data[DATA_KNX].connected
@property
def should_poll(self):
"""No polling needed within KNX."""

View File

@@ -36,7 +36,7 @@ class MaxCubeShutter(BinarySensorDevice):
def __init__(self, hass, name, rf_address):
"""Initialize MAX! Cube BinarySensorDevice."""
self._name = name
self._sensor_type = 'opening'
self._sensor_type = 'window'
self._rf_address = rf_address
self._cubehandle = hass.data[MAXCUBE_HANDLE]
self._state = STATE_UNKNOWN

View File

@@ -0,0 +1,94 @@
"""
Support for Mercedes cars with Mercedes ME.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mercedesme/
"""
import logging
import datetime
from homeassistant.components.binary_sensor import (BinarySensorDevice)
from homeassistant.components.mercedesme import (
DATA_MME, MercedesMeEntity, BINARY_SENSORS)
DEPENDENCIES = ['mercedesme']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the sensor platform."""
data = hass.data[DATA_MME].data
if not data.cars:
_LOGGER.error("No cars found. Check component log.")
return
devices = []
for car in data.cars:
for key, value in sorted(BINARY_SENSORS.items()):
devices.append(MercedesMEBinarySensor(
data, key, value[0], car["vin"], None))
add_devices(devices, True)
class MercedesMEBinarySensor(MercedesMeEntity, BinarySensorDevice):
"""Representation of a Sensor."""
@property
def is_on(self):
"""Return the state of the binary sensor."""
return self._state
@property
def device_state_attributes(self):
"""Return the state attributes."""
if self._internal_name == "windowsClosed":
return {
"window_front_left": self._car["windowStatusFrontLeft"],
"window_front_right": self._car["windowStatusFrontRight"],
"window_rear_left": self._car["windowStatusRearLeft"],
"window_rear_right": self._car["windowStatusRearRight"],
"original_value": self._car[self._internal_name],
"last_update": datetime.datetime.fromtimestamp(
self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
"car": self._car["license"]
}
elif self._internal_name == "tireWarningLight":
return {
"front_right_tire_pressure_kpa":
self._car["frontRightTirePressureKpa"],
"front_left_tire_pressure_kpa":
self._car["frontLeftTirePressureKpa"],
"rear_right_tire_pressure_kpa":
self._car["rearRightTirePressureKpa"],
"rear_left_tire_pressure_kpa":
self._car["rearLeftTirePressureKpa"],
"original_value": self._car[self._internal_name],
"last_update": datetime.datetime.fromtimestamp(
self._car["lastUpdate"]
).strftime('%Y-%m-%d %H:%M:%S'),
"car": self._car["license"],
}
return {
"original_value": self._car[self._internal_name],
"last_update": datetime.datetime.fromtimestamp(
self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
"car": self._car["license"]
}
def update(self):
"""Fetch new state data for the sensor."""
self._car = next(
car for car in self._data.cars if car["vin"] == self._vin)
if self._internal_name == "windowsClosed":
self._state = bool(self._car[self._internal_name] == "CLOSED")
elif self._internal_name == "tireWarningLight":
self._state = bool(self._car[self._internal_name] != "INACTIVE")
else:
self._state = self._car[self._internal_name] is True
_LOGGER.debug("Updated %s Value: %s IsOn: %s",
self._internal_name, self._state, self.is_on)

View File

@@ -14,22 +14,20 @@ import homeassistant.components.mqtt as mqtt
from homeassistant.components.binary_sensor import (
BinarySensorDevice, DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON, CONF_PAYLOAD_OFF,
CONF_DEVICE_CLASS)
CONF_FORCE_UPDATE, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON,
CONF_PAYLOAD_OFF, CONF_DEVICE_CLASS)
from homeassistant.components.mqtt import (
CONF_STATE_TOPIC, CONF_AVAILABILITY_TOPIC, CONF_QOS, valid_subscribe_topic)
CONF_STATE_TOPIC, CONF_AVAILABILITY_TOPIC, CONF_PAYLOAD_AVAILABLE,
CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, MqttAvailability)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
CONF_PAYLOAD_AVAILABLE = 'payload_available'
CONF_PAYLOAD_NOT_AVAILABLE = 'payload_not_available'
DEFAULT_NAME = 'MQTT Binary sensor'
DEFAULT_PAYLOAD_OFF = 'OFF'
DEFAULT_PAYLOAD_ON = 'ON'
DEFAULT_PAYLOAD_AVAILABLE = 'online'
DEFAULT_PAYLOAD_NOT_AVAILABLE = 'offline'
DEFAULT_FORCE_UPDATE = False
DEPENDENCIES = ['mqtt']
@@ -38,12 +36,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_AVAILABILITY_TOPIC): valid_subscribe_topic,
vol.Optional(CONF_PAYLOAD_AVAILABLE,
default=DEFAULT_PAYLOAD_AVAILABLE): cv.string,
vol.Optional(CONF_PAYLOAD_NOT_AVAILABLE,
default=DEFAULT_PAYLOAD_NOT_AVAILABLE): cv.string,
})
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@asyncio.coroutine
@@ -62,6 +56,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
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),
@@ -70,31 +65,30 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
)])
class MqttBinarySensor(BinarySensorDevice):
class MqttBinarySensor(MqttAvailability, BinarySensorDevice):
"""Representation a binary sensor that is updated by MQTT."""
def __init__(self, name, state_topic, availability_topic, device_class,
qos, payload_on, payload_off, payload_available,
qos, force_update, payload_on, payload_off, payload_available,
payload_not_available, value_template):
"""Initialize the MQTT binary sensor."""
super().__init__(availability_topic, qos, payload_available,
payload_not_available)
self._name = name
self._state = None
self._state_topic = state_topic
self._availability_topic = availability_topic
self._available = True if availability_topic is None else False
self._device_class = device_class
self._payload_on = payload_on
self._payload_off = payload_off
self._payload_available = payload_available
self._payload_not_available = payload_not_available
self._qos = qos
self._force_update = force_update
self._template = value_template
@asyncio.coroutine
def async_added_to_hass(self):
"""Subscribe mqtt events.
"""Subscribe mqtt events."""
yield from super().async_added_to_hass()
This method must be run in the event loop and returns a coroutine.
"""
@callback
def state_message_received(topic, payload, qos):
"""Handle a new received MQTT state message."""
@@ -105,27 +99,17 @@ class MqttBinarySensor(BinarySensorDevice):
self._state = True
elif payload == self._payload_off:
self._state = False
else: # Payload is not for this entity
_LOGGER.warning('No matching payload found'
' for entity: %s with state_topic: %s',
self._name, self._state_topic)
return
self.async_schedule_update_ha_state()
yield from mqtt.async_subscribe(
self.hass, self._state_topic, state_message_received, self._qos)
@callback
def availability_message_received(topic, payload, qos):
"""Handle a new received MQTT availability message."""
if payload == self._payload_available:
self._available = True
elif payload == self._payload_not_available:
self._available = False
self.async_schedule_update_ha_state()
if self._availability_topic is not None:
yield from mqtt.async_subscribe(
self.hass, self._availability_topic,
availability_message_received, self._qos)
@property
def should_poll(self):
"""Return the polling state."""
@@ -136,11 +120,6 @@ class MqttBinarySensor(BinarySensorDevice):
"""Return the name of the binary sensor."""
return self._name
@property
def available(self) -> bool:
"""Return if the binary sensor is available."""
return self._available
@property
def is_on(self):
"""Return true if the binary sensor is on."""
@@ -150,3 +129,8 @@ class MqttBinarySensor(BinarySensorDevice):
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

@@ -0,0 +1,85 @@
"""Support for MyChevy sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mychevy/
"""
import asyncio
import logging
from homeassistant.components.mychevy import (
EVBinarySensorConfig, DOMAIN as MYCHEVY_DOMAIN, UPDATE_TOPIC
)
from homeassistant.components.binary_sensor import (
ENTITY_ID_FORMAT, BinarySensorDevice)
from homeassistant.core import callback
from homeassistant.util import slugify
_LOGGER = logging.getLogger(__name__)
SENSORS = [
EVBinarySensorConfig("Plugged In", "plugged_in", "plug")
]
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the MyChevy sensors."""
if discovery_info is None:
return
sensors = []
hub = hass.data[MYCHEVY_DOMAIN]
for sconfig in SENSORS:
sensors.append(EVBinarySensor(hub, sconfig))
async_add_devices(sensors)
class EVBinarySensor(BinarySensorDevice):
"""Base EVSensor class.
The only real difference between sensors is which units and what
attribute from the car object they are returning. All logic can be
built with just setting subclass attributes.
"""
def __init__(self, connection, config):
"""Initialize sensor with car connection."""
self._conn = connection
self._name = config.name
self._attr = config.attr
self._type = config.device_class
self._is_on = None
self.entity_id = ENTITY_ID_FORMAT.format(
'{}_{}'.format(MYCHEVY_DOMAIN, slugify(self._name)))
@property
def name(self):
"""Return the name."""
return self._name
@property
def is_on(self):
"""Return if on."""
return self._is_on
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
self.hass.helpers.dispatcher.async_dispatcher_connect(
UPDATE_TOPIC, self.async_update_callback)
@callback
def async_update_callback(self):
"""Update state."""
if self._conn.car is not None:
self._is_on = getattr(self._conn.car, self._attr, None)
self.async_schedule_update_ha_state()
@property
def should_poll(self):
"""Return the polling state."""
return False

View File

@@ -5,21 +5,20 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mysensors/
"""
from homeassistant.components import mysensors
from homeassistant.components.binary_sensor import (DEVICE_CLASSES, DOMAIN,
BinarySensorDevice)
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES, DOMAIN, BinarySensorDevice)
from homeassistant.const import STATE_ON
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the mysensors platform for binary sensors."""
"""Set up the MySensors platform for binary sensors."""
mysensors.setup_mysensors_platform(
hass, DOMAIN, discovery_info, MySensorsBinarySensor,
add_devices=add_devices)
class MySensorsBinarySensor(
mysensors.MySensorsEntity, BinarySensorDevice):
"""Represent the value of a MySensors Binary Sensor child node."""
class MySensorsBinarySensor(mysensors.MySensorsEntity, BinarySensorDevice):
"""Representation of a MySensors Binary Sensor child node."""
@property
def is_on(self):

View File

@@ -7,7 +7,7 @@ https://home-assistant.io/components/binary_sensor.mystrom/
import asyncio
import logging
from homeassistant.components.binary_sensor import (BinarySensorDevice, DOMAIN)
from homeassistant.components.binary_sensor import DOMAIN, BinarySensorDevice
from homeassistant.components.http import HomeAssistantView
from homeassistant.const import HTTP_UNPROCESSABLE_ENTITY
@@ -37,7 +37,7 @@ class MyStromView(HomeAssistantView):
@asyncio.coroutine
def get(self, request):
"""The GET request received from a myStrom button."""
"""Handle the GET request received from a myStrom button."""
res = yield from self._handle(request.app['hass'], request.query)
return res

View File

@@ -131,10 +131,8 @@ class NetatmoBinarySensor(BinarySensorDevice):
self._name += ' / ' + module_name
self._sensor_name = sensor
self._name += ' ' + sensor
camera_id = data.camera_data.cameraByName(
self._unique_id = data.camera_data.cameraByName(
camera=camera_name, home=home)['id']
self._unique_id = "Netatmo_binary_sensor {0} - {1}".format(
self._name, camera_id)
self._cameratype = camera_type
self._state = None

View File

@@ -97,7 +97,7 @@ class PilightBinarySensor(BinarySensorDevice):
def _handle_code(self, call):
"""Handle received code by the pilight-daemon.
If the code matches the defined playload
If the code matches the defined payload
of this sensor the sensor state is changed accordingly.
"""
# Check if received code matches defined playoad
@@ -162,10 +162,10 @@ class PilightTriggerSensor(BinarySensorDevice):
def _handle_code(self, call):
"""Handle received code by the pilight-daemon.
If the code matches the defined playload
If the code matches the defined payload
of this sensor the sensor state is changed accordingly.
"""
# Check if received code matches defined playoad
# Check if received code matches defined payload
# True if payload is contained in received code dict
payload_ok = True
for key in self._payload:

View File

@@ -39,7 +39,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
sensor_type))
else:
# create an sensor for each zone managed by faucet
# create a sensor for each zone managed by faucet
for zone in raincloud.controller.faucet.zones:
sensors.append(RainCloudBinarySensor(zone, sensor_type))

View File

@@ -5,18 +5,17 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.raspihats/
"""
import logging
import voluptuous as vol
from homeassistant.const import (
CONF_NAME, CONF_DEVICE_CLASS, DEVICE_DEFAULT_NAME
)
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA, BinarySensorDevice
)
PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.components.raspihats import (
CONF_I2C_HATS, CONF_BOARD, CONF_ADDRESS, CONF_CHANNELS, CONF_INDEX,
CONF_INVERT_LOGIC, I2C_HAT_NAMES, I2C_HATS_MANAGER, I2CHatsException
)
CONF_ADDRESS, CONF_BOARD, CONF_CHANNELS, CONF_I2C_HATS, CONF_INDEX,
CONF_INVERT_LOGIC, I2C_HAT_NAMES, I2C_HATS_MANAGER, I2CHatsException)
from homeassistant.const import (
CONF_DEVICE_CLASS, CONF_NAME, DEVICE_DEFAULT_NAME)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
@@ -45,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the raspihats binary_sensor devices."""
"""Set up the raspihats binary_sensor devices."""
I2CHatBinarySensor.I2C_HATS_MANAGER = hass.data[I2C_HATS_MANAGER]
binary_sensors = []
i2c_hat_configs = config.get(CONF_I2C_HATS)
@@ -65,39 +64,32 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
)
)
except I2CHatsException as ex:
_LOGGER.error(
"Failed to register " + board + "I2CHat@" + hex(address) + " "
+ str(ex)
)
_LOGGER.error("Failed to register %s I2CHat@%s %s",
board, hex(address), str(ex))
add_devices(binary_sensors)
class I2CHatBinarySensor(BinarySensorDevice):
"""Represents a binary sensor that uses a I2C-HAT digital input."""
"""Representation of a binary sensor that uses a I2C-HAT digital input."""
I2C_HATS_MANAGER = None
def __init__(self, address, channel, name, invert_logic, device_class):
"""Initialize sensor."""
"""Initialize the raspihats sensor."""
self._address = address
self._channel = channel
self._name = name or DEVICE_DEFAULT_NAME
self._invert_logic = invert_logic
self._device_class = device_class
self._state = self.I2C_HATS_MANAGER.read_di(
self._address,
self._channel
)
self._address, self._channel)
def online_callback():
"""Callback fired when board is online."""
"""Call fired when board is online."""
self.schedule_update_ha_state()
self.I2C_HATS_MANAGER.register_online_callback(
self._address,
self._channel,
online_callback
)
self._address, self._channel, online_callback)
def edge_callback(state):
"""Read digital input state."""
@@ -105,10 +97,7 @@ class I2CHatBinarySensor(BinarySensorDevice):
self.schedule_update_ha_state()
self.I2C_HATS_MANAGER.register_di_callback(
self._address,
self._channel,
edge_callback
)
self._address, self._channel, edge_callback)
@property
def device_class(self):
@@ -122,7 +111,7 @@ class I2CHatBinarySensor(BinarySensorDevice):
@property
def should_poll(self):
"""Polling not needed for this sensor."""
"""No polling needed for this sensor."""
return False
@property

View File

@@ -98,6 +98,11 @@ class RestBinarySensor(BinarySensorDevice):
"""Return the class of this sensor."""
return self._device_class
@property
def available(self):
"""Return the availability of this sensor."""
return self.rest.data is not None
@property
def is_on(self):
"""Return true if the binary sensor is on."""

View File

@@ -1,41 +1,50 @@
"""
Support for RFXtrx binary sensors.
Lighting4 devices (sensors based on PT2262 encoder) are supported and
tested. Other types may need some work.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.rfxtrx/
"""
import logging
import voluptuous as vol
from homeassistant.components import rfxtrx
from homeassistant.util import slugify
from homeassistant.util import dt as dt_util
from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA, BinarySensorDevice)
from homeassistant.components.rfxtrx import (
ATTR_NAME, CONF_AUTOMATIC_ADD, CONF_DATA_BITS, CONF_DEVICES,
CONF_FIRE_EVENT, CONF_OFF_DELAY)
from homeassistant.const import (
CONF_COMMAND_OFF, CONF_COMMAND_ON, CONF_DEVICE_CLASS, CONF_NAME)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import event as evt
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.rfxtrx import (
ATTR_AUTOMATIC_ADD, ATTR_NAME, ATTR_OFF_DELAY, ATTR_FIREEVENT,
ATTR_DATA_BITS, CONF_DEVICES
)
from homeassistant.const import (
CONF_DEVICE_CLASS, CONF_COMMAND_ON, CONF_COMMAND_OFF
)
DEPENDENCIES = ["rfxtrx"]
from homeassistant.util import dt as dt_util
from homeassistant.util import slugify
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = vol.Schema({
vol.Required("platform"): rfxtrx.DOMAIN,
vol.Optional(CONF_DEVICES, default={}): vol.All(
dict, rfxtrx.valid_binary_sensor),
vol.Optional(ATTR_AUTOMATIC_ADD, default=False): cv.boolean,
DEPENDENCIES = ['rfxtrx']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_DEVICES, default={}): {
cv.string: vol.Schema({
vol.Optional(CONF_NAME, default=None): cv.string,
vol.Optional(CONF_DEVICE_CLASS, default=None):
DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
vol.Optional(CONF_OFF_DELAY, default=None):
vol.Any(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_DATA_BITS, default=None): cv.positive_int,
vol.Optional(CONF_COMMAND_ON, default=None): cv.byte,
vol.Optional(CONF_COMMAND_OFF, default=None): cv.byte
})
},
vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean,
}, extra=vol.ALLOW_EXTRA)
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup the Binary Sensor platform to rfxtrx."""
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Binary Sensor platform to RFXtrx."""
import RFXtrx as rfxtrxmod
sensors = []
@@ -46,30 +55,27 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
if device_id in rfxtrx.RFX_DEVICES:
continue
if entity[ATTR_DATA_BITS] is not None:
_LOGGER.info("Masked device id: %s",
rfxtrx.get_pt2262_deviceid(device_id,
entity[ATTR_DATA_BITS]))
if entity[CONF_DATA_BITS] is not None:
_LOGGER.debug(
"Masked device id: %s", rfxtrx.get_pt2262_deviceid(
device_id, entity[CONF_DATA_BITS]))
_LOGGER.info("Add %s rfxtrx.binary_sensor (class %s)",
entity[ATTR_NAME], entity[CONF_DEVICE_CLASS])
_LOGGER.debug("Add %s rfxtrx.binary_sensor (class %s)",
entity[ATTR_NAME], entity[CONF_DEVICE_CLASS])
device = RfxtrxBinarySensor(event, entity[ATTR_NAME],
entity[CONF_DEVICE_CLASS],
entity[ATTR_FIREEVENT],
entity[ATTR_OFF_DELAY],
entity[ATTR_DATA_BITS],
entity[CONF_COMMAND_ON],
entity[CONF_COMMAND_OFF])
device = RfxtrxBinarySensor(
event, entity[ATTR_NAME], entity[CONF_DEVICE_CLASS],
entity[CONF_FIRE_EVENT], entity[CONF_OFF_DELAY],
entity[CONF_DATA_BITS], entity[CONF_COMMAND_ON],
entity[CONF_COMMAND_OFF])
device.hass = hass
sensors.append(device)
rfxtrx.RFX_DEVICES[device_id] = device
add_devices_callback(sensors)
add_devices(sensors)
# pylint: disable=too-many-branches
def binary_sensor_update(event):
"""Callback for control updates from the RFXtrx gateway."""
"""Call for control updates from the RFXtrx gateway."""
if not isinstance(event, rfxtrxmod.ControlEvent):
return
@@ -82,36 +88,33 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
if sensor is None:
# Add the entity if not exists and automatic_add is True
if not config[ATTR_AUTOMATIC_ADD]:
if not config[CONF_AUTOMATIC_ADD]:
return
if event.device.packettype == 0x13:
poss_dev = rfxtrx.find_possible_pt2262_device(device_id)
if poss_dev is not None:
poss_id = slugify(poss_dev.event.device.id_string.lower())
_LOGGER.info("Found possible matching deviceid %s.",
poss_id)
_LOGGER.debug(
"Found possible matching device ID: %s", poss_id)
pkt_id = "".join("{0:02x}".format(x) for x in event.data)
sensor = RfxtrxBinarySensor(event, pkt_id)
sensor.hass = hass
rfxtrx.RFX_DEVICES[device_id] = sensor
add_devices_callback([sensor])
_LOGGER.info("Added binary sensor %s "
"(Device_id: %s Class: %s Sub: %s)",
pkt_id,
slugify(event.device.id_string.lower()),
event.device.__class__.__name__,
event.device.subtype)
add_devices([sensor])
_LOGGER.info(
"Added binary sensor %s (Device ID: %s Class: %s Sub: %s)",
pkt_id, slugify(event.device.id_string.lower()),
event.device.__class__.__name__, event.device.subtype)
elif not isinstance(sensor, RfxtrxBinarySensor):
return
else:
_LOGGER.info("Binary sensor update "
"(Device_id: %s Class: %s Sub: %s)",
slugify(event.device.id_string.lower()),
event.device.__class__.__name__,
event.device.subtype)
_LOGGER.debug(
"Binary sensor update (Device ID: %s Class: %s Sub: %s)",
slugify(event.device.id_string.lower()),
event.device.__class__.__name__, event.device.subtype)
if sensor.is_lighting4:
if sensor.data_bits is not None:
@@ -131,22 +134,20 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
sensor.update_state(False)
sensor.delay_listener = evt.track_point_in_time(
hass, off_delay_listener, dt_util.utcnow() + sensor.off_delay
)
hass, off_delay_listener, dt_util.utcnow() + sensor.off_delay)
# Subscribe to main rfxtrx events
# Subscribe to main RFXtrx events
if binary_sensor_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(binary_sensor_update)
# pylint: disable=too-many-instance-attributes,too-many-arguments
class RfxtrxBinarySensor(BinarySensorDevice):
"""An Rfxtrx binary sensor."""
"""A representation of a RFXtrx binary sensor."""
def __init__(self, event, name, device_class=None,
should_fire=False, off_delay=None, data_bits=None,
cmd_on=None, cmd_off=None):
"""Initialize the sensor."""
"""Initialize the RFXtrx sensor."""
self.event = event
self._name = name
self._should_fire_event = should_fire
@@ -161,12 +162,9 @@ class RfxtrxBinarySensor(BinarySensorDevice):
if data_bits is not None:
self._masked_id = rfxtrx.get_pt2262_deviceid(
event.device.id_string.lower(),
data_bits)
def __str__(self):
"""Return the name of the sensor."""
return self._name
event.device.id_string.lower(), data_bits)
else:
self._masked_id = None
@property
def name(self):

View File

@@ -8,18 +8,17 @@ import logging
import voluptuous as vol
import homeassistant.components.rpi_pfio as rpi_pfio
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import DEVICE_DEFAULT_NAME
PLATFORM_SCHEMA, BinarySensorDevice)
import homeassistant.components.rpi_pfio as rpi_pfio
from homeassistant.const import CONF_NAME, DEVICE_DEFAULT_NAME
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
ATTR_NAME = 'name'
ATTR_INVERT_LOGIC = 'invert_logic'
ATTR_SETTLE_TIME = 'settle_time'
CONF_INVERT_LOGIC = 'invert_logic'
CONF_PORTS = 'ports'
CONF_SETTLE_TIME = 'settle_time'
DEFAULT_INVERT_LOGIC = False
DEFAULT_SETTLE_TIME = 20
@@ -27,27 +26,27 @@ DEFAULT_SETTLE_TIME = 20
DEPENDENCIES = ['rpi_pfio']
PORT_SCHEMA = vol.Schema({
vol.Optional(ATTR_NAME, default=None): cv.string,
vol.Optional(ATTR_SETTLE_TIME, default=DEFAULT_SETTLE_TIME):
vol.Optional(CONF_NAME, default=None): cv.string,
vol.Optional(CONF_SETTLE_TIME, default=DEFAULT_SETTLE_TIME):
cv.positive_int,
vol.Optional(ATTR_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean
vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_PORTS, default={}): vol.Schema({
cv.positive_int: PORT_SCHEMA
cv.positive_int: PORT_SCHEMA,
})
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the PiFace Digital Input devices."""
"""Set up the PiFace Digital Input devices."""
binary_sensors = []
ports = config.get('ports')
ports = config.get(CONF_PORTS)
for port, port_entity in ports.items():
name = port_entity[ATTR_NAME]
settle_time = port_entity[ATTR_SETTLE_TIME] / 1000
invert_logic = port_entity[ATTR_INVERT_LOGIC]
name = port_entity[CONF_NAME]
settle_time = port_entity[CONF_SETTLE_TIME] / 1000
invert_logic = port_entity[CONF_INVERT_LOGIC]
binary_sensors.append(RPiPFIOBinarySensor(
hass, port, name, settle_time, invert_logic))

View File

@@ -4,46 +4,49 @@ Support for Vanderbilt (formerly Siemens) SPC alarm systems.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.spc/
"""
import logging
import asyncio
import logging
from homeassistant.components.spc import (
ATTR_DISCOVER_DEVICES, DATA_REGISTRY)
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import (STATE_UNAVAILABLE, STATE_ON, STATE_OFF)
from homeassistant.components.spc import ATTR_DISCOVER_DEVICES, DATA_REGISTRY
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
_LOGGER = logging.getLogger(__name__)
SPC_TYPE_TO_DEVICE_CLASS = {'0': 'motion',
'1': 'opening',
'3': 'smoke'}
SPC_TYPE_TO_DEVICE_CLASS = {
'0': 'motion',
'1': 'opening',
'3': 'smoke',
}
SPC_INPUT_TO_SENSOR_STATE = {'0': STATE_OFF,
'1': STATE_ON}
SPC_INPUT_TO_SENSOR_STATE = {
'0': STATE_OFF,
'1': STATE_ON,
}
def _get_device_class(spc_type):
"""Get the device class."""
return SPC_TYPE_TO_DEVICE_CLASS.get(spc_type, None)
def _get_sensor_state(spc_input):
"""Get the sensor state."""
return SPC_INPUT_TO_SENSOR_STATE.get(spc_input, STATE_UNAVAILABLE)
def _create_sensor(hass, zone):
return SpcBinarySensor(zone_id=zone['id'],
name=zone['zone_name'],
state=_get_sensor_state(zone['input']),
device_class=_get_device_class(zone['type']),
spc_registry=hass.data[DATA_REGISTRY])
"""Create a SPC sensor."""
return SpcBinarySensor(
zone_id=zone['id'], name=zone['zone_name'],
state=_get_sensor_state(zone['input']),
device_class=_get_device_class(zone['type']),
spc_registry=hass.data[DATA_REGISTRY])
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Initialize the platform."""
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the SPC binary sensor."""
if (discovery_info is None or
discovery_info[ATTR_DISCOVER_DEVICES] is None):
return
@@ -55,7 +58,7 @@ def async_setup_platform(hass, config, async_add_devices,
class SpcBinarySensor(BinarySensorDevice):
"""Represents a sensor based on an SPC zone."""
"""Representation of a sensor based on a SPC zone."""
def __init__(self, zone_id, name, state, device_class, spc_registry):
"""Initialize the sensor device."""
@@ -74,7 +77,7 @@ class SpcBinarySensor(BinarySensorDevice):
@property
def name(self):
"""The name of the device."""
"""Return the name of the device."""
return self._name
@property
@@ -85,7 +88,7 @@ class SpcBinarySensor(BinarySensorDevice):
@property
def hidden(self) -> bool:
"""Whether the device is hidden by default."""
# these type of sensors are probably mainly used for automations
# These type of sensors are probably mainly used for automations
return True
@property
@@ -95,5 +98,5 @@ class SpcBinarySensor(BinarySensorDevice):
@property
def device_class(self):
"""The device class."""
"""Return the device class."""
return self._device_class

View File

@@ -4,15 +4,15 @@ Support for Taps Affs.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.tapsaff/
"""
import logging
from datetime import timedelta
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_NAME)
PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.const import CONF_NAME
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['tapsaff==0.1.3']
@@ -67,7 +67,7 @@ class TapsAffData(object):
"""Class for handling the data retrieval for pins."""
def __init__(self, location):
"""Initialize the sensor."""
"""Initialize the data object."""
from tapsaff import TapsAff
self._is_taps_aff = None

View File

@@ -15,6 +15,7 @@ from homeassistant.components.binary_sensor import (
DEVICE_CLASSES_SCHEMA)
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)
from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv
@@ -29,6 +30,8 @@ CONF_DELAY_OFF = 'delay_off'
SENSOR_SCHEMA = vol.Schema({
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_ICON_TEMPLATE): cv.template,
vol.Optional(CONF_ENTITY_PICTURE_TEMPLATE): cv.template,
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
@@ -50,6 +53,9 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
for device, device_config in config[CONF_SENSORS].items():
value_template = device_config[CONF_VALUE_TEMPLATE]
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())
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
@@ -60,10 +66,17 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
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,
entity_ids, delay_on, delay_off)
icon_template, entity_picture_template, entity_ids,
delay_on, delay_off)
)
if not sensors:
_LOGGER.error("No sensors added")
@@ -77,7 +90,8 @@ class BinarySensorTemplate(BinarySensorDevice):
"""A virtual binary sensor that triggers from another sensor."""
def __init__(self, hass, device, friendly_name, device_class,
value_template, entity_ids, delay_on, delay_off):
value_template, icon_template, entity_picture_template,
entity_ids, delay_on, delay_off):
"""Initialize the Template binary sensor."""
self.hass = hass
self.entity_id = async_generate_entity_id(
@@ -86,6 +100,10 @@ class BinarySensorTemplate(BinarySensorDevice):
self._device_class = device_class
self._template = value_template
self._state = None
self._icon_template = icon_template
self._entity_picture_template = entity_picture_template
self._icon = None
self._entity_picture = None
self._entities = entity_ids
self._delay_on = delay_on
self._delay_off = delay_off
@@ -114,6 +132,16 @@ class BinarySensorTemplate(BinarySensorDevice):
"""Return the name of the sensor."""
return self._name
@property
def icon(self):
"""Return the icon to use in the frontend, if any."""
return self._icon
@property
def entity_picture(self):
"""Return the entity_picture to use in the frontend, if any."""
return self._entity_picture
@property
def is_on(self):
"""Return true if sensor is on."""
@@ -132,8 +160,9 @@ class BinarySensorTemplate(BinarySensorDevice):
@callback
def _async_render(self):
"""Get the state of template."""
state = None
try:
return self._template.async_render().lower() == 'true'
state = (self._template.async_render().lower() == 'true')
except TemplateError as ex:
if ex.args and ex.args[0].startswith(
"UndefinedError: 'None' has no attribute"):
@@ -143,6 +172,29 @@ class BinarySensorTemplate(BinarySensorDevice):
return
_LOGGER.error("Could not render template %s: %s", self._name, ex)
for property_name, template in (
('_icon', self._icon_template),
('_entity_picture', self._entity_picture_template)):
if template is None:
continue
try:
setattr(self, property_name, template.async_render())
except TemplateError as ex:
friendly_property_name = property_name[1:].replace('_', ' ')
if ex.args and ex.args[0].startswith(
"UndefinedError: 'None' has no attribute"):
# Common during HA startup - so just a warning
_LOGGER.warning('Could not render %s template %s,'
' the state is unknown.',
friendly_property_name, self._name)
else:
_LOGGER.error('Could not render %s template %s: %s',
friendly_property_name, self._name, ex)
return state
return state
@callback
def async_check_state(self):
"""Update the state from the template."""

View File

@@ -28,7 +28,7 @@ class TeslaBinarySensor(TeslaDevice, BinarySensorDevice):
"""Implement an Tesla binary sensor for parking and charger."""
def __init__(self, tesla_device, controller, sensor_type):
"""Initialisation of binary sensor."""
"""Initialise of a Tesla binary sensor."""
super().__init__(tesla_device, controller)
self._state = False
self.entity_id = ENTITY_ID_FORMAT.format(self.tesla_id)

View File

@@ -9,40 +9,48 @@ import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA)
DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA, BinarySensorDevice)
from homeassistant.const import (
CONF_NAME, CONF_ENTITY_ID, CONF_TYPE, STATE_UNKNOWN,
ATTR_ENTITY_ID, CONF_DEVICE_CLASS)
ATTR_ENTITY_ID, CONF_DEVICE_CLASS, CONF_ENTITY_ID, CONF_NAME,
STATE_UNKNOWN)
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import async_track_state_change
_LOGGER = logging.getLogger(__name__)
ATTR_HYSTERESIS = 'hysteresis'
ATTR_LOWER = 'lower'
ATTR_POSITION = 'position'
ATTR_SENSOR_VALUE = 'sensor_value'
ATTR_THRESHOLD = 'threshold'
ATTR_TYPE = 'type'
ATTR_UPPER = 'upper'
CONF_HYSTERESIS = 'hysteresis'
CONF_LOWER = 'lower'
CONF_THRESHOLD = 'threshold'
CONF_UPPER = 'upper'
DEFAULT_NAME = 'Threshold'
DEFAULT_HYSTERESIS = 0.0
SENSOR_TYPES = [CONF_LOWER, CONF_UPPER]
POSITION_ABOVE = 'above'
POSITION_BELOW = 'below'
POSITION_IN_RANGE = 'in_range'
POSITION_UNKNOWN = 'unknown'
TYPE_LOWER = 'lower'
TYPE_RANGE = 'range'
TYPE_UPPER = 'upper'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_THRESHOLD): vol.Coerce(float),
vol.Required(CONF_TYPE): vol.In(SENSOR_TYPES),
vol.Optional(
CONF_HYSTERESIS, default=DEFAULT_HYSTERESIS): vol.Coerce(float),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_HYSTERESIS, default=DEFAULT_HYSTERESIS):
vol.Coerce(float),
vol.Optional(CONF_LOWER): vol.Coerce(float),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_UPPER): vol.Coerce(float),
})
@@ -51,47 +59,44 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Threshold sensor."""
entity_id = config.get(CONF_ENTITY_ID)
name = config.get(CONF_NAME)
threshold = config.get(CONF_THRESHOLD)
lower = config.get(CONF_LOWER)
upper = config.get(CONF_UPPER)
hysteresis = config.get(CONF_HYSTERESIS)
limit_type = config.get(CONF_TYPE)
device_class = config.get(CONF_DEVICE_CLASS)
async_add_devices([ThresholdSensor(
hass, entity_id, name, threshold,
hysteresis, limit_type, device_class)
], True)
return True
hass, entity_id, name, lower, upper, hysteresis, device_class)], True)
class ThresholdSensor(BinarySensorDevice):
"""Representation of a Threshold sensor."""
def __init__(self, hass, entity_id, name, threshold,
hysteresis, limit_type, device_class):
def __init__(self, hass, entity_id, name, lower, upper, hysteresis,
device_class):
"""Initialize the Threshold sensor."""
self._hass = hass
self._entity_id = entity_id
self.is_upper = limit_type == 'upper'
self._name = name
self._threshold = threshold
self._threshold_lower = lower
self._threshold_upper = upper
self._hysteresis = hysteresis
self._device_class = device_class
self._state = False
self.sensor_value = 0
@callback
self._state_position = None
self._state = False
self.sensor_value = None
# pylint: disable=invalid-name
@callback
def async_threshold_sensor_state_listener(
entity, old_state, new_state):
"""Handle sensor state changes."""
if new_state.state == STATE_UNKNOWN:
return
try:
self.sensor_value = float(new_state.state)
except ValueError:
_LOGGER.error("State is not numerical")
self.sensor_value = None if new_state.state == STATE_UNKNOWN \
else float(new_state.state)
except (ValueError, TypeError):
self.sensor_value = None
_LOGGER.warning("State is not numerical")
hass.async_add_job(self.async_update_ha_state, True)
@@ -118,23 +123,68 @@ class ThresholdSensor(BinarySensorDevice):
"""Return the sensor class of the sensor."""
return self._device_class
@property
def threshold_type(self):
"""Return the type of threshold this sensor represents."""
if self._threshold_lower is not None and \
self._threshold_upper is not None:
return TYPE_RANGE
elif self._threshold_lower is not None:
return TYPE_LOWER
elif self._threshold_upper is not None:
return TYPE_UPPER
@property
def device_state_attributes(self):
"""Return the state attributes of the sensor."""
return {
ATTR_ENTITY_ID: self._entity_id,
ATTR_SENSOR_VALUE: self.sensor_value,
ATTR_THRESHOLD: self._threshold,
ATTR_HYSTERESIS: self._hysteresis,
ATTR_TYPE: CONF_UPPER if self.is_upper else CONF_LOWER,
ATTR_LOWER: self._threshold_lower,
ATTR_POSITION: self._state_position,
ATTR_SENSOR_VALUE: self.sensor_value,
ATTR_TYPE: self.threshold_type,
ATTR_UPPER: self._threshold_upper,
}
@asyncio.coroutine
def async_update(self):
"""Get the latest data and updates the states."""
if self._hysteresis == 0 and self.sensor_value == self._threshold:
def below(threshold):
"""Determine if the sensor value is below a threshold."""
return self.sensor_value < (threshold - self._hysteresis)
def above(threshold):
"""Determine if the sensor value is above a threshold."""
return self.sensor_value > (threshold + self._hysteresis)
if self.sensor_value is None:
self._state_position = POSITION_UNKNOWN
self._state = False
elif self.sensor_value > (self._threshold + self._hysteresis):
self._state = self.is_upper
elif self.sensor_value < (self._threshold - self._hysteresis):
self._state = not self.is_upper
elif self.threshold_type == TYPE_LOWER:
if below(self._threshold_lower):
self._state_position = POSITION_BELOW
self._state = True
elif above(self._threshold_lower):
self._state_position = POSITION_ABOVE
self._state = False
elif self.threshold_type == TYPE_UPPER:
if above(self._threshold_upper):
self._state_position = POSITION_ABOVE
self._state = True
elif below(self._threshold_upper):
self._state_position = POSITION_BELOW
self._state = False
elif self.threshold_type == TYPE_RANGE:
if below(self._threshold_lower):
self._state_position = POSITION_BELOW
self._state = False
if above(self._threshold_upper):
self._state_position = POSITION_ABOVE
self._state = False
elif above(self._threshold_lower) and below(self._threshold_upper):
self._state_position = POSITION_IN_RANGE
self._state = True

View File

@@ -11,21 +11,19 @@ import math
import voluptuous as vol
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES_SCHEMA, ENTITY_ID_FORMAT, PLATFORM_SCHEMA,
BinarySensorDevice)
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, CONF_DEVICE_CLASS, CONF_ENTITY_ID,
CONF_FRIENDLY_NAME, STATE_UNKNOWN)
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA,
DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME,
CONF_DEVICE_CLASS, CONF_ENTITY_ID, CONF_FRIENDLY_NAME,
STATE_UNKNOWN)
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.13.3']
REQUIREMENTS = ['numpy==1.14.0']
_LOGGER = logging.getLogger(__name__)
@@ -36,21 +34,21 @@ ATTR_INVERT = 'invert'
ATTR_SAMPLE_DURATION = 'sample_duration'
ATTR_SAMPLE_COUNT = 'sample_count'
CONF_SENSORS = 'sensors'
CONF_ATTRIBUTE = 'attribute'
CONF_INVERT = 'invert'
CONF_MAX_SAMPLES = 'max_samples'
CONF_MIN_GRADIENT = 'min_gradient'
CONF_INVERT = 'invert'
CONF_SAMPLE_DURATION = 'sample_duration'
CONF_SENSORS = 'sensors'
SENSOR_SCHEMA = vol.Schema({
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Optional(CONF_ATTRIBUTE): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_FRIENDLY_NAME): cv.string,
vol.Optional(CONF_INVERT, default=False): cv.boolean,
vol.Optional(CONF_MAX_SAMPLES, default=2): cv.positive_int,
vol.Optional(CONF_MIN_GRADIENT, default=0.0): vol.Coerce(float),
vol.Optional(CONF_INVERT, default=False): cv.boolean,
vol.Optional(CONF_SAMPLE_DURATION, default=0): cv.positive_int,
})
@@ -129,11 +127,11 @@ class SensorTrend(BinarySensorDevice):
return {
ATTR_ENTITY_ID: self._entity_id,
ATTR_FRIENDLY_NAME: self._name,
ATTR_INVERT: self._invert,
ATTR_GRADIENT: self._gradient,
ATTR_INVERT: self._invert,
ATTR_MIN_GRADIENT: self._min_gradient,
ATTR_SAMPLE_DURATION: self._sample_duration,
ATTR_SAMPLE_COUNT: len(self.samples),
ATTR_SAMPLE_DURATION: self._sample_duration,
}
@property

View File

@@ -19,8 +19,8 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Perform the setup for Vera controller devices."""
add_devices(
VeraBinarySensor(device, VERA_CONTROLLER)
for device in VERA_DEVICES['binary_sensor'])
VeraBinarySensor(device, hass.data[VERA_CONTROLLER])
for device in hass.data[VERA_DEVICES]['binary_sensor'])
class VeraBinarySensor(VeraDevice, BinarySensorDevice):

View File

@@ -6,15 +6,15 @@ https://home-assistant.io/components/binary_sensor.verisure/
"""
import logging
from homeassistant.components.verisure import HUB as hub
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.verisure import CONF_DOOR_WINDOW
from homeassistant.components.verisure import HUB as hub
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Verisure binary sensors."""
"""Set up the Verisure binary sensors."""
sensors = []
hub.update_overview()
@@ -27,10 +27,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class VerisureDoorWindowSensor(BinarySensorDevice):
"""Verisure door window sensor."""
"""Representation of a Verisure door window sensor."""
def __init__(self, device_label):
"""Initialize the modbus coil sensor."""
"""Initialize the Verisure door window sensor."""
self._device_label = device_label
@property

View File

@@ -31,7 +31,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Vultr subscription (server) sensor."""
"""Set up the Vultr subscription (server) binary sensor."""
vultr = hass.data[DATA_VULTR]
subscription = config.get(CONF_SUBSCRIPTION)
@@ -39,7 +39,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if subscription not in vultr.data:
_LOGGER.error("Subscription %s not found", subscription)
return False
return
add_devices([VultrBinarySensor(vultr, subscription, name)], True)
@@ -48,7 +48,7 @@ class VultrBinarySensor(BinarySensorDevice):
"""Representation of a Vultr subscription sensor."""
def __init__(self, vultr, subscription, name):
"""Initialize a new Vultr sensor."""
"""Initialize a new Vultr binary sensor."""
self._vultr = vultr
self._name = name

View File

@@ -58,11 +58,11 @@ class WemoBinarySensor(BinarySensorDevice):
@property
def unique_id(self):
"""Return the id of this WeMo device."""
return '{}.{}'.format(self.__class__, self.wemo.serialnumber)
return self.wemo.serialnumber
@property
def name(self):
"""Return the name of the sevice if any."""
"""Return the name of the service if any."""
return self.wemo.name
@property

View File

@@ -8,7 +8,7 @@ import asyncio
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.wink import WinkDevice, DOMAIN
from homeassistant.components.wink import DOMAIN, WinkDevice
_LOGGER = logging.getLogger(__name__)
@@ -16,18 +16,18 @@ DEPENDENCIES = ['wink']
# These are the available sensors mapped to binary_sensor class
SENSOR_TYPES = {
'opened': 'opening',
'brightness': 'light',
'vibration': 'vibration',
'loudness': 'sound',
'noise': 'sound',
'capturing_audio': 'sound',
'liquid_detected': 'moisture',
'motion': 'motion',
'presence': 'occupancy',
'capturing_video': None,
'co_detected': 'gas',
'liquid_detected': 'moisture',
'loudness': 'sound',
'motion': 'motion',
'noise': 'sound',
'opened': 'opening',
'presence': 'occupancy',
'smoke_detected': 'smoke',
'capturing_video': None
'vibration': 'vibration',
}
@@ -103,7 +103,7 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice):
@asyncio.coroutine
def async_added_to_hass(self):
"""Callback when entity is added to hass."""
"""Call when entity is added to hass."""
self.hass.data[DOMAIN]['entities']['binary_sensor'].append(self)
@property
@@ -118,7 +118,7 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice):
@property
def device_state_attributes(self):
"""Return the state attributes."""
"""Return the device state attributes."""
return super().device_state_attributes
@@ -127,7 +127,7 @@ class WinkSmokeDetector(WinkBinarySensorDevice):
@property
def device_state_attributes(self):
"""Return the state attributes."""
"""Return the device state attributes."""
_attributes = super().device_state_attributes
_attributes['test_activated'] = self.wink.test_activated()
return _attributes
@@ -138,11 +138,18 @@ class WinkHub(WinkBinarySensorDevice):
@property
def device_state_attributes(self):
"""Return the state attributes."""
"""Return the device state attributes."""
_attributes = super().device_state_attributes
_attributes['update_needed'] = self.wink.update_needed()
_attributes['firmware_version'] = self.wink.firmware_version()
_attributes['pairing_mode'] = self.wink.pairing_mode()
_kidde_code = self.wink.kidde_radio_code()
if _kidde_code is not None:
# The service call to set the Kidde code
# takes a string of 1s and 0s so it makes
# sense to display it to the user that way
_formatted_kidde_code = "{:b}".format(_kidde_code).zfill(8)
_attributes['kidde_radio_code'] = _formatted_kidde_code
return _attributes
@@ -170,7 +177,7 @@ class WinkButton(WinkBinarySensorDevice):
@property
def device_state_attributes(self):
"""Return the state attributes."""
"""Return the device state attributes."""
_attributes = super().device_state_attributes
_attributes['pressed'] = self.wink.pressed()
_attributes['long_pressed'] = self.wink.long_pressed()

View File

@@ -17,17 +17,21 @@ import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['holidays==0.8.1']
REQUIREMENTS = ['holidays==0.9.3']
# List of all countries currently supported by holidays
# There seems to be no way to get the list out at runtime
ALL_COUNTRIES = ['Australia', 'AU', 'Austria', 'AT', 'Canada', 'CA',
'Colombia', 'CO', 'Czech', 'CZ', 'Denmark', 'DK', 'England',
'EuropeanCentralBank', 'ECB', 'TAR', 'Germany', 'DE',
'Ireland', 'Isle of Man', 'Mexico', 'MX', 'Netherlands', 'NL',
'NewZealand', 'NZ', 'Northern Ireland', 'Norway', 'NO',
'Portugal', 'PT', 'PortugalExt', 'PTE', 'Scotland', 'Spain',
'ES', 'UnitedKingdom', 'UK', 'UnitedStates', 'US', 'Wales']
ALL_COUNTRIES = ['Australia', 'AU', 'Austria', 'AT', 'Belgium', 'BE', 'Canada',
'CA', 'Colombia', 'CO', 'Czech', 'CZ', 'Denmark', 'DK',
'England', 'EuropeanCentralBank', 'ECB', 'TAR', 'Finland',
'FI', 'France', 'FRA', 'Germany', 'DE', 'Ireland',
'Isle of Man', 'Italy', 'IT', 'Japan', 'JP', 'Mexico', 'MX',
'Netherlands', 'NL', 'NewZealand', 'NZ', 'Northern Ireland',
'Norway', 'NO', 'Polish', 'PL', 'Portugal', 'PT',
'PortugalExt', 'PTE', 'Scotland', 'Slovenia', 'SI',
'Slovakia', 'SK', 'South Africa', 'ZA', 'Spain', 'ES',
'Sweden', 'SE', 'UnitedKingdom', 'UK', 'UnitedStates', 'US',
'Wales']
CONF_COUNTRY = 'country'
CONF_PROVINCE = 'province'
CONF_WORKDAYS = 'workdays'
@@ -64,7 +68,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
excludes = config.get(CONF_EXCLUDES)
days_offset = config.get(CONF_OFFSET)
year = (datetime.now() + timedelta(days=days_offset)).year
year = (get_date(datetime.today()) + timedelta(days=days_offset)).year
obj_holidays = getattr(holidays, country)(years=year)
if province:
@@ -99,6 +103,11 @@ def day_to_string(day):
return None
def get_date(date):
"""Return date. Needed for testing."""
return date
class IsWorkdaySensor(BinarySensorDevice):
"""Implementation of a Workday sensor."""
@@ -156,7 +165,7 @@ class IsWorkdaySensor(BinarySensorDevice):
self._state = False
# Get iso day of the week (1 = Monday, 7 = Sunday)
date = datetime.today() + timedelta(days=self._days_offset)
date = get_date(datetime.today()) + timedelta(days=self._days_offset)
day = date.isoweekday() - 1
day_of_week = day_to_string(day)

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