Compare commits

...

1079 Commits
0.38 ... 0.44

Author SHA1 Message Date
Paulus Schoutsen
43ff95ad3b Merge pull request #7444 from home-assistant/release-0-44
0.44
2017-05-06 10:38:45 -07:00
Josh Wright
e2559fd6cf 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...
2017-05-06 10:27:36 -07:00
Gergely Imreh
abe6f9343f sensor.envirophat: add missing requirement (#7451)
Adding requirements that is not explicitly pulled in by the library
that manages the Enviro pHAT.
2017-05-06 10:27:17 -07:00
Daniel Høyer Iversen
94f7c397d7 Add hass to rfxtrx object (#6844) 2017-05-04 23:51:35 -07:00
Paulus Schoutsen
03e3fb77c4 Version bump to 0.44 2017-05-04 21:41:11 -07:00
Anders Melchiorsen
bfd6110091 LIFX: handle unavailable lights gracefully
Recent aiolifx allow sending messages to unregistered devices (as a
no-op). This is handy because bulbs can disappear anytime we yield and
constantly testing for availability is both error-prone and annoying.

So keep the aiolifx device around until a new one registers on the same
mac_addr.
2017-05-04 21:40:35 -07:00
Anders Melchiorsen
71f9507df7 LIFX: fix color restore after running effects
State restoration takes up to a second because bulbs can be slow to react.
During this time an effect could keep running, overwriting the state that we
were trying to restore.

Now the effect forgets the light immediately and it thus avoids further
changes while the restored state settles.
2017-05-04 21:40:35 -07:00
Anders Melchiorsen
1c5eb88368 LIFX: avoid warnings about already running updates
Forcing a refresh will log a warning if the periodic async_update happens
to be running already.

So let's do the refresh locally and remove the force_refresh.
2017-05-04 21:40:35 -07:00
Anders Melchiorsen
4be89521d4 LIFX: Update aiolifx requirement
This update silences some warnings (frawau/aiolifx#7).
2017-05-04 21:40:35 -07:00
Anders Melchiorsen
1e4b56c4d4 LIFX: Move random hue initial color to the LIFXEffect base class
It's a reasonable default for several light effects.
2017-05-04 21:40:35 -07:00
Anders Melchiorsen
655b82c1e2 LIFX: Use 3500K as neutral white
This does not really matter because the colorloop uses saturated colors
(without much white). Anyway, just copy the 3500K that the LIFX app uses.
2017-05-04 21:40:35 -07:00
Anders Melchiorsen
81b567b68f LIFX: refresh state after stopping an effect
This clears the internal cache in case polling picked up the state as set by
an effect.

For example, aborting an effect by selecting a new brightness could keep a
color set by the effect.
2017-05-04 21:40:34 -07:00
Paulus Schoutsen
009a9d59ed Update frontend 2017-05-04 21:38:50 -07:00
Paulus Schoutsen
80e55fb286 Merge remote-tracking branch 'origin/master' into release-0-44 2017-05-04 21:23:18 -07:00
William Scanlon
1d0acb5a2c Get new token to keep pubnub updates working (#7437) 2017-05-04 13:17:35 -07:00
Daniel Perna
ea36c91919 Fix for broken virtual keys (#7439) 2017-05-04 13:15:36 -07:00
Greg Dowling
1d9f1487c3 Bump pyvera version - handle malformed json replies in poll thread. (#7440) 2017-05-04 13:14:36 -07:00
Nolan Gilley
d251621f2b Update join (#7443)
* update python-join-api to 0.0.2

* bump python-join-api to 0.0.2
2017-05-04 13:14:14 -07:00
William Scanlon
8d50045971 Suppress logs when octorpint goes offline (#7441)
* Suppress logs when octorpint goes offline

* Fixed line length
2017-05-04 13:13:09 -07:00
Philipp Schmitt
cc0299d046 Replace pymailgun with pymailgunner (#7436)
* mailgun: Replace pymailgun with pymailgunner

* Fix imports
2017-05-04 20:34:00 +03:00
Pascal Vizeli
7e539a3cb2 Add support for face recognition with dlib (#7421)
* Add support for face recognition with dlib

* fix lint

* fix lint p2

* update library

* dlib can not build

* fix lint

* Fix int p1

* Update dlib_face_detect.py

* Update dlib_face_detect.py

* Update dlib_face_detect.py
2017-05-04 16:03:50 +02:00
deisi
e3bb45c906 Added osramlightify groups. (#7376)
* Added osramlighrify groups.

Allows you to make use of the build in osram lightify groups. Group states get
handeled similar as in the case of phillips hue. A lightify group shows up as
light in the homeassistant webinterface. If one light of the
group is on, the complete group is considered to be on.

To use this feature, first define some groups within your lighrify bridge, then
set add `allow_lightify_groups=true` to you osramlightify config.

It might look like:
````yaml
- platform: osramlightify
  host: IP-ADDRES
  allow_lightify_groups: true
```

* Fixed Pylint errors.

* Included requests.

* Included more requests.

* Fixed setup bridge and removed _light attribute.

* Update osramlightify.py
2017-05-03 23:11:27 -07:00
Gergely Imreh
df13352989 Add new sensor: Enviro pHAT (#7427)
* Add new sensor: Enviro pHAT

Add support for the Enviro pHAT for Raspberry Pi, see hardware
info at https://shop.pimoroni.com/products/enviro-phat

* Move update to add_devices call
2017-05-03 22:59:50 -07:00
Nolan Gilley
05a3c463bf update for pypi (#7430) 2017-05-04 07:48:43 +02:00
Fabian Affolter
c44ebbefc4 Upgrade temperusb to 1.5.3 (#7428) 2017-05-04 07:46:43 +02:00
Paulus Schoutsen
fab533de87 ps - fix websocket yielding pt2 (#7434) 2017-05-03 21:12:08 -07:00
Paulus Schoutsen
ad5a9bf5ac wsock.send_json is a coroutine (#7433) 2017-05-03 20:27:03 -07:00
Paulus Schoutsen
c5a91393e4 Guard against no content type (#7432) 2017-05-03 20:12:51 -07:00
Anders Melchiorsen
dbd6f7e4ed Reverse limitlessled color_temp range (#7359)
Reverse limitlessled color_temp range
2017-05-03 23:32:49 +02:00
Andrey
403a721e91 Comment out opencv-python that is not installable on arm (#7426)
* Comment out opencv-python that is not installable on arm

* Disable import-error
2017-05-03 21:08:21 +03:00
Paulus Schoutsen
af5439860f Update opencv.py 2017-05-03 08:29:17 -07:00
Paulus Schoutsen
0f94c8a2e7 ps - fix opencv (#7419)
* ps - fix opencv

* fix lint
2017-05-03 12:15:04 +02:00
Fabian Affolter
203f48cadc Update docstrings (#7420) 2017-05-03 10:11:39 +02:00
Luar Roji
1a74c41056 Fixed extra R in variable name. (#7418) 2017-05-03 08:32:19 +02:00
Teagan Glenn
b321e0ef80 Opencv (#7261)
* OpenCV

* Fix

* Type-o

* Remove unused opencv camera component discovery.
2017-05-02 21:55:51 -07:00
Gergely Imreh
70ad06d71c light.piglow update (#7408)
* light.piglow: brightness control logic update

Do not reset brightness when brightness is not explicitly supplied.
Based on conversation at:
https://github.com/home-assistant/home-assistant/pull/7377#discussion_r114102005

* light.piglow: add assumed state
2017-05-02 21:21:37 -07:00
Adam Mills
c35d09d5f0 Convert automatic device tracker to push updates (#7404)
* Convert automatic device tracker to push updates

* Update test

* Add to coveragerc

* Fire hass events when automatic update received

* Change brace indentation
2017-05-02 21:21:17 -07:00
Henrik Nicolaisen
f389266f5f remove charset if set in content type header (#7411)
* remove charset if set in content type header like this “Content-Type: image/jpeg;charset=UTF-8”

* fixed lint error
2017-05-02 21:19:16 -07:00
wokar
f9627a5646 applx suggested fix from issue #6573 (#7390) 2017-05-02 21:04:00 -07:00
zeltom
517bd39015 Pilight binary sensor components (#6774)
* Add files via upload

Pilight binary sensor components.

* Pep8 fixed

* Remove unused imports

* Remove STATE_UNKNOWN import

* Grouping import

* New import grouping

* Update pilight.py

* Update pilight.py

* Update pilight.py

* Prevent multiple timer call

* Update .coveragerc

* Fix alphabet ordre

* Fix & clean code (change payload comparaison, delete state function)

* Fix payload comparison and remove state methode

* Fix unused import, whitespaces

* Fix ident error
2017-05-02 20:48:49 -07:00
Andrey
11dc7246af Add Sensibo climate platform (#7379)
* Add Sensibo climate platform

* Force update after running a service

* Add sensibo to .coveragerc

* Use 10s timeout

* Fix schema. Remove print.

* Better handle unit conversions.
2017-05-02 17:23:36 -07:00
Gergely Imreh
8654993b18 light.sensehat: brightness control logic update (#7409)
Do not reset brightness when brightness is not explicitly supplied.
Based on conversation at:
https://github.com/home-assistant/home-assistant/pull/7377#discussion_r114102005
2017-05-02 17:02:13 -07:00
Anders Melchiorsen
1aa3ab52b7 LIFX: Add transition option to colorloop effect (#7410)
This allows for more of a disco mode where lights change so fast that you
actually notice it.

Also change the valid period to the maximum 20 msgs/sec that LIFX bulbs
can handle.
2017-05-03 00:41:43 +02:00
Anders Melchiorsen
d68f59ca6c Update LIFX default color for breathe/pulse effects (#7407)
First, move the default away from turn_on so we do not have to test for
the current service.

Next, change the default color away from random. The new default is that
saturated colors will flash white and desatured colors will flash to their
fully satured color. Always with full brightness.

After many experiments, this was the method that best produced results that
are both visually pleasing and always noticeable as a flash.
2017-05-03 00:05:11 +02:00
Fabian Affolter
4d52b0ecd5 Update docstrings (#7405)
* Update docstrings

* Fix lint issues

* Update docstrings
2017-05-02 22:47:20 +02:00
Gergely Imreh
12c8266942 light.blinkt: update brightness control logic (#7389)
Always use the current brightness, as per discussion at
https://github.com/home-assistant/home-assistant/pull/7377#discussion_r114102005
2017-05-02 18:35:23 +02:00
Fabian Affolter
a4f1f6e724 Update docstrings (#7374)
* Update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* Update docstring

* Update docstrings

* Update docstrings

* Fix lint issues

* Update docstrings

* Revert changes in dict
2017-05-02 09:18:47 -07:00
amigian74
0e08925259 correct MQTT subscription filter (#7269)
* correct MQTT subscription filter

* wildcard handling (#) fixed

* wildcard handling (#) fixed

* added tests for topic subscription like +/something/#

* function names changed (line too long)

* using raw strings for regular expression
import order changed
2017-05-02 09:18:34 -07:00
Andrey
570c5549a9 Clean up requirements (#7391) 2017-05-02 09:15:02 -07:00
Scott Bradshaw
f4f06af0c5 OpenGarage support (#7338)
* OpenGarage.io support

Cleaned up component and ran lint checking

* Fixing lint errors

* Added supported_features and device_class

* Added timeout to HTTP Requests and other changes based on feedback.

* Removed watcher. It provided little value and could cause issues if status was stuck in a state.

* Changes based on feedback. Added error checking for invalid device_key.

* Lint
2017-05-02 08:46:56 -07:00
John Mihalic
752a4b958e Add Eight sleep component (#7275)
* Eight Sleep Implementation

* Update coverage

* Update hass requirements

* Remove unnecessary debug statements

* Bump version to fix date error

* Address comments

* Update requirements
2017-05-02 08:38:27 -07:00
Paulus Schoutsen
350a6fd5fa Lint 2017-05-02 07:47:02 -07:00
Paulus Schoutsen
f17c1090e1 Remove path whitelisting for hassio (#7399)
* Remove path whitelisting for hassio

* Update frontend

* Lint
2017-05-02 00:27:50 -07:00
Paulus Schoutsen
8ea6c7319a Migrate updater to aiohttp (#7387)
* Migrate updater to aiohttp

* Fix tests

* Update updater.py

* Docs
2017-05-01 23:29:01 -07:00
Paulus Schoutsen
da2521a299 Fix YAML dump (#7388)
* Fix YAML dump

* Add test
2017-05-01 20:09:49 -07:00
Daniel Perna
fafd0d4e4c Fix impulse events, added error event for Homegear (#7349)
* Fix impulse event, added error event

* Requested changes
2017-05-01 06:37:00 +02:00
Robbie Trencheny
8ba7e61ed6 Merge pull request #7385 from robbiet480/dont-validate-ios-identify
Disable iOS device identify schema validation for now
2017-04-30 20:11:21 -07:00
Alok Saboo
86cfc2a0ed Updated docstrings (#7383)
* Updated docstrings

* Updated docstrings

* Updated docstrings

* Update docstrings

* Update more docstrings
2017-04-30 20:10:08 -07:00
Marcelo Moreira de Mello
6aac53399d Upgrade Ring to 0.1.4 (#7386) 2017-04-30 20:08:14 -07:00
Robbie Trencheny
ae93cf702a Merge pull request #7347 from cribbstechnologies/dev
Adding tilt functionality for MQTT cover
2017-04-30 15:56:45 -07:00
Robbie Trencheny
ecf511ff35 Remove unused dependency 2017-04-30 15:55:34 -07:00
Robbie Trencheny
87ef26be22 Disable identify schema validation for now 2017-04-30 15:23:49 -07:00
Brian Cribbs
0fe0f1918a more requested changes 2017-04-30 16:33:29 -04:00
abmantis
c085f06df5 Add support for shuffle toggling on Spotify component. (#7339)
* add support for shuffle toggling on Spotify component.

	this also required adding support for shuffle on the
	media_player component.

* lint

* Use ATTR_MEDIA_SHUFFLING for service handler param

* Line too long fix

* fix tests

* add shuffle set to demo mediaplayer

* rename shuffle attribute
2017-04-30 12:41:21 -07:00
ChristianKuehnel
5d7403bd81 Plant (replacement for MiGardener) (#7131)
* new implementation without mqtt

* fixed lint findings

* fixed more lint findings

* fixed final flak8 error

* added unit tests for platform "plant"

* - changed status to "OK" / "problem"
- added attribute "problem" with details on the problems
- removed unused constant
- setting icon to "?" until we have meaningful data

* reformatted code to meet line length requirements
2017-04-30 12:32:32 -07:00
Wojciech Bederski
c14b829f27 improve handling of flux_led lights in RGBW mode (#7221)
allows simultaneous control of both RGB and White
channels.
2017-04-30 12:03:03 -07:00
Gergely Imreh
f20a81d0c5 light.blinkt: add support for Blinkt! lights on Raspberry Pi (#7377) 2017-04-30 11:48:54 -07:00
Paulus Schoutsen
9afbbbf3fe Remove ordered_dict validator (#7375)
* Remove ordered_dict validator

* Lint

* Update test_config_validation.py
2017-04-30 10:55:03 -07:00
Fabian Affolter
1f4f2d7086 Upgrade voluptuous to 0.10.5 (#7107)
* Upgrade voluptuous to 0.10.5

* Fix tests
2017-04-30 00:42:19 -07:00
Dan Ports
7ff1ded0b5 binary_sensor.workday: fix handling of states vs provinces (#7162)
* binary_sensor.workday: fix handling of states vs provinces

* Add test cases for workday sensor with states

* remove redundant assignment

* Repair unit test to improve coverage

Patch from Wolf-Bastian Pöttner

* Fix handling of invalid states/provinces

* fix indentation to satisfy pylint
2017-04-30 00:31:46 -07:00
Henrik Nicolaisen
8df5de2bb8 optimize remote calls and apps on webostv media_player (#7191)
* - changed updater to only do updated if they succed and handle calls when tv is off better by only doing 1 remote call
- show all sources instead of only connected, to fix source selection when unit is powered off
- fixed sources so they can launch apps and select sources

* fixed lint errors

* show all sources and apps if no custom options are defined in the conf

* fixed indentation for lint

* set _current_source when state is off and fixed timeout exception
2017-04-30 00:30:37 -07:00
Brent Hughes
955e3e0542 Zoneminder: Fixed undefined index error (#7340)
* Zoneminder: Fixed undefined index error

* Add Pascal's correct fix.
2017-04-30 00:18:00 -07:00
Anders Melchiorsen
9f68fd9184 Flux switch: avoid updates when off (#7363)
* Flux switch: avoid updates when off

Calling turn_on when the switch is already on would orphan the existing
time tracker, losing our ability to cancel it when turn_off is called.

* Cleanups

The self.is_on property can now be found from self.unsub_tracker, so
get rid of the self._state attribute.

Add an entry guard to turn_on, making further conditionals unnecessary.
2017-04-30 00:05:29 -07:00
Paulus Schoutsen
85b7433bc4 Update sensehat.py 2017-04-29 22:42:12 -07:00
Fabian Affolter
3ee4d1060f Update docstrings (#7361)
* Update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* Update docstrings

* Update tomato.py

* Update isy994.py

* Lint + fix tests

* Lint
2017-04-29 22:04:49 -07:00
Paulus Schoutsen
e22e70a01a Update sensehat.py 2017-04-29 21:40:10 -07:00
Paulus Schoutsen
cf664e42cc Add assumed state to sensehat light. 2017-04-29 21:39:27 -07:00
Gergely Imreh
b815ccc3b8 light.sensehat: plugin to control the 8x8 LED matrix on a Sense hat (#7365)
* light.sensehat: adding plugin to control the 8x8 LED matrix on a Sense Hat

* add new .coveragerc entry

* light.sensehat: formatting and removing unused import

* light.sensehat: add to requirements list

* light.sensehat: update docstrings to the linter's specs

* light.sensehat: add a bit more docstring
2017-04-29 21:34:31 -07:00
onsmam
7b1e948e8d Create knx.py (#7356)
* Create knx.py

light device for the knx component

* Fix doc strings
2017-04-29 21:20:46 -07:00
Jason Carter
607394a0a0 Netdisco now returns a dictionary while it used to be a tuple, fixed (#7350) 2017-04-29 20:54:45 -07:00
LvivEchoes
e4ebae55d5 Feature/add mikrotik device tracker (#7366)
* Add Mikroik device tracker platform

* Update coveragerc with mikrotik.py

* Update coveragerc with mikrotik.py

* Fix lint errors
2017-04-29 20:39:11 -07:00
Paulus Schoutsen
ce3d8be72b Remove binary sensor platforms implementing state property (#7371)
* Remove binary sensor platforms implementing state property

* Fix workday inheritance
2017-04-29 20:36:50 -07:00
Brian Cribbs
a1be80d5d4 added optimistic configuration for tilt state 2017-04-29 19:27:19 -04:00
Brian Cribbs
dc3706523a I was thinking *far* too hard about this 2017-04-29 19:19:24 -04:00
Paulus Schoutsen
55731b759f Fix lint 2017-04-29 15:47:21 -07:00
Paulus Schoutsen
064b2cdb9f Remove state property from alarmdecoder binary sensor (#7370) 2017-04-29 15:12:18 -07:00
Anders Melchiorsen
64a7be66b1 Remove global limit on white light temperature (#7206)
* Remove global limit on white light temperature

Here are the supported temperatures of some popular bulbs:

 Philips Hue: 2000K-6500K (the current 500-154 mired range)
 LIFX Color 1000: 2500K-9000K
 IKEA TRÅDFRI: 2200K, 2700K, 4000K

Obviously, Home Assistant cannot enforce a global limit and work properly
with all of these bulbs. So just remove the limit and leave it up to each
platform to work it out.

This commit updates the existing users and adds a clamp to Hue (where the
limit appears to have originated). It does not attempt to update other
platforms that might need extra handling of the larger range that is now
possible.

* Add min_mireds/max_mireds state attributes to lights

* Support min_mireds/max_mireds with LIFX lights
2017-04-29 15:04:20 -07:00
Fabian Affolter
ae9f44c708 Upgrade speedtest-cli to 1.0.6 (#7354) 2017-04-30 00:00:04 +02:00
Fabian Affolter
74362df19c Upgrade xmltodict to 0.11.0 (#7355) 2017-04-29 23:59:38 +02:00
Greg Dowling
d8afea64af Add debug logging to pyvera events. (#7364) 2017-04-29 17:19:22 +01:00
Daniel Høyer Iversen
b853fb2178 Upgrade Flux led lb to 0.19 (#7352) 2017-04-29 07:46:34 +02:00
Brian Cribbs
5b22e57643 some changes requested on PR 2017-04-28 21:41:50 -04:00
Brian Cribbs
88782fa90a added coroutine annotation to async method 2017-04-28 16:32:06 -04:00
Brian Cribbs
4c06cca3e1 left trailing whitespace 2017-04-28 13:58:01 -04:00
Brian Cribbs
d3042a8199 forgot to remove constructor arg 2017-04-28 13:57:13 -04:00
Brian Cribbs
e61c1ffbc2 fixing hound violations 2017-04-28 13:25:15 -04:00
Brian Cribbs
6cfc1b6af8 removing unnecessary payload value for tilt 2017-04-28 13:15:05 -04:00
Brian Cribbs
c120c47bc1 style changes 2017-04-28 12:14:17 -04:00
Brian Cribbs
44dbf2678b adding tests to cover new functionality 2017-04-28 11:32:42 -04:00
Brian Cribbs
bbe8b2019b style/lint updates 2017-04-28 10:45:32 -04:00
Fabian Affolter
f9c9b3c1b8 Multiple changes (typo, ordering, docstrings, timeouts) (#7343)
* Multiple changes (typo, ordering, docstrings, timeouts)

* Remove debug output

* Catch exception

* Separate URL
2017-04-28 13:25:39 +02:00
Robbie Trencheny
9dd28ac18f Properly return self._unit_of_measurement in the unit_of_measurement function (#7341)
Add an optional extended description…
2017-04-28 12:26:17 +02:00
Thibault Cohen
8114c45b3d Add auxheat to ecobee climate (#6562)
* Add auxheat to ecobee

* Add is_aux_heat_on property in ecobee climate
2017-04-28 11:52:48 +02:00
Anders Melchiorsen
89164d0244 Allow multiple recipients for SMTP notify (#7319)
The existing (singular) configuration keyword is kept for compatibility.
2017-04-28 11:29:30 +02:00
Brian Cribbs
79e134b076 removing accidentally added file 2017-04-27 23:43:54 -04:00
Brian Cribbs
630516f309 slider and tilt open/close seem to work 2017-04-27 23:42:50 -04:00
Paulus Schoutsen
6902e522b9 Merge pull request #7335 from home-assistant/release-0-43-2
0.43.2
2017-04-27 12:42:25 -07:00
Fabian Affolter
0298522fd5 Use four-digits year (#7336) 2017-04-27 09:30:34 -07:00
Paulus Schoutsen
6750e33525 Right fix for Python Open Z-Wave in Docker (#7337) 2017-04-27 09:28:40 -07:00
Paulus Schoutsen
9a67111a0f Right fix for Python Open Z-Wave in Docker (#7337) 2017-04-27 09:28:08 -07:00
Paulus Schoutsen
e6a690558b Fix breaking SSL in test HTML5 (#7310) 2017-04-27 09:27:31 -07:00
Adam Mills
a3bc559fa3 Version bump for automatic (#7329) 2017-04-27 09:05:58 -07:00
Adam Mills
3a1072a158 Version bump of aioautomatic (#7300)
* Version bump of aioautomatic

* Update requirements_all.txt
2017-04-27 09:05:58 -07:00
Paulus Schoutsen
0841bf8529 Update frontend (#7324)
* Initial version of hassio panel

* Update frontend
2017-04-27 09:03:54 -07:00
Fabian Affolter
2b82c222b0 Upgrade python-telegram-bot to 5.3.1 (#7311) 2017-04-27 09:03:46 -07:00
Paulus Schoutsen
d966129fd8 Upgrade pytradfri to 1.1 (#7290) 2017-04-27 09:03:25 -07:00
Paulus Schoutsen
84752b3b13 Hassio api v3 (#7323)
* HassIO rest API v3

* fix content type

* fix lint

* Update comment

* fix content type

* change proxy handling

* fix handling

* fix register

* fix addons

* fix routing

* Update hassio to just proxy

* Fix tests

* Lint
2017-04-27 09:02:43 -07:00
Pascal Vizeli
3735c2e761 Fix HassIO bug with supervisor update & log (#7282) 2017-04-27 09:02:43 -07:00
Pascal Vizeli
9fc89ba744 WIP: HassIO allow to access to container logs. (#7271)
* HassIO allow to access to container logs.

* Add unittest & make a fixture for env

* Add unittest to check if no env exists

* Fix lint
2017-04-27 09:02:43 -07:00
Paulus Schoutsen
f7603a421f Version bump to 0.43.2 2017-04-27 09:02:08 -07:00
Adam Mills
6631e9e939 Version bump for automatic (#7329) 2017-04-27 08:01:30 -04:00
Paulus Schoutsen
3e4e84e3a7 Re-enable Open Z-Wave in Dockerfile (#7325)
Turbo fixed it in #7316
2017-04-27 01:02:14 -07:00
John Arild Berentsen
ce63bb0842 Fix broken docker build (#7316)
* Fix broken docker build

python3 branch

* Update python_openzwave
2017-04-27 01:00:07 -07:00
Anders Melchiorsen
d1121478ab Reduce color_xy_brightness_to_hsv to color_xy_to_hs (#7320)
This makes more sense because the input and output brightness is the same.

We currently convert through RGB which does contain a brightness so we supply
an arbitrary value as input and discard the output.
2017-04-27 00:59:49 -07:00
Paulus Schoutsen
9527390736 Update frontend (#7324)
* Initial version of hassio panel

* Update frontend
2017-04-27 00:57:40 -07:00
Paulus Schoutsen
a732271793 HassIO API fix 2017-04-26 23:24:02 -07:00
Paulus Schoutsen
b532267596 HassIO API fix 2017-04-26 23:23:18 -07:00
Paulus Schoutsen
b14c07a60c Hassio api v3 (#7323)
* HassIO rest API v3

* fix content type

* fix lint

* Update comment

* fix content type

* change proxy handling

* fix handling

* fix register

* fix addons

* fix routing

* Update hassio to just proxy

* Fix tests

* Lint
2017-04-26 22:36:48 -07:00
Jan Losinski
3374169c74 Allow InfluxDB to blacklist domains (#7264)
* Allow InfluxDB to blacklist domains

This adds an option to InfluxDB to blacklist whole domains. This is
useful for domains like automation or script, where no statistic data
is needed.

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

* Add unittest for InfluxDB domain blacklist

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

* Use common include/exclude config for InfluxDB.

Its now the same syntax as it is for recorder.

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

* Add unittests for InfluxDB include whitelist.

There where no tests for that feature before.

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>
2017-04-26 21:14:52 +02:00
Anders Melchiorsen
ffb8872f95 LIFX: use white light when setting a specific temperature (#7256)
* Default to white when setting LIFX temperature

Changing the temperature of a saturated color is possible but not very
interesting. So assume that a change of the temperature implies setting
the color to white, unless a different color is actually specified.

This makes the frontend temperature picker much more useful because it can
now be used to get away from a colored light.

* Default to a neutral white temperature when setting LIFX colors

This means that setting a particular color will always give the same output,
no matter what the temperature was previously at.

* Find brightness after colors

Now the color_temp logic will not see a changed color when setting
temperature+brightness and thus we will actually get a white light in
this situation.

The XY conversion can then not use brightness as input. This is not
an issue because XY only affects hue and saturation, not brightness. So
we can just use an arbitrary value as brightness input.

* Add a simple comment to a complex conditional
2017-04-26 17:21:14 +02:00
Paulus Schoutsen
d2fb4675e1 Disable Open Z-Wave in Docker (#7315) 2017-04-26 07:37:05 -07:00
Fabian Affolter
569ea0cc01 Upgrade python-telegram-bot to 5.3.1 (#7311) 2017-04-26 10:50:08 +02:00
Adam Mills
00f034cef2 Version bump of aioautomatic (#7300)
* Version bump of aioautomatic

* Update requirements_all.txt
2017-04-25 20:21:16 -07:00
Henrik Nicolaisen
615691efc3 Issue 7218 update pylgtv to 0.1.7 (#7302)
* update pylgtv module to 0.1.7

* update pylgtv to 0.1.7 requirements
2017-04-25 20:20:54 -07:00
Daniel Perna
760d2f1f0a Upgrade pyhomematic, extend device support (#7303) 2017-04-25 20:20:10 -07:00
Paulus Schoutsen
8bb952e416 Fix breaking SSL in test HTML5 (#7310) 2017-04-25 20:18:23 -07:00
Fabian Affolter
f29e0bf53e Don't stack up error messages, fix link, and ordering (#7291) 2017-04-25 12:40:13 +02:00
Alan Fischer
28aab33cd1 Added scene controller support to the vera component, along with proper polling when a vera device needs it (#7234)
Add an optional extended description…
2017-04-25 09:17:25 +02:00
Russell Cloran
d79f89e168 Add support for Zigbee Home Automation (#6263)
* Add support for Zigbee Home Automation

* Fewer magic numbers

* Make optional device config work

* Remove non-zha device_tracker stuff

* Always return boolean from is_on

* Only pass through JSON serializable discovery_info

* Update to bellows 0.2.4

* Fewer magic numbers in binary sensor

* Populate const structures from a function

* Update bellows to 0.2.6

* Fewer magic numbers in light

* Take all possible clusters when overriding

* Update bellows to 0.2.7
2017-04-24 22:24:57 -07:00
micw
699cc7213d Feature/rss feed template (#7032)
* rss_feed_template initial checking

* lint

* Remove use of deprecated cgi-escape()

* Switching back to chardet==2.3 (resolve failing tests with 3.0)

* Code and test improvments

* Option 'requires_api_password', default is True
2017-04-24 22:16:47 -07:00
Ron Klinkien
f65d8e1254 Adding group control to tradfri light component (#7248)
* Added initial support for tradfri group control

* Tried to keep original variable structure

* pylint and pep8 fixes

* Fixed lint error about docstring

* Removed unneeded stuff, renamed _light. Needs to be released pytradfri version.

* Better naming of variables inside add_devices call.
2017-04-24 21:57:38 -07:00
Paulus Schoutsen
fb297981af Upgrade pytradfri to 1.1 (#7290) 2017-04-24 21:57:27 -07:00
Paulus Schoutsen
66a63b983e Merge branch 'master' into dev 2017-04-24 21:10:03 -07:00
Paulus Schoutsen
758aed07e8 Merge pull request #7288 from home-assistant/release-0-43-1
0.43.1
2017-04-24 21:02:39 -07:00
Paulus Schoutsen
166bcc0687 Recorder: Check for ENTITY_ID key that contains None value (#7287) 2017-04-24 20:51:14 -07:00
Paulus Schoutsen
335362ffc4 Recorder: Check for ENTITY_ID key that contains None value (#7287) 2017-04-24 20:51:03 -07:00
Klaas Hoekema
41a803a7be Work around bad content-type in Hook api response (#7267) 2017-04-24 20:36:16 -07:00
Martin Hjelmare
1b55dbeb44 Fix telegram webhooks (#7236)
* Always register the view if a webhook exists.
* Return True if platform is set up succesfully, False otherwise.
* Remove the webhook when home assistant stops. Webhooks and long
  polling are mutually excklusive. If a webhook is left after home
  assistant is stopped, a polling telegram bot is unable to be set up,
  on next start of home assistant.
2017-04-24 20:36:08 -07:00
Greg Dowling
6c594e20f6 Workround for wemo subscription bug. (#7245) 2017-04-24 20:35:59 -07:00
Fabian Affolter
c8404cb299 Upgrade paho-mqtt to 1.2.3 (#7214) 2017-04-24 20:35:51 -07:00
John Arild Berentsen
79c6467797 Zwave cover workaround for graber shades. (#7204)
* wierd pylint complaint

* Workaround for Graber csz1 shades

* logging

* Try direct

* Try direct

* Use workaround

* Review changes and tests

* test

* reset test

* Use Bright and Dim also as open and close is
2017-04-24 20:35:27 -07:00
Paulus Schoutsen
e01c36c906 Version bump to 0.43.1 2017-04-24 20:34:56 -07:00
Keaton Taylor
17bdb9558a Fixes utf-8 encoding no longer required by python-openzwave0.3.3 (#7266)
* Fixes utf-8 encoding no longer required by libopenzwave0.3.3

Removes byte encoding for values operation mode, fan mode and swing
mode.

* Fix zwave climate tests for utf-8 change
2017-04-24 17:59:51 -07:00
Patrick Easters
9738bffc3f Updating ping binary sensor with Windows support (#7253)
Fixed ping command syntax and updated regex match
2017-04-24 23:32:12 +02:00
Pascal Vizeli
f58d200ecb Fix HassIO bug with supervisor update & log (#7282) 2017-04-24 23:22:40 +02:00
Jan Losinski
215987d5a7 Add script to import state events to InfluxDB (#7254)
* Add script to import state events to InfluxDB

This adds a script to import recorded events from a recorder database
to a InfluxDB instance. This can be useful for initial importing after
setup of a InfluxDB.

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

* Fix step argument handling in Influx import

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

* Correct typo in InfluxDB Importer

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

* Update influxdb_import.py
2017-04-24 23:01:09 +02:00
Nils Uliczka
16227704d7 Fix telegram_polling no first_name or last_name (#7281)
* Default to 'N/A' if sender has no first_name or last_name

* Fixed as requested
2017-04-24 22:08:06 +02:00
Fabrizio Furnari
aad375b713 Add https certificate expiry sensor (#7272)
* fixing rebase issues

* cert_expiry: added .coveragerc entry

* cert_expiry: renamed to SCAN_INTERVAL, removed Throttle

* cert_expiry: better socket exception management

* cert_expiry: splitted line too long

* Update cert_expiry.py

* Fix hass style
2017-04-24 22:01:00 +02:00
LvivEchoes
104d372dfa Add support for Ukrainian Language in Google TTS (#7278) 2017-04-24 21:43:56 +02:00
Stuart Mumford
7960206e2e Refactor matrix notify service (#7122)
* Refactor matrix notify service.

This refactor aims to close #6118 by making the save / restore of the
authentication tokens much more resilient to failure.

It also refactors the module so that all the functionality is part of the class
and that a login failure causes the service to fail on setup rather than at
message send time.

* Make the linter overlords happy

* Improve logger levels and messages

* small style change

* Fix indentation issue
2017-04-24 21:43:02 +02:00
Anders Melchiorsen
4f5ec3e360 Update aiolifx (#7279)
This contains a fix for TypeError bug seen only with LIFX Z.
2017-04-24 21:09:14 +02:00
Pascal Vizeli
ead457f312 WIP: HassIO allow to access to container logs. (#7271)
* HassIO allow to access to container logs.

* Add unittest & make a fixture for env

* Add unittest to check if no env exists

* Fix lint
2017-04-24 15:16:28 +02:00
Daniel Høyer Iversen
575f57a24e Rfxtrx upgrade lib 0.18 (#7273) 2017-04-24 13:42:26 +02:00
Klaas Hoekema
64da8cd47d Work around bad content-type in Hook api response (#7267) 2017-04-23 23:58:17 -07:00
Martin Hjelmare
0e662c4007 Fix telegram webhooks (#7236)
* Always register the view if a webhook exists.
* Return True if platform is set up succesfully, False otherwise.
* Remove the webhook when home assistant stops. Webhooks and long
  polling are mutually excklusive. If a webhook is left after home
  assistant is stopped, a polling telegram bot is unable to be set up,
  on next start of home assistant.
2017-04-23 23:20:04 -07:00
Greg Dowling
6a8a656fef Workround for wemo subscription bug. (#7245) 2017-04-23 23:18:43 -07:00
Fabian Affolter
cfc023e128 Don't use len(SEQUENCE) as condition value (#7249)
* Don't use len(SEQUENCE) as condition value

* Update volvooncall.py
2017-04-23 20:41:09 -07:00
Fabian Affolter
15b2473224 Iterating the dictionary directly (#7251) 2017-04-23 20:16:52 -07:00
clayton craft
48eeb55198 Add notice regarding submission of analytics (#7263) 2017-04-23 19:59:26 -07:00
Oliver
4cd024d91e Pushed to version 0.4.0 of denonavr which also includes experimental support for Marantz receivers (#7250) 2017-04-23 21:00:00 +02:00
Fabian Affolter
fa4a912a86 Use consts and string formatting (#7243) 2017-04-23 13:54:39 +02:00
Fabian Affolter
209da6f338 Upgrade aiohttp_cors to 0.5.3 (#7213) 2017-04-23 09:25:58 +02:00
Fabian Affolter
ec5e9fcd0d Upgrade paho-mqtt to 1.2.3 (#7214) 2017-04-23 09:25:34 +02:00
Fabian Affolter
e9eb7edda6 Upgrade speedtest-cli to 1.0.5 (#7215) 2017-04-23 09:25:11 +02:00
Fabian Affolter
b60b06a062 Upgrade mutagen to 1.37.0 (#7216) 2017-04-23 09:24:53 +02:00
Fabian Affolter
efe8b46576 Upgrade pygatt to 3.1.1 (#7220)
* Upgrade pygatt to 3.1.1

* Fix mess
2017-04-23 09:24:26 +02:00
Anders Melchiorsen
91b8eea6ad LIFX: avoid "Unable to remove unknown listener" warning (#7235)
Forget the cancelled update handler so it is not cancelled a second time
later on (if when <= BULB_LATENCY) and thus invoking the warning.
2017-04-23 09:24:08 +02:00
Adam Mills
b6a4a0d9af Refactor lyft sensor update (#7233) 2017-04-23 09:23:00 +02:00
Matthew Garrett
7b3cc9fe1f Bump a couple of dependencies (#7231)
* avion light: Bump python-avion dependency version

The dependencies in python-avion weren't sufficiently strict. This is now
fixed, but means we need to depend on a new version.

* decora light: Bump python-decora dependency

There's a new version of python-decora with a reliability fix, so depend on
that.
2017-04-23 09:20:58 +02:00
Dan Ports
2c39038507 lyft sensor: re-enable Prime Time rate attribute (#6982)
Turns out this does work correctly even without a user login
(assuming that sandbox mode is disabled)
2017-04-22 21:16:06 +02:00
Fabian Affolter
5bfe5b3f70 Remove superfluous comments and update ordering (#7227)
* Remove superfluous comments and update ordering

* Fix pylint issues
2017-04-22 21:13:04 +02:00
Alok Saboo
d229787fa6 Fixed typo and clarified details for Lifx effects (#7226)
* Fixed typo

* Update services.yaml

* Clarified service details for Lifx effects
2017-04-22 20:43:17 +02:00
John Arild Berentsen
1836c7a358 Zwave cover workaround for graber shades. (#7204)
* wierd pylint complaint

* Workaround for Graber csz1 shades

* logging

* Try direct

* Try direct

* Use workaround

* Review changes and tests

* test

* reset test

* Use Bright and Dim also as open and close is
2017-04-22 16:23:39 +02:00
Joakim af Sandeberg
1b83ce8759 Pushbullet notification sensor (#7182)
* Added the pushbullet sensor component

* Updated requirements_all.txt and .coveragerc with the new sensor

* Updated acording to houndci-bots comments

* Some more changes

* Final change by the hound (?)

* Fixes from balloobs review and from houndci-bot

This changes the sensors information to only contain one attribute
as information, and the rest as device_state_attributes.

* Added leading space to comments

* Added docstrings, removed API_KEY from log, changed imports

* The hound is at it again

* Fix remaining issues

* Fix pylint issue
2017-04-22 14:01:30 +02:00
Fabian Affolter
8c72a57344 Bump version to 0.44.0.dev0 (#7217) 2017-04-22 11:52:24 +02:00
Paulus Schoutsen
8be2ac70ec Merge pull request #7197 from home-assistant/release-0-43
0.43
2017-04-22 00:33:01 -07:00
Paulus Schoutsen
477ebd99b4 Version bump to 0.43 2017-04-22 00:32:27 -07:00
Martin Hjelmare
093c7f0e44 Fix tradfri lights (#7212)
* Remove leftover use of slugify

* The IKEA manufacturer key is now exactly as found in device info.

* Fix bitwise addition of supported features
2017-04-22 00:31:44 -07:00
Martin Hjelmare
3f47bf6b77 Fix tradfri lights (#7212)
* Remove leftover use of slugify

* The IKEA manufacturer key is now exactly as found in device info.

* Fix bitwise addition of supported features
2017-04-22 00:31:23 -07:00
Paulus Schoutsen
80e9e9bfda tradfri: Improve color temp support detection (#7211) 2017-04-21 23:33:25 -07:00
Paulus Schoutsen
40f480c24e tradfri: Improve color temp support detection (#7211) 2017-04-21 23:32:51 -07:00
Henrik Nicolaisen
dafbdbd2d0 Issue 6749 updated pylgtv to 0.1.6 to fix thread leak in asyncio loop (#7199)
* updated pylgtv module to fix problems with timeouts

* - update pylgtv to 0.1.6
- handle new TimeoutError exception from pylgtv

* used full name for exception handling of concurrent.futures._base.TimeoutError

* the exception handling should now follow the rules

* float typecasting should not be necessary

* use asyncio for TimeoutError it’s an alias for concurrent.futures.TimeoutError
2017-04-21 20:24:33 -07:00
Henrik Nicolaisen
8e716780b7 Issue 6749 updated pylgtv to 0.1.6 to fix thread leak in asyncio loop (#7199)
* updated pylgtv module to fix problems with timeouts

* - update pylgtv to 0.1.6
- handle new TimeoutError exception from pylgtv

* used full name for exception handling of concurrent.futures._base.TimeoutError

* the exception handling should now follow the rules

* float typecasting should not be necessary

* use asyncio for TimeoutError it’s an alias for concurrent.futures.TimeoutError
2017-04-21 20:24:21 -07:00
Sean Dague
b641f6863c Fix arwn platform to update hass state when events are received (#7202)
The arwn platform was refactored to be asyncio friendly, however in
doing so one thing was missed which was explicitly telling hass when
something interesting has happened. This led to the very interesting
to debug issue that the state cards were all out of date, even though
the graphs were not.
2017-04-21 20:22:49 -07:00
Sean Dague
b77b22b01a Fix arwn platform to update hass state when events are received (#7202)
The arwn platform was refactored to be asyncio friendly, however in
doing so one thing was missed which was explicitly telling hass when
something interesting has happened. This led to the very interesting
to debug issue that the state cards were all out of date, even though
the graphs were not.
2017-04-21 20:22:36 -07:00
Nikolas Beutler
07fcf22aeb Update ios.py (#7160)
* Update ios.py

as discussed. the part: 
       if battery_state == ios.ATTR_BATTERY_STATE_FULL:
            returning_icon_level = DEFAULT_ICON_LEVEL
kinda screws up the charging icon.

i might just miss a logical solution for that though.
let me know what you think. it might not be beautiful but i think its an overall improve over the current "double battery" solution

* Update ios.py

chound fix and full_battery_charge fix

* Update ios.py

removed new line

* Update ios.py

* Update ios.py

* Update ios.py

* Update ios.py

* Update ios.py

* Update ios.py

* merged request from robbie

* Update ios.py

* Update ios.py

* Update ios.py
2017-04-21 20:18:31 -07:00
Anders Melchiorsen
2d57c6a1c7 Support xy_color with LIFX lights (#7208) 2017-04-21 20:18:31 -07:00
Nikolas Beutler
1194690c42 Update ios.py (#7160)
* Update ios.py

as discussed. the part: 
       if battery_state == ios.ATTR_BATTERY_STATE_FULL:
            returning_icon_level = DEFAULT_ICON_LEVEL
kinda screws up the charging icon.

i might just miss a logical solution for that though.
let me know what you think. it might not be beautiful but i think its an overall improve over the current "double battery" solution

* Update ios.py

chound fix and full_battery_charge fix

* Update ios.py

removed new line

* Update ios.py

* Update ios.py

* Update ios.py

* Update ios.py

* Update ios.py

* Update ios.py

* merged request from robbie

* Update ios.py

* Update ios.py

* Update ios.py
2017-04-21 20:16:59 -07:00
Anders Melchiorsen
2657668a86 Support xy_color with LIFX lights (#7208) 2017-04-21 20:16:36 -07:00
Pierre Ståhl
f5dd25c87f Capture and log pip install error output (#7200)
Add an optional extended description…
2017-04-21 14:15:05 +02:00
Pascal Vizeli
5c737cfa6e HassIO API v2 (#7201)
Add an optional extended description…
2017-04-21 12:21:55 +02:00
Pascal Vizeli
0acc52b23b HassIO API v2 (#7201)
Add an optional extended description…
2017-04-21 12:20:19 +02:00
Anders Melchiorsen
e3f682c7d3 LIFX light effects (#7145)
* Refactor into find_hsbk

This will be useful for new methods that also have to find passed in colors.

* Add AwaitAioLIFX

This encapsulates the callback and Event that aiolifx needs and thus avoids an
explosion of those when new calls are added.

The refresh_state is now generally useful, so move it into its own method.

* Initial effects support for LIFX

These effects are useful as notifications. They mimic the breathe and pulse
effects from the LIFX HTTP API:

    https://api.developer.lifx.com/docs/breathe-effect
    https://api.developer.lifx.com/docs/pulse-effect

However, this implementation runs locally with the LIFX LAN protocol.

* Saturate LIFX no color value

Now the color is "full saturation, no brightness". This avoids a lot of
temporary white when fading from the "no color" value and into a real color.

* Organize LIFX effects in classes

This is to move the setup/restore away from the actual effect, making it quite
simple to add additional effects.

* Stop running LIFX effects on conflicting service calls

Turning the light on/off or starting a new effect will now stop the running
effect.

* Present default LIFX effects as light.turn_on effects

This makes the effects (with default parameters) easily accessible from
the UI.

* Add LIFX colorloop effect

This cycles the HSV colors, so that is added as an internal way to set a
color.

* Move lifx to its own package and split effects into a separate file

* Always show LIFX light name in logs

The name is actually the easiest way to identify a bulb so just using it
as a fallback was a bit odd.

* Compact effect getter

* Always use full brightness for random flash color

This is a stopgap. When a bit more infrastructure is in place, the intention
is to turn the current hue some degrees. This will guarantee a flash color
that is both unlike the current color and unlike white.

* Clear effects concurrently

We have to wait for the bulbs, so let us wait for all of them at once.

* Add lifx_effect_stop

The colorloop effect is most impressive if run on many lights. Testing
this has revealed the need for an easy way to stop effects on all lights
and return to the initial state of each bulb. This new call does just that.

Calling turn_on/turn_off could also stop the effect but that would not
restore the initial state.

* Always calculate the initial effect color

To fade nicely from power off, the breathe effect needs to keep an
unchanging hue. So give up on using a static start color and just find the
correct hue from the target color.

The colorloop effect can start from anything but we use a random color
just to keep things a little interesting during power on.

* Fix lint

* Update .coveragerc
2017-04-20 22:46:29 -07:00
Anders Melchiorsen
d4b085081a LIFX light effects (#7145)
* Refactor into find_hsbk

This will be useful for new methods that also have to find passed in colors.

* Add AwaitAioLIFX

This encapsulates the callback and Event that aiolifx needs and thus avoids an
explosion of those when new calls are added.

The refresh_state is now generally useful, so move it into its own method.

* Initial effects support for LIFX

These effects are useful as notifications. They mimic the breathe and pulse
effects from the LIFX HTTP API:

    https://api.developer.lifx.com/docs/breathe-effect
    https://api.developer.lifx.com/docs/pulse-effect

However, this implementation runs locally with the LIFX LAN protocol.

* Saturate LIFX no color value

Now the color is "full saturation, no brightness". This avoids a lot of
temporary white when fading from the "no color" value and into a real color.

* Organize LIFX effects in classes

This is to move the setup/restore away from the actual effect, making it quite
simple to add additional effects.

* Stop running LIFX effects on conflicting service calls

Turning the light on/off or starting a new effect will now stop the running
effect.

* Present default LIFX effects as light.turn_on effects

This makes the effects (with default parameters) easily accessible from
the UI.

* Add LIFX colorloop effect

This cycles the HSV colors, so that is added as an internal way to set a
color.

* Move lifx to its own package and split effects into a separate file

* Always show LIFX light name in logs

The name is actually the easiest way to identify a bulb so just using it
as a fallback was a bit odd.

* Compact effect getter

* Always use full brightness for random flash color

This is a stopgap. When a bit more infrastructure is in place, the intention
is to turn the current hue some degrees. This will guarantee a flash color
that is both unlike the current color and unlike white.

* Clear effects concurrently

We have to wait for the bulbs, so let us wait for all of them at once.

* Add lifx_effect_stop

The colorloop effect is most impressive if run on many lights. Testing
this has revealed the need for an easy way to stop effects on all lights
and return to the initial state of each bulb. This new call does just that.

Calling turn_on/turn_off could also stop the effect but that would not
restore the initial state.

* Always calculate the initial effect color

To fade nicely from power off, the breathe effect needs to keep an
unchanging hue. So give up on using a static start color and just find the
correct hue from the target color.

The colorloop effect can start from anything but we use a random color
just to keep things a little interesting during power on.

* Fix lint

* Update .coveragerc
2017-04-20 22:46:12 -07:00
Paulus Schoutsen
dbb0525311 Merge branch 'master' into dev 2017-04-20 22:39:09 -07:00
Pascal Vizeli
f641287aa2 Add HassIO to discovery component (#7195)
* Add HassIO to autodiscovery

* Fix tests

* fix tests

* fix test v2

* fix mock test

* call
2017-04-20 18:45:15 -07:00
LvivEchoes
bbeb64eb24 Add support of input registers while querying modbus sensor. (#7082)
* Add support of input registers while querying modbus sensor.

* Changed config option. Refactoring.
2017-04-20 21:28:49 -04:00
Fabian Affolter
eb2e5e5b9d Upgrade py-cpuinfo to 3.2.0 (#7190) 2017-04-20 12:07:56 +02:00
mountainsandcode
920d298c7e mvglive bug fixes and improvements (#6953)
* Refactored mvglive.py

This pull requests builds on the first work with the mvglive sensor:
- Refactoring the code so that multiple sensors for departures can be added
- Rewrites the transport mode restrictions ("products") to be more modular
- Fixes bugs, such as missing implementation of line restriction
- Other improvements, such as including data attribution

* Further improvements to mvglive sensor

- The API returns the property 'direction', which can be used to filter U-Bahn trains by direction without having to enter all final destinations
- The sensor icon now corresponds to the mode of transport of the next departure

* UBahnDirection refactored

U-Bahn SEV (bus replacement services) have unexpected direction values, fixed resulting bug and hound issues
2017-04-20 00:11:55 -07:00
Pierre Ståhl
93820d5124 Do not request artwork if not available (#7189)
This should fix the "dancing media player" issue where the media player
requests artwork when it's not really available, making the UI "dance".
2017-04-20 00:10:06 -07:00
Pierre Ståhl
2e11d49af3 Fix auto discovery for Apple TV (#7188) 2017-04-20 00:09:27 -07:00
Mitko Masarliev
2d5ab520ef Fix for errors on missing preview on LG webos TV (#6755)
* fix for missing image preview on LG webos TV

* fix to use largeIcon if it start with http
2017-04-20 00:08:53 -07:00
Sören Oldag
0c14c66fbc Added light.pwm component. (#7009)
* Added light.pwm component.

* Renamed pwm platform to rpi_gpio_pwm.

* Update requirements_all.txt
2017-04-19 23:32:20 -07:00
Fabian Affolter
b1621d4175 Add ping binary sensor (#7052)
* Add ping binary sensor

* Fix typo and lint issues

* Use SCAN_INTERVAL
2017-04-19 23:15:26 -07:00
happyleavesaoc
1860b6c521 opensky sensor (#7061)
* opensky sensor

* address opensky review comments

* update opensky distance calc
2017-04-19 22:56:20 -07:00
Gianluca Barbaro
f59b3da5fe JSON MQTT Device tracker (#7055)
* ready for PR

* minor fix

* another minor fix

* new platform mqtt_json

* using ATTR constants

* voluptuous check on JSON payload

* voluptuous check on JSON payload
2017-04-19 22:53:07 -07:00
happyleavesaoc
e020d5114a spotify media player (#6980)
* spotify media player

* fix refresh token

* spotify improvements

* add checks for idle

* import STATE_IDLE

* support more media_ids, limit updates

* move spotify device update

* Remove schedule_update_ha_state because should_poll is true
2017-04-19 22:45:12 -07:00
Paulus Schoutsen
ce51866bd2 Update frontend 2017-04-19 22:03:48 -07:00
Charles Blonde
931fce8239 Add Bose soundtouch discovery support and upgrade libsoundtouch library (#7005)
* Add Bose soundtouch discovery support and upgrade libsoundtouch library

* Remove DEVICE global variable

* Update netdisco to lastest version
2017-04-19 21:52:37 -07:00
Paulus Schoutsen
76d2154820 Fix wemo discovery (#7183)
* Fix wemo discovery

* Fix key
2017-04-19 21:25:45 -07:00
Henrik Nicolaisen
b985e4ef0b updated pylgtv module to fix problems with timeouts (#7184) 2017-04-19 19:36:11 -04:00
Gianluca Barbaro
632256fae2 Mqtt camera test (#7175)
* mock mqtt

* minor fix

* minor fix

* minor fix
2017-04-19 09:26:44 -07:00
Paulus Schoutsen
9b43b39370 Update frontend 2017-04-19 09:24:02 -07:00
Paulus Schoutsen
1a635fede3 Tweak Tradfri (#7172) 2017-04-19 09:15:39 -07:00
Paulus Schoutsen
90baa2ce4d Add history to component priority list (#7173) 2017-04-19 09:15:18 -07:00
Sytone
2f4b2ddc0a Add condition for API failure (#7181)
* Add condition for API failure

If you are not running the latest ve3rsion of ZM this will cause exceptions to fire. This fix handles a response from ZM but a non successful attempt. 

This resolves the issue https://github.com/home-assistant/home-assistant/issues/7178

* Fixed houndci-bot issues
2017-04-19 09:08:48 -07:00
Fabian Affolter
921760f8c1 Upgrade mypy to 0.501 (was renamed from mypy-lang) (#7117) 2017-04-19 14:34:23 +02:00
Fabian Affolter
8ba41563c9 Disable invalid-sequence-index (#7177) 2017-04-19 14:09:00 +02:00
Fabian Affolter
a41d0aced7 Supress trackback and upgrade PyMata to 2.14 (#7176) 2017-04-19 12:48:15 +02:00
Alessandro Mogavero
5179832f6f Added new services to platform kodi (#6426)
* added new service

* fixed basic test in kodi platform

* Added new method async_get_albums

* Added new methods in module kodi

* added method find_song in kodi module

* method add_song_to_playlist made
async

* Added media type to method async_play_media

* added methods async_clear_playlist
and play_song

* methods play_song and find_song
made async

* added new service play_song

* Improved kodi._find
now it find for whole words only

* added possibility to specify artist in
kodi.async_find_artist

* added kodi.async_find_album

* added new optional input to play_song service

* In async_play_song added handling of no song found

* default artist value changed to ''

* async_add_song_to_playlist now can also
search for musinc

* added service add_song_to_playlist

* Added new service add_album_to_playlist

* added services to switch shuffle mode

* added service add_all_albums_to_playlist

* handled error in async_unset_shuffle
and async_set_shuffle

* Added abstract methods to media_player

* _server substituted with server property

* style made consistent with requirements

* Fixed issue with pylint

* Services moved to kodi platform

* service play_song removed

* removed service unset_shuffle

* all add services merged into one

* removed service get_artists

* added kodi_ to service names

* Fixed some style issues

* Removed changes in media_player __init__

* Implemented requested changes

* Fixed pylint problem
2017-04-18 23:19:27 -07:00
Paulus Schoutsen
ce9bb0e84c Upgrade netdisco (#7171) 2017-04-18 20:58:25 -07:00
Johan Bloemberg
e5feeec7a4 Value of 0 should not be considered unknown. (#7139)
* Value of 0 should not be considered `unknown`.

* Reflect disconnect state in entity states.

* Due to adding unknown state on disconnect, the amount of reconnects can sometimes be more. Test for at least 2 reconnect attempts.
2017-04-18 20:24:44 -07:00
Paulus Schoutsen
4becfb66e3 Upgrade pytradfri to 1.0 (#7163) 2017-04-18 20:11:18 -07:00
Mitesh Patel
e4bbbe20dd Fix id zone mismatch (#7165)
* Fixes issue with id mismatch when multiple devices are connected to the lutron bridge

* Updates labels

* removes no longer needed config values.

* removes no longer needed imports
2017-04-19 00:24:58 +02:00
Erik Eriksson
1e758ed030 Keep track of already added players (#7149) 2017-04-19 00:20:52 +02:00
Michaël Arnauts
d007269ecc Update neato.py (#7166)
Fix leftover copy/paste error in comment of neato.py
2017-04-18 22:03:06 +02:00
Greg Dowling
bbad15f853 Add subscription update for Wemo switches, fix bug in Insight switches, fix wemo motion bug, fix wemo discovery (#7135)
* Fix wemo discovery.

* Bump wemo version, add subscription_update for basic switch, fix bug with turning insight switches off.

* Fix missed callback change for wemo motion.

* Regress netdisco changes.
2017-04-18 09:11:08 -07:00
Thibault Cohen
de71fee0a0 Fix #7026 adding a new wol parameter (#7144) 2017-04-18 09:09:06 -07:00
Fabian Affolter
c7a11277ac myStrom WiFi bulbs (#7161)
* Add initial support for myStrom WiFi bulbs

* Upgrade python-mystrom to 0.3.8

* Add myStrom light

* Fix lint issue
2017-04-18 09:03:56 -07:00
Paulus Schoutsen
5574686d74 Disable MQTT camera test (#7164) 2017-04-18 08:55:51 -07:00
Martin Hjelmare
15d8f8b827 Add support for tradfri color temp (#7153)
* Add support for tradfri color temp

* Only return rgb_color if supported features indicate support.
* Return color_temp if supported features indicate support and dict
  with allowed color temperatures exist for manufacturer.
* Add manufacturer specific supported features, with default.
* Color temperature is set from a dict of allowed pairs per
  manufacturer, where kelvin is mapped to hex_color. When a user sets a
  color temperature, the closest matching temperature is selected and
  set.

* Clean up
2017-04-18 08:26:59 -07:00
Greg Dowling
1925748f61 Add vera power meter. (#7134)
* Add vera power meter.

* Use W for power.
2017-04-18 12:01:23 +02:00
Mike Megally
226066eafd exposed content_type in rest_command (#7101)
* exposed content_type in rest_command, which allows for manually specifying the content_type for more-strict api endpoints

* fixed up column length

Length was 86 chars, and it needed to be 79

* double import of HTTP_HEADER_CONTENT_TYPE

Removed the accidental double-import of HTTP_HEADER_CONTENT_TYPE

* moved rest_command-specific config value into component

* if no content_type, default to None

* unit test

* newline

* unused CONTENT_TYPE_TEXT_PLAIN

* removed the http-agnostic abstraction hass provided in favor of aiohttps hdrs constant
2017-04-18 11:50:43 +02:00
Kevin
43799b8fee small fix for random effect in order to use the whole rgb range. So 255 is not excluded anymore. (#7156) 2017-04-18 11:46:18 +02:00
Robbie Trencheny
9c0171ec5e Track device last identify time 2017-04-17 23:31:50 -07:00
Robbie Trencheny
b7141901f6 Change iOS sensor unique ID to use the device ID 2017-04-17 22:58:04 -07:00
Robbie Trencheny
919bb08d02 Fix iOS icon calculation to return mdi:battery for levels above 95 2017-04-17 22:51:06 -07:00
Pascal Vizeli
cec39077ba Fix HassIO timeout bug (#7155)
* Fix HassIO timeout bug

* fix lint

* Add long polling timeout to stop event
2017-04-18 00:25:50 +02:00
thecynic
9ed4ed2e47 lutron: fix typo that prevented callback registration (#7148) 2017-04-17 23:04:44 +02:00
Anders Melchiorsen
d4b05a6a85 Fix LIFX lights with disappearing names (#7119)
* Cache the name of LIFX lights

After #7031 the LIFX device will change during an unregister/register
transition. This has the user-visible effect of the new device missing
a friendly name until the next poll.

We now cache the name internally and it will then transfer to the new
device when it registers.

* Allow LIFX logging even without an available device

This will allow us to set the device to None when it unregisters.

* Calculate LIFX availability from the existence of a device

This has become possible because the device is no longer needed
to provide the name of the light when it is unavailable.

We just have to forget the device when it unregisters.
2017-04-16 17:40:22 -07:00
Anders Melchiorsen
103377bdb0 Add LIFX Cloud scene support (#7124)
This uses the LIFX HTTP API to list and activate the scenes that are
stored in the LIFX cloud by the native LIFX smartphone apps.
2017-04-16 16:40:12 -07:00
Anders Melchiorsen
5fa8037231 Always return True/False from is_state and is_state_attr (#7138)
* Always return True/False from is_state and is_state_attr

These functions are documented to always return True/False but the
short-circuit evaluation would return None if the entity_id did not exist.

* Reword into a single statement
2017-04-16 16:36:15 -07:00
Paulus Schoutsen
a2d268a061 Merge pull request #7142 from home-assistant/release-0-42-4
0.42.4
2017-04-16 16:02:10 -07:00
Adam Mills
37f959eb02 Add debug logging to automation initial state (#7068) 2017-04-16 15:45:40 -07:00
Robbie Trencheny
1ce2b6357a Replace rollershutter with cover in demo (#7140) 2017-04-16 15:27:03 -07:00
Adam Mills
527223b992 Fix for zwave RGB setting (#7137) 2017-04-16 15:07:11 -07:00
Adam Mills
409fd62a7c Fix for zwave RGB setting (#7137) 2017-04-16 15:06:59 -07:00
Robbie Trencheny
fadd33bcb2 Make version number optional and a string to fix identify issue introduced in iOS 1.0.1 (#7141) 2017-04-16 15:00:08 -07:00
Fabian Affolter
904b017552 Upgrade aiohttp to 2.0.7 (#7106) 2017-04-16 15:00:08 -07:00
Martin Hjelmare
1efa6eaf0f Fix mysensors callback (#7057)
* Fix mysensors callback

* All messages was not triggering proper updates. Fix by checking all
  child value types each update.

* Upgrade mysensors dep

* Fix pickle persistence when upgrading.
2017-04-16 15:00:08 -07:00
Paulus Schoutsen
9744ec584a Version bump to 0.42.4 2017-04-16 14:59:15 -07:00
Robbie Trencheny
58dfc1d1b1 Make version number optional and a string to fix identify issue introduced in iOS 1.0.1 (#7141) 2017-04-16 14:53:03 -07:00
Paulus Schoutsen
951af6c76d Make Tradfri discoverable (#7128)
* Make Tradfri discoverable

* Fix lint errors

* Fix bugs and clean up calls to light_control

* Add more color util tests

* Add coap client to dockerfile
2017-04-16 14:37:39 -07:00
Patrik
75242e67a7 IKEA Tradfri Gateway: added support for RGB (#7115)
* After rebase and all fixes

* Added color_rgb_to_hex to util.color

* Added test_color_rgb_to_hex

* Changed reference to color_rgb_to_hex

* Bumped to pytradfri 0.5, having support for retry

* Bumped to pytradfri 0.5, having support for retry

* Bumped to pytradfri 0.5, having support for retry

* Bumped to pytradfri 0.5, having support for retry

* Rolled back to 0.4

* Rolled back to 0.4
2017-04-16 11:35:52 -07:00
Paulus Schoutsen
a1208261a8 Load zwave panel (#7127)
* Load Z-Wave panel when component loads

* Update frontend

* Fix tests
2017-04-16 11:10:55 -07:00
Martin Hjelmare
3528705afd Bump version to 0.43.0.dev0 (#7132) 2017-04-16 13:27:25 +02:00
Gianluca Barbaro
7d76186798 Mqtt camera (#7092)
* first commit

* minor fixes

* minor fix

* async_camera_image + test

* minor fix

* async calls
2017-04-16 11:06:57 +02:00
Marcelo Moreira de Mello
9249b6bc33 Upgraded Amcrest module to 1.1.9 to support new firmware versions: (#7130)
- V2.400.AC01.15.R.20170328
    - V2.420.AC00.17.R.20170322
2017-04-16 09:05:15 +02:00
Anders Melchiorsen
6cbe28a9cd Send stderr of ping tracker to devnull (#7096)
When pinging an inaccessible device, OS errors like

    ping: sendto: No route to host

can occur. For a ping tracker this is not an error but rather a normal
situation. Thus, it makes sense to hide the error.
2017-04-15 19:00:01 -07:00
Fabian Affolter
f7b6f8e8fb Upgrade chardet to 3.0.2 (#7112) 2017-04-15 18:32:06 -07:00
Adam Mills
35de3a1dc4 Use third-party lib aioautomatic for automatic (#7126) 2017-04-15 18:11:36 -07:00
Robbie Trencheny
815422a886 Merge pull request #7109 from home-assistant/allow-extra-in-zone-config
Allow extra keys in zone config
2017-04-15 16:39:29 -07:00
Fabian Affolter
c43a3efabd Remove globally disabled pylint issue and update docstrings (#7111) 2017-04-15 00:32:04 +02:00
Fabian Affolter
b0ffc55cfa Upgrade speedtest-cli to 1.0.4 (#7105) 2017-04-15 00:28:04 +02:00
Fabian Affolter
cce372ff66 Update file header, add const for defaults, and update log messages (#7110) 2017-04-15 00:26:04 +02:00
Fabian Affolter
5ffda53805 Upgrade aiohttp to 2.0.7 (#7106) 2017-04-15 00:18:39 +02:00
Robbie Trencheny
60f7a1947f Allow extra keys in zone config 2017-04-14 14:31:10 -07:00
Adam Mills
0ca80cc27e No product ids configured should fetch all ids (#7091) 2017-04-14 19:09:21 +02:00
Adam Mills
46352f6de9 Uber version bump (#7100) 2017-04-14 19:08:28 +02:00
Robbie Trencheny
7e3e742938 Merge pull request #7094 from robbiet480/zwave-manufacturer-product-names
Break Z-Wave product name up into manufacturer name and product name
2017-04-13 23:10:40 -07:00
Robbie Trencheny
e5756ba41d Break product name up into manufacturer name and product name 2017-04-13 22:48:59 -07:00
Andrey
b6ee2332f4 Better thread safety in zwave node_entity (#7087)
* Better thread safety

* Update node_entity.py
2017-04-13 23:45:27 +03:00
Patrik
c267326891 Added initial support for IKEA Tradfri Gateway (#7074)
* Added initial support for IKEA Tradfri Gateway

* Pinned requirement

* Fixed lint-errors

* Added file to .coveragerc

* Trying to fix commit

* Fixed requirements_all again

* Minor reorder of code

* Minor reorder of code

* Made the changes suggested by @balloob

* Made the changes suggested by @balloob and removed debug

* Update tradfri.py
2017-04-13 10:04:42 -07:00
John Arild Berentsen
38ad5714cd Add support fo map data from Neato (#6939)
* Responsiveness

* Delay was not needed as commands does not return until done.

* Add support for cleaning maps and cleaning data

* Hound

* Docstring

* Update requirements

* Review changes

* External lib now returns the raw data.

* debug

* Sensor did not refresh

* Error handling

* Issue warning on connection error

* Update requirements

* Review changes
2017-04-13 07:41:25 -07:00
Colin O'Dell
01c7616147 Bump qnapstats library version to 0.2.4 (#7085) 2017-04-13 07:39:36 -07:00
Gianluca Barbaro
fa65783f39 MQTT: Managing binary payloads (#6976)
* Managing binary payloads

Hello,
background: I wrote a HA camera component that gets the image from a binary payload. I'm testing it with Zanzito (https://play.google.com/store/apps/details?id=it.barbaro.zanzito) and it works apparently well: it gets the image and correctly displays it in the front-end.
But I had to make the changes I'm proposing here: the message was being blocked because the utf-8 decoding failed.
As far as I know, the utf-8 encoding is required for the topic, not for the payload. What I did here was try the utf-8 decoding, but even if unsuccessful, it dispatches the message anyway.
Is there anything else I'm missing?
thanks
Gianluca

* Update __init__.py

* Update __init__.py

* Update __init__.py

* git test - ignore

* Should work

* minor fixes

* updated mqtt/services.yaml

* added two tests, modified threaded subscribe

* removing polymer

* requested changes

* requested changes - minor fix

* security wrap around payload_file_path

* services.yaml updated

* removed file publishing

* minor fix
2017-04-13 07:38:09 -07:00
Thibault Cohen
9a9342ec3f Fix account balance in fido sensor (#7077) 2017-04-13 07:42:48 +02:00
Robbie Trencheny
34cb02177d Bump braviarc version to 0.3.7 (#7078) 2017-04-12 18:22:23 -07:00
Robbie Trencheny
5ba4033651 Merge pull request #6869 from JesseWebDotCom/dev
Exposed more attributes, enabled play_media tv show or season episodes
2017-04-12 15:17:53 -07:00
Andrey
5e18c997f7 Add product_name attribute to zwave nodes. (#7071) 2017-04-12 21:12:37 +03:00
John Arild Berentsen
d63028e44a Add communication data attributes to Zwave node_entity (#6813)
* Add quality attribute to node

* Move quality to node_entity

* adjustments

* Line lenght

* flake8

* Cleanup and add each entry from getNodeStatistics as attribute

* resolve conflict

* Move NETWORK to hass.data

* Test Done

* Cleanup from review

* Resolve conflicts

* Review changes

* Long lines....

* blank line

* import-error-disable

* Update tests Part1... Again

* Hound

* Argh!

* Argh!

* YABBADABBADOOOOOOO!

* Enhance tests

* hound

* Resolve

* resolve tests...
2017-04-12 19:09:29 +02:00
hawk259
f68542ba0d Adding AlarmDecoder platform (#6900)
* Added AlarmDecoder platform

* remove try/catch for generic execption

* Changes for @pvizeli, thanks for the review!

Removed _ prefix from normal function variables
Removed _hass as it will be set via .hass for us
Broke out the three config (socket, serial, usb) and use vol.Any
Added support for USB I think, don't have device, but should work
Removed components dictionary, was form old group all code that didn't work

* Fix hass string handling
2017-04-12 11:35:35 +02:00
Pascal Vizeli
9d20a17642 Lutron. Bugfix callback registration. (#7042)
* Lutron. Bugfix callback registration.

* Change handling to event
2017-04-12 09:52:01 +02:00
Pascal Vizeli
e026717239 Fix handling with register callbacks on added_to_hass (#7067) 2017-04-12 09:51:19 +02:00
Fabian Affolter
f06cff35ff Upgrade paho-mqtt to 1.2.2 (#7066) 2017-04-12 09:48:21 +02:00
sander76
7cb8f49d62 Telegram bot component (incl. webhook and polling platform) (#6913)
* first commit.

* removed pointless string statement

* manually removed  # homeassistant.components.telegram_webhooks from requirements_all.txt

* deleted obsolete file.

* coveragerc abc
2017-04-11 21:10:56 -07:00
Paulus Schoutsen
edf500e66b Upgrade netdisco to 1.0.0rc2 (#7008)
* Upgrade netdisco to 1.0.0rc2

* fix tests
2017-04-11 20:10:02 -07:00
Paulus Schoutsen
72a01b8a90 Speed up aiohttp (#7064) 2017-04-11 19:58:54 -07:00
micw
3c35d5ea58 Fix/slugify with german umlaut ss (#7029)
* more tests for slugify

* Fix german umlauts in slugify

* Update __init__.py
2017-04-11 19:51:07 -07:00
Paulus Schoutsen
4d9e681fc1 Constrain chardet to 2.3 (#7063) 2017-04-11 19:50:43 -07:00
Martin Hjelmare
4e388666b2 Fix mysensors callback (#7057)
* Fix mysensors callback

* All messages was not triggering proper updates. Fix by checking all
  child value types each update.

* Upgrade mysensors dep

* Fix pickle persistence when upgrading.
2017-04-11 19:17:09 -07:00
johanpalmqvist
ed012014bc Add MaryTTS platform (#6988)
* Add MaryTTS platform

* Fix lint error

* Doc link, config and formatting fixes

* Remove stuff not needed with aiohttp2

* Get rid of unnecessary else statement
2017-04-11 22:52:44 +02:00
Paulus Schoutsen
bf6c4604f4 Merge pull request #7050 from home-assistant/release-0-42-3
0.42.3
2017-04-11 09:30:04 -07:00
Pascal Vizeli
c91cf66dec Bugfix slider (#7047)
* Bugfix slider

* Update input_slider.py

* Update input_slider.py
2017-04-11 09:24:25 -07:00
Pascal Vizeli
11125864c6 Bugfix slider (#7047)
* Bugfix slider

* Update input_slider.py

* Update input_slider.py
2017-04-11 09:23:41 -07:00
Pascal Vizeli
7377ce2640 Bugfix wait on start event (#7013)
* Bugfix wait on start event

* Paulus sugestion

* Change handling with stop_track_task

* Add new unittests

* Update test_core.py
2017-04-11 09:15:31 -07:00
Anders Melchiorsen
0013139591 Plug file leak on LIFX unregister (#7031)
* Plug file leak on LIFX unregister

The aiolifx 0.4.4 release closes its socket when the unregister callback is
called. This plugs a file descriptor leak but also means that we must be
careful to not use the device after it goes unavailable.

Also, when a light reappears, it has a new device that must be used.

* Do not test self.available in service calls

The core will learn to handle that.
2017-04-11 09:15:30 -07:00
Fabian Affolter
e3c2d27f4a Fix US states check (fixes #7015) (#7017) 2017-04-11 09:15:30 -07:00
Xorso
f00d721293 Bump pyalarmdotcom to support new version of aiohttp (#7021)
Add an optional extended description…
2017-04-11 09:15:30 -07:00
Paulus Schoutsen
b295451d46 Fix two more instances of JSON parsing synology (#7014)
Add an optional extended description…
2017-04-11 09:15:30 -07:00
Paulus Schoutsen
7a3df037ba Fix Synology camera content type (#7010) 2017-04-11 09:15:30 -07:00
Paulus Schoutsen
a60e8b16c0 Version bump to 0.42.3 2017-04-11 09:14:37 -07:00
Pascal Vizeli
b52cabf2c0 Bugfix wait on start event (#7013)
* Bugfix wait on start event

* Paulus sugestion

* Change handling with stop_track_task

* Add new unittests

* Update test_core.py
2017-04-11 09:09:31 -07:00
Fabian Affolter
cc459e25cc Remove configuration sample (#7048) 2017-04-11 09:05:27 -07:00
Pascal Vizeli
d7ca9e7a66 Make core to look avilable state of device on servicecall (#7045) 2017-04-11 08:59:46 -07:00
Anders Melchiorsen
f099aee69a Plug file leak on LIFX unregister (#7031)
* Plug file leak on LIFX unregister

The aiolifx 0.4.4 release closes its socket when the unregister callback is
called. This plugs a file descriptor leak but also means that we must be
careful to not use the device after it goes unavailable.

Also, when a light reappears, it has a new device that must be used.

* Do not test self.available in service calls

The core will learn to handle that.
2017-04-11 08:58:51 -07:00
David Straub
07bb64815d Missing line name restriction added (fixes #7039) (#7040) 2017-04-11 13:55:42 +02:00
Fabian Affolter
2cfdb44df6 Upgrade sendgrid to 4.0.0 (#7038) 2017-04-11 13:52:47 +02:00
Fabian Affolter
2748bc4165 Upgrade psutil to 5.2.2 (#7037) 2017-04-11 13:52:34 +02:00
micw
f76a4b2806 Feature/min max improvements (#6786)
* Fix #6783, remove a test that makes no sense anymore

* Fix #6784

* Fix typo in docstring

* Fix handling of known->unknown state, extended test, fix lint errors

* Better handling of mismatch in unit of measurement.

Set state to "unkown" and unit of measurement to "ERR" if unit of measurement differs between aggregatet states.
Add entity_id to logged warning.

* Make icon configurable

* Fix typo

* Fix lint

* Fix lint

* Fix lint

* Add option to set entity_id on min_max sensor

* Fix lint logging-not-lazy

* Revert "Add option to set entity_id on min_max sensor"

This reverts commit 4685f266477dfaba92cf8a256ecfe62c929c877b.

* Revert "Make icon configurable"

This reverts commit fe45aec82d9a07e730bebb4d47dc9618fb695fe6.

* Fixes
2017-04-11 13:52:12 +02:00
pezinek
197db6bded Google TTS can't read percent sign (#6971) (#7030) 2017-04-11 10:27:45 +02:00
happyleavesaoc
aa3ccf16ca update fedex (#7034) 2017-04-11 08:10:31 +02:00
happyleavesaoc
aa91351ff0 update usps version (#7035) 2017-04-11 08:10:07 +02:00
happyleavesaoc
32da163421 bump ups version (#7033) 2017-04-11 08:09:39 +02:00
Adam Mills
ee988dc884 Additional ZWave coverage (#7024)
* Additional ZWave coverage

* setup_platform tests
2017-04-10 16:11:39 -04:00
micw
05eb73a0e3 more tests for slugify (#7027) 2017-04-10 22:51:46 +03:00
Fabian Affolter
89e8e1a4c7 Replace 'vendor_id' with 'arch' (fixes #7003) (#7023) 2017-04-10 18:43:40 +02:00
Paulus Schoutsen
d081e5ab3a Remove deprecated remote classes (#7011)
* Remove deprecated remote classes

* Lint

* Fix tests

* Lint
2017-04-10 09:04:19 -07:00
Fabian Affolter
ab247b0f4d Fix US states check (fixes #7015) (#7017) 2017-04-10 16:13:43 +02:00
Xorso
6cd3758b58 Bump pyalarmdotcom to support new version of aiohttp (#7021)
Add an optional extended description…
2017-04-10 16:13:07 +02:00
Paulus Schoutsen
90e73fda3c Fix two more instances of JSON parsing synology (#7014)
Add an optional extended description…
2017-04-10 10:18:37 +02:00
Paulus Schoutsen
d5e3cd51a5 Fix Synology camera content type (#7010) 2017-04-10 08:19:22 +02:00
Greg Dowling
ecfe0770ed Bump pywemo version. (#7004) 2017-04-09 22:48:18 +01:00
Paulus Schoutsen
6cc5bb0713 Merge pull request #6995 from home-assistant/release-0-42-2
0.42.2
2017-04-09 01:37:18 -07:00
Paulus Schoutsen
f6e819e799 Downgrade aiohttp to 205 (#6994) 2017-04-09 01:36:36 -07:00
Paulus Schoutsen
c42293eb10 Downgrade aiohttp to 205 (#6994) 2017-04-09 01:36:01 -07:00
Paulus Schoutsen
a6dc86fa75 version bump to 0.42.2 2017-04-09 01:31:46 -07:00
Paulus Schoutsen
9c386c68dd Merge pull request #6993 from home-assistant/release-0-42-1
0.42.1
2017-04-09 01:06:10 -07:00
Paulus Schoutsen
f51d705ac7 Make discovery not block start (#6991)
* Make discovery not block start

* Fix tests
2017-04-09 01:06:16 -07:00
Paulus Schoutsen
ba8488d8f1 Make discovery not block start (#6991)
* Make discovery not block start

* Fix tests
2017-04-09 01:05:34 -07:00
Paulus Schoutsen
62d0df4f73 Upgrade to aiohttp 2.0.6 (#6992) 2017-04-08 18:30:02 -07:00
Paulus Schoutsen
d675804119 Version bump to 0.42.1 2017-04-08 18:29:39 -07:00
Paulus Schoutsen
eb0a9869d8 Upgrade to aiohttp 2.0.6 (#6992) 2017-04-08 18:29:28 -07:00
Paulus Schoutsen
cd8723f742 Merge pull request #6956 from home-assistant/release-0-42
0.42
2017-04-08 15:40:30 -07:00
Marcelo Moreira de Mello
50cc2ed97c Bump Amcrest module to 1.1.8 (#6990)
Fixed traceback when calculating SD card percent storage

   self._state = self._camera.percent(sd_used[0], sd_total[0])
AttributeError: 'Http' object has no attribute 'percent'
2017-04-08 14:55:12 -07:00
Paulus Schoutsen
dea9aec268 Warn if start takes a long time. (#6975)
* Warn if start takes a long time.

* ps - cleanup

* Tweak message

* Add tests

* Tweak messagE
2017-04-08 14:55:12 -07:00
Paulus Schoutsen
5d3fe83e62 Warn if start takes a long time. (#6975)
* Warn if start takes a long time.

* ps - cleanup

* Tweak message

* Add tests

* Tweak messagE
2017-04-08 14:53:32 -07:00
happyleavesaoc
2277778d8d update gstreamer (#6987) 2017-04-08 14:53:16 -07:00
Marcelo Moreira de Mello
c5d89499fa Bump Amcrest module to 1.1.8 (#6990)
Fixed traceback when calculating SD card percent storage

   self._state = self._camera.percent(sd_used[0], sd_total[0])
AttributeError: 'Http' object has no attribute 'percent'
2017-04-08 14:52:10 -07:00
Adam Mills
31da54d530 Add tests for ZWaveDeviceEntityValues helper (#6978)
* Add tests for ZWaveDeviceEntityValues helper

* Add remaining coverage
2017-04-08 06:34:59 -07:00
Teemu R
5a2ab3167b switch.tplink: bump pyhs100 version requirement (#6986) 2017-04-08 06:33:59 -07:00
Teemu R
475ac52180 switch.tplink: bump pyhs100 version requirement (#6986) 2017-04-08 06:33:25 -07:00
John Mihalic
660b1b616b Update Emby for aiohttp v2 (#6981) 2017-04-08 04:51:47 -07:00
Paulus Schoutsen
d8558ad173 Fix control+c quitting HASS (#6974) 2017-04-08 04:50:52 -07:00
Pascal Vizeli
a93c01788d Bugfix time and task coro (#6968)
* Bugfix time and task coro

* fix also other create_task

* fix tests

* fix lint in test
2017-04-08 04:50:52 -07:00
Adam Mills
d3c1a48475 Update kodi for aiohttp2 (#6967) 2017-04-08 04:50:52 -07:00
happyleavesaoc
01672e63ea Crime Reports sensor (#6966)
* add crimereports

* add crimereports metadata

* implicit interval

* remove zone support
2017-04-08 04:50:52 -07:00
viswa-swami
382519e082 Foscam Camera: Adding exception handling when fetching the camera image to avoid python exception errors when host is not reachable or rather any url error to camera (#6964)
* Adding exception handling when fetching the camera image to avoid python errors when host is not reachable or any url errors to camera

* Added exception as ConnectionError instead of plain except

* Added exception as ConnectionError instead of plain except. Removed the unused error handle
2017-04-08 04:50:52 -07:00
Andrey
5d1dbd61b2 Preserve customize glob order. (#6963)
* Preserve customize glob order.

* add tests
2017-04-08 04:50:52 -07:00
aufano
69dee168a1 Fix current_temperature is rounded (#6960)
* Fix current_temperature is rounded

* fix  Unnecessary parens after 'if'
2017-04-08 04:50:52 -07:00
Teemu R
6d8af58891 light.yeelight: catch i/o related exceptions from the backend lib (#6952)
Fixes/mitigates problems with #5949 and #6624
2017-04-08 04:50:52 -07:00
Pascal Vizeli
0bb224d8c7 Initial import for HassIO (#6935)
* Initial import for HassIO

* Cleanup api code for views

* First unittest for view

* Add test for edit view

* Finish unittest

* fix addons test

* cleanup service.yaml

* Address first round with ping command

* handle timeout dynamic

* fix lint
2017-04-08 04:50:52 -07:00
Teemu R
55077b9965 switch.tplink: upgrade to the newest upstream release which adds support for plugs using the newer communication protocol (#6979) 2017-04-07 19:19:11 -07:00
John Mihalic
ad8ee1383c Update Emby for aiohttp v2 (#6981) 2017-04-07 19:17:10 -07:00
Paulus Schoutsen
64174f5763 Fix control+c quitting HASS (#6974) 2017-04-07 21:02:49 +02:00
Adam Mills
df77529bfe Tests for zwave services (#6937)
* Initial tests for zwave services

* Fix linter issues

* Complete zwave service tests
2017-04-07 09:17:23 -04:00
Nate
8cff98d07b From Dusk till Dawn (#6857)
* Added dawn, dusk, noon and midnight to the Sun component

* Created a helper method for the solar events
2017-04-06 22:59:41 -07:00
happyleavesaoc
216c2682f0 Crime Reports sensor (#6966)
* add crimereports

* add crimereports metadata

* implicit interval

* remove zone support
2017-04-06 22:47:03 -07:00
Teemu R
d952a07658 light.yeelight: catch i/o related exceptions from the backend lib (#6952)
Fixes/mitigates problems with #5949 and #6624
2017-04-06 22:41:47 -07:00
viswa-swami
9254e7e862 Foscam Camera: Adding exception handling when fetching the camera image to avoid python exception errors when host is not reachable or rather any url error to camera (#6964)
* Adding exception handling when fetching the camera image to avoid python errors when host is not reachable or any url errors to camera

* Added exception as ConnectionError instead of plain except

* Added exception as ConnectionError instead of plain except. Removed the unused error handle
2017-04-06 22:40:33 -07:00
Andrey
f96e06a2c2 Preserve customize glob order. (#6963)
* Preserve customize glob order.

* add tests
2017-04-06 22:39:35 -07:00
Pascal Vizeli
3e66df50c8 Initial import for HassIO (#6935)
* Initial import for HassIO

* Cleanup api code for views

* First unittest for view

* Add test for edit view

* Finish unittest

* fix addons test

* cleanup service.yaml

* Address first round with ping command

* handle timeout dynamic

* fix lint
2017-04-06 22:19:08 -07:00
Pascal Vizeli
74ac160355 Bugfix time and task coro (#6968)
* Bugfix time and task coro

* fix also other create_task

* fix tests

* fix lint in test
2017-04-06 21:00:58 -07:00
JesseWebDotCom
c20d48c8e0 import order fix 2017-04-06 20:52:56 -04:00
aufano
2ce8c2f80e Fix current_temperature is rounded (#6960)
* Fix current_temperature is rounded

* fix  Unnecessary parens after 'if'
2017-04-06 17:40:59 -07:00
Adam Mills
51dc8b78cc Update kodi for aiohttp2 (#6967) 2017-04-07 00:12:24 +02:00
Fabian Affolter
eb55fc8e77 Update for 0.42 2017-04-06 09:36:57 +02:00
Fabian Affolter
37246449f1 Upgrade sqlalchemy to 1.1.9 (#6955) 2017-04-06 00:27:49 -07:00
Diogo Soares
2551bf8645 Added average temperature for the day before and the current period (#6883)
* Added average temperature for the day before and the current period

* Fixed "line too long" warnings

* Fixed "indentation contains tabs" and "indentation contains mixed spaces and tabs" warnings

* Fixed "trailing whitespace" warnings

* upgrade pyhydroquebec requirements to version 1.1.0
2017-04-06 00:26:26 -07:00
Martin Hjelmare
749f79e813 Upgrade mysensors dep and callbacks (#6950) 2017-04-06 00:21:21 -07:00
Pascal Vizeli
86568b443c Fix startup of sonos / snapshot handling / error handling (#6945)
* Fix startup of sonos / snapshot handling / error handling

* Use decorator for coordinator relay

* fix lint

* Fix unittest

* Move subscribe into executor
2017-04-05 23:24:30 -07:00
Paulus Schoutsen
29f385ea76 Fix automations listening to HOMEASSISTANT_START (#6936)
* Fire EVENT_HOMEASSISTANT_START automations off right away while starting

* Actually have core state be set to 'starting' during boot

* Fix correct start implementation

* Test and deprecate event automation platform on start

* Fix doc strings

* Remove shutting down exception

* More strict when to mark an instance as finished

* Add automation platform to listen for start/shutdown

* When we stop we should wait till it's all done

* Fix testing

* Fix async bugs in tests

* Only set UVLOOP when hass starts from CLI

* This hangs normal asyncio event loop

* Clean up Z-Wave node entity test
2017-04-05 23:23:02 -07:00
Fabian Affolter
289d6b6605 Upgrade py-cpuinfo to 3.0.0 (#6948) 2017-04-05 21:29:59 +02:00
Fabian Affolter
73f69085d9 Upgrade Sphinx to 1.5.5 (#6947) 2017-04-05 21:05:50 +02:00
Thibault Cohen
118bd34d74 Add multi phone numbers support (#6605)
* Add multi phone numbers support

* Update fido.py
2017-04-05 17:18:02 +02:00
Jeff Wilson
f1f033e5d2 Report proper features in mqtt_json light (#6941)
* Add tests for supported features in mqtt_json (it fails)

* Fix supported features in mqtt_json
2017-04-05 14:39:19 +02:00
Adam Mills
75a3747f61 Rename zwave nodes by node ID instead of entity ID (#6938) 2017-04-05 08:11:37 -04:00
Marcelo Moreira de Mello
a5f77d5f46 Clean artifacts after running Ring tests. (#6944)
* Clean artifacts after running Ring tests.

* Clean artifacts from top level test_ring.py
2017-04-05 11:26:56 +02:00
Greg Dowling
534187f4cd Bump pywemo version. Fixes Osram/Sylvania Lightify tunable white bulbs. (#6946)
Add an optional extended description…
2017-04-05 11:26:03 +02:00
Pascal Vizeli
8f4fd951e5 Add android ip webcam support for aiohttp2 (#6940) 2017-04-04 21:40:19 -07:00
JesseWebDotCom
90a834cbda String formatting, import order, type check fixes 2017-04-04 22:33:52 -04:00
citruz
e4e7141ae7 Eddystone Beacon Temperature Sensor (#6789)
* Added eddystone_temperature platform.

* Fixed style issues.

* Fixed style issues #2.

* Fixed style issues #3.

* Added new platform to .coveragerc

* Refactored platform to use the beacontools package.

* Fixed style issues and added beacontools to excluded requirements.

* Removed obsolete constants and added pylint exception.

* Added blank line

* Updated beacontools to version 1.0.0

* Updated beacontools to version 1.0.1

* Forgot to regenerate requirements_all

* Minor changes
2017-04-04 23:57:19 +02:00
Paulus Schoutsen
c4e1255a84 Initial state over restore state (#6924)
* Input Boolean: initial state > restore state

* Input select: initial state overrules restored state

* Input slider: initial state overrule restore state

* Lint

* Lint
2017-04-04 09:29:49 -07:00
Craig J. Ward
c5574c2684 total connect alarm support (#6887)
* total connect alarm support

* linting fixes

* linting fixes

* docstring

* docstring

* use sync and update coveragerc

* remove unused import

* changes as per notes

* Update HA code style
2017-04-04 12:21:53 +02:00
Greg Dowling
dcbc0b490c WIP - Fix bug in state handling in Vera Switch and Light (#6931)
* Fix bug in state handling.

* Tidy.
2017-04-04 12:02:09 +02:00
Klaas Hoekema
57a00c1fbf Allow token authentication for 'hook' switch component (#6922)
The Hook switch component currently uses username/password to get a token
from the Hook web app to use for subsequent requests. This adds an option
to specify the token directly in config.

Makes the 'password' and 'token' options mutually exclusive since
otherwise one would have to take precedence, and it seems worth
preventing people from filling their config with passwords that don't
even need to be there.
2017-04-04 10:55:43 +02:00
Fabian Affolter
aff8c0f695 Upgrade Sphinx to 1.5.4 (#6927) 2017-04-04 10:50:04 +02:00
Fabian Affolter
542e430c1c Upgrade distro to 1.0.4 (#6926) 2017-04-04 10:44:08 +02:00
Fabian Affolter
26e9e59a5b Upgrade paho-mqtt to 1.2.1 (#6928) 2017-04-04 10:43:41 +02:00
Daniel Høyer Iversen
86d265d407 Upgrade flux_led to 0.17 (#6929)
* Update flux_led lib
2017-04-04 10:42:51 +02:00
Paulus Schoutsen
23645da74c Automation: initial state > restore state (#6911)
* Automation: initial state > restore state

* Clean up code

* Ensure MQTT defaults are used.

* Ensure failed platforms always return None

* Automation: write state to state machine after start
2017-04-03 23:11:39 -07:00
Paulus Schoutsen
3895979e39 Update frontend 2017-04-03 23:02:15 -07:00
Greg Dowling
5b9d9954c5 Update vera cover refresh logic (#6897)
* Update cover update logic to fix compatibility bug. Bump vera library.

* Tidy.

* Add missed file.
2017-04-03 22:44:52 -07:00
John Mihalic
4c7ec4932c Bump pyHik library version to support more cameras (#6921) 2017-04-04 06:54:33 +02:00
Adam Mills
06e1c21b1f Support for zwave light transitions (#6868)
* Support for zwave light transitions

* Dimming duration is optional

* Updated supported_features to show transition
2017-04-03 14:56:48 -04:00
Mitesh Patel
01e581aced Adds support for the PlugInDimmer hardware (#6915) 2017-04-03 08:52:02 -07:00
John Arild Berentsen
a107a592de Fix for #6691 Neato Connection error handling (#6731)
* Responsiveness

* Delay was not needed as commands does not return until done.

* Offline error catch

* Remove unneeded code
2017-04-03 14:42:21 +02:00
Dan
134b21dfea Onkyo update (#6906)
* Update onkyo req, change volume to int

* Update Onkyo

Updates onkyo component. Pulls added sources (Bluetooth, built-in
streaming, etc.)

* Regenerated requirements_all.txt via script

* Update onkyo.py

* Update requirements_all.txt
2017-04-03 00:35:36 -07:00
David McNett
c27a526f5b Eliminate needless async_add_job invocation of async_add_devices (#6864) 2017-04-03 00:01:53 -07:00
Marcelo Moreira de Mello
f4d2ece2fe Make sensor.ring to handle scan_interval option as expected. (#6886)
* Make sensor.ring to handle scan_interval option as expected.

* Fix lint

* Fixed lint timedelta
2017-04-02 23:46:54 -07:00
Marcelo Moreira de Mello
5b8f1850fa Makes amcrest.sensor to handle properly the scan_interval option. (#6885)
* Makes amcrest.sensor to handle scan_interval option as expected.

* Added _LOGGER.debug statement for troubleshooting.

* Fixed lint
2017-04-02 23:46:18 -07:00
Paulus Schoutsen
ce42648a51 Update README.rst 2017-04-02 17:35:03 -07:00
Paulus Schoutsen
36e5878b2e Move examples out (#6908)
* Remove examples from main repo

* Simplify README

* Point screenshot for components at dev branch for now
2017-04-02 17:01:51 -07:00
Dan
f0027e3cc1 Fox UMP volume set (#6904)
async needs consistant paramater namming accross platforms. This fixes
UMP's volume set method by renaming the paramater.
2017-04-02 15:31:28 -07:00
Wolfgang Malgadey
864b57d42c Fix Tado climate set off mode (#6848) 2017-04-02 12:47:15 -04:00
JesseWebDotCom
b99dd19ad6 Fixed log errors if session username or content rating is blank 2017-04-02 10:51:03 -04:00
Daniel Høyer Iversen
8806265e99 Fluxled (#6892)
* Update flux_led lib
2017-04-02 14:12:38 +02:00
ChristianKuehnel
2413d97415 added support for Fibaro FGR-222 (similar to FGRM-222) (#6890) 2017-04-02 12:41:53 +03:00
Fabian Affolter
395f9b6548 Upgrade sqlalchemy to 1.1.8 (#6873) 2017-04-01 12:36:46 +02:00
Fabian Affolter
7afe694cc7 Upgrade aiohttp_cors to 0.5.2 (#6874) 2017-04-01 12:36:35 +02:00
Fabian Affolter
ec2df2ca0f Upgrade pytz to 2017.02 (#6875) 2017-04-01 12:36:24 +02:00
Marcelo Moreira de Mello
65b9383e04 Bumped amcrest module to 1.1.5 (#6872) 2017-04-01 12:36:04 +02:00
JesseWebDotCom
ae21fa9ce1 Fixed setting username and content rating data 2017-03-31 23:20:36 -04:00
JesseWebDotCom
564a01f344 mend
Exposed more attributes, enabled play_media tv show or season episodes
2017-03-31 22:36:37 -04:00
JesseWebDotCom
05bab8c808 Exposed more attributes, enabled play_media tv show or season episodes 2017-03-31 22:19:04 -04:00
Fabian Affolter
a0bb554f8a Upgrade speedtest-cli to 1.0.3 (#6867) 2017-03-31 22:57:29 +02:00
Jacob Tomlinson
2d6b09586d Added Met Office weather and sensor components (#6742)
* Added Met Office weather and sensor components

* Removed unnecessary dependancy

* Generated requirements

* Fix time interval

* Updated coverage

* Some review changes

* Allow user to specify lat and lon in component

* Added missing import

* Fixed unit

* Fixed import indent

* Updated condition to use CONDITION_CLASSES
2017-03-31 22:03:27 +02:00
Fabian Affolter
573b2a11c0 Upgrade sphinx-autodoc-typehints to 1.2.0 (#6865) 2017-03-31 21:39:22 +02:00
Fabian Affolter
ac25eff2d0 Upgrade sendgrid to 3.6.5 (#6866) 2017-03-31 12:37:34 -07:00
Marcelo Moreira de Mello
05398a9dff Introduced Ring binary sensors and refactored Ring component (#6520)
* - Introduced Ring binary_sensor.

- Added unittest for Ring binary_sensor.

- Bumped ring_doorbell 3rd party module.

* Updated requirements

* Added correct file for unittest

* - Introduced Ring binary_sensor.

- Added unittest for Ring binary_sensor.

- Bumped ring_doorbell 3rd party module.

* Updated requirements

* Added correct file for unittest

* Added extra sensors last_ding and last_motion

* Modified Ring binary_sensor and sensor to inherit DOMAIN configuration

* Moved static to top ring.py

* Fixed requirements

* Bump version ring_doorbell to 0.1.2

* testing unittests

* Use hass.data dict instead GLOBALS

* Fixed unittests

* Bump ring_doorbell to 0.1.3

* Updated unittest and coverted to use decorator @requests_mock.Mocker()

* Updated ring_session with lower case
2017-03-31 08:53:56 -07:00
Paulus Schoutsen
8c97bccaaa Handle aiohttp task cancellation better (#6862) 2017-03-31 11:55:22 +02:00
Craig J. Ward
5bb201c7fc use change light level to avoid variable ramp speeds (#6860) 2017-03-30 23:53:10 -07:00
Pascal Vizeli
72db4a80dd Update aioHTTP to 2.0.5 (#6856) 2017-03-30 08:27:53 -07:00
Johan Bloemberg
816b1891b5 Add option to disable automatic add for lights and sensors. (#6852) 2017-03-30 08:02:03 -07:00
Beat
ee8701b560 Fix configuration setup (#6853)
When the user exceeds the request limit for google APIs, the response status stays at 200 but the response body is different:
```
{
   "error_message" : "You have exceeded your daily request quota for this API. We recommend registering for a key at the Google Developers Console: https://console.developers.google.com/apis/credentials?project=_",
   "results" : [],
   "status" : "OVER_QUERY_LIMIT"
}
```
This prevents HA from creating the initial configuration
2017-03-30 15:26:11 +02:00
Paulus Schoutsen
714b516176 aiohttp 2 (#6835)
* Upgrade aiohttp2

* Fix resource caching

* Fix helpers.aiohttp_client

* Lint

* Use static path for api error_log

* Fix ClientErrors import

* Remove not needed DisconnectError

* Remove releasing responses code

* Add timeout if stream starts non responding

* More async_aiohttp_proxy_stream cleanup

* Fix references to ClientError

* Fix fingerprinting

* Fix aiohttp stream tests

* Rename aiohttp_proxy_stream

* Remove impossible darksky test

* Fix sleepiq requests escaping mocker

* Lint

* Remove deprecated parameter

* Break up aiohttp_proxy_stream in 2 methods

* Lint

* Upgrade to aiohttp 2.0.4

* Convert connector close to a callback

* Fix static fingerprinted links
2017-03-30 00:50:53 -07:00
Anders Melchiorsen
7b83a836f3 Lifx legacy (#6847)
* Add legacy LIFX platform for Windows support

The async platform introduced in 9ef084d903 has
turned out to use Python functionality that is not available in Windows.

This commit restores the previous implementation, now named lifx_legacy.

* Add a comment about the platform being a legacy implementation

* Warn when using unsupported lifx platform on Windows

* Update .coveragerc
2017-03-29 23:00:22 -07:00
Johan Bloemberg
ead00e956f Handle initial event after entity is instantiated. (#6760) 2017-03-29 22:50:32 -07:00
Paulus Schoutsen
556dba4020 Convert Alexa tests to use aiohttp test utils (#6839) 2017-03-29 22:21:39 -07:00
Paulus Schoutsen
bfe0aee468 Locative tests to use aiohttp test utils (#6838) 2017-03-29 22:19:58 -07:00
Lewis Juggins
9de4c2b056 [switch.wemo] Fix today_energy_kwh calculation. (#6846)
* [switch.wemo] Fix today_energy_kwh calculation.

* Blank line fail

* Round to two decimal places.
2017-03-29 21:49:28 +02:00
Anubhaw Arya
c935bfce2a Integration with lockitron (#6805)
* Integration with lockitron

* Let super class deal with polling and updating
2017-03-29 17:25:23 +02:00
Martin Hjelmare
7c614a6738 Add voluptuous config validation to scenes (#6830)
* Add platform schema to scene component and homeassistant platform.
* Clean up code and add constants.
* Add unit test and clean up tests.
2017-03-28 23:39:53 -07:00
Xorso
d1b519a418 Updating Alarm.com Component for async and no Selenium (#6752)
* Updating Alarm.com Component for async and no Selenium

* Fixed gen_all_requirements
2017-03-28 23:21:40 -07:00
Johan Bloemberg
e1ed076015 Rflink group commands (#5969)
* Add support for group commands (allon/alloff).
Add 'group_aliasses' config attribute that only respond to group commands.
Add nogroup_aliases that only respond to 'on' 'off' commands.
Allow settings device id group behaviour.

* Fix linting.

* Fix lint.
2017-03-29 01:04:25 -04:00
Oleksii Serdiuk
63c15e997a history_stats: Fix schema, as state can be arbitrary string (#6753) 2017-03-29 00:58:59 -04:00
Andrey
fb8323f48d Remove zwave cover invert workaround. Use config instead. (#6832) 2017-03-28 23:01:29 +03:00
William Scanlon
b5336ed04e Updated pubnubsub-handler version (#6829) 2017-03-28 14:13:45 -04:00
Teemu R
429367409c yeelight: adjust supported features on update() (#6799)
* yeelight: adjust supported features on update()

Earlier we checked for the type only during the initialization,
but this won't work when the bulb is disconnected during the init,
causing failures to adjust rgb&color temperature even if those should be supported.

fixes #6692

* Use reassign instead of OR for updating the supported features
2017-03-28 17:26:43 +02:00
Lewis Juggins
6dba05c79f [switch.wemo] Fix mW to kW conversion. (#6826)
* Fix mW to kW conversion.

* Line length.
2017-03-28 17:24:33 +02:00
Janne Grunau
5c80da6a8f lights/hue: use device class for on/off devices like the osram lightify plug (#6817)
* hue: remove duplicate SUPPORT_FLASH flag

* hue: use correct device class for the Osram Lightify Plug
2017-03-28 00:04:28 +02:00
Fabian Affolter
d027df5a89 Allow to monitor Windows hosts (#6803) 2017-03-27 22:11:15 +02:00
goto100
b8c1bc9542 fix WOL in docker/jail (#6810)
* fix WOL in docker/jail

add ip_address parameter to send_magic_packet if host specific.

in docker/jail, WOL doesn't works due to subnet broadcast issues.

* Update wake_on_lan.py

lint
2017-03-27 14:02:43 +02:00
Greg Dowling
c53de19246 Update Insight parameters using the subscription data. (#6782)
* Update Insight parameters using the subscription dta.

* Minor refactor.

* Tidy.
2017-03-27 12:43:43 +02:00
John Mihalic
f242ad26ca Add NVR support to Hikvision Binary Sensors (#6807)
* Add NVR support to hikvision

* Only append channel for nvr devices

* Descriptor cleanup

* Update requirements
2017-03-27 12:41:57 +02:00
tantecky
a70af62e60 Make get_snmp_data more robust (#6798) 2017-03-27 12:22:59 +02:00
Fabian Affolter
be04ef7be1 Upgrade matrix-client to 0.0.6 (#6808) 2017-03-27 10:35:40 +02:00
Fabian Affolter
f4f72e420a Fix typo and update name (#6809) 2017-03-27 10:35:27 +02:00
Fabian Affolter
84287872bb Use string formatting and remove already global disabled pylint issue (#6801) 2017-03-26 21:13:38 +02:00
David Straub
78b5eb7aac Platform for Munich public transport departure times (#6704)
* Add MVGLive (Munich public transport real-time departure) sensor platform

* Move update on startup to add_devices; rewrite dictionary filtering

* Fix lint error

* Updated requirement to PyMVGLive 1.1.3 (PyPI version)

* Refactor and clean up MVGLiveData.update method

* Shorten line
2017-03-26 19:06:40 +02:00
Fabian Affolter
6e44ccf683 Upgrade pysnmp to 4.3.5 (#6793) 2017-03-26 15:53:53 +02:00
Fabian Affolter
ad649009cd Upgrade zeroconf to 0.19.0 (#6792) 2017-03-26 15:53:42 +02:00
Fabian Affolter
7782e7e948 Add optional unit of measurement (#6796) 2017-03-26 15:52:59 +02:00
Fabian Affolter
5d5547cdb6 Update docstrings (#6795)
* Add link to docs and remove comments which are obvious

* Update docstrings

* Repleace conf details with link to docs

* Add link to docs

* Update docstrings

* Update import

* Update ordering

* Update ordering

* Update docstring

* Update ordering

* Update ordering
2017-03-26 15:50:40 +02:00
Fabian Affolter
22b28d85db Add switch to MQTT discovery (#6733) 2017-03-26 15:48:28 +02:00
Teemu R
f5d4f853ba switch.tplink: upgrade to the newest upstream release which adds support for plugs using the newer communication protocol (#6790) 2017-03-26 10:55:17 +02:00
Fabian Affolter
0f098df232 Merge branch 'master' into dev 2017-03-26 00:07:25 +01:00
Fabian Affolter
1f046972d9 Merge pull request #6756 from home-assistant/release-0-41
0.41
2017-03-26 00:01:49 +01:00
John Arild Berentsen
5a7155fc4a Wrong info in discovery schema (#6779) 2017-03-25 19:39:03 +01:00
Nick Sabinske
c817ab08b7 Fix bridge-led support in limitlessled.py (#6776)
Addressing #6382 . Feedback from github & forums is the bridge_led feature never worked and defining the bridge LED as another group+bulb type is the right way to do this in the limitlessled component.
2017-03-25 15:32:57 +01:00
William Scanlon
f8005153c9 Fix wink siren (#6775)
* Fix siren/switch attributes and update python-wink

* Updated requirements_all.txt
2017-03-25 15:28:16 +01:00
Daniel Perna
447048701c Homematic Fixes (#6769)
* Added missing operational modes for thermostats

* Added attributes

* Updated requirements

* Bumped dependency
2017-03-25 09:48:05 +01:00
Pascal Vizeli
f4e9466394 Bugfix automation fire on bootstrap (#6770)
* Bugfix automation fire on bootstrap

* Add test & fix bug

* fix lint
2017-03-24 15:52:14 -07:00
Adam Mills
cffc6c7bea Tests for zwave workaround detection (#6761)
* Tests for zwave workaround detection

* Remove unused code

* Revert "Remove unused code"

This reverts commit e06cce0abecc233dab3488dc4194b2d296eee002.

* Tests for empty manufacturer ID
2017-03-24 15:31:46 -07:00
Fabian Affolter
8d606f8d16 Upgrade sleekxmpp to 1.3.2 (#6773) 2017-03-24 21:44:04 +01:00
Fabian Affolter
7ae814357a Upgrade psutil to 5.2.1 (#6771) 2017-03-24 21:43:48 +01:00
Fabian Affolter
1be2706de3 Upgrade pydroid-ipcam to 0.7 (#6772) 2017-03-24 21:42:00 +01:00
geekofweek
06d3889e1b Wink Aros Fixes (#6726)
Wink Aros only supports 3 Fan Modes:

Low
Medium
High

Fan Mode had a Typo and wasn't represented in the UI
2017-03-24 16:13:14 -04:00
John Arild Berentsen
ee6c9ab6a9 Typing error and update test (#6757) 2017-03-23 23:53:59 -07:00
John Arild Berentsen
82c599a749 current temp could be none (#6759) 2017-03-23 23:50:36 -07:00
Paulus Schoutsen
0b7f873120 Merge branch 'release-0-41' into dev 2017-03-23 23:34:08 -07:00
Paulus Schoutsen
9f2f0c5566 Version bump to 0.42.0.dev0 2017-03-23 23:33:49 -07:00
Paulus Schoutsen
53f8828181 Merge branch 'master' into release-0-41 2017-03-23 23:32:50 -07:00
Adam Mills
22613d8e2e Repair zwave sensor coverage (#6764) 2017-03-23 20:57:15 -07:00
Adam Mills
efbd66bca1 Fix flaky template test (#6768) 2017-03-23 20:56:39 -07:00
Tim Soderstrom
5dfdb9e481 New indexes for states and recording_runs tables (#6688)
* New indexes for states table

* Added recorder_runs indexes

* Created a new function for compound indexes.

A new function was created because it makes it a little cleaner when creating
a single-field index since one doesn't have to create a list. This is mostly
when creating the name of the index so with a bit more logic it's possible
to combine it into one function. Given how often migration changes are run,
I thought that code bloat was probably a worthy trade-off for now.

* Adjusted indexes, POC for ref indexes by name.

* Corrected lint errors

* Fixed pydocstyle error

* Moved create_index function outside apply_update

* Moved to single line (just barely)
2017-03-23 20:48:31 -07:00
micw
6c5989895a Adding expire_after to mqtt sensor to expire outdated values (#6708)
* Adding expire_after to mqtt sensor to expire outdated values

* Extending test case

* mqtt: refactoring expire_after to use timed events instead of polling; lint

* refactor to reset unused trigger

* Fix: handler must be set to None after execution or removal to avoid warning

* Commenting out non-working test

* Fix lint

* Commit to trigger new build

* Commit to trigger new build

* Make testcase work

* Undo unnecessary change

* Remove default value, add extra check
2017-03-23 17:55:07 -04:00
Daniel Høyer Iversen
3acd926d29 Flux led update lib (#6763)
* Update flux_led lib
2017-03-23 21:58:22 +01:00
Paulus Schoutsen
b6b40286ef Version bump to 0.41 2017-03-23 08:42:01 -07:00
Andrey
8a86ec5b74 Add zwave per-node entity. (#6690)
* Add zwave per-node entity.

* Disable lint import error

* Add tests for base class

* More tests

* More tests

* Sort .coveragerc

* more tests

* Move location, battery and wakeup to node entity

* More tests

* Cleanup

* Make zwave node entity visible by default

* Remove battery sensor

* Fix tests
2017-03-23 08:37:20 -07:00
Dan Ports
20c5f9de4b Add sensor for Lyft time and price (based on Uber sensor) (#6711)
* Add sensor for Lyft time and price (based on Uber sensor)

* Minor fixes to lyft sensor
 - use add_devices(...,True) instead of explicitly calling update
 - move sensor name check into constructor

* lyft sensor: disable sandbox mode
2017-03-23 08:15:52 -07:00
Mitesh Patel
61730012d8 Adds Support for Lutron Caseta devices. (#6631)
* Adds support for the Lutron Caseta family of devices

* Added external requirement

* Removes unuse import

* Adds requirement to requirements_all.txt

* Removes unuse import

* fixes requirement_all.txt. by regenerating

* Cleans up syantax

* Cleans up syantax

* Cleans up syantax

* Cleans up syantax

* Shortens long line

* adds lutron_caseta component to .coveragerc

* Merges into light, removes component

* Fixes long lines

* Fixes requirement.txt

* Removes 'ERROR' log statements. Adds missing dependency

* savig work to pick up on other machine

* Enables Lutron Caseta component with Light and Switch platforms

* Add missing file to .coveragerc

* Changes based on PR review

* fixes requirements file

* Fixes install of paramiko dependency.

* Moves callback registration to

* comment changes

* Platform have no return value

* Change style for guard

* fix logic

* fix lint
2017-03-23 01:18:14 +01:00
Paulus Schoutsen
25d2df5689 Merge pull request #6740 from home-assistant/release-0-40-2
0.40.2
2017-03-22 09:31:21 -07:00
Paulus Schoutsen
672b83db8a Update constraints 2017-03-22 09:30:36 -07:00
Paulus Schoutsen
b37438ebb7 Constrain core dependencies to core versions (#6738)
* Require at least pip 7.1

* Write and use constraint files for packages

* Update gen_requirements_all.py
2017-03-22 08:51:18 -07:00
Paulus Schoutsen
902b72ba1a Constrain core dependencies to core versions (#6738)
* Require at least pip 7.1

* Write and use constraint files for packages

* Update gen_requirements_all.py
2017-03-22 08:50:54 -07:00
Paulus Schoutsen
f10fede17f Bump PyChromecast to 0.8.1 (#6702) 2017-03-22 08:50:42 -07:00
Paulus Schoutsen
c9548b11b1 Version bump to 0.40.2 2017-03-22 08:50:15 -07:00
Wolfgang Malgadey
f4aec3ac88 Tado climate device (#6572)
* Added tado climate component

named the component v1 because of the unsupported state of the api I
used (mytado.com)

* sensor component
* climate component which uses sensors
* main component initiating sensor and climate devices
* order of imports
* consts for username and password
* removed redundant code
* changed wrong calls and properties

* remove pylint overrides

* merged update() and push_update()

* changed wrong calls
* removed pylint overrides
* moved try..except

* renamed MyTado hass-data object

* added TadoDataStore

* moved update methods from sensor to TadoDataStore

* reorganised climate component

* use new TadoDataStore

* small change to overlay handling

* code refactoring

* removed unnessesary comments
* changed throttle to attribute
* changed suggestions from PR

* Added constant variable for string literal

* remove wrong fget() call

* changed dependencies

* Changed operation mode list

* added human readable list of operations
* removed unnecessary const
* activated update on add_devices

* droped unit

* removed unnused property

* changed temperature conversion

* removed defaults from config
changed naming of tado data const

* switched operation_list key/values

* changed the value returned as state

* added one extra line

* dropped state to use base impl.

* renamed component

* had to inplement temperature_unit

* because it is not implemented in base class

* create a copy of the sensors list

* because it can be changed by other components

* had to check for empty data object

* hass is too fast now
2017-03-22 08:18:13 -04:00
Adam Mills
e7425e9808 ZWave Lock Tests (#6730)
* ZWave Lock Tests

* Linting fixes

* Missed coveragerc
2017-03-21 08:55:21 -07:00
Matt N
978b539111 camera.zoneminder: Show recording state (#6686) 2017-03-21 07:25:10 +01:00
Paulus Schoutsen
9f4cd5fafe Do not log warning on rest_command if no error (#6713) 2017-03-21 07:18:33 +01:00
Anders Melchiorsen
ba3c9f9765 Fix LIFX unregister races (#6723)
* Fix LIFX unregister races

If the initial state request never got a response, we tried to unregister
a device that was not yet registered.

Also, aiolifx 0.4.2 has an "unregister" race fix.

* Update requirements
2017-03-21 07:17:58 +01:00
Paulus Schoutsen
4ee8be52fe Update frontend 2017-03-20 21:31:58 -07:00
Adam Mills
866bf887d3 ZWave switch tests (#6722) 2017-03-20 13:17:42 -04:00
Adam Mills
dddbce82f5 ZWave Sensor tests (#6721)
* ZWave Sensor tests

* Add missed coverage
2017-03-20 13:17:17 -04:00
Jeff Wilson
be15ca3f23 Don't warn if octoprint completion is null (#6719) 2017-03-20 09:00:45 -07:00
Finbarr Brady
9a305c9742 Fix for issue: luci returns 403 invalid token when rebooted #6715 (#6717) 2017-03-20 08:55:59 -07:00
Paulus Schoutsen
de231cf9ab restore_state: do not crash if domain not defined (#6714) 2017-03-20 08:54:51 -07:00
Adam Mills
8325f9db8a Add zwave light tests (#6710)
* Add zwave light tests

* Test turn_off
2017-03-19 22:22:13 -07:00
Paulus Schoutsen
3f38b9e52f Update frontend 2017-03-19 21:59:13 -07:00
printzlau
1cb2a6add0 automatically use bundled certificate it set to auto (#6707)
* automatically use bundled certificate if certificate-parameter is set to 'auto' and seperate this from which port is specified

* Fix travis error and long lines

* Update __init__.py
2017-03-19 14:51:53 -07:00
Greg Dowling
acf75b5253 Revise power and energy units and property names. (#6212)
* Revise power and energy units and property names.

* Add change for new wemo parameter.
2017-03-19 22:02:11 +01:00
Adam Mills
970bde9e99 Fix Kodi when websocket is disabled (#6706) 2017-03-19 21:38:12 +01:00
Adam Mills
796143a6c6 Kodi use websocket loop task created by library (#6703) 2017-03-19 12:46:14 -07:00
Paulus Schoutsen
5569ae38f1 Bump PyChromecast to 0.8.1 (#6702) 2017-03-19 11:53:58 -07:00
John Mihalic
7eaad4fb3a Fix longitude (#6697) 2017-03-19 11:00:13 -07:00
Fabian Affolter
35c679a956 Upgrade distro to 1.0.3 (#6693) 2017-03-19 15:59:07 +01:00
martinfrancois
678f273002 Rflink: added support for lights with toggle type (#6521)
* added support for lights with toggle type

* fixed style errors

* introduced tests for the toggle type

it's not passing yet because of an assertionerror at line 407

* updated to reflect tristate of "state"

* Format code according to pep8

Added line break for import that was too long.

* fixed lint, replaced if statement with 'var = bool(test)'

* changed implementation of state check according to bug on 6bceb04ca1 (r106758784)
2017-03-18 21:34:17 +01:00
Tyler Crumpton
4e91c65d6e Update Torque component to match recent API. (#6671) 2017-03-18 11:25:38 +01:00
Robbie Trencheny
f6106706e5 Merge pull request #6672 from robbiet480/new-plex-fix
Fixed Show All Controls feature
2017-03-17 17:34:26 -07:00
JesseWebDotCom
ecf337b123 Fixed Show All Controls feature 2017-03-17 17:22:38 -07:00
Martin Nöhrer
f5d8327d9a Fix hass script execution on Windows (#4977). (#6601)
* Fix hass script execution on Windows (#4977).

hass.exe returned ERRNO2 on a windows machine and must be started using
package loading. This fix adapts the command line options for
`setup_and_run_hass()` to start
either a script with `python homeassistant/__main__.py` or with
`Scripts/hass.exe`

* Fix code style
2017-03-17 17:07:36 -07:00
John Mihalic
30d4c54187 Update Emby component to async (#6664)
* Update Emby component to async

* Address comments

* Make SSL default

* Bump library

* Port based on SSL, use available property
2017-03-17 15:55:07 +01:00
David Straub
edf20f542a Phone book lookup support for Fritz!Box call monitor (#6474)
* Update fritzconnection dependency in fritz and fritzbox_netmonitor components

* Add phone book name lookup support to FritzBox call monitor

* Updated requirements_all.txt

* Requested changes to FritzBox call monitor

* Listen to HOME_ASSISTANT_STOP and close thread

* Safe CPU time
2017-03-17 14:40:12 +01:00
Jay Love
9778000e9a Add new media_player platform: Volumio Media Player (#6556)
* Add new media_player platform: Volumio Media Player

Volumio media player is a rpi music player, this platfor adds http based control of the player.

* Modify mute command to accept boolean

* Adjust mute call to reset volume after unmute
Remove references to volimi"a"

* Use yield from calls in mute and volume calls

Trying to speed up the indication of mute and volume level changes in UI, but doesn't seem to do much.

* Adjust async_add_devices call
2017-03-16 23:32:52 -07:00
miniconfig
b5149dfba6 Added support for multiple efergy sensors in the same household. (#6630)
* Added support for multiple efergy sensors in the same household.
Also added inital tests for the efergy platform.

* Fixed current_values units.
Changed name to include efergy_ prefix.
2017-03-16 23:22:10 -07:00
John Mihalic
ced3cd2616 Refactor Neurio to add Daily Power Sensor (#6662)
* Refactor Neurio to add Daily Power Sensor
2017-03-16 23:20:14 -07:00
RickyTaterSalad
7050236a61 add latitude and longitude configuration to darksky sensor (#6191)
* Optional latitude and longitude to darksky sensor

allow configuration of latitude and longitude in the darksky sensor.
falls back to home assistant coordinates if latitude/longitude not
specified.

* lat/long as inclusive on schema. removed None check for lat/long in setup_platorm

altered schema to require latitude and longitude configured as a pair.
removed None check on latitude and longitude since values will fall back
to hass config if not present

* adhere to line limit of 79 characters

adhere to line limit of 79 characters
2017-03-16 23:04:01 -07:00
Pascal Vizeli
c8e1ffad89 Pump Android ip webcam to 0.6 (#6665)
* Pump Android ip webcam to 0.5

* update to 0.6
2017-03-16 22:19:48 +01:00
hawk259
e3edff8a72 Add configurable timeout option to camera.synology (#6655) 2017-03-16 21:26:35 +01:00
Sebastian
d6fd0f405e Corrected help text for refresh_node (#6659)
Changed entity_id to node_id.
2017-03-16 21:50:01 +02:00
Fabian Affolter
1ab47b5d2b Check if droplet exists (#6663)
* Check if droplet exists

* Add droplet to message and remove else
2017-03-16 19:59:34 +01:00
Fabian Affolter
a2365eccf6 Upgrade aiohttp to 1.3.5 (#6660) 2017-03-16 18:04:00 +01:00
Fabian Affolter
c46ba3446d Upgrade astral to 1.4 (#6332)
* Upgrade astral to 1.4

* Update test for norway
2017-03-16 17:38:46 +01:00
JesseWebDotCom
5714f156c3 Support for non-clients, NVidia shield, dynamic grouping, extra metad… (#6054)
* Support for non-clients, NVidia shield, dynamic grouping, extra metadata, and more

* Fixed import orderdering, line lengths, and comment violations

* Local player check and season fixes

* Honor entity_namespace when using custom entity ids

* Semi compatibility with channels, force controls option added

* media_position_updated_at fix - only update when media is playing

* Fix: controls now work as expected on 1) casted sessions and 2) client sessions when client and PMS reside on the same sever

* Made PEP8 compliant

* Made PEP8 compliant

* Made PEP8 compliant, hopefully

* Better Tivo compatibility

* Added frozen detection and remediation

* PlayMedia EPISODE now supports season number and episode number (instead of episode index)

* Fix: Dynamic groups now exclude hidden devices

* Fix: Dynamic groups now exclude hidden devices

* Implemented arsaboo suggested formatting

* Implemented pylint command line suggested fixes

* Implemented Travis CI build suggested fixes

* Sorted Imports using Importanize

* Grouped request imports

* Removed dynamic groups, network calls from properties, and other cleanup

* Balloob recommendations and Plex Protocol Capabilities checks

* Remove deprecated disable-msg in favor of disable

* Removed position related items (seek, frozen detection, etc)

* Removed unused datetime
2017-03-16 09:09:46 -07:00
joe248
959dd29c90 round output values (#6657) 2017-03-16 15:36:44 +01:00
John Arild Berentsen
e75a66ed20 Add Zwave sensors test (#6640)
* Test for zwave sensor

* Add test for ZWave sensors

* Hound...

* Hound...

* Review changes
2017-03-16 08:25:37 -04:00
Fabian Affolter
3e72aa8643 Upgrade python-digitalocean to 1.11 (#6653) 2017-03-16 11:14:36 +01:00
John Arild Berentsen
5aaa1f8404 Add test for Z-wave switch (#6619)
* Add test for Z-wave switch

* Changes for new tests
2017-03-16 11:05:51 +01:00
Paulus Schoutsen
7292e564f8 Merge pull request #6652 from home-assistant/release-0-40-1
0.40.1
2017-03-15 23:47:10 -07:00
Wolf-Bastian Pöttner
509cfb6433 Added workday sensor (#6599)
* Added workday sensor

* Added unit tests
2017-03-15 23:46:13 -07:00
Pascal Vizeli
acdab67c1b Bugfix RFLINK remove group (#6580)
* Bugfix RFLINK remove group

* Remove group hack from lutron too

* fix tests

* fix lint

* fix lint
2017-03-15 23:19:33 -07:00
deisi
d7addf59cd Fix #6534 (#6598)
* Fix #6534

Makes sure 0 is not passes to `color_temperature_kelvin_to_mired`.

* Update osramlightify.py

* Update osramlightify.py
2017-03-15 23:19:24 -07:00
Yum
ccf9edf815 since knx_2_float can't handle 0, bypass converting 0 value from knx to float (#6626) 2017-03-15 23:18:55 -07:00
Johann Kellerman
2fd3c186e2 Update SMA solar sensor to work with the new add_devices callback (#6602) 2017-03-15 23:18:11 -07:00
Dale Higgs
719199da45 Update pyecobee version to 0.0.7 (#6593) 2017-03-15 23:17:44 -07:00
Thibault Cohen
a3cd7d653d Fix hydroquebec (#6574) 2017-03-15 23:17:17 -07:00
Andrey
aeeb927e19 Fix for the case of zwave value used in several devices. (#6577) 2017-03-15 23:16:50 -07:00
Jesse Newland
a3a14f9ea4 Don't start the push updater if the Apple TV is 'off' (#6552)
Add an optional extended description…
2017-03-15 23:16:32 -07:00
Tyler Page
f4e7b231bc Fix wake_on_lan ping with None as host (#6532)
* Update configuration validation

With the new update, wake_on_lan requires a host key in the configuration

* cast self._host to str as requested

* Changed host key back to optional
2017-03-15 23:15:56 -07:00
Paulus Schoutsen
5f68735375 Version bump to 0.40.1 2017-03-15 23:10:50 -07:00
Pascal Vizeli
774fd19638 Bugfix RFLINK remove group (#6580)
* Bugfix RFLINK remove group

* Remove group hack from lutron too

* fix tests

* fix lint

* fix lint
2017-03-15 23:08:47 -07:00
Paulus Schoutsen
e265401cd0 self.loop.create_task -> self.add_job (#6632)
* self.loop.create_task -> self.add_job

* Core to use create task
2017-03-16 06:58:54 +01:00
deisi
5b3dc7f2a5 Fix #6534 (#6598)
* Fix #6534

Makes sure 0 is not passes to `color_temperature_kelvin_to_mired`.

* Update osramlightify.py

* Update osramlightify.py
2017-03-15 22:58:06 -07:00
Anders Melchiorsen
9ef084d903 Move LIFX to aiolifx for driving the bulbs (#6584)
* Move LIFX to aiolifx for driving the bulbs

* Fix whitespace

* Fix more whitespace

* Fix lint

* Define _available in init

* Add @callback decorators

* Use hass.async_add_job

* Rename class
2017-03-15 22:50:33 -07:00
Robbie Trencheny
95b1e257bb Merge pull request #6633 from home-assistant/deprecate-event-forwarding
Deprecate event forwarding
2017-03-15 22:27:49 -07:00
Adam Mills
b06cf87c74 Kodi: Fix episode media type classification (#6645) 2017-03-15 22:07:30 -07:00
Adam Mills
326337777a Add ZWave cover tests (#6648) 2017-03-15 22:06:37 -07:00
mvillarejo
2c8a06bfbe media_player.kodi extra attributes for tvshow and music media (#6622)
* media_player.kodi extra attributes for tvshow and music media

* removed extra whitespaces/CR

* Kodi - add extra attributes #6250 (removed music attributes)

* Restored music attributes, this is ready for merge

* linting amended

* Fix Kodi artist support

* Copy-paste error

* Fix for non-music artist lookup

Kodi returns an emtpy list on videos, so we need to be able to
handle that as well.
2017-03-15 19:51:31 -04:00
Pascal Vizeli
198a234468 aioHttp 1.3.4 (#6643) 2017-03-15 22:30:46 +01:00
Paulus Schoutsen
e94aa3afe9 Deprecate event forwarding 2017-03-15 08:38:26 -07:00
Paulus Schoutsen
96e22c7b41 Remove event decorators (#6634) 2017-03-15 14:46:57 +01:00
Nathan Henrie
33450c726d Use sqlite's WAL mode to avoid database is locked errors (#6519)
* Use sqlite's WAL mode to avoid `database is locked` errors

- Relevant issue: https://github.com/home-assistant/home-assistant/issues/4780

Code:

- http://stackoverflow.com/a/23661501/1588795
- http://docs.sqlalchemy.org/en/rel_0_9/dialects/sqlite.html#foreign-key-support
- https://github.com/g2p/bedup/pull/86/files

* Only set WAL if using sqlite

* Reorder imports

* Fix pylint warnings
2017-03-15 00:14:12 -07:00
Yum
97b9d3bd21 since knx_2_float can't handle 0, bypass converting 0 value from knx to float (#6626) 2017-03-14 20:25:52 -07:00
Adam Mills
fff589eeab Correctly flag Kodi media types (#6628) 2017-03-14 20:25:15 -07:00
Adam Mills
5e5d2e8ab8 Tests for ZWave climate (#6629)
But wait, there's more! Also a few fixes discovered writing the tests.
2017-03-14 20:24:35 -07:00
Paulus Schoutsen
1a7ffdca52 Add "Refactor zwave discovery to entity schema" (#6565)
* Revert "Revert "Refactor zwave discovery to entity schema (#6445)" (#6564)"

This reverts commit 58826b264a.

* Update zwave tests for enitity schema

* Fix merge error

* Switch dict_id to id(self)
2017-03-14 19:55:33 -04:00
Erik Eriksson
cada74df22 Merge pull request #6583 from molobrakos/voc-fix
Bump VOC version (fixes heater bug)
2017-03-14 23:37:32 +01:00
Johan Bloemberg
bd3fbe8363 Upgrade to dsmr_parser 0.8, supporting protocol 3 and 5. (#6600)
* Upgrade to dsmr_parser 0.8, supporting protocol 3 and 5.

* Update tests for new import.
2017-03-14 20:16:43 +01:00
Daniyar Yeralin
4d9c7d9684 Update mpd.py (#6553)
* Update mpd.py

Introducing new parameter "Name"

* Update mpd.py

Change `CONF_LOCATION` to `CONF_NAME`
2017-03-14 20:10:35 +01:00
ArrayLabs
0bf66384ed Cover myq fix update pymyq (#6595)
* update pymyq to 0.0.8

update to correct wrong version in setup.py

* update pymyq to 0.0.8

update to correct wrong version in setup.py
2017-03-14 20:06:30 +01:00
tflack
c7798ef43c Define db for SHOW DIAGNOSTICS query since some users will not have a… (#6566)
* Define db for SHOW DIAGNOSTICS query since some users will not have admin perms

* fix white space error from CI
2017-03-14 11:46:46 -07:00
hawk259
f4d8095e54 Add configurable timeout option to notify/smtp (#6609)
* Add configurable timeout option to notify/smtp

* Updated smtp test to include timeout param

* fixed 80 column style issue
2017-03-14 19:00:16 +01:00
Pascal Vizeli
5529d77c62 Prevent entities running multiple updates simultaneously (#6511)
* Protect entity for multible updates on same time.

* Address all comments / make update more robust

* fix unittest

* fix lint

* address comments
2017-03-14 09:26:55 -07:00
Erik Eriksson
c4e151f621 Error handling when connection refused (#6614)
Add an optional extended description…
2017-03-14 10:08:40 +01:00
Fabian Affolter
f58941a0d4 Upgrade googlemaps to 2.4.6 (#6611) 2017-03-14 07:54:19 +01:00
Fabian Affolter
bca673f039 Upgrade py-cpuinfo to 0.2.7 (#6610) 2017-03-14 07:54:10 +01:00
Fabian Affolter
2687f2f623 Fix link (#6612) 2017-03-14 07:53:48 +01:00
Johann Kellerman
134b3d2f3b Update SMA solar sensor to work with the new add_devices callback (#6602) 2017-03-14 06:39:30 +02:00
Dale Higgs
f450c1351c Update pyecobee version to 0.0.7 (#6593) 2017-03-13 21:19:51 +01:00
Fabian Affolter
c6b10f3703 Upgrade Sphinx to 1.5.3 (#6587) 2017-03-13 21:05:27 +01:00
Fabian Affolter
4a08067b9c Upgrade psutil to 5.2.0 (#6585) 2017-03-13 21:05:07 +01:00
Fabian Affolter
9c37437a59 Upgrade sqlalchemy to 1.1.6 (#6591) 2017-03-13 21:02:28 +01:00
Fabian Affolter
9330142987 Upgrade pyasn1 to 0.2.3 (#6588) 2017-03-13 21:01:45 +01:00
Fabian Affolter
2bbaac44d4 Upgrade async_timeout to 1.2.0 (#6590) 2017-03-13 21:01:25 +01:00
Thibault Cohen
253dee8e4d Fix hydroquebec (#6574) 2017-03-13 18:54:23 +01:00
Andrey
5722cf53bf Fix for the case of zwave value used in several devices. (#6577) 2017-03-13 12:19:45 -05:00
Pascal Vizeli
5d301590c3 Remove dispatcher camera (#6579) 2017-03-13 17:54:28 +01:00
Erik
353f5d6b49 bump voc version (fixes heater bug) 2017-03-13 17:28:27 +01:00
Jesse Newland
11da7bed12 Don't start the push updater if the Apple TV is 'off' (#6552)
Add an optional extended description…
2017-03-13 14:23:15 +01:00
Kevin Fronczak
a358c8e10d Upgraded blinkpy version, increased Throttle time for camera (#6561) 2017-03-13 00:12:48 -07:00
Paulus Schoutsen
58826b264a Revert "Refactor zwave discovery to entity schema (#6445)" (#6564)
This reverts commit 56abc7f9b4.
2017-03-12 23:35:10 -07:00
Adam Mills
56abc7f9b4 Refactor zwave discovery to entity schema (#6445)
* Refactor zwave discovery to entity schema

* Address PR concerns

* Split DISCOVERY_SCHEMAS into separate file

* Only check cover reverse workaround once
2017-03-12 23:13:34 -07:00
Adam Mills
55d60a6a13 ZWave binary sensor tests (#6555)
* ZWave binary sensor tests

* Test fixes

* Improve coverage of features
2017-03-12 22:08:53 -07:00
Dennis de Greef
5183cb5903 Be able to select mqtt:tls_version for Python < 3.6 (#6442)
* Be able to select tls_version

* This test should always assert this value, not only in 3.6

* Disable linting on future property (py36)

* Only allow TLS 1.0, 1.1 and 1.2

* Fix line length issue

* Fix check config tests

* Allow auto as a TLS version
2017-03-12 22:02:59 -07:00
Tyler Page
0aa8933df6 Fix wake_on_lan ping with None as host (#6532)
* Update configuration validation

With the new update, wake_on_lan requires a host key in the configuration

* cast self._host to str as requested

* Changed host key back to optional
2017-03-12 20:46:58 +01:00
siebert
fc46a24996 Fix gen_requirements_all.py script for Windows. (#6547) 2017-03-12 21:08:49 +02:00
Paulus Schoutsen
5be58bd056 Simplify Android IP webcam discovery (#6528) 2017-03-12 18:56:48 +01:00
Lewis Juggins
4a423e63f3 Version bump to 0.41.0.dev0 2017-03-12 08:34:35 +00:00
Paulus Schoutsen
a8b32edc8e Merge pull request #6509 from home-assistant/release-0-40
0.40
2017-03-11 11:08:40 -08:00
Greg Dowling
4a5b9db394 Discovery is a dict rather than an array. (#6525) 2017-03-11 11:06:05 -08:00
Greg Dowling
9c23178457 Append vera device id to entity id - but not name. (#6523)
* Append vera device id to entity id - but not name.

* Tidy.

* Tidy.

* Tidy after review.

* Re-order.
2017-03-11 11:06:05 -08:00
Paulus Schoutsen
764d31efcb Remove mint finance sensor (#6522) 2017-03-11 11:06:05 -08:00
Anders Melchiorsen
fc90ccea36 Fix colortemp conversion for osramlightify (#6516)
* Fix colortemp conversion for osramlightify

Copied from the LIFX fix in 75df4be733.

* Fix style

* Updates from review

@armills:

While we're doing cleanup here, can you just change self._brightness,
self._rgb, self._name, self._temperature, and self._state assignments in
__init__ to None? These will get overwritten when self.update() is called, so
it's safer/cleaner to initialize them to None since it shouldn't matter if
everything is working.
2017-03-11 11:06:05 -08:00
Martin Hjelmare
aab63ea22a Fix mysensors gateway windows setup (#6500) 2017-03-11 11:06:05 -08:00
Adam Mills
157ab77232 Update Kodi notifier to async (#6497)
* Update Kodi notifier to async

* Change Kodi CONF_SSL to CONF_PROXY_SSL
2017-03-11 10:41:05 -08:00
Anders Melchiorsen
9a86ccaaea Fix colortemp conversion for osramlightify (#6516)
* Fix colortemp conversion for osramlightify

Copied from the LIFX fix in 75df4be733.

* Fix style

* Updates from review

@armills:

While we're doing cleanup here, can you just change self._brightness,
self._rgb, self._name, self._temperature, and self._state assignments in
__init__ to None? These will get overwritten when self.update() is called, so
it's safer/cleaner to initialize them to None since it shouldn't matter if
everything is working.
2017-03-11 10:40:16 -08:00
Greg Dowling
32dd815852 Discovery is a dict rather than an array. (#6525) 2017-03-11 10:39:26 -08:00
Boris K
9ac3928600 Add type configuration in history_stats (#6430) 2017-03-11 10:38:18 -08:00
William Scanlon
62e57456e1 Wink scene(shortcut) support (#6147)
* Wink scene(shortcut) support

* Scenes to Scene

* Moved wink scenes from switches to scenes

* Updated python-wink version
2017-03-11 10:18:29 -08:00
Róbert Nagy
11f11481b2 Force update support for MQTT sensor (#6492) 2017-03-11 10:07:52 -08:00
Greg Dowling
10f5e9744b Append vera device id to entity id - but not name. (#6523)
* Append vera device id to entity id - but not name.

* Tidy.

* Tidy.

* Tidy after review.

* Re-order.
2017-03-11 10:06:46 -08:00
Paulus Schoutsen
b2a2193ba3 Remove mint finance sensor (#6522) 2017-03-11 01:02:32 -08:00
Paulus Schoutsen
c8b2ba6559 Version bump to 0.40 2017-03-10 23:09:44 -08:00
Paulus Schoutsen
1496f1a570 Update frontend 2017-03-10 22:52:16 -08:00
Paulus Schoutsen
493c0bbb4c Update frontend 2017-03-10 22:51:44 -08:00
Martin Hjelmare
13dd17b2ab Fix mysensors gateway windows setup (#6500) 2017-03-11 03:30:23 +01:00
Pascal Vizeli
0ef1c3af34 Android webcam better error handling / pump library 0.4 (#6518) 2017-03-10 23:11:16 +01:00
Pascal Vizeli
44da43065f Android webcam better error handling / pump library 0.4 (#6518) 2017-03-10 23:10:35 +01:00
Pascal Bach
ffb1613d55 [packaging] Include LICENSE.md in tarball (#6514) 2017-03-10 19:59:38 +00:00
Pascal Vizeli
b0a2909835 Bugfix rpi_rf cleanup (#6513)
Add an optional extended description…
2017-03-10 14:57:03 +01:00
Pascal Vizeli
b5fb558c62 Bugfix rpi_rf cleanup (#6513)
Add an optional extended description…
2017-03-10 14:56:13 +01:00
Robbie Trencheny
846a0513c7 Don't allow sending to invalid iOS targets (#6115)
* Don't allow sending to invalid targets

* Fix valid target check
2017-03-10 12:32:43 +01:00
Craig J. Ward
0f1cad24ce Insteon lib (#6505)
* use lib with caching to reduce collisions

* use 0.43

* change requirements

* update the  lib to 0.44

* update req

* fix typo

* just keep checking

* just keep checking - switch

* use 0.45 with file cache

* requirements

* Update requirements_all.txt

* Update insteon_local.py

* Update requirements_all.txt

* Update insteon_local.py

* update library

* fix lint
2017-03-10 11:17:09 +01:00
Caleb
24630b1ebe Update to Pyunifi2.0 (#6490)
* Updated pyUnifi

* Missing comma

* Security opt-out, not opt-in

* Adjust minimal values

* Update to pyUnifi 2.0
2017-03-10 11:16:51 +01:00
Caleb
b705b3ddb9 Update to Pyunifi2.0 (#6490)
* Updated pyUnifi

* Missing comma

* Security opt-out, not opt-in

* Adjust minimal values

* Update to pyUnifi 2.0
2017-03-10 11:15:21 +01:00
Craig J. Ward
330d352d3a Insteon lib (#6505)
* use lib with caching to reduce collisions

* use 0.43

* change requirements

* update the  lib to 0.44

* update req

* fix typo

* just keep checking

* just keep checking - switch

* use 0.45 with file cache

* requirements

* Update requirements_all.txt

* Update insteon_local.py

* Update requirements_all.txt

* Update insteon_local.py

* update library

* fix lint
2017-03-10 11:14:31 +01:00
Pascal Vizeli
bdaae6f844 Bugfix android camera autodiscovery settings (#6510)
Add an optional extended description…
2017-03-10 10:14:05 +01:00
Pascal Vizeli
49308bec13 Bugfix android camera autodiscovery settings (#6510)
Add an optional extended description…
2017-03-10 10:10:35 +01:00
Paulus Schoutsen
edd96c2b04 Merge remote-tracking branch 'origin/master' into dev 2017-03-09 21:32:04 -08:00
Robbie Trencheny
11c4d3892f Merge pull request #6001 from jumpkick/patch-2
Improvements for WeMo Insight switches
2017-03-09 21:14:33 -08:00
Robbie Trencheny
75817ad46d Merge pull request #6361 from GreenTurtwig/dev
Updated to catch timeout error
2017-03-09 20:39:20 -08:00
Robbie Trencheny
780cdd5f90 Merge pull request #6389 from Deinara/discord_connect_fix
Discord connect fix
2017-03-09 19:57:29 -08:00
Robbie Trencheny
d70eaeb118 Merge pull request #6407 from jvolkman/patch-1
Small typo fix in setup_docker_prereqs
2017-03-09 19:55:57 -08:00
Robbie Trencheny
9e9c6d0184 Make states constants 2017-03-09 19:55:18 -08:00
Robbie Trencheny
2cdc0febf5 Merge pull request #6494 from armills/kodi-command-exceptions
Catch exceptions on kodi commands
2017-03-09 19:50:53 -08:00
Robbie Trencheny
c721ec7ab0 Merge pull request #6507 from amelchio/longer-light-transitions
Increase upper limit on light transitions (#2843)
2017-03-09 19:50:22 -08:00
Robbie Trencheny
4e63e8328e Merge pull request #6506 from happyleavesaoc/enhance-moon
more moon states
2017-03-09 19:45:40 -08:00
Robbie Trencheny
8f2009a187 Merge pull request #6488 from pvizeli/pydroid-ipcam
Android IP Cam support
2017-03-09 19:41:23 -08:00
Adam Mills
529eee994b Include functools.wraps 2017-03-09 19:52:45 -05:00
Christiaan Blom
3f7dd7ed9a Added an extra space 2017-03-10 00:33:29 +01:00
Christiaan Blom
b952cfe705 Added pylint ignore message and re-added .close() 2017-03-10 00:21:26 +01:00
Anders Melchiorsen
b9cf4df557 Increase upper limit on light transitions (#2843)
This increases the global limit to 6535 seconds (1h48m55s) because that is
supported by all light platforms.

Some platforms support even longer transition times so the limit should
actually be platform specific.
2017-03-09 23:59:35 +01:00
happyleaves
7892297240 more moon states 2017-03-09 16:54:04 -05:00
Pascal Vizeli
20fcd1f0e2 Bugfix mqtt socket memory error (#6501)
* Bugfix mqtt socket memory error

* Fix tests

* Fix lint
2017-03-09 06:31:43 -08:00
pvizeli
8bbf13ef9f Fix lint 2017-03-09 15:10:39 +01:00
Paulus Schoutsen
855756cb2a Add first pass at Z-Wave light tests (#6483)
* Add first pass at Z-Wave light tests

* Remove unused SIGNAL_VALUE

* Lint

* Update test_init.py
2017-03-09 14:35:04 +01:00
pvizeli
bbcfb9158a fix lint 2017-03-09 12:03:08 +01:00
pvizeli
bcd4def0ae pump version 0.3 / make a lot of improvments 2017-03-09 12:00:50 +01:00
Robbie Trencheny
ddc260b628 Add required changes to support MQTT discovery that I previously missed. See #6481. 2017-03-08 23:57:54 -08:00
Robbie Trencheny
06bc062221 MQTT should load the provided platform not DOMAIN
See #6481
2017-03-08 23:53:17 -08:00
Pascal Vizeli
21f3b62d09 fix coverage 2017-03-09 01:03:15 +01:00
Pascal Vizeli
185ccc4fc4 Fix some things 2017-03-09 01:00:57 +01:00
Adam Mills
2d337fd29a Catch exceptions on kodi commands 2017-03-08 15:54:51 -05:00
Paulus Schoutsen
c625e219c7 Not always asume manufacturername is present (#6484) 2017-03-08 08:57:38 -08:00
pvizeli
b1736994b7 fix lint 2017-03-08 17:57:22 +01:00
pvizeli
21feff5fd8 add available 2017-03-08 17:52:49 +01:00
pvizeli
93118fcade Android IP Cam support 2017-03-08 17:48:55 +01:00
ArrayLabs
5e1c74b430 Update pymyq requirement (#6486)
* update pymyq to 0.0.7

* update pymyq requirement

Adds additional state for stopped door.
2017-03-08 16:47:43 +01:00
Reed Riley
3d3a0a7a4f Improved iCloud 2FA support. (#5984) 2017-03-08 12:07:34 +01:00
Colin O'Dell
fdd1957750 Allow configurable conditions for Pi-Hole sensor (#6465)
* Allow configurable conditions for Pi-Hole sensor

* Include all three conditions by default

* Share Pi-Hole API data across all sensors; eliminate redundant API calls
2017-03-07 23:20:30 -08:00
Robbie Trencheny
2b97449d98 Expand MQTT lights (#6481)
* Add effect support to MQTT Light

* Use effect state topic for supported_features

* Dont use rainbow as default color

* Add color_temp support to MQTT JSON Light

* Add effect to MQTT JSON light

* Support lights in MQTT discovery

* Allow discovered devices to set their platform

* Add white value support to MQTT Light

* Add white value support to MQTT JSON Light

* Remove blank line

* Add color_temp support to MQTT Template light

* Add white value support to MQTT Template Light

* Remove unused SUPPORT_MQTT_TEMPLATE and stale unused flash and transition code from MQTT Template

* Add XY Color to MQTT Light Platform

* Fix syntax

* Fix more syntax errors

* Revert "Remove unused SUPPORT_MQTT_TEMPLATE and stale unused flash and transition code from MQTT Template"

This reverts commit c03798cb636e6b3258fce6f676fc6ca34c9b7d37.

* MQTT Template supports flash and transition but doesnt allow templating of the values

* Add XY color support to MQTT JSON

* Proper variable names

* Only allow whitelisted MQTT platforms to be loaded via MQTT Discovery

* Minor tweaks.
2017-03-07 23:01:36 -08:00
Pascal Vizeli
c937a7bcb0 Add support for remove services / Reload script support (#6441)
* Add support for remove services / Reload script support

* Reload support for scripts

* Add more unittest for services

* Add unittest for script reload

* Address paulus comments
2017-03-07 22:51:34 -08:00
Pascal Vizeli
e7f442d66b Add dispatcher camera for internal image. (#6471)
* Add dispatcher camera for internal image.

* fix lint

* Add unittest

* Update dispatcher.py
2017-03-07 22:37:23 -08:00
siebert
2c5d3387f2 Fix wake_on_lan ping for Linux. (#6480) 2017-03-07 20:57:35 -08:00
Paulus Schoutsen
bb4f23f8e7 Add warning for slow platforms/components (#6467)
* Add warning for slow platforms/components

* Add test for slow component setup.

* Add test for slow platform setup

* Fix tests on Py34
2017-03-07 20:31:57 -08:00
Kevin Fronczak
629b2e81ba Support for Blink Camera System (#6444)
* Passing pep8, no tests yet

* Fixed some issues with the request throttling

* Removed ability to set throttle time because it was causing more issues than it was worth

* Added blink to .coveragerc

* Changed blinkpy version

* Removed global var, fixed per PR requests

* Added services for camera, migrated switch to binary_sensor

* Added schema for service, fixed naming, removed unused function
2017-03-07 23:26:53 +01:00
Johan Bloemberg
3508f74fb2 Remove connection status state. (#6475)
Current implementation of connection status doesn't follow convention and is not properly configurable. Might be added again in the future as a full fledged entity or some other way.

For now users can rely on error logging to determine connection status.
2017-03-07 23:20:27 +01:00
Kevin Siml
d16bc632da fix issue (#6470)
* fix issue

fix issue: https://community.home-assistant.io/t/error-in-new-notification-pushsafer/13308

* Update pushsafer.py

* Update requirements_all.txt

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py
2017-03-07 21:18:28 +01:00
Paulus Schoutsen
44d4987536 Allow testing against uvloop (#6468) 2017-03-07 10:11:41 +01:00
Paulus Schoutsen
470702261a Upgrade netdisco to 0.9.2 (#6466) 2017-03-06 22:35:49 -08:00
Josh Anderson
5fb7aa212b Send a logo with webostv notifications (#6380)
* Update to pylgtv 0.1.4

* Send icon with webostv notifications

Default to the homeassistant logo, but allow customizing it on the
component and for individual notifications
2017-03-06 20:56:31 -08:00
Barry Williams
9522fe3a92 Bumped version number for supporting lib (#6462) 2017-03-06 20:38:33 -08:00
Markus Peter
ff3c90fb80 KWB Easyfire support (#6018)
* KWB Easyfire Support

* requirements, coverage

* Initialization fun

* lint

* requirements bump

* lint

* Second best validation ...

* changes

* reworked validation
2017-03-06 17:37:29 +01:00
Paulus Schoutsen
90ad54da7d Shorten recorder connection init (#6432)
* Wait up to 9 seconds

* Set number of recorder retries to 8

* Do not sleep when reporting last connection error if no retries left

* Make sure we clean up old engine if connection is retrying

* Update __init__.py
2017-03-06 12:20:12 +01:00
Marcelo Moreira de Mello
2baa838ba7 Added unittest for Ring sensor (#6447)
Add an optional extended description…
2017-03-06 12:15:08 +01:00
Pascal Vizeli
a8add06a40 Bugfix samsungtv discovery (#6438) 2017-03-05 23:52:15 +01:00
Dennis de Greef
1b23b32817 Use bundled certificates if port matches mqtts (#6429)
* Use bundled certificates if port matches mqtts

* Move import requests.certs to top, since it's used in more places

* Add happy and non-happy path tests for default certificate bundle on mqtts port
2017-03-05 14:08:29 -08:00
Andrey
eaaa0442e2 Add a Z-wave workaround to do full refresh on update (#6403)
* Add Zwave refresh services

* services file

* Use dispatcher

* Add zwave prefix to signal

* Add a Z-wave workaround to do full refresh on update
2017-03-05 12:55:52 -08:00
Job Vermeulen
bc9f2d21c4 Tado device_tracker exception when mobile device has geofencing enabled but location is currently unknown. (#6401) 2017-03-05 21:38:14 +01:00
Adam Mills
1a139234af Revert "Use dynamic port allocation for tests" (#6436) 2017-03-05 21:14:21 +01:00
Andrey
d5435cf066 Rename _scheduled_update to _update_scheduled (#6434) 2017-03-05 10:53:47 -08:00
Andrey
46ec6d6dce Delay zwave updates for 100ms to group them. (#6420)
* Add Zwave refresh services

* services file

* Use dispatcher

* Add zwave prefix to signal

* Delay zwave updates for 100ms to group them.

* Fixes

* lint

* Access _scheduled_update from loop thread only.

* More async

* Some optimizations

* Fix
2017-03-05 09:29:59 -08:00
Anders Melchiorsen
660e777f01 Ignore deleted mails in IMAP unread count (#6394) (#6395)
Message deletion in IMAP is a two step process: first delete, then expunge.
Deleting a message just sets a flag that usually makes the mail client hide
the message. It is the expunge that actually removes the message.

Thus, exclude the deleted messages so that the unread count matches up with
that of most mail clients.
2017-03-05 08:15:25 -08:00
Igor Shults
de038bae65 Don't log username and password in camera url (#6390)
* Don't log username and password in camera url

* Attempt fix of tox issues

* Attempt to fix indentation issue
2017-03-05 08:07:09 -08:00
Anders Melchiorsen
7774f0ae53 Set new color before turning LIFX bulbs on (#6402)
A LIFX bulb maintains its previous color even when the light is off.
For example, if the previous color is blue and the bulb is turned on
and then set to a red color, it will transition through purple colors.

After this commit, the target color is set while the bulb is still
turned off. This overrides the previous color and brightness that the
bulb remembered. The light is then turned on with the requested
transition duration.

For the example, this gives the expected result of only going through
red colors.
2017-03-05 11:11:33 +01:00
Paulus Schoutsen
7655b6271d Better restore_state warnings (#6418) 2017-03-05 10:54:49 +01:00
Paulus Schoutsen
10bf659773 Fix unnecessary warning for ip bans.yaml (#6417) 2017-03-05 10:53:21 +01:00
Paulus Schoutsen
e8a22cb4a8 Tweak recorder/restore_state (#6412)
* Tweak recorder/restore_state

* Lint
2017-03-05 10:52:08 +01:00
Paulus Schoutsen
2650c73a89 Split bootstrap into bs + setup (#6416)
* Split bootstrap into bs + setup

* Lint
2017-03-05 10:41:54 +01:00
Thibault Cohen
bdf948d866 Add Mint finance sensor (#6132)
* Add Mint finance sensor

* Add retry

* Fix PR comments

* Upgrade mintapi version

* Update mint_finance.py

* Doc tweak

* Update mint_finance.py
2017-03-05 00:08:58 -08:00
Marcelo Moreira de Mello
928e025910 Added sensors to support Ring.com devices (#6419) 2017-03-05 00:03:00 -08:00
Teemu R
96aae1292b switch.tplink: catch exceptions coming from pyHS100 to avoid flooding the logs when the plug is not available (#6400) 2017-03-05 08:44:34 +01:00
Pascal Vizeli
c0bf3d7f32 Restore flow on device_tracker platform (#6374)
* Restore flow on device_tracker platform

* fix flow

* fix lint
2017-03-05 08:06:53 +01:00
Paulus Schoutsen
307514e3a7 Prevent more I/O in apns (#6413) 2017-03-04 19:57:04 -08:00
Paulus Schoutsen
b939626497 Fix tests no internet (#6411)
* Fix honeywell tests without internet

* Fix device tracker without internet

* Fix MFI using internet during tests

* Remove I/O from apns tests
2017-03-04 17:15:20 -08:00
Johann Kellerman
1522e67351 Restore for automation entities (#6254)
* Restore for automation entities

* coroutine

* no clue what i'm doing now

* Still passes nicely in py 3.4
2017-03-04 15:19:01 -08:00
Pascal Vizeli
8232f1ef65 Cleanup async handling (#6388)
* Cleanups unneeded blocks

* Cleanup bootstrap

* dedicated update_ha_state

* Fix imap_email_content

* fx tests

* Fix lint & spell
2017-03-04 15:10:36 -08:00
Jeremy Volkman
78f5a8a6f8 Small typo fix in setup_docker_prereqs 2017-03-04 12:39:25 -08:00
Daniel Høyer Iversen
3044aecbe9 flux led lib (#6404) 2017-03-04 21:33:24 +01:00
siebert
a5081ac307 Fix wake_on_lan for german version of Windows 10 (#6397) (#6398) 2017-03-04 09:58:01 -08:00
Lev Aronsky
f396a4593e Add keep-alive feature to the generic thermostat (#6040)
* Add keep-alive feature to the generic thermostat

* Comply with maximum line lengths

* Added tests for the keep-alive functionality
2017-03-04 09:42:43 -08:00
Andrey
aac9f972cf Add Zwave refresh services (#6377)
* Add Zwave refresh services

* services file

* Use dispatcher

* Add zwave prefix to signal
2017-03-04 09:13:24 -08:00
Thibault Cohen
aaa0944595 Add multi contracts support for Hydroquebec (#6392) 2017-03-04 09:11:58 +01:00
Paulus Schoutsen
6cca127bbf Merge pull request #6384 from home-assistant/release-0-39-3
0.39.3
2017-03-03 19:24:29 -08:00
Christiaan Blom
c1f3ce78e1 Edit docstring 2017-03-04 01:48:47 +01:00
Christiaan Blom
887b53b794 Changes for Travis bot. Unused variable 'on_ready' will likely remain reported 2017-03-04 01:31:19 +01:00
Christiaan Blom
a444df3fde tweaks 2017-03-04 01:03:10 +01:00
Christiaan Blom
b038a1650e Resolved issue #5688 2017-03-03 23:15:03 +01:00
joe248
483556ac5b Comed Hourly Pricing sensor (#6378)
* Add ComEd RRTP price sensor

* Update wording to reflect ComEd's naming change from 'RRTP' to 'Hourly Pricing'

* Changed name of sensor source file

* Cleanup based on requested changes

* More cleanup

* small cleanups
2017-03-03 23:14:22 +01:00
Paulus Schoutsen
3e9e388745 Version bump to 0.39.3 2017-03-03 13:15:07 -08:00
Colin O'Dell
ab42acf4d7 Don't initialize components which have already been discovered (#6381)
* Don't initialize components which have already been discovered (fixes #5588)

* Don't log that we've found a service unless we know it's not a duplicate

* Encode discovery data hash with JSON

This also solves the issue of trying to hash non-hashable objects like dicts

* Add test for duplicate device discovery
2017-03-03 13:13:04 -08:00
Colin O'Dell
0489ae53c4 Don't initialize components which have already been discovered (#6381)
* Don't initialize components which have already been discovered (fixes #5588)

* Don't log that we've found a service unless we know it's not a duplicate

* Encode discovery data hash with JSON

This also solves the issue of trying to hash non-hashable objects like dicts

* Add test for duplicate device discovery
2017-03-03 13:11:40 -08:00
John Mihalic
35fcc299c0 Update Hikvision Binary Sensors to latest library, remove pyDispatcher (#6231)
* Update pyHik version, remove pyDispatcher in favor of callbacks

* Fix naming

* Fix lint blank line

* Move stream thread start to HOMEASSISTANT_START event

* Bump library version to cleanup shutdown

* Fix requirements
2017-03-03 15:11:30 +01:00
Valentin Alexeev
568c549353 Update pwaqi to 3.0 to use public API (#6376)
The underlying PWAQI library version 3.0 is now using public API to
access AQICN data.
2017-03-03 14:50:54 +01:00
Paulus Schoutsen
edf130b341 Z-Wave prevent I/O event loop (#6369)
* Prevent Z-Wave I/O in event loop

* Move value_handler to util class.

* Add docstring
2017-03-03 14:47:59 +02:00
Pascal Vizeli
ed9e93c29f Migrate mqtt tracker and arwn sensor to async / cleanup owntrack (#6373)
* Migrate mqtt tracker and arwn sensor to async / cleanup owntrack

* Fix tests / lint
2017-03-03 12:09:10 +01:00
Pascal Vizeli
55f8ec8866 Fix possibility that have multible topic subscribe mqtt (#6372) 2017-03-03 10:05:52 +01:00
Pascal Vizeli
3e70154695 OwnTrack Async (#6363)
* Migrate owntrack to async

* fix tests
2017-03-03 09:23:58 +01:00
Andrey
aa17481c94 Add Z-Wave battery level as a sensor. (#6341) 2017-03-03 09:19:06 +02:00
happyleavesaoc
b53bc24a63 twilio component (#6348)
* twilio component

* add http dependency to twilio

* fire->async_fire
2017-03-03 08:14:51 +01:00
Johann Kellerman
fbd0bf77c7 [recorder] Catch more startup errors #6179 (#6192)
* [recorder] Catch more startup errors #6179

* Rebase on new recorder
2017-03-02 22:44:52 -08:00
Jose Juan Montes
4da2156ebf Return None instead of raising ValueException from as_timestamp template function. (#6155) 2017-03-02 22:18:01 -08:00
Open Home Automation
8a67fcfee3 Added IPv4 data collector (#6304)
* Added IPv4 data collector

* Formatting

* Bugfix: data is in kBit/s not kByte/s
2017-03-02 22:16:50 -08:00
Pascal Vizeli
08f9793175 Restore for input_slider (#6360) 2017-03-02 08:36:26 -08:00
Pascal Vizeli
a5b2fc9759 Bugfix new async_add_devices function (#6362) 2017-03-02 17:27:45 +01:00
Micha LaQua
3fa8aff78e snmp: upgrade pysnmp to 4.3.4 (#6359)
* snmp: upgrade pysnmp to 4.3.4

fixes https://github.com/home-assistant/home-assistant/issues/6238

* snmp: v4.3.4: add missing definition changes
2017-03-02 16:12:44 +01:00
Rowan
09ff9cb08e Updated to catch timeout error 2017-03-02 14:58:35 +00:00
Jan Losinski
c32300a386 Bump limitlessled dependency to 1.0.5. (#6334)
This fixes issue #6295.
2017-03-02 14:18:44 +01:00
Pascal Vizeli
55dc483c91 Template switch change flow / add restore (#6356)
* Template switch change flow / add restore

* fix tests

* fix binary_sensor template
2017-03-02 14:09:53 +01:00
Andrey
597ae2e716 Zwave: Add remove/replace failed node services. (#6248)
* Zwave: Add remove/replace failed node services.

* Fix text
2017-03-02 12:36:40 +01:00
Pascal Vizeli
50887e7e2c Move dispatcher out of init. (#6355) 2017-03-02 10:20:57 +01:00
Alan Fischer
8743f23f13 Fix calendar authentication text, and handle calendar events without summaries. (#6337)
* Fixed google authorization text

* Let calendar handle events without a summary
2017-03-02 00:22:38 -08:00
Jeff Wilson
72fe50bef6 Fix command sudo not found error in dev Dockerfile (#6346) 2017-03-02 00:14:20 -08:00
Pierre Ståhl
bae6333c26 Use push updates in Apple TV (#6323)
* Use push updates in Apple TV

* Fix review comments
2017-03-02 00:12:55 -08:00
martinfrancois
a08539d88d Added support for multiple codes executed in a row (#5908)
* Added support for multiple codes executed in a row

now codes can be specified either by simply providing a single code, which will then be sent like usual, or multiple codes can be executed in a row, specified in a comma delimited format in the configuration.yaml. For example: 111111,222222,333333,444444 would mean 111111 would be sent first, followed by 222222 and 333333 and 444444.

* rpi_rf: added line breaks to not exceed 79 characters per line

* include validation for correct formatting of codes

added regex which only allows either a single number (like 1252456245) or a sequence of commas followed by another number.

* added line breaks to not exceed 79 characters per line

* fix for 'continuation line under-indented for visual indent'

* another try at 'continuation line under-indented for visual indent'

* changed from regex to list for easier maintainability

* removed unnecessary splitting of strings
2017-03-02 00:10:49 -08:00
Adam Mills
bf7aecce90 Use dynamic ports for test instances (#6232) 2017-03-02 00:07:50 -08:00
Paulus Schoutsen
e2aa024a05 Update coveragerc 2017-03-02 00:06:26 -08:00
dramamoose
edd5db296d Update Formulas in Convert XY to RGB (#6322)
* Update to Current RGB D65 Conversion

As per Philips Hue https://developers.meethue.com/documentation/color-conversions-rgb-xy

* Update the source of the XYZ to RGB formulas

* Fix Whitespace

* Update Whitespace

* Update Tests for new Formulas

* Update Tests

* Update XY_Brightness_to_hsv tests

* Update test_color.py
2017-03-02 08:54:45 +01:00
Duoxilian
e14d6f11c6 Additional support for ecobee hold mode (#6258)
* Integrate suggestion in #5590 by nordlead2005. This change has been
sitting in limbo for over a month, but it is a good idea. I don't
mean to step on nordlead2005's toes, but we need to make progress.

* Use defined constant for TEMPERATURE_HOLD

* Integrate handling of vacation into hold mode. Canceling vacation
hold requires an update to the external pyecobee library. Creation
of vacation is not supported (it would be straightforward in the code,
but a complex user interface would be required, similar to what is
now done in the ecobee thermostat).

* Add capability to retrieve list of defined climates from ecobee.

* The mode() method used to return the system mode in internal
representation. However, the user sees a different notation in
the ecobee thermostat. Seeing some internal name is particularly
weired with user-defined climates, where these are named "smart1",
"smart2", etc., instead of the name the user has defined. Return
the user-defined name instead. This change might break some user
interfaces but is easily remedied (e.g., use "Away" instead of
"away").

* Simplify is_away_mode_on().

* Correction of erroneously indented else statement.

* Change comment as flake8 gets confused.
2017-03-01 23:52:31 -08:00
Pascal Vizeli
f3870a8a48 Template binary_sensor change flow / add restore (#6343)
* Template binary_sensor change flow / add restore

* fix lint
2017-03-02 08:50:41 +01:00
Thibault Cohen
31bf5b8ff0 Improve Honeywell US climate component (#5313)
* Improve Honeywell US climate component

* Fix tests

* Fix tests

* Add cool_away_temp and heat_away_temp for honeywell US

* Fix honeywell tests

* Fix PR comments
2017-03-01 23:49:49 -08:00
Paulus Schoutsen
a7ae456a06 Merge remote-tracking branch 'origin/master' into dev 2017-03-01 23:44:11 -08:00
Reed Riley
c03022efa3 Add fallback for name if userdevicename isn't set using old serialnumber logic (#6265)
Add an optional extended description…
2017-03-02 08:41:31 +01:00
Mitko Masarliev
46f5a65e68 Update Adafruit_Python_DHT to support new raspberry kernel (#6325)
* Update Adafruit_Python_DHT to support new raspberry kernel

* update Adafruit Python DHT
2017-03-02 08:39:33 +01:00
Alexander Fortin
44ec6b056e Update Vagrant provision.sh (#6236)
- Bugfix: with f63a79ee we removed `script/home-assistant@.service`
  systemd unit file, which is used by Vagrant box to start/stop hass
- simplify interaction with Vagrant, provision.sh now is the only
  entry point and doesn't need the user to touch/remove files in
  order to change provisioner behavior
2017-03-01 23:15:30 -08:00
Andrey
354007f265 Zwave optimize value_added (#6210)
* Make zwave devices listen on less network changes.

* Convert more platforms

* Remove printouts.

* Fix copy-paste

* Change default dependent list to empty list
2017-03-01 22:41:19 -08:00
Pascal Vizeli
6cb8a36cf1 Template sensor change flow / add restore (#6336) 2017-03-02 07:38:19 +02:00
Fabian Affolter
435f253be8 Upgrade py-cpuinfo to 0.2.6 (#6335) 2017-03-02 05:58:03 +01:00
Fabian Affolter
0fe41ffb00 Upgrade TwitterAPI to 2.4.5 (#6351) 2017-03-02 05:57:51 +01:00
Martin Hjelmare
bafa0cc3b8 Fix mysensors callback race (#6311)
* Fix possible race at startup in mysensors callback

* Update devices via persistence before starting gateway to avoid
  two threads calling the same callback at the same time.

* Call add_devices max once per callback
2017-03-01 23:09:27 +01:00
Erik Eriksson
e23aa1ccf8 sensor.dovado: compute state in update (#6340) 2017-03-01 22:57:37 +01:00
Paulus Schoutsen
a9db6b16eb Merge pull request #6339 from home-assistant/release-0-39-2
0.39.2
2017-03-01 12:43:00 -08:00
Paulus Schoutsen
bf30f2e9e8 Version bump to 0.39.2 2017-03-01 09:29:34 -08:00
Paulus Schoutsen
ee9d50c0a5 Bump netdisco to 0.9.1 (#6338) 2017-03-01 09:29:14 -08:00
Paulus Schoutsen
6736534a52 Discovery fix (#6321)
* Fix incorrect import

* Create own discovery service

* Fix tests

* Fix hdmi_cec bad import
2017-03-01 09:28:49 -08:00
Paulus Schoutsen
4ccd819ec5 Bump netdisco to 0.9.1 (#6338) 2017-03-01 09:05:05 -08:00
Pascal Vizeli
52b1e13aca Bugfix ZigBee / Move from eventbus to dispatcher (#6333)
* Bugfix ZigBee / Move from eventbus to dispatcher

* fix lint
2017-03-01 08:57:53 -08:00
Pascal Vizeli
67f3910f03 Bugfix ZigBee / Move from eventbus to dispatcher (#6333)
* Bugfix ZigBee / Move from eventbus to dispatcher

* fix lint
2017-03-01 08:57:23 -08:00
Paulus Schoutsen
64cb3390ea Test against 3.6-dev (#6324) 2017-03-01 08:53:40 -08:00
Paulus Schoutsen
0ac4a152be Discovery fix (#6321)
* Fix incorrect import

* Create own discovery service

* Fix tests

* Fix hdmi_cec bad import
2017-03-01 07:38:49 -08:00
Pascal Vizeli
4e96e461f7 Cleanup component track_point_in_utc_time usage (#6330) 2017-03-01 07:37:48 -08:00
Stefano Scipioni
30bed8341a Telegram webhooks new text event (#6301)
* new TELEGRAM_TEXT

* telegram command event renamed in 'telegram_command'

* fire telegram_text event anyway
2017-03-01 12:15:16 +01:00
Erik Eriksson
d17733427b Merge pull request #6329 from molobrakos/dovado
sensor.dovado: Upgraded library version
2017-03-01 12:02:58 +01:00
Erik Eriksson
782d2a30cd Merge pull request #6328 from molobrakos/eliqonline
sensor.eliqonline: Change to more appropriate icon
2017-03-01 11:52:44 +01:00
Paulus Schoutsen
84f30d9ef8 Bootstrap tweaks tests (#6326)
* Update strings/fix component not found message.

* Fix tests

* More tweak text
2017-02-28 23:42:31 -08:00
Johann Kellerman
ac49298c8d Log errors when loading yaml (#6257) 2017-03-01 06:56:23 +02:00
jumpkick
a0256e1947 Rollback netdisco to 0.8.2 to resolve #6165 (#6314)
* Rollback netdisco to 0.8.2 to resolve #6165

* Rollback netdisco to 0.8.2 to resolve #6165
2017-02-28 20:37:56 -08:00
ericgingras
7bc2e1238d Convert kpH and mpH to kph and mph (#6316)
There is no reason for the H to be capitalized. Changing it to lowercase increases consistency with other components and allows for use of the min/max sensor, which throws an error if the units of measurement are not the same.
2017-03-01 05:34:40 +01:00
Pascal Vizeli
41f558b181 Bootstrap / Component setup async (#6264)
* Bootstrap / Entiy setup async

* Cleanup add_job stuff / return task/future object

* Address paulus comments / part 1

* fix install pip

* Cleanup bootstrap / move config stuff to config.py

* Make demo async

* Further bootstrap improvement

* Address Martin's comments

* Fix initial tests

* Fix final tests

* Fix bug with prepare loader

* Remove no longer needed things

* Log error when invalid config

* More cleanup

* Cleanups platform events & fix lint

* Use a non blocking add_entities callback for platform

* Fix Autoamtion is setup befor entity is ready

* Better automation fix

* Address paulus comments

* Typo

* fix lint

* rename functions

* fix tests

* fix test

* change exceptions

* fix spell
2017-02-28 20:33:19 -08:00
Adam Mills
383b0914b3 Version bump to 0.40.0.dev0 2017-02-28 11:01:19 -05:00
Krasimir Zhelev
be297c4c7e Frontier silicon (#6131)
* added frontier_silicon constant

* added the frontier_silicon component

* cleaning up according to travis

* trying to satisfy pylint

* trying to satisfy pylint

* fsapi version 0.0.6

* with fsapi version 0.0.7

* added fsapi dependency

* yielding the FSAPI

* Removing white space from docstring

* Removing white space from an empty line

* Switching to sync

* clean up white spaces and rename device to FSAPIDevice

* added frontier_silicon constant

* added the frontier_silicon component

* cleaning up according to travis

* trying to satisfy pylint

* trying to satisfy pylint

* fsapi version 0.0.6

* with fsapi version 0.0.7

* added fsapi dependency

* yielding the FSAPI

* Removing white space from docstring

* Removing white space from an empty line

* Switching to sync

* clean up white spaces and rename device to FSAPIDevice

* changed info to debug

* added frontier_silicon constant

* added the frontier_silicon component

* cleaning up according to travis

* trying to satisfy pylint

* trying to satisfy pylint

* fsapi version 0.0.6

* with fsapi version 0.0.7

* added fsapi dependency

* yielding the FSAPI

* Removing white space from docstring

* Removing white space from an empty line

* Switching to sync

* clean up white spaces and rename device to FSAPIDevice

* added the frontier_silicon component

* trying to satisfy pylint

* fsapi version 0.0.6

* remove white space

* generated requirements

* added the frontier_silicon component

* cleaning up according to travis

* trying to satisfy pylint

* trying to satisfy pylint

* fsapi version 0.0.6

* with fsapi version 0.0.7

* added fsapi dependency

* yielding the FSAPI

* Removing white space from docstring

* Removing white space from an empty line

* Switching to sync

* clean up white spaces and rename device to FSAPIDevice

* trying to satisfy pylint

* changed info to debug

* added the frontier_silicon component

* fsapi version 0.0.6

* generated requirements

* pylint

* moved import requests to the method where it is being used

* add a basic unit test

* cleaned up source code

* added frontier_silicon constant

* added the frontier_silicon component

* added basic test

* added fsapi to requirements_all.txt

* added coverage omit, though a basic test was included

* added MEDIA_TYPE_MUSIC for artist and album

* removed duplicate cons

* switched fsapi call to a property, removed unecessary comment

* detailed docstring for fs_device

* added a space for the info_name - info_text separator

* reduced proeprty (fsapi) access for volume down/up
2017-02-28 09:23:07 -05:00
Pascal Vizeli
aa1f64bed6 Migrate calendar setup to async. (#6305) 2017-02-28 10:49:06 +01:00
Adam Mills
faf8bbcf13 Fix toggle and media_play_pause post async (#6291) 2017-02-27 19:55:34 -08:00
Open Home Automation
0fa259089d Influx fix (#6289)
* Fix: replace influxdb query by another query that is more lightweight and won't timeout

* Fix: replace influxdb query by another query that is more lightweight and won't timeout
2017-02-27 19:54:43 -08:00
Alan Fischer
f7c7073cd7 Updated pyitachip2ir (#6296)
* Updated pyitachip2ir

* Updated requirements_all.txt
2017-02-27 19:52:32 -08:00
Boris K
d7bf3920a5 improve history_stats accuracy (#6294) 2017-02-27 19:52:10 -08:00
Andrey
7ee75d67c5 Add temperature support for MH-Z19 CO2 sensor. (#6169)
* Add temperature support for MH-Z19 CO2 sensor.

* Remove debug printout

* More tests

* Minor fixes
2017-02-27 21:19:11 +02:00
arjenfvellinga
d7db3aba36 Prevent duplicate names on Vera devices by appending the device id (#6100)
* Prevent duplicate names by prepending device id to it.

* Always append device id, not conditionally.

* Moved naming of devices

* flake8
2017-02-27 18:57:39 +00:00
Lindsay Ward
7f99e99dad Update library version for Yeelight Sunflower lights platform (fix for packaging problem with 0.0.7) (#6233) 2017-02-27 13:47:51 -05:00
Greg Dowling
fbea5b4cac Merge pull request #6278 from home-assistant/fix_vera_thormostat_bug
Fix vera thermostat bug
2017-02-27 10:55:33 +00:00
Daniel Perna
e6c88c05ad [sensor.dnsip] New Sensor: DNS IP (#6214)
* Added DNS IP sensor

* Removed unused import

* Added coverage

* fixed flake

* Applied suggested changes

* Removed debug code

* Switched to aiodns

* Raised scan interval

* Updating state with entity creation

* Lint

* Updated requirements_all
2017-02-27 10:45:32 +00:00
pavoni
757813411d Fix vera thermostat mode set bug 2017-02-27 10:18:22 +00:00
TimV
7dc05785cc Analog modem callerid support (#5840)
* analog-modem-callerid

* analog-modem-callerid

* analog-mod

* Updates from latest review

* Updates from latest review
2017-02-26 21:38:47 -08:00
Wolf-Bastian Pöttner
d7af43b87d Add support for MAX!Cube thermostats and window shutter sensors (#6105) 2017-02-26 21:35:33 -08:00
groth-its
6ea74ce740 Fix for OSRAM lights connected to hue bridge (#6122)
* Fix for OSRAM lights connected to hue bridge

Do not send command "effect = none" to OSRAM lights
Osram lights connected to a hue bridge do not seem to handle "effect =
none" very well. Most of the times they jump to the selected color and
then change to red within a second.

Osram lights connected to a hue bridge do not handle xy values outside
of their gamut. Since they just stay at their old color value, handling
the UI is very unpredictable. Sending HSV values to the lights fixes this.

* Add tests for new util methods
2017-02-26 21:28:31 -08:00
Nate
d5bdf7783e light.transition now supports float instead of int in order to be able to perform faster transitions (#6163) 2017-02-26 21:21:12 -08:00
Jose Juan Montes
65d255a626 Local file camera now supports yet inexisting files. (#6157) 2017-02-26 21:16:11 -08:00
Jeff Wilson
53a735a329 Properly report features for each hue bulb type (#6271) 2017-02-26 20:59:23 -08:00
Paulus Schoutsen
68713822fd Merge pull request #6272 from home-assistant/release-0-39-1
0.39.1
2017-02-26 20:48:57 -08:00
Pascal Vizeli
3d26ac3323 Bugfix mqtt paho client to speend time (#6266) 2017-02-26 20:31:11 -08:00
Paulus Schoutsen
d487960ad8 Config fix (#6261) 2017-02-26 20:31:11 -08:00
Pascal Vizeli
9403cdd2a5 Bugfix mqtt socket error (#6256) 2017-02-26 20:31:11 -08:00
Paulus Schoutsen
1fb1a32c9a Version bump to 0.39.1 2017-02-26 20:30:21 -08:00
Pascal Vizeli
31ddcc6278 Bugfix mqtt paho client to speend time (#6266) 2017-02-26 15:28:54 -08:00
Paulus Schoutsen
d789de9ea2 Config fix (#6261) 2017-02-26 15:28:12 -08:00
Scott Henning
e2014eb153 Notify ciscospark (#6130)
* Adding ciscospark notifier

* Adding ciscospark notifier

* CI cleanup.

* houndci-bot changes

* ok --- a bunch of code verify changes
2017-02-26 15:04:30 -08:00
Pascal Vizeli
5932446508 Bugfix mqtt socket error (#6256) 2017-02-26 14:43:02 -08:00
Paulus Schoutsen
61909e873f Feature/reorg recorder (#6237)
* Re-organize recorder

* Fix history

* Fix history stats

* Fix restore state

* Lint

* Fix session reconfigure

* Move imports around

* Do not start recording till HASS started

* Lint

* Fix logbook

* Fix race condition recorder init

* Better reporting on errors
2017-02-26 14:38:06 -08:00
Pascal Vizeli
48cf7a4af9 Move ffmpeg to dispatcher from hass.data entity store. (#6211)
* Move ffmpeg to dispatcher from hass.data entity store.

* fix lint

* address paulus comments

* add more unittest for better coverage
2017-02-26 14:31:46 -08:00
Pierre Ståhl
9490cb4c8f Add service to change log levels (#6221)
* Add service to change log levels

* Fix review comments
2017-02-26 14:15:44 -08:00
Paulus Schoutsen
86d4d10176 Ensure we properly close HASS instances. (#6234) 2017-02-26 14:05:18 -08:00
Philipp Schmitt
7b3b755aaf Fix livebox-play interactions for Python < 3.6 (#6243) 2017-02-26 14:04:22 -08:00
Paulus Schoutsen
f5a1cd5b3c Merge pull request #6229 from home-assistant/release-0-39
Fix recorder async (#6228)
2017-02-25 15:23:55 -08:00
Paulus Schoutsen
7b9f7889d2 Fix recorder async (#6228) 2017-02-25 15:22:23 -08:00
Paulus Schoutsen
9afcbaed1d Fix recorder async (#6228) 2017-02-25 15:21:40 -08:00
Paulus Schoutsen
58f9455604 Merge pull request #6227 from home-assistant/release-0-39
Release 0 39
2017-02-25 15:04:54 -08:00
Paulus Schoutsen
596f7b99f6 Update frontend 2017-02-25 15:03:54 -08:00
Johann Kellerman
94183e1992 No wait for start and more async 2017-02-25 15:03:54 -08:00
Johann Kellerman
0e5df9b641 Allow 4.5min startup time for recorder 2017-02-25 15:03:54 -08:00
Paulus Schoutsen
3a7cc9bb45 Update frontend 2017-02-25 15:03:24 -08:00
Paulus Schoutsen
ecd1da6525 Merge pull request #6167 from kellerza/recorder_timer
Recorder async & remove start_recording event
2017-02-25 15:01:29 -08:00
Paulus Schoutsen
a19a285bb0 Merge pull request #6199 from home-assistant/release-0-39
0.39
2017-02-25 14:36:17 -08:00
Andrey
eb36174b51 Make glob preserve order (#6224) 2017-02-25 14:35:27 -08:00
Fabian Affolter
6e51f7d987 Update regex (#6216) 2017-02-25 14:35:27 -08:00
Lindsay Ward
4ba9020859 Update Yeelight Sunflower light platform to 0.0.6 (#6208)
Add an optional extended description…
2017-02-25 14:35:27 -08:00
Paulus Schoutsen
505725f9d3 Fix reporting on bad login (#6201) 2017-02-25 14:35:27 -08:00
Paulus Schoutsen
2566d01aaa Remove automatically reloading group config (#6197) 2017-02-25 14:35:27 -08:00
Johann Kellerman
477f621705 Bugfix restore startup state (#6189) 2017-02-25 14:35:27 -08:00
Pascal Vizeli
7fcc3ae00a Refactory of envisalink (#6160)
* Refactory of envisalink

* remove event buss

* init dispatcher from hass.

* Move platform to new dispatcher

* fix lint

* add unittest & threadded functions

* fix copy & past error
2017-02-25 14:35:27 -08:00
Fabian Affolter
9f2719bb1f Update regex (#6216) 2017-02-25 12:55:01 -08:00
Andrey
85d0f2e861 Make glob preserve order (#6224) 2017-02-25 12:54:04 -08:00
Paulus Schoutsen
a44d849405 Version bump to 0.39 2017-02-25 12:53:23 -08:00
Johann Kellerman
5d007e636b No wait for start and more async 2017-02-25 17:51:37 +02:00
Johann Kellerman
7cd6f9038c Allow 4.5min startup time for recorder 2017-02-25 17:28:53 +02:00
Fabian Affolter
a80fd2f243 Fix link (#6219) 2017-02-25 13:24:43 +01:00
Erik
2487d27c45 sensor.eliqonline: Change icon 2017-02-25 12:51:48 +01:00
Erik
be7162a0df sensor.dovado: Upgraded library version 2017-02-25 12:50:10 +01:00
Andrey
c5a8372f13 Update flake8 and pylint to latest (#6217) 2017-02-25 09:44:22 +01:00
Pascal Vizeli
81ca978413 Move mqtt from eventbus to dispatcher / add unsub for dispatcher (#6206)
* Move mqtt from eventbus to dispatcher / add unsub for dispatcher

* Fix lint

* Fix test

* Fix lint v2

* fix dispatcher_send
2017-02-24 17:11:50 -08:00
Paulus Schoutsen
d6818c7015 Fix reporting on bad login (#6201) 2017-02-24 16:33:58 -08:00
Greg Dowling
df5866dd95 Merge pull request #6213 from home-assistant/bump_pyloopenergy
Bump pyloopenergy - catch socketIO exceptions.
2017-02-24 22:16:03 +00:00
pavoni
34ee2b1ae9 Bump pyloopenergy - catch socketIO exceptions. 2017-02-24 22:04:41 +00:00
Zac Hatfield Dodds
8ca897da57 Zamg weather (#5894)
* Fast & efficient updates for ZAMG weather data

ZAMG updates on the hour, so instead of checking every half-hour we can
check each minute - only after the observations are taken until
receiving them.

* sensor.zamg: test instead of whitelist for station_id

* Autodetect closest ZAMG station if not given

* ZAMG weather component, based on the sensor

* Review improvements

* Update to new ZAMG schema, add logging

Turns out it wasn't a typo, but rather an upstream schema change.  Added
better error handling to ease diagnosis in case it happens again.

* No hardcoded name
2017-02-24 22:45:46 +01:00
Lev Aronsky
c7fcd98cad Test the temperature returned by RM2 (#6205)
* Test the temperature returned by RM2
* Validate fields via voluptuous
* Fixed range for humidity
2017-02-24 20:54:31 +01:00
Erik Eriksson
8aa3124aa6 sensor.speedtest: provide a default icon (#6207) 2017-02-24 18:40:52 +01:00
Andrey
b27ba9660b Some zwave cleanup (#6203) 2017-02-24 16:17:27 +02:00
Lindsay Ward
9f04b55572 Update Yeelight Sunflower light platform to 0.0.6 (#6208)
Add an optional extended description…
2017-02-24 14:13:55 +01:00
Daniel Høyer Iversen
c4f4a9a158 minor broadlink fix (#6202) 2017-02-24 09:49:42 +01:00
Paulus Schoutsen
e2e8b43902 Default config to setup group editor (#6198) 2017-02-23 22:53:16 -08:00
Paulus Schoutsen
3a35642dc1 Remove automatically reloading group config (#6197) 2017-02-23 22:40:21 -08:00
Paulus Schoutsen
34a7aa2376 Extend test for group config 2017-02-23 21:57:48 -08:00
Paulus Schoutsen
58eb32bce4 Random test fixes (#6195)
* Store persistent errors in hass (speeds up tests)

* Fix sleepiq test dependency on test order

* Fix sleepiq validation
2017-02-23 21:44:47 -08:00
Johann Kellerman
c940d26f07 Bugfix restore startup state (#6189) 2017-02-23 20:06:21 -08:00
jumpkick
fc5e25a07b Incorporate comment suggestions
- Separate attribs from coffeemaker condition
- Set power units for threshold to mW to be consistent with others
- Adjust on-time labels to be more clear
2017-02-23 18:03:49 -05:00
Andrey
1d32bced1c Create zwave devices on OZW thread and only add them during discovery (#6096)
* Create zwave devices on OZW thread and only add them during discovery.

* Read and write devices dict from loop thread.

* More async

* replace callback with coroutine

* import common function instead of callin git
2017-02-23 13:06:28 -08:00
Pascal Vizeli
f2a2d6bfa1 Refactory of envisalink (#6160)
* Refactory of envisalink

* remove event buss

* init dispatcher from hass.

* Move platform to new dispatcher

* fix lint

* add unittest & threadded functions

* fix copy & past error
2017-02-23 13:02:56 -08:00
Colin O'Dell
4f990ce488 Use H2 headers to split up the different sections (#6183)
Using headers makes it easier to visually differentiate between the different sections
2017-02-23 12:58:18 -08:00
Pascal Vizeli
106b7a9d8f Cleanup run_callback_threadsafe (#6187)
* Cleanup run_callback_threadsafe

* fix spell

* Revert image_processing, they need to wait for update
2017-02-23 12:57:25 -08:00
Pascal Vizeli
1cd1facbd0 Add device_class to image_processing (#6186)
* Add image_processing device_class

* Fix comments

* address comments
2017-02-23 17:33:54 +01:00
Pascal Vizeli
b725eaf67f Homematic icon map / upper case on services (#6178)
* Set upper on service / add sensor icon mapper

* Add more icons

* fix id
2017-02-23 15:31:32 +01:00
Colin O'Dell
89807f24ad QNAP update (#6182)
* Bump qnapstats library to 0.2.3

* Expose the new timeout setting

* Show persistent notification if QNAP fails to set up

This sitaution will usually occur if the server configuration is wrong or the
timeout is set too low.  In both cases `api.update()` will fail, which is a
problem because we cannot initialize many of the sensors without having this
data.

* Add new system_temp condition to QNAP sensor
2017-02-23 15:01:25 +01:00
Erik Eriksson
7935c54420 's' is SI symbol for seconds (#6181) 2017-02-23 14:57:51 +01:00
Erik Eriksson
46d0d38444 Merge pull request #6180 from home-assistant/molobrakos-patch-1
volvooncall: icon and unit were mixed
2017-02-23 13:28:03 +01:00
Erik Eriksson
5da110d764 volvooncall: icon and unit were mixed 2017-02-23 13:27:17 +01:00
Erik Eriksson
c88527ce79 Merge pull request #6177 from molobrakos/volvooncall
volvooncall: support for naming vehicle and selecting what attributes to display
2017-02-23 13:00:11 +01:00
Erik Eriksson
6127173d2a cache name in entity so we can display it even if the connection is lost (#6176)
update tellduslive dependency
check return value from update
2017-02-23 12:37:25 +01:00
Erik
1c6ba989a9 Support for naming vehicle. Support for selecting what resources to display 2017-02-23 12:00:51 +01:00
Erik Eriksson
827e3c4395 Merge pull request #6162 from molobrakos/nut
sensor.nut: Handle multiple statuses returned
2017-02-23 11:56:25 +01:00
Pierre Ståhl
eefedaf332 Make it possible to ignore platforms in discovery (#6048)
* Make it possible to ignore platforms in discovery

* Add tests for discovery component

* small cleanups
2017-02-23 11:54:35 +01:00
Fabian Affolter
ac1e811dcd Upgrade slacker to 0.9.42 (#6173) 2017-02-23 10:56:35 +01:00
Fabian Affolter
49b4cd3c41 Upgrade fuzzywuzzy to 0.15.0 (#6175)
Add an optional extended description…
2017-02-23 10:56:00 +01:00
jumpkick
ef87d4dad4 Update device_state_attributes only
This gets rid of the other stuff and just updates device_state_attributes, leaving the default properties alone.
2017-02-23 04:54:09 -05:00
Barry Williams
960af20cc9 Added Openhome Support (#6153)
* Added Openhome Support

* added to coveragerc

* PR suggestions

* revert accidental deletion

* More PR suggestions and a lint fix

* Removed semicolons
2017-02-22 17:01:06 -05:00
Daniel Høyer Iversen
6c91e04852 Refactor broadlink (#6168)
* refactor broadlink

* typo
2017-02-22 22:11:49 +01:00
Johann Kellerman
74837dbf45 Restore for device_tracker (#6150) 2017-02-22 22:55:11 +02:00
Erik Eriksson
3b693d5e70 generic camera: improved exception handling (#6158)
Avoid unhandled exception and stack trace when server closes connection by changing from handle ClientDisconnectedError to DisconnectedError. Also added HttpProcessingError, which was missing.
2017-02-22 07:43:52 -08:00
Erik
23dd76cdc5 Handle UPS:es that returns more than one status (e.g. 'OL CHRG'). 2017-02-22 14:38:00 +01:00
Greg Dowling
896e0476ff Bump pywemo version. Improves notifications for insight devices. (#6159)
Add an optional extended description…
2017-02-22 12:23:25 +01:00
Pascal Vizeli
b0d3bbed79 Convert mqtt platforms to async (#6145)
* Convert mqtt platforms to async

* fix lint

* add more platforms

* convert mqtt_eventstream

* fix lint / add mqtt_room

* fix lint

* fix test part 1

* fix test part 2

* fix out of memory bug

* address comments
2017-02-22 09:43:22 +01:00
Erik Eriksson
65ed85c6eb volvooncall: fix missing property. see vehicle when discovered. (#6144) 2017-02-22 00:24:42 -08:00
Johann Kellerman
aee8758fc1 Restore input_select and test helper proposal (#6148)
* Restore input_select and test helper proposal

* DB still active
2017-02-22 00:15:48 -08:00
Pascal Vizeli
8983b826c4 Bugfix automation state linsteners (#6120)
* Bugfix automation state linsteners

* address paulus comments.

* fix lint

* fix lint v2
2017-02-22 00:02:37 -08:00
Johann Kellerman
11d3093a30 Restore: migrate fastdotcom and speedtest to restore (#6149) 2017-02-21 18:10:09 -08:00
Erik Eriksson
15e8a22100 dovado: GiB -> GB (#6143) 2017-02-21 18:54:20 -05:00
Pascal Vizeli
10fb30e924 Update jinja to 2.9.5 (#6146) 2017-02-21 09:05:44 -08:00
Justin Dray
b7b1429ac7 Add support for waking up Samsung TVs over the network (#6114)
* Add support for waking up Samsung TVs over the network

* Return the correct supported features for samsungtv

* Update requirements_all
2017-02-21 16:57:29 +01:00
Daniel Høyer Iversen
9f4a9585d2 miflora lib version (#6142) 2017-02-21 14:43:17 +01:00
Lev Aronsky
c1be5ede1c Add 'entity_picture' to Darksky component (#6141) 2017-02-21 00:01:44 -08:00
David McNett
3beb87c54d New component 'insteon_plm' and related platforms (#6104)
* Connect to PLM and process simple protocol callbacks

* Baseline commit

* Connect to PLM and process simple protocol callbacks

* Baseline commit

* Connection working again

* Async add devices is working via callback now

* Beginning to interface with PLM library for control and state

* Deal with brightness in 255 levels with library

* Change sub names to match API changes

* Remove PLM-level update callback

* Support dimmable based on underlying PLM device attributes

* Expand to non-light platforms

* Stubs for turn on and off

* Current version of Python library

* Amend to use switch device attributes

* Use asyncio endpoints for control

* Add logging line

* Bump module version to 0.7.1

* Auto-load platforms, display device info/attributes

* Unify method name for getting a device attribute

* Require Current version of insteonplm module

* Import the component function in each platform in the balloob-recommend manner

* For consistency, handle switch state as onlevel just like lights

* Use level 0xff for on state, even with binary switches

Observing the behavior of a 2477S switch, it looks like even the non-dimmable
devices use 0x00 and 0xff for off/on respectively.  I was using 0x01 for on
previously, but that yields unnecessary state change callbacks when message
traffic ends up flipping the onlevel from 0xff to 0x01 or 0x01 to 0xff.

* Use sensorstate attribute for sensor onoff

* Move new device callback to devices attribute

* Add support for platform override on a device

* Bump version of insteonplm module

* Default overrides is an empty list

* Avoid calling private methods when doing common attributes

* Remove unused CONF_DEBUG for now

* flake8 and pylint code cleanup

* Move get_component to local function where it is needed

* Update to include insteonplm module.

* New files for insteon_plm component

* Legitimate class doctring instead of stub

* Docstring changes.

* Style changes as requested by @SEJeff

* Changes requested by @pvizeli

* Add @callback decorator to callback functions

* Opportunistic platform loading triggered by qualifying device detection

Instead of loading all the constituent platforms that comprise the insteon_plm
component, instead we defer and wait until we receive a callback for a device
that requires the platform.
2017-02-21 08:53:39 +01:00
Johann Kellerman
fdc373f27e Restore_state helper to restore entity states from the DB on startup (#4614)
* Restore states

* feedback

* Remove component move into recorder

* space

* helper

* Address my own comments

* Improve test coverage

* Add test for light restore state
2017-02-20 23:40:27 -08:00
Matt N
2b9fb73032 zoneminder: Add camera mjpeg stream support (#6098) 2017-02-20 22:17:11 -08:00
Paulus Schoutsen
36cda8c6b2 Merge remote-tracking branch 'origin/master' into dev 2017-02-20 21:57:37 -08:00
Paulus Schoutsen
041f1edd35 Update frontend 2017-02-20 21:56:38 -08:00
Paulus Schoutsen
32873508b7 Add initial group config (#6135) 2017-02-20 21:53:55 -08:00
Paulus Schoutsen
addd955a6b Version bump to 0.38.4 (#6137) 2017-02-20 21:52:36 -08:00
Paulus Schoutsen
022afcf050 Merge pull request #6136 from home-assistant/release-0-38-4
0.38.4
2017-02-20 21:50:00 -08:00
Paulus Schoutsen
7ce2b9e018 Update frontend 2017-02-20 21:35:10 -08:00
Paulus Schoutsen
f256d1fe2f Bump netdisco to 0.8.3 2017-02-20 21:30:38 -08:00
Pascal Vizeli
1910440a3c Update aiohttp to 1.3.3 (#6129) 2017-02-20 21:29:38 -08:00
Lewis Juggins
1d4c3febee [google] suppress file_cache warning (#6128) 2017-02-20 14:14:45 -08:00
Pascal Vizeli
1d7ab0fa95 Cleanup some async stuff (#6127)
* Cleanup some async stuff

* change to schedule_update_ha_state()

* fix media player

* fix zigbee
2017-02-20 13:24:03 -08:00
Stefano Scipioni
14cf5b884b fixed error caused by POST call with no 'message' inside (for example… (#6038)
* fixed error caused by POST call with no 'message' inside (for example in edited messages)

* avoid assert
2017-02-20 21:15:45 +01:00
arraylabs
3d34368e6e myq cover support gates (#6123)
* update myq to 0.0.6

* update req to 0.0.6

Adds support for gates
2017-02-20 18:25:29 +01:00
Pascal Vizeli
e425801fe0 Homematic cleanup & hass best praxis (#6121) 2017-02-20 17:07:33 +01:00
John Arild Berentsen
73a4c09597 Set configurable refresh for zwave light to 5 seconds default. (#5957)
* Set configurable refresh value delay to 5 seconds

* Revert "Remove configurable refresh value delay, and fix it to 5 seconds"

This reverts commit edc2dc35d165e5e13b0f3cf4df40493a7ce764f1.

* Use default value of 5 sec for refresh, and still configurable

* Make default delay 5secs, but needs to be activated
2017-02-20 15:49:34 +01:00
Pascal Vizeli
1a4b62909b Pump ffmpeg to 1.5 (#6119) 2017-02-20 15:12:09 +01:00
Scott Bradshaw
37a8035c54 Added support for alternate SSH ports in AsusWRT (#4832) (#6109)
* Added support for alternate SSH ports in AsusWRT (#4832)

* Always set the SSH port in SSH arguments

* Removed whitespace

* Adding port=22 to the mock calls

* Changed config.get(CONF_PORT)  to config[CONF_PORT] per feedback from @pvizeli
2017-02-20 09:06:50 +01:00
Paulus Schoutsen
25408941de Mqtt fixes (#6116)
* Fix MQTT stop

* MQTT: Make sure to have connection setup at end of MQTT setup.

* Fix MQTT connect
2017-02-19 22:43:10 -08:00
Paulus Schoutsen
b969fea900 Z-Wave config panel fix (#6113) 2017-02-19 22:25:03 -08:00
Robbie Trencheny
2cc6fe6609 Fix links in template
Closes #6112
2017-02-19 21:00:54 -08:00
Tom Matheussen
66d8787d47 Weather platform Forecast (#4721)
* Added forecast functionality to the weather platform, updated OWM to get forecast data

* style fixes

* Changed returned forecast data to a more managable dict

* Fixed line length

* forecast will always be collected, data returned from owm is based on metric setting

* use list comprehension to create the forecast data

* Added forecast data to the weather demo

* Create dict directly in list comprehension

* Minor variable change in weather demo platform

* Convert forecast temperatures in weather component

* set forecast attributes as constants

* Style fixes and tests

* Copied forecast_entry instead of mutating data
2017-02-19 16:42:12 -08:00
Pascal Vizeli
5d8e219448 Update aiohttp handling with upc connect (#6108)
* Refactor upc connect

* fix aiohttp cleanup

* fix test

* fix tests

* allow status code for login
2017-02-19 23:25:45 +01:00
Daniel Høyer Iversen
58f813b518 broadlink (#6101) 2017-02-19 17:45:57 +01:00
normakm
dee4c85c32 Add support for aliased owfs sensors (#6043)
* Support aliased owfs sensors

Current implementation does not support OneWire OWFS sensors that are aliased by OWFS alias.txt file:
http://owfs.org/index.php?page=aliases
Assumption is that folder name == sensor address

This change reads the supported families from owfs "family" file and adds both aliased and unaliased sensors.
(this approach also skips the "management" folders.. eg simultaenous, bus, alarm, statistics etc. For example when adding "simultaneous" as sensor (it also has "temperature" file) then owfs crashes)

* Update onewire.py

lint suggested style fixes

* Update onewire.py

Empty line removed

* Update onewire.py

comments removed
2017-02-19 01:59:44 -08:00
William Scanlon
a4318c3125 Added tamper detection to Wink devices. (#6072)
* Added tamper detection to wink devices.
2017-02-18 23:00:27 -05:00
Adam Mills
5f095b5126 Add supported_features to cover component (#6082) 2017-02-18 18:11:03 -08:00
William Scanlon
3cb1a5dd89 SimpliSafe updates (#6034)
* SimpliSafe updates

* Check login status

* Fixed requirements_all.txt
2017-02-18 17:47:52 -08:00
Kevin Siml
dfbef45e49 Add pushsafer.com notification service (#6050)
* Add pushsafer.com notification service

* Add pushsafer.com notification service

* Add pushsafer.com notification service

* Add pushsafer.com notification service

* Update pushsafer.py

* Update pushsafer.py

* Update pushsafer.py

* Update README.rst
2017-02-18 17:36:28 -08:00
Erik Eriksson
9e73115337 Updated volvooncall library + support sensors, heater and lock (#6052) 2017-02-18 17:09:25 -08:00
Andrey
beb8b4b11f Zwave: add power_consumption attribute (#6067)
* Zwave: Pull power consumption value into attribute.

* Zwave: Add power_consumption attribute.

* fix condition

* Update __init__.py

* Update

* Simplify class condition

* Handle empty class_id
2017-02-18 16:51:13 -08:00
dramamoose
003815c91a Update FLUX_LED by adding Effects (#6083)
* Add FLUX_LED Effects

Add add the various supported FLUX_LED effects

* Correct Flux_LED Issues

* Whitespace Changes

* Feed the Hound

* Feed the hound better food
2017-02-18 18:45:21 -05:00
Pascal Vizeli
e1cbd6b4c0 MQTT convert to async (#6064)
* Migrate mqtt to async

* address paulus comment / convert it complet async

* adress paulus comment / remove future

* Automation triggers should be async

* Fix MQTT async calls

* Show that event helpers are callbacks

* Fix tests

* Lint
2017-02-18 14:17:18 -08:00
Lindsay Ward
fa2c1dafdf Add platform for Yeelight Sunflower lights (#6060) 2017-02-18 14:05:55 -08:00
Erik Eriksson
76d1ee9fc2 Support for Pocket Casts (#6084) 2017-02-18 13:52:37 -08:00
Paulus Schoutsen
f29ee24b72 Do not allow config dependency (#6036)
* Do not allow config dependency

* Prevent config in discovery

* Migrate to blacklist
2017-02-18 11:31:37 -08:00
Adam Mills
b277fd55f9 [media_player.kodi] Fix for when no item id is provided (#6088) 2017-02-18 19:09:17 +00:00
kitcorey
75df4be733 Fix colortemp conversion for lifx lights (#6087) 2017-02-18 20:42:57 +02:00
Adam Mills
86a1b0a6c6 Websocket push notifications for Kodi (#6063)
* Websocket push notifications for Kodi

* Only create ws server if ws enabled

* Fix conditional websocket server creation
2017-02-18 00:26:07 -08:00
John Arild Berentsen
799fbe42f8 zwave refactor, don't use ozw values directly in properties. (#5961)
* First round of not using values directly

* Round two

* lint

* Round four

* Conflict

* Round five

* Update zwave.py

* round six

* Docstring

* flakywakie

* Fetch values in constructor

* Blank line removal

* Set attributes in callback

* Docstring

* Round seven

* Ughgit add homeassistant/components/lock/zwave.py!

* Sloppy code
2017-02-17 23:56:05 -08:00
Andrey
c1eed148cc Clean up value_added in zwave light. (#6074) 2017-02-17 23:54:45 -08:00
Erik Eriksson
62fe9f955e update dovado version (#6081) 2017-02-18 08:15:32 +01:00
Daniel Høyer Iversen
b857f838df Broadlink (#6051)
* Add fail checking of broadlink data
2017-02-18 07:38:50 +01:00
Philipp Schmitt
c2dc940819 Update liveboxplaytv and catch connection errors (#6056)
* Update liveboxplaytv and catch connection errors

* Implement @pvizeli's suggestion

* lint
2017-02-17 21:40:19 +01:00
Fabian Affolter
ca9eb31d1d Upgrade aiohttp to 1.3.2 (#6059) 2017-02-17 21:39:29 +01:00
William Scanlon
8a5fe38d69 Slugify trackr device_id (#6062)
* Slugify trackr device_id

* Removed replace
2017-02-17 21:39:05 +01:00
Andrey
91c3a49a5b Zwave: Add forgotten service file (#6073)
* add print

* Add 'print_node' service to zwave.

* Add forgotten service file
2017-02-17 22:09:38 +02:00
Andrey
1f72506f9b Add 'print_node' service to zwave (#6069)
* add print

* Add 'print_node' service to zwave.
2017-02-17 22:03:55 +02:00
Adam Mills
843840b963 Add effect_list to hue light (#6065) 2017-02-17 20:37:45 +02:00
Andrey
bb64560089 Zwave: Make different messages for ignores by woraround and device config. (#6061) 2017-02-17 16:19:21 +01:00
Walker Boyle
ba305ee71c Add aurora sensor (#6003)
* Add aurora sensor

* allow custom forecast threshold for aurora binary sensor

* move AuroraGateway functionality to Aurora data object to conform with HA standards
2017-02-17 09:13:52 +01:00
Andrey
905f4bf994 Support zwave glob & domain device settings. (#6046)
* Support zwave glob & domain device settings.

* data[DATA_DEVICE_CONFIG].get() now always return non-None

* Update test

* Update tests2

* Lint fix
2017-02-16 15:19:22 -08:00
Pascal Vizeli
a496a7c792 Protect device_tracker scan interval / TTS logging (#6041)
* Protect device_tracker scan interval / TTS logging

* clear pass
2017-02-16 07:13:33 -08:00
Jose Juan Montes
714ba31b75 Mediaplayer clementine remote (#5877)
* Added Clementine Music Player Remote component.

* Remove stale stuff
2017-02-16 15:34:34 +01:00
Pascal Vizeli
2574b915dd Fix name in logging message (#6039)
Add an optional extended description…
2017-02-16 10:30:12 +01:00
Thibault Cohen
1eceb405ce [WIP] Hydroquebec plugin now use pyhydroquebec lib (#6000)
* Hydroquebec plugin now use pyhydroquebec lib

* Fix logger message

* Fix platform name
2017-02-16 10:22:21 +01:00
Thibault Cohen
8bef7d84bb Add Ebox sensor component (#5998)
* Add Ebox sensor component

* Fix PR #5998 comments

* Fix logger message
2017-02-16 09:29:43 +01:00
Paulus Schoutsen
75e41a21c9 Clean up mock_coro (#6037) 2017-02-15 23:19:34 -08:00
Jon Caruana
9c176ad85a LiteJet: Lights should have the option to dim in the UI. (#6031)
* LiteJet: Lights should have the option to dim in the UI.

* Fix lint error.
2017-02-15 22:41:03 -08:00
Paulus Schoutsen
0f1a254f3b Update frontend 2017-02-15 22:33:52 -08:00
Pascal Vizeli
6674a8ad57 [Device Tracker] Remove coro (#6014)
* Remove coro and make flow faster.

* fix lint

* address comments
2017-02-15 19:52:06 -08:00
Paulus Schoutsen
235d0057b1 Simplify customize (#6007)
* Simplify customize

* Maintain glob order

* Have glob overrule domain
2017-02-15 19:47:30 -08:00
Adam Mills
eb9400de4c cmus remove IO from properties (#6030) 2017-02-15 19:13:25 -08:00
Thibault Cohen
4addcccfac Update to pyfido 0.1.4 (#6033) 2017-02-15 19:12:29 -08:00
jumpkick
f6e46aecf5 Update wemo.py 2017-02-15 17:32:45 -05:00
jumpkick
e9cf5f6f42 Update wemo.py 2017-02-15 16:58:11 -05:00
jumpkick
e221c8a37d Update wemo.py 2017-02-15 16:57:16 -05:00
jumpkick
b163544e3c Back to you travis.... 2017-02-15 16:47:02 -05:00
jumpkick
a718e92708 Update wemo.py
trailing whitespace... (argh... the bot should just trim it)
2017-02-15 15:40:02 -05:00
jumpkick
44d274e428 Update wemo.py
* continuation line under-indented for visual indent
2017-02-15 15:38:41 -05:00
jumpkick
c404fb7142 Update wemo.py
* Reordered datetime import
* Spaces by 4
2017-02-15 15:34:42 -05:00
Thibault Cohen
5895f431b4 [WIP] Add Fido sensor (#5997)
* Add Fido sensor

* Fix PR #5997 comments

* Make error message usable
2017-02-15 21:21:38 +01:00
Erik Eriksson
0d06454a94 eliqonline lib upgrade (#6021) 2017-02-15 19:02:58 +01:00
Pierre Ståhl
fdb6dd81ce Add fake support for turn on/off for Apple TV (#5962)
* Add fake support for turn on/off for Apple TV

When the device is "turned off", no requests are sent to the device.
When the setting "start_off" is set to true, the device starts in off
state.

* Fix async comments

* Clean up supported features
2017-02-15 09:10:48 -08:00
Johan Bloemberg
2d33ee6258 Reconnect robustness, expose connection state. (#5869)
* Reconnect robustness, expose connection state.

- Expose connection status as rflink.connection_status state.
- Handle alternative timeout scenario.
- Explicitly set a timeout for connections.
- Error when trying to send commands if disconnected.
- Do not block component setup on gateway connection.

* Don't use coroutine where none is needed.

* Test disconnected behaviour.

* Use proper conventions for task creation.

* Possibly fix test race condition?

* Update hass import style
2017-02-15 16:10:19 +01:00
George.M
b1fa178df4 Added a config flag[Boolean] to declare if SenseHAT is attached (#5883)
* Added a config flag[Boolean] to declare if SenseHAT is attached to RaspberryPi

* Hound found a line too long violation - fix
2017-02-15 11:11:55 +01:00
Robbie Trencheny
cf99551110 Merge pull request #6008 from tdickman/dev
Fix abreviation for miles in darksky sensor
2017-02-14 23:57:33 -08:00
happyleavesaoc
58e707a264 Limitless light: bump version; fix conf (#6006) 2017-02-15 08:45:04 +02:00
Paulus Schoutsen
c1988acb36 Merge pull request #6010 from home-assistant/merge-master
Merge master
2017-02-14 21:55:30 -08:00
Paulus Schoutsen
7776bfefc2 Merge branch 'master' into merge-master 2017-02-14 21:53:07 -08:00
Paulus Schoutsen
ad95b2715e Merge pull request #6009 from home-assistant/release-0-38-3
0.38.3
2017-02-14 21:48:49 -08:00
Pascal Vizeli
d6f525a23f Bugfix sonos favorite_source after lost connection (#5996) 2017-02-14 21:38:56 -08:00
happyleavesaoc
b1eb3243bd timeMin fix (#5983)
Add an optional extended description…
2017-02-14 21:38:56 -08:00
William Scanlon
9bcc692ff2 Fix #5979 (#5980) 2017-02-14 21:38:56 -08:00
Fabian Affolter
91d2ba609e Remove unit of measurement 2017-02-14 21:38:43 -08:00
Martin Hjelmare
bbc5c3a300 Fix mysensors platforms version requirement (#5942)
* Notify and device tracker platforms require mysensors version 2.0 or
  greater.
2017-02-14 21:37:54 -08:00
Andrey
04f3fe0ba3 Point-fix zwave getter not to ignore label (#5938) 2017-02-14 21:37:32 -08:00
William Scanlon
ea26aa2c81 Fixed typos in wink climate (#5936) 2017-02-14 21:37:17 -08:00
Tom Dickman
71dc41655c Fix abreviation for miles in darksky sensor 2017-02-14 23:06:06 -06:00
jumpkick
29c7987453 Improvements for WeMo Insight switches
* Changes current power units to watts
* Adds power on times and additional totals
2017-02-14 18:29:23 -05:00
Pascal Vizeli
80bc2666ac Make homematic climate dynamic for datapoints. (#5993)
* Make homematic climate dynamic for datapoints.

* Code cleanup

* Add more option

* add options

* Pump version 0.1.22

* optimaze
2017-02-14 23:19:57 +01:00
arraylabs
039559882b myq-cover updated to new requirement file, changed error message to be more informative (#5995) 2017-02-14 12:03:50 -08:00
Adam Mills
2993a4a7a5 Add object-assign polyfill support to polymer (#5994)
* Add object-assign polyfill support to polymer

* Conditionally load compatibility.js

* Remove compatibility preload

* Include newly compiled files

* Update compiled frontend with latest polymer
2017-02-14 12:00:45 -08:00
Pascal Vizeli
30ad8bcc80 Bugfix sonos favorite_source after lost connection (#5996) 2017-02-14 11:59:54 -08:00
Andrey
67d35e6454 Point-fix zwave getter not to ignore label (#5938) 2017-02-14 11:59:34 -08:00
Paulus Schoutsen
409b74b780 Update hassbian component with real output (#5989) 2017-02-14 09:34:17 -08:00
Pascal Vizeli
4b8e6e36b6 Make EntityComponent update process more robust. (#5943)
* Make EntityComponent update process more robust.

* address paulus comments

* Add platform to log message.
2017-02-14 09:32:40 -08:00
Fabian Affolter
cd9f3fa215 Upgrade pylast to 1.8.0 (#5991) 2017-02-14 13:10:38 +01:00
Sören Oldag
a06f89085d Added limitlessled support for bridge v6 and RGBWW bulbs. (#5958)
* Added limitlessled support for bridge v6 and RGBWW bulbs.

* Fix minor code style issue.

* Updated requirements_all.txt
2017-02-14 11:12:32 +01:00
happyleavesaoc
1bdd8e235a timeMin fix (#5983)
Add an optional extended description…
2017-02-14 10:30:16 +01:00
Erik Eriksson
39ca1a5a0d install libsodium to enable decryption of encrypted owntracks payload (#5976) 2017-02-13 23:59:09 -08:00
PetePriority
e17410c9a1 Added fritzbox_netmonitor.py (#5469)
* Added fritzbox_netmonitor.py

* Implemented changes
2017-02-13 23:58:23 -08:00
Fabian Affolter
f82ac0af60 Enable sensor for discovery (#5974)
* Enable sensor for discovery

* Remove blank line
2017-02-13 23:54:13 -08:00
Paulus Schoutsen
462b47c725 Update frontend (#5987) 2017-02-13 22:25:26 -08:00
Paulus Schoutsen
52567b1a48 Fix Z-Wave node config (#5986) 2017-02-13 22:16:39 -08:00
Andrey
ffb46ab541 Add 'days' flag to history fetch urls. (#5895)
* Add 'days' flag to history fetch urls.

* Fix unrenamed variable

* Switch to end_time param instead of days

* Checkthat end_time is parsed
2017-02-13 22:10:39 -08:00
Paulus Schoutsen
0effe14619 Z-Wave file name fix (#5985) 2017-02-13 21:58:16 -08:00
Andrey
e70b7ab509 Allow printing the number of states returned by history and time it took to extract. (#5973) 2017-02-13 21:48:53 -08:00
Paulus Schoutsen
36c196f9e8 Add initial Z-Wave config panel (#5937)
* Add Z-Wave config panel

* Add config to Z-Wave dependencies

* Lint

* lint

* Add tests

* Remove temp workaround

* Lint

* Fix tests

* Address comments

* Fix tests under Py34
2017-02-13 21:34:36 -08:00
Robbie Trencheny
6005933451 Merge pull request #5975 from fabaff/unit-moon
Remove unit of measurement
2017-02-13 18:08:49 -08:00
William Scanlon
41c2392f8b Fix #5979 (#5980) 2017-02-13 21:08:37 -05:00
Fabian Affolter
e866eeb518 Remove unit of measurement 2017-02-13 23:04:25 +01:00
Paulus Schoutsen
32fc164df3 Clean up HDMI_CEC [Breaking change] (#5932) 2017-02-13 13:52:11 -08:00
Gert-Jan van de Streek
5cad539859 Fix slow status updates from the knx bus (#5963)
* Fix slow status updates from the knx bus

The data set in the entity was an array, not the value.

@fixes https://github.com/home-assistant/home-assistant/issues/4407

* speed up status update
2017-02-13 22:48:48 +01:00
Josh Anderson
401263519d Only try to pair notify.webostv when not paired (#5967)
This allows the notify.webostv component to successfully register when
the TV is not currently powered on as long as a pairing record exists.
2017-02-13 22:29:18 +01:00
Andrey
0feb1c3e28 Add workaround for ignoring zwave devices and reversing cover open/close (#5922) 2017-02-13 20:59:42 +02:00
Paulus Schoutsen
b2d1774293 Fix Z-Wave (#5955) 2017-02-13 08:54:11 -08:00
Stuart Mumford
a8dc559519 Add support for the Open Energy Monitor Thermostat (#5583)
* Add support for the Open Energy Monitor Thermostat

* Fix linting errors

* Define an update method and local state

* fix linter

* Small tweaks.

Update oemthermostat version, default name and docstrings

* Fail to setup oem platform if connection fails.

* update requirements

* More tweaks to auth and exceptions

* Remove target temp
2017-02-13 16:45:04 +01:00
Philipp Schmitt
6d7041cd42 Reduce battery drain on Nuki Lock (#5945) 2017-02-13 14:43:12 +01:00
Valentin Alexeev
2ffdf1fdcd Bugfix/waqi sensor pwaqi version bump (#5944)
* Bump pwaqi to 1.4 to fix a typo in the underlying library.

* Update WAQI sensor to use pwaqi 2.0 which relies on AQICN public API.
This is a breaking change as the component now requires 'token' parameter.

* Fix lint
2017-02-13 14:28:40 +01:00
Fabian Affolter
f77eda2981 Upgrade thingspeak to 0.4.1 and use the correct API key (#5906) 2017-02-13 11:25:28 +01:00
Martin Hjelmare
b6404d70ec Fix mysensors platforms version requirement (#5942)
* Notify and device tracker platforms require mysensors version 2.0 or
  greater.
2017-02-13 11:23:28 +01:00
Fabian Affolter
9a5618fe96 Upgrade TwitterAPI to 2.4.4 (#5940) 2017-02-13 11:20:37 +01:00
arraylabs
bc1d14f9c3 Added myq cover component (#5886)
Add an optional extended description…
2017-02-13 11:20:07 +01:00
Alan Fischer
18f38229b2 iTach Remote Platform (#5660)
* Added itach remote device

* Added coverage & requirements

* Updated requirements

* Added schema, inline commands, and platform_setup failure if itach not found

* Removed unnecessary optional parameter

* Removed filename option for itach remote
2017-02-13 11:10:34 +01:00
Robbie Trencheny
feb2ebbc03 Fix AWS Lambda breakage after #5824 (#5935)
Add an optional extended description…
2017-02-13 09:27:50 +01:00
Paulus Schoutsen
7b56fe2af6 Update frontend (#5939) 2017-02-13 00:00:41 -08:00
Paulus Schoutsen
8ca3ca8564 Z-Wave: Rename customize to device_config [Breaking change] (#5933)
* Z-Wave: Rename customize to device_config

* Fix light

* Make entity id not required
2017-02-12 23:55:27 -08:00
Paulus Schoutsen
7401ec96b5 Version bump to 0.38.3 2017-02-12 23:31:04 -08:00
Pascal Vizeli
41849eab06 Core cleanup: two stage shutdown (#5876)
* Core cleanup: two stage shutdown

* fix spell

* fix

* add async logger to close

* change aiohttp to use CLOSE

* address paulus comments

* Fix tests

* Add unittest
2017-02-13 06:24:07 +01:00
William Scanlon
4623d1071e Fixed typos in wink climate (#5936) 2017-02-12 19:34:13 -08:00
Paulus Schoutsen
a37a3af126 Merge pull request #5928 from home-assistant/release-0-38-2
0.38.2
2017-02-12 15:49:58 -08:00
John Arild Berentsen
1a0a8f106e Bugfix for #5900 (#5901) 2017-02-12 15:47:20 -08:00
John Arild Berentsen
6311f21d31 Bugfix for #5900 (#5901) 2017-02-12 15:47:04 -08:00
Andrey
f4372a7df5 Fix getters that ignored labels. (#5903)
* Fix getters that ignored labels.

* Try 5 times for changed dict

* fix lint

* Add decorator with retrying functions.

* Fix lint

* use retries instead of decorator
2017-02-12 15:42:09 -08:00
Andrey
9b0a3e4c5a force_update zwave sensors. (#5844)
* force_update zwave sensors with polling_intensity.

* use bool to cast

* Make all zwave sensors force_update=True
2017-02-12 14:10:56 -08:00
Andrey
35118b6d9c Make hdmi_cec work with the new customize (#5916) 2017-02-12 14:02:45 -08:00
Fabian Affolter
8991fcf835 Fix name (#5912) 2017-02-12 14:02:45 -08:00
happyleavesaoc
15ef55a4c8 bump myusps version (#5911) 2017-02-12 14:02:45 -08:00
Philipp Schmitt
d3c444ff10 [lock.nuki] Fix Nuki lock for Python 3.4 and 3.5 (#5899) 2017-02-12 14:02:45 -08:00
Paulus Schoutsen
153e354002 Version bump to 0.38.2 2017-02-12 14:01:26 -08:00
Paulus Schoutsen
da5823becb Make check ha config file work with custom config dir 2017-02-12 14:00:06 -08:00
Paulus Schoutsen
8d0731e9fc Merge branch 'master' into dev 2017-02-12 13:58:09 -08:00
Pierre Ståhl
3a262cd7e0 Fix artwork in Apple TV platform (#5874) 2017-02-12 22:34:02 +01:00
Pascal Vizeli
9aac2113b6 Add 'wait_template' to script commands / Refactory track_template (#5827)
* Add 'wait' to script commands.

* Add track_template + unittest / rename wait_template

* fix lint & test

* Fix handling / change automation-template / add tests

* address paulus comments
2017-02-12 13:27:53 -08:00
happyleavesaoc
5f0b2a7d15 [WIP] gstreamer media player (#5839)
* gstreamer media player

* gstreamer meta
2017-02-12 13:00:27 -08:00
happyleavesaoc
64cb65a04e fedex sensor (#5891)
* fedex sensor

* fix fedex requirement
2017-02-12 12:47:27 -08:00
happyleavesaoc
3f675afd5b ups sensor (#5890) 2017-02-12 12:47:12 -08:00
Colin O'Dell
289767522b Update qnapstats library; add support for new verify_ssl config (#5919) 2017-02-12 12:38:29 -08:00
Per Sandström
675dd04e97 vasttrafik: update token on read error (#5875) 2017-02-12 11:57:29 -08:00
Pierre Ståhl
e5085bf620 Add media_image to media_player component (#5754) 2017-02-12 11:42:56 -08:00
Paulus Schoutsen
780173befb Update frontend (#5923) 2017-02-12 11:35:36 -08:00
Paulus Schoutsen
dab6d011ca Add check_config API (#5898)
* Add check_config API

* Add config panel to default config

* Add tests

* Lint

* lint
2017-02-12 11:31:46 -08:00
Andrey
dc6a28a8b2 Make hdmi_cec work with the new customize (#5916) 2017-02-12 11:19:15 -08:00
Fabian Affolter
b2fae212cb Fix name (#5912) 2017-02-12 11:16:06 -08:00
Greg Dowling
9c400de64b Bump pywemo - fix for latest bridge firmware. (#5921) 2017-02-12 11:14:23 -08:00
Adam Mills
e4bbe37112 Add device_class support to cover component (#5881) 2017-02-12 11:08:06 -08:00
Jose Juan Montes
2103bfc824 Fixed proximity zone incorrectly using name instead of zone setting. (#5862)
* Fixed proximity zone incorrectly using name instead of zone setting.

* Fixed proximity tests to suit change.
2017-02-12 11:03:53 -08:00
Pascal Bach
f8be731891 [google] Update google component dependencies (#5904) 2017-02-12 17:55:17 +00:00
happyleavesaoc
4af9d0f9ea bump myusps version (#5911) 2017-02-12 18:49:02 +01:00
Philipp Schmitt
533d28ce40 [lock.nuki] Fix Nuki lock for Python 3.4 and 3.5 (#5899) 2017-02-12 10:22:55 +00:00
Paulus Schoutsen
b59b42db2c 0.38.1 (#5889)
* Upgrade AppleTV dep to 0.1.4

* Version bump to 0.38.1

* Update logbook in frontend
2017-02-11 19:58:20 -08:00
Paulus Schoutsen
a25e394a11 Upgrade AppleTV dep to 0.1.4 2017-02-11 19:25:20 -08:00
Paulus Schoutsen
44311193ef Add config component and hassbian example panel (#5868)
* Add hassbian panel

* Rename to generic config panel

* Allow loading hassbian as test

* Add tests

* Update frontend

* Lint

* Lint
2017-02-11 17:29:05 -08:00
Robbie Trencheny
2b2c1562a5 Version bump to 0.39.0.dev0 2017-02-11 14:39:35 -08:00
Johann Kellerman
abaf9e53c2 Component set add unsing OR (#5880) 2017-02-11 23:27:06 +02:00
Paulus Schoutsen
5ad934907a Revert "Stop using entity_picture that is known to be bad." (#5882) 2017-02-11 13:10:28 -08:00
Fabian Affolter
88653e66c8 Style updates (#5878)
* Use consts, update quoting, and update comments

* Update log message

* Update docstrings

* Update log messages

* Update log messages

* Update style

* Fix typo

* Add newline

* Fix indent

* Fix line too long
2017-02-11 11:29:37 -08:00
Andrey
b981bfba7e Stop using entity_picture that is known to be bad. (#5856)
* Stop using entity_picture that is known to be bad.

* Only abandon image on 400 or 404 response

* Return is_permanent_failure as a third part of response

* Add debug printout

* Fix lint

* Fix lint
2017-02-11 20:33:41 +02:00
Fabian Affolter
2711c12928 Upgrade psutil to 5.1.3 (#5873) 2017-02-11 14:48:54 +01:00
Petr Vraník
0aad6c72d2 version bump (#5871) 2017-02-11 13:53:45 +01:00
Daniel Høyer Iversen
d32949b099 rfxtrx 0.17 (#5870) 2017-02-11 10:55:38 +01:00
Jose Juan Montes
f5c58748b7 Adds play URL support to mpd (makes it work with tts). (#5863)
* Adds play URL support to mpd (makes it work with tts).

* Removed extra line at the end of the file.
2017-02-11 10:07:31 +01:00
Paulus Schoutsen
3a7309ab62 Update frontend (#5866) 2017-02-10 21:06:42 -08:00
Marcelo Moreira de Mello
75887e6069 Avoid traceback for Amcrest cameras/firmware that does not have the software_information API call (#5865)
* Avoid traceback for Amcrest cameras/firmware that does not have the software_information API call

* Make lint happy
2017-02-10 20:51:19 -08:00
Adam Mills
e877d572f5 binary_sensor sensor_class to entity device_class (#5860)
* binary_sensor sensor_class to entity device_class

* Linter fixes

* Should be it
2017-02-10 20:46:15 -08:00
Johan Bloemberg
67957cbfa8 Rflink update and small refactor. (#5789)
* Use same pattern for device defaults in both platforms.

* Update Rflink that passes loop downstream.

* Update requirements.
2017-02-11 00:24:07 +01:00
Paulus Schoutsen
b10d20bcab Recorder run can be None (#5854) 2017-02-10 12:55:59 -08:00
Johann Kellerman
cbf3a2ecae [recorder] Run end model changed in session scope (#5858) 2017-02-10 22:22:15 +02:00
Paulus Schoutsen
23ff2eb79c Update frontend (#5855) 2017-02-10 09:30:13 -08:00
Paulus Schoutsen
6ffab53377 Core: cleanup timer (#5825)
* Minor core cleanup

* Cleanup timer

* Lint

* timeout with correct loop

* Improve timer thanks to pvizeli

* Update core.py

* More tests
2017-02-10 09:00:17 -08:00
Erik Eriksson
c7c3b30e0a Do not call state if device isn't available (#5835) 2017-02-10 08:59:58 -08:00
Andrey
0b5191a247 Add support for zwave wakeup setting. (#5849)
* Add support for zwave wakeup setting.

* rename wakeup
2017-02-10 08:54:48 -08:00
Pascal Vizeli
4e8d20328a Fix check_config script. (#5853) 2017-02-10 08:51:08 -08:00
Pascal Vizeli
8785e5826e telegram small cleanup/style (#5852) 2017-02-10 16:39:02 +01:00
Teemu R
1da6181491 bump python-yeelight version (#5850)
Add an optional extended description…
2017-02-10 14:45:31 +01:00
Christian Brædstrup
a150a69cca D-Link switch version bump of external library (#5843) 2017-02-10 12:00:28 +01:00
Andrey
5bd54f69cc Fix zwave helper getter not to fail on some None results. (#5845) 2017-02-10 12:30:44 +02:00
Mark Oude Veldhuis
0d76d72b9f Add support for multiple devices to Tado device tracker (#5810)
* Add support for multiple devices to Tado device tracker

* Hound did not agree with my usage of spaces

* Two blank lines were expected

* Keep CONF_HOME_ID in the Tado file

* Make home_id optional

* Work with different API URLs depending on home_id being present

* Remove CONF_HOME_ID from HA's const.py file

* Missed removing CONF_HOME_ID from the import
2017-02-09 18:50:14 -08:00
Boris K
5ecef6aaac Add history_stats sensor (#5610)
* Add new sensor/history_stats component

* Add real unit tests

* Code style changes requested for pull request

* Remove time aliases & allow datetime values

* Reformat unit tests

* Remove all async behavior in history_stats

* Change duration format
2017-02-09 18:47:12 -08:00
Adam Mills
be08bf0ef7 [recorder] Add tests for full schema migration (#5831)
* [recorder] Add tests for full schema migration

* Remove leftover code

* Fix duplicate creation of sqlalchemy Index object

* It's that kind of day...

* Improve models_original docstring
2017-02-09 18:17:17 -08:00
Philipp Schmitt
4c5e6399e9 Refactoring and JSON decode error handling (#5826)
* Refactoring and JSON decode error handling

* Catch ValueError instead of simplejson.scanner.JSONDecodeError
2017-02-09 17:57:19 -08:00
Pascal Vizeli
2e8e5a35b5 Update aiohttp 1.3.1 (#5838) 2017-02-09 17:31:20 -08:00
Pierre Ståhl
841321f154 Reuse default aiohttp session (#5836) 2017-02-09 23:07:46 +01:00
Stefano Scipioni
ebfff6a907 Telegram webhooks (#5793)
* new component telegram_webhooks

* keyboard support in telegram notify

* telegram_webhooks has no tests

* requirement like notify/telegram

* ops, requirements_all.txt needed for travis

* ops, requirements_all.txt is generated by script/gen_requirements_all.py

* check telegram trusted networks in web handler

* raise an event now

* use of hass.config.api.base_url

* more readable

* small cleanups

* Small style change for HA guideline

* fix lint

* revert return to origin
2017-02-09 23:05:28 +01:00
Pierre Ståhl
ecbbb06b2f Handle connection errors when connecting to Apple TVs (#5829)
* Handle connection errors when connecting to Apple TVs

Also bump pyatv to 0.1.2 which fixes a request leak.

* Fix pylint error

* Fix import order
2017-02-09 22:25:06 +01:00
Paulus Schoutsen
c54517de90 Convert config.components to a set (#5824) 2017-02-09 20:21:57 +02:00
Erik Eriksson
f3b9fa2f41 Don't thow exception if connection to server is lost (#5775) 2017-02-09 09:00:18 -08:00
1057 changed files with 45183 additions and 16473 deletions

View File

@@ -8,15 +8,24 @@ omit =
homeassistant/helpers/signal.py
# omit pieces of code that rely on external devices being present
homeassistant/components/alarmdecoder.py
homeassistant/components/*/alarmdecoder.py
homeassistant/components/apcupsd.py
homeassistant/components/*/apcupsd.py
homeassistant/components/arduino.py
homeassistant/components/*/arduino.py
homeassistant/components/android_ip_webcam.py
homeassistant/components/*/android_ip_webcam.py
homeassistant/components/bbb_gpio.py
homeassistant/components/*/bbb_gpio.py
homeassistant/components/blink.py
homeassistant/components/*/blink.py
homeassistant/components/bloomsky.py
homeassistant/components/*/bloomsky.py
@@ -41,6 +50,9 @@ omit =
homeassistant/components/insteon_local.py
homeassistant/components/*/insteon_local.py
homeassistant/components/insteon_plm.py
homeassistant/components/*/insteon_plm.py
homeassistant/components/ios.py
homeassistant/components/*/ios.py
@@ -50,6 +62,9 @@ omit =
homeassistant/components/lutron.py
homeassistant/components/*/lutron.py
homeassistant/components/lutron_caseta.py
homeassistant/components/*/lutron_caseta.py
homeassistant/components/modbus.py
homeassistant/components/*/modbus.py
@@ -62,6 +77,9 @@ omit =
homeassistant/components/octoprint.py
homeassistant/components/*/octoprint.py
homeassistant/components/opencv.py
homeassistant/components/*/opencv.py
homeassistant/components/qwikswitch.py
homeassistant/components/*/qwikswitch.py
@@ -82,12 +100,22 @@ omit =
homeassistant/components/*/thinkingcleaner.py
homeassistant/components/tradfri.py
homeassistant/components/*/tradfri.py
homeassistant/components/twilio.py
homeassistant/components/notify/twilio_sms.py
homeassistant/components/notify/twilio_call.py
homeassistant/components/vera.py
homeassistant/components/*/vera.py
homeassistant/components/verisure.py
homeassistant/components/*/verisure.py
homeassistant/components/volvooncall.py
homeassistant/components/*/volvooncall.py
homeassistant/components/*/webostv.py
homeassistant/components/wemo.py
@@ -99,9 +127,6 @@ omit =
homeassistant/components/zigbee.py
homeassistant/components/*/zigbee.py
homeassistant/components/zwave/*
homeassistant/components/*/zwave.py
homeassistant/components/enocean.py
homeassistant/components/*/enocean.py
@@ -126,16 +151,32 @@ omit =
homeassistant/components/zabbix.py
homeassistant/components/*/zabbix.py
homeassistant/components/maxcube.py
homeassistant/components/*/maxcube.py
homeassistant/components/tado.py
homeassistant/components/*/tado.py
homeassistant/components/zha/__init__.py
homeassistant/components/zha/const.py
homeassistant/components/*/zha.py
homeassistant/components/eight_sleep.py
homeassistant/components/*/eight_sleep.py
homeassistant/components/alarm_control_panel/alarmdotcom.py
homeassistant/components/alarm_control_panel/concord232.py
homeassistant/components/alarm_control_panel/nx584.py
homeassistant/components/alarm_control_panel/simplisafe.py
homeassistant/components/alarm_control_panel/totalconnect.py
homeassistant/components/apiai.py
homeassistant/components/binary_sensor/arest.py
homeassistant/components/binary_sensor/concord232.py
homeassistant/components/binary_sensor/flic.py
homeassistant/components/binary_sensor/hikvision.py
homeassistant/components/binary_sensor/iss.py
homeassistant/components/binary_sensor/pilight.py
homeassistant/components/binary_sensor/ping.py
homeassistant/components/binary_sensor/rest.py
homeassistant/components/browser.py
homeassistant/components/camera/amcrest.py
@@ -149,16 +190,21 @@ omit =
homeassistant/components/climate/heatmiser.py
homeassistant/components/climate/homematic.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/cover/garadget.py
homeassistant/components/cover/homematic.py
homeassistant/components/cover/myq.py
homeassistant/components/cover/opengarage.py
homeassistant/components/cover/rpi_gpio.py
homeassistant/components/cover/scsgate.py
homeassistant/components/cover/wink.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
homeassistant/components/device_tracker/bluetooth_tracker.py
@@ -169,6 +215,7 @@ omit =
homeassistant/components/device_tracker/icloud.py
homeassistant/components/device_tracker/linksys_ap.py
homeassistant/components/device_tracker/luci.py
homeassistant/components/device_tracker/mikrotik.py
homeassistant/components/device_tracker/netgear.py
homeassistant/components/device_tracker/nmap_tracker.py
homeassistant/components/device_tracker/ping.py
@@ -181,9 +228,7 @@ omit =
homeassistant/components/device_tracker/tplink.py
homeassistant/components/device_tracker/trackr.py
homeassistant/components/device_tracker/ubus.py
homeassistant/components/device_tracker/volvooncall.py
homeassistant/components/device_tracker/xiaomi.py
homeassistant/components/discovery.py
homeassistant/components/downloader.py
homeassistant/components/emoncms_history.py
homeassistant/components/emulated_hue/upnp.py
@@ -192,30 +237,41 @@ omit =
homeassistant/components/foursquare.py
homeassistant/components/hdmi_cec.py
homeassistant/components/ifttt.py
homeassistant/components/image_processing/dlib_face_detect.py
homeassistant/components/image_processing/dlib_face_identify.py
homeassistant/components/joaoapps_join.py
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/decora.py
homeassistant/components/light/flux_led.py
homeassistant/components/light/hue.py
homeassistant/components/light/hyperion.py
homeassistant/components/light/lifx.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/sensehat.py
homeassistant/components/light/tikteck.py
homeassistant/components/light/tradfri.py
homeassistant/components/light/x10.py
homeassistant/components/light/yeelight.py
homeassistant/components/light/piglow.py
homeassistant/components/light/yeelightsunflower.py
homeassistant/components/light/zengge.py
homeassistant/components/lirc.py
homeassistant/components/lock/nuki.py
homeassistant/components/lock/lockitron.py
homeassistant/components/media_player/anthemav.py
homeassistant/components/media_player/apple_tv.py
homeassistant/components/media_player/aquostv.py
homeassistant/components/media_player/braviatv.py
homeassistant/components/media_player/cast.py
homeassistant/components/media_player/clementine.py
homeassistant/components/media_player/cmus.py
homeassistant/components/media_player/denon.py
homeassistant/components/media_player/denonavr.py
@@ -223,7 +279,9 @@ omit =
homeassistant/components/media_player/dunehd.py
homeassistant/components/media_player/emby.py
homeassistant/components/media_player/firetv.py
homeassistant/components/media_player/frontier_silicon.py
homeassistant/components/media_player/gpmdp.py
homeassistant/components/media_player/gstreamer.py
homeassistant/components/media_player/hdmi_cec.py
homeassistant/components/media_player/itunes.py
homeassistant/components/media_player/kodi.py
@@ -233,6 +291,7 @@ omit =
homeassistant/components/media_player/mpd.py
homeassistant/components/media_player/nad.py
homeassistant/components/media_player/onkyo.py
homeassistant/components/media_player/openhome.py
homeassistant/components/media_player/panasonic_viera.py
homeassistant/components/media_player/pandora.py
homeassistant/components/media_player/philips_js.py
@@ -243,12 +302,15 @@ omit =
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/vlc.py
homeassistant/components/media_player/volumio.py
homeassistant/components/media_player/yamaha.py
homeassistant/components/notify/aws_lambda.py
homeassistant/components/notify/aws_sns.py
homeassistant/components/notify/aws_sqs.py
homeassistant/components/notify/ciscospark.py
homeassistant/components/notify/discord.py
homeassistant/components/notify/facebook.py
homeassistant/components/notify/free_mobile.py
@@ -267,6 +329,7 @@ omit =
homeassistant/components/notify/pushbullet.py
homeassistant/components/notify/pushetta.py
homeassistant/components/notify/pushover.py
homeassistant/components/notify/pushsafer.py
homeassistant/components/notify/rest.py
homeassistant/components/notify/sendgrid.py
homeassistant/components/notify/simplepush.py
@@ -275,13 +338,13 @@ omit =
homeassistant/components/notify/syslog.py
homeassistant/components/notify/telegram.py
homeassistant/components/notify/telstra.py
homeassistant/components/notify/twilio_sms.py
homeassistant/components/notify/twilio_call.py
homeassistant/components/notify/twitter.py
homeassistant/components/notify/xmpp.py
homeassistant/components/nuimo_controller.py
homeassistant/components/remote/harmony.py
homeassistant/components/remote/itach.py
homeassistant/components/scene/hunterdouglas_powerview.py
homeassistant/components/scene/lifx_cloud.py
homeassistant/components/sensor/amcrest.py
homeassistant/components/sensor/arest.py
homeassistant/components/sensor/arwn.py
@@ -291,21 +354,30 @@ omit =
homeassistant/components/sensor/broadlink.py
homeassistant/components/sensor/dublin_bus_transport.py
homeassistant/components/sensor/coinmarketcap.py
homeassistant/components/sensor/cert_expiry.py
homeassistant/components/sensor/comed_hourly_pricing.py
homeassistant/components/sensor/cpuspeed.py
homeassistant/components/sensor/crimereports.py
homeassistant/components/sensor/cups.py
homeassistant/components/sensor/currencylayer.py
homeassistant/components/sensor/darksky.py
homeassistant/components/sensor/deutsche_bahn.py
homeassistant/components/sensor/dht.py
homeassistant/components/sensor/dnsip.py
homeassistant/components/sensor/dovado.py
homeassistant/components/sensor/dte_energy_bridge.py
homeassistant/components/sensor/efergy.py
homeassistant/components/sensor/ebox.py
homeassistant/components/sensor/eddystone_temperature.py
homeassistant/components/sensor/eliqonline.py
homeassistant/components/sensor/emoncms.py
homeassistant/components/sensor/envirophat.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/glances.py
homeassistant/components/sensor/google_travel_time.py
homeassistant/components/sensor/gpsd.py
@@ -317,12 +389,16 @@ omit =
homeassistant/components/sensor/imap.py
homeassistant/components/sensor/imap_email_content.py
homeassistant/components/sensor/influxdb.py
homeassistant/components/sensor/kwb.py
homeassistant/components/sensor/lastfm.py
homeassistant/components/sensor/linux_battery.py
homeassistant/components/sensor/loopenergy.py
homeassistant/components/sensor/mhz19.py
homeassistant/components/sensor/lyft.py
homeassistant/components/sensor/metoffice.py
homeassistant/components/sensor/miflora.py
homeassistant/components/sensor/modem_callerid.py
homeassistant/components/sensor/mqtt_room.py
homeassistant/components/sensor/mvglive.py
homeassistant/components/sensor/netdata.py
homeassistant/components/sensor/neurio_energy.py
homeassistant/components/sensor/nut.py
@@ -331,9 +407,12 @@ omit =
homeassistant/components/sensor/onewire.py
homeassistant/components/sensor/openevse.py
homeassistant/components/sensor/openexchangerates.py
homeassistant/components/sensor/opensky.py
homeassistant/components/sensor/openweathermap.py
homeassistant/components/sensor/pi_hole.py
homeassistant/components/sensor/plex.py
homeassistant/components/sensor/pocketcasts.py
homeassistant/components/sensor/pushbullet.py
homeassistant/components/sensor/pvoutput.py
homeassistant/components/sensor/qnap.py
homeassistant/components/sensor/sabnzbd.py
@@ -358,6 +437,7 @@ omit =
homeassistant/components/sensor/transmission.py
homeassistant/components/sensor/twitch.py
homeassistant/components/sensor/uber.py
homeassistant/components/sensor/ups.py
homeassistant/components/sensor/usps.py
homeassistant/components/sensor/vasttrafik.py
homeassistant/components/sensor/waqi.py
@@ -386,13 +466,17 @@ omit =
homeassistant/components/switch/tplink.py
homeassistant/components/switch/transmission.py
homeassistant/components/switch/wake_on_lan.py
homeassistant/components/telegram_bot/*
homeassistant/components/thingspeak.py
homeassistant/components/tts/amazon_polly.py
homeassistant/components/tts/picotts.py
homeassistant/components/upnp.py
homeassistant/components/weather/bom.py
homeassistant/components/weather/metoffice.py
homeassistant/components/weather/openweathermap.py
homeassistant/components/weather/zamg.py
homeassistant/components/zeroconf.py
homeassistant/components/zwave/util.py
[report]

View File

@@ -1,16 +1,16 @@
**Description:**
## Description:
**Related issue (if applicable):** fixes #<home-assistant issue number goes here>
**Pull request in [home-assistant.github.io](https://github.com/home-assistant/home-assistant.github.io) with documentation (if applicable):** home-assistant/home-assistant.github.io#<home-assistant.github.io PR number goes here>
**Example entry for `configuration.yaml` (if applicable):**
## Example entry for `configuration.yaml` (if applicable):
```yaml
```
**Checklist:**
## Checklist:
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)
@@ -26,5 +26,5 @@ If the code does not interact with devices:
- [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**
- [ ] Tests have been added to verify that the new code works.
[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L16
[ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L51
[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L14
[ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L54

11
.gitignore vendored
View File

@@ -1,15 +1,4 @@
config/*
!config/home-assistant.conf.default
# There is not a better solution afaik..
!config/custom_components
config/custom_components/*
!config/custom_components/example.py
!config/custom_components/hello_world.py
!config/custom_components/mqtt_example.py
!config/panels
config/panels/*
!config/panels/react.html
tests/testing_config/deps
tests/testing_config/home-assistant.log

View File

@@ -14,6 +14,8 @@ matrix:
env: TOXENV=py35
- python: "3.6"
env: TOXENV=py36
- python: "3.6-dev"
env: TOXENV=py36
# allow_failures:
# - python: "3.5"
# env: TOXENV=typing

View File

@@ -8,6 +8,7 @@ MAINTAINER Paulus Schoutsen <Paulus@PaulusSchoutsen.nl>
#ENV INSTALL_OPENZWAVE no
#ENV INSTALL_LIBCEC no
#ENV INSTALL_PHANTOMJS no
#ENV INSTALL_COAP_CLIENT no
VOLUME /config
@@ -21,9 +22,9 @@ RUN virtualization/Docker/setup_docker_prereqs
# Install hass component dependencies
COPY requirements_all.txt requirements_all.txt
RUN pip3 install --no-cache-dir -r requirements_all.txt && \
pip3 install --no-cache-dir mysqlclient psycopg2 uvloop
pip3 install --no-cache-dir mysqlclient psycopg2 uvloop cchardet
# Copy source
COPY . .
CMD [ "python", "-m", "homeassistant", "--config", "/config" ]
CMD [ "python", "-m", "homeassistant", "--config", "/config" ]

View File

@@ -1,5 +1,5 @@
include README.rst
include LICENSE
include LICENSE.md
graft homeassistant
prune homeassistant/components/frontend/www_static/home-assistant-polymer
recursive-exclude * *.py[co]

View File

@@ -1,9 +1,7 @@
Home Assistant |Build Status| |Coverage Status| |Join the chat at https://gitter.im/home-assistant/home-assistant| |Join the dev chat at https://gitter.im/home-assistant/home-assistant/devs|
==============================================================================================================================================================================================
Home Assistant is a home automation platform running on Python 3. The
goal of Home Assistant is to be able to track and control all devices at
home and offer a platform for automating control.
Home Assistant is a home automation platform running on Python 3. It is able to track and control all devices at home and offer a platform for automating control.
To get started:
@@ -12,82 +10,22 @@ To get started:
python3 -m pip install homeassistant
hass --open-ui
Check out `the website <https://home-assistant.io>`__ for `a
demo <https://home-assistant.io/demo/>`__, installation instructions,
tutorials and documentation.
Check out `home-assistant.io <https://home-assistant.io>`__ for `a
demo <https://home-assistant.io/demo/>`__, `installation instructions <https://home-assistant.io/getting-started/>`__,
`tutorials <https://home-assistant.io/getting-started/automation-2/>`__ and `documentation <https://home-assistant.io/docs/>`__.
|screenshot-states|
Examples of devices Home Assistant can interface with:
Featured integrations
---------------------
- Monitoring connected devices to a wireless router:
`OpenWrt <https://openwrt.org/>`__,
`Tomato <http://www.polarcloud.com/tomato>`__,
`Netgear <http://netgear.com>`__,
`DD-WRT <http://www.dd-wrt.com/site/index>`__,
`TPLink <http://www.tp-link.us/>`__,
`ASUSWRT <http://event.asus.com/2013/nw/ASUSWRT/>`__,
`Xiaomi <http://miwifi.com/>`__ and any SNMP
capable Linksys WAP/WRT
- `Philips Hue <http://meethue.com>`__ lights,
`WeMo <http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/>`__
switches, `Edimax <http://www.edimax.com/>`__ switches,
`Efergy <https://efergy.com>`__ energy monitoring, and
`Tellstick <http://www.telldus.se/products/tellstick>`__ devices and
sensors
- `Google
Chromecasts <http://www.google.com/intl/en/chrome/devices/chromecast>`__,
`Music Player Daemon <http://www.musicpd.org/>`__, `Logitech
Squeezebox <https://en.wikipedia.org/wiki/Squeezebox_%28network_music_player%29>`__,
`Plex <https://plex.tv/>`__, `Kodi (XBMC) <http://kodi.tv/>`__,
iTunes (by way of
`itunes-api <https://github.com/maddox/itunes-api>`__), and Amazon
Fire TV (by way of
`python-firetv <https://github.com/happyleavesaoc/python-firetv>`__)
- Support for
`ISY994 <https://www.universal-devices.com/residential/isy994i-series/>`__
(Insteon and X10 devices), `Z-Wave <http://www.z-wave.com/>`__, `Nest
Thermostats <https://nest.com/>`__,
`RFXtrx <http://www.rfxcom.com/>`__,
`Arduino <https://www.arduino.cc/>`__, `Raspberry
Pi <https://www.raspberrypi.org/>`__, and
`Modbus <http://www.modbus.org/>`__
- Interaction with `IFTTT <https://ifttt.com/>`__
- Integrate data from the `Bitcoin <https://bitcoin.org>`__ network,
meteorological data from
`OpenWeatherMap <http://openweathermap.org/>`__ and
`Forecast.io <https://forecast.io/>`__,
`Transmission <http://www.transmissionbt.com/>`__, or
`SABnzbd <http://sabnzbd.org>`__.
- `See full list of supported
devices <https://home-assistant.io/components/>`__
|screenshot-components|
Build home automation on top of your devices:
- Keep a precise history of every change to the state of your house
- Turn on the lights when people get home after sunset
- Turn on lights slowly during sunset to compensate for less light
- Turn off all lights and devices when everybody leaves the house
- Offers a `REST API <https://home-assistant.io/developers/rest_api/>`__
and can interface with MQTT for easy integration with other projects
like `OwnTracks <http://owntracks.org/>`__
- Allow sending notifications using
`Instapush <https://instapush.im>`__, `Notify My Android
(NMA) <http://www.notifymyandroid.com/>`__,
`PushBullet <https://www.pushbullet.com/>`__,
`PushOver <https://pushover.net/>`__, `Slack <https://slack.com/>`__,
`Telegram <https://telegram.org/>`__, `Join <http://joaoapps.com/join/>`__, and `Jabber
(XMPP) <http://xmpp.org>`__
The system is built using a modular approach so support for other devices or actions can
be implemented easily. See also the `section on
architecture <https://home-assistant.io/developers/architecture/>`__
and the `section on creating your own
The system is built using a modular approach so support for other devices or actions can be implemented easily. See also the `section on architecture <https://home-assistant.io/developers/architecture/>`__ and the `section on creating your own
components <https://home-assistant.io/developers/creating_components/>`__.
If you run into issues while using Home Assistant or during development
of a component, check the `Home Assistant help
section <https://home-assistant.io/help/>`__ of our website for further help and information.
of a component, check the `Home Assistant help section <https://home-assistant.io/help/>`__ of our website for further help and information.
.. |Build Status| image:: https://travis-ci.org/home-assistant/home-assistant.svg?branch=master
:target: https://travis-ci.org/home-assistant/home-assistant
@@ -99,3 +37,5 @@ section <https://home-assistant.io/help/>`__ of our website for further help and
:target: https://gitter.im/home-assistant/home-assistant/devs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
.. |screenshot-states| image:: https://raw.github.com/home-assistant/home-assistant/master/docs/screenshots.png
:target: https://home-assistant.io/demo/
.. |screenshot-components| image:: https://raw.github.com/home-assistant/home-assistant/dev/docs/screenshot-components.png
:target: https://home-assistant.io/components/

View File

@@ -1,158 +0,0 @@
homeassistant:
# Omitted values in this section will be auto detected using freegeoip.io
# Location required to calculate the time the sun rises and sets.
# Coordinates are also used for location for weather related components.
# Google Maps can be used to determine more precise GPS coordinates.
latitude: 32.87336
longitude: 117.22743
# Impacts weather/sunrise data
elevation: 665
# 'metric' for Metric System, 'imperial' for imperial system
unit_system: metric
# Pick yours from here:
# http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
time_zone: America/Los_Angeles
# Name of the location where Home Assistant is running
name: Home
http:
api_password: mypass
# Set to 1 to enable development mode
# development: 1
# Enable the frontend
frontend:
light:
# platform: hue
wink:
# Get your token at https://winkbearertoken.appspot.com
access_token: 'YOUR_TOKEN'
device_tracker:
# The following tracker are available:
# https://home-assistant.io/components/#presence-detection
platform: netgear
host: 192.168.1.1
username: admin
password: PASSWORD
switch:
platform: wemo
climate:
platform: nest
# Required: username and password that are used to login to the Nest thermostat.
username: myemail@mydomain.com
password: mypassword
downloader:
download_dir: downloads
notify:
platform: pushbullet
api_key: ABCDEFGHJKLMNOPQRSTUVXYZ
device_sun_light_trigger:
# Optional: specify a specific light/group of lights that has to be turned on
light_group: group.living_room
# Optional: specify which light profile to use when turning lights on
light_profile: relax
# Optional: disable lights being turned off when everybody leaves the house
# disable_turn_off: 1
# A comma separated list of states that have to be tracked as a single group
# Grouped states should share the same type of states (ON/OFF or HOME/NOT_HOME)
# You can also have groups within groups.
# https://home-assistant.io/components/group/
group:
default_view:
view: yes
entities:
- group.awesome_people
- group.climate
kitchen:
name: Kitchen
entities:
- switch.kitchen_pin_3
upstairs:
name: Kids
icon: mdi:account-multiple
view: yes
entities:
- input_boolean.notify_home
- camera.demo_camera
browser:
keyboard:
# https://home-assistant.io/getting-started/automation/
automation:
- alias: Turn on light when sun sets
trigger:
platform: sun
event: sunset
offset: "-01:00:00"
condition:
condition: state
entity_id: group.all_devices
state: 'home'
action:
service: light.turn_on
# Another way to do is to collect all entries under one "sensor:"
# sensor:
# - platform: mqtt
# name: "MQTT Sensor 1"
# - platform: mqtt
# name: "MQTT Sensor 2"
#
# Details: https://home-assistant.io/getting-started/devices/
sensor:
platform: systemmonitor
resources:
- type: 'disk_use_percent'
arg: '/'
- type: 'disk_use_percent'
arg: '/home'
sensor 2:
platform: cpuspeed
script:
wakeup:
alias: Wake Up
sequence:
- event: LOGBOOK_ENTRY
event_data:
name: Paulus
message: is waking up
entity_id: device_tracker.paulus
domain: light
- alias: Bedroom lights on
service: light.turn_on
data:
entity_id: group.bedroom
brightness: 100
- delay:
minutes: 1
- alias: Living room lights on
service: light.turn_on
data:
entity_id: group.living_room
scene:
- name: Romantic
entities:
light.tv_back_light: on
light.ceiling:
state: on
xy_color: [0.33, 0.66]
brightness: 200

View File

@@ -1,149 +0,0 @@
"""
Example of a custom component.
Example component to target an entity_id to:
- turn it on at 7AM in the morning
- turn it on if anyone comes home and it is off
- turn it off if all lights are turned off
- turn it off if all people leave the house
- offer a service to turn it on for 10 seconds
Configuration:
To use the Example custom component you will need to add the following to
your configuration.yaml file.
example:
target: TARGET_ENTITY
Variable:
target
*Required
TARGET_ENTITY should be one of your devices that can be turned on and off,
ie a light or a switch. Example value could be light.Ceiling or switch.AC
(if you have these devices with those names).
"""
import time
import logging
from homeassistant.const import STATE_HOME, STATE_NOT_HOME, STATE_ON, STATE_OFF
from homeassistant.helpers import validate_config
from homeassistant.helpers.event_decorators import \
track_state_change, track_time_change
from homeassistant.helpers.service import service
import homeassistant.components as core
from homeassistant.components import device_tracker
from homeassistant.components import light
# The domain of your component. Should be equal to the name of your component.
DOMAIN = "example"
# List of component names (string) your component depends upon.
# We depend on group because group will be loaded after all the components that
# initialize devices have been setup.
DEPENDENCIES = ['group', 'device_tracker', 'light']
# Configuration key for the entity id we are targeting.
CONF_TARGET = 'target'
# Variable for storing configuration parameters.
TARGET_ID = None
# Name of the service that we expose.
SERVICE_FLASH = 'flash'
# Shortcut for the logger
_LOGGER = logging.getLogger(__name__)
def setup(hass, config):
"""Setup example component."""
global TARGET_ID
# Validate that all required config options are given.
if not validate_config(config, {DOMAIN: [CONF_TARGET]}, _LOGGER):
return False
TARGET_ID = config[DOMAIN][CONF_TARGET]
# Validate that the target entity id exists.
if hass.states.get(TARGET_ID) is None:
_LOGGER.error("Target entity id %s does not exist",
TARGET_ID)
# Tell the bootstrapper that we failed to initialize and clear the
# stored target id so our functions don't run.
TARGET_ID = None
return False
# Tell the bootstrapper that we initialized successfully.
return True
@track_state_change(device_tracker.ENTITY_ID_ALL_DEVICES)
def track_devices(hass, entity_id, old_state, new_state):
"""Called when the group.all devices change state."""
# If the target id is not set, return
if not TARGET_ID:
return
# If anyone comes home and the entity is not on, turn it on.
if new_state.state == STATE_HOME and not core.is_on(hass, TARGET_ID):
core.turn_on(hass, TARGET_ID)
# If all people leave the house and the entity is on, turn it off.
elif new_state.state == STATE_NOT_HOME and core.is_on(hass, TARGET_ID):
core.turn_off(hass, TARGET_ID)
@track_time_change(hour=7, minute=0, second=0)
def wake_up(hass, now):
"""Turn light on in the morning.
Turn the light on at 7 AM if there are people home and it is not already
on.
"""
if not TARGET_ID:
return
if device_tracker.is_on(hass) and not core.is_on(hass, TARGET_ID):
_LOGGER.info('People home at 7AM, turning it on')
core.turn_on(hass, TARGET_ID)
@track_state_change(light.ENTITY_ID_ALL_LIGHTS, STATE_ON, STATE_OFF)
def all_lights_off(hass, entity_id, old_state, new_state):
"""If all lights turn off, turn off."""
if not TARGET_ID:
return
if core.is_on(hass, TARGET_ID):
_LOGGER.info('All lights have been turned off, turning it off')
core.turn_off(hass, TARGET_ID)
@service(DOMAIN, SERVICE_FLASH)
def flash_service(hass, call):
"""Service that will toggle the target.
Set the light to off for 10 seconds if on and vice versa.
"""
if not TARGET_ID:
return
if core.is_on(hass, TARGET_ID):
core.turn_off(hass, TARGET_ID)
time.sleep(10)
core.turn_on(hass, TARGET_ID)
else:
core.turn_on(hass, TARGET_ID)
time.sleep(10)
core.turn_off(hass, TARGET_ID)

View File

@@ -1,27 +0,0 @@
"""
The "hello world" custom component.
This component implements the bare minimum that a component should implement.
Configuration:
To use the hello_word component you will need to add the following to your
configuration.yaml file.
hello_world:
"""
# The domain of your component. Should be equal to the name of your component.
DOMAIN = "hello_world"
# List of component names (string) your component depends upon.
DEPENDENCIES = []
def setup(hass, config):
"""Setup our skeleton component."""
# States are in the format DOMAIN.OBJECT_ID.
hass.states.set('hello_world.Hello_World', 'Works!')
# Return boolean to indicate that initialization was successfully.
return True

View File

@@ -1,55 +0,0 @@
"""
Example of a custom MQTT component.
Shows how to communicate with MQTT. Follows a topic on MQTT and updates the
state of an entity to the last message received on that topic.
Also offers a service 'set_state' that will publish a message on the topic that
will be passed via MQTT to our message received listener. Call the service with
example payload {"new_state": "some new state"}.
Configuration:
To use the mqtt_example component you will need to add the following to your
configuration.yaml file.
mqtt_example:
topic: "home-assistant/mqtt_example"
"""
import homeassistant.loader as loader
# The domain of your component. Should be equal to the name of your component.
DOMAIN = "mqtt_example"
# List of component names (string) your component depends upon.
DEPENDENCIES = ['mqtt']
CONF_TOPIC = 'topic'
DEFAULT_TOPIC = 'home-assistant/mqtt_example'
def setup(hass, config):
"""Setup the MQTT example component."""
mqtt = loader.get_component('mqtt')
topic = config[DOMAIN].get('topic', DEFAULT_TOPIC)
entity_id = 'mqtt_example.last_message'
# Listen to a message on MQTT.
def message_received(topic, payload, qos):
"""A new MQTT message has been received."""
hass.states.set(entity_id, payload)
mqtt.subscribe(hass, topic, message_received)
hass.states.set(entity_id, 'No messages')
# Service to publish a message on MQTT.
def set_state_service(call):
"""Service to send a message."""
mqtt.publish(hass, topic, call.data.get('new_state'))
# Register our service with Home Assistant.
hass.services.register(DOMAIN, 'set_state', set_state_service)
# Return boolean to indicate that initialization was successfully.
return True

View File

@@ -1,432 +0,0 @@
<!--
Custom Home Assistant panel example.
Currently only works in Firefox and Chrome because it uses ES6.
Make sure this file is in <config>/panels/react.html
Add to your configuration.yaml:
panel_custom:
- name: react
sidebar_title: TodoMVC
sidebar_icon: mdi:checkbox-marked-outline
config:
title: Wow hello!
-->
<script src="https://fb.me/react-15.2.1.min.js"></script>
<script src="https://fb.me/react-dom-15.2.1.min.js"></script>
<!-- for development, replace with:
<script src="https://fb.me/react-15.2.1.js"></script>
<script src="https://fb.me/react-dom-15.2.1.js"></script>
-->
<!--
CSS taken from ReactJS TodoMVC example by Pete Hunt
http://todomvc.com/examples/react/
-->
<style>
.todoapp input[type="checkbox"] {
outline: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.todoapp .main {
position: relative;
border-top: 1px solid #e6e6e6;
}
.todoapp .todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todoapp .todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todoapp .todo-list li:last-child {
border-bottom: none;
}
.todoapp .todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
cursor: pointer;
}
.todoapp .todo-list li .toggle:focus {
border-left: 3px solid rgba(175, 47, 47, 0.35);
}
.todoapp .todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
}
.todoapp .todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
}
.todoapp .todo-list li label {
white-space: pre-line;
word-break: break-all;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todoapp .todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todoapp .footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.todoapp .footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todoapp .todo-count {
float: left;
text-align: left;
font-weight: 300;
}
.todoapp .toggle-menu {
position: absolute;
right: 15px;
font-weight: 300;
color: rgba(175, 47, 47, 0.75);
}
.todoapp .filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.todoapp .filters li {
display: inline;
}
.todoapp .filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.todoapp .filters li a.selected,
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.todoapp .filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.todoapp .toggle-all,
.todoapp .todo-list li .toggle {
background: none;
}
.todoapp .todo-list li .toggle {
height: 40px;
}
.todoapp .toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
@media (max-width: 430px) {
.todoapp .footer {
height: 50px;
}
.todoapp .filters {
bottom: 10px;
}
}
</style>
<dom-module id='ha-panel-react'>
<template>
<style>
:host {
background: #f5f5f5;
display: block;
height: 100%;
overflow: auto;
}
.mount {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300;
}
</style>
<div id='mount' class='mount'></div>
</template>
</dom-module>
<script>
// Example uses ES6. Will only work in modern browsers
class TodoMVC extends React.Component {
constructor(props) {
super(props);
this.state = {
filter: 'all',
// load initial value of entities
entities: this.props.hass.reactor.evaluate(
this.props.hass.entityGetters.visibleEntityMap),
};
}
componentDidMount() {
// register to entity updates
this._unwatchHass = this.props.hass.reactor.observe(
this.props.hass.entityGetters.visibleEntityMap,
entities => this.setState({entities}))
}
componentWillUnmount() {
// unregister to entity updates
this._unwatchHass();
}
handlePickFilter(filter, ev) {
ev.preventDefault();
this.setState({filter});
}
handleEntityToggle(entity, ev) {
this.props.hass.serviceActions.callService(
entity.domain, 'toggle', { entity_id: entity.entityId });
}
handleToggleMenu(ev) {
ev.preventDefault();
Polymer.Base.fire('open-menu', null, {node: ev.target});
}
entityRow(entity) {
const completed = entity.state === 'on';
return React.createElement(
'li', {
className: completed && 'completed',
key: entity.entityId,
},
React.createElement(
"div", { className: "view" },
React.createElement(
"input", {
checked: completed,
className: "toggle",
type: "checkbox",
onChange: ev => this.handleEntityToggle(entity, ev),
}),
React.createElement("label", null, entity.entityDisplay)));
}
filterRow(filter) {
return React.createElement(
"li", { key: filter },
React.createElement(
"a", {
href: "#",
className: this.state.filter === filter && "selected",
onClick: ev => this.handlePickFilter(filter, ev),
},
filter.substring(0, 1).toUpperCase() + filter.substring(1)
)
);
}
render() {
const { entities, filter } = this.state;
if (!entities) return null;
const filters = ['all', 'light', 'switch'];
const showEntities = filter === 'all' ?
entities.filter(ent => filters.includes(ent.domain)) :
entities.filter(ent => ent.domain == filter);
return React.createElement(
'div', { className: 'todoapp-wrapper' },
React.createElement(
"section", { className: "todoapp" },
React.createElement(
"div", null,
React.createElement(
"header", { className: "header" },
React.createElement("h1", null, this.props.title || "todos")
),
React.createElement(
"section", { className: "main" },
React.createElement(
"ul", { className: "todo-list" },
showEntities.valueSeq().map(ent => this.entityRow(ent)))
)
),
React.createElement(
"footer", { className: "footer" },
React.createElement(
"span", { className: "todo-count" },
showEntities.filter(ent => ent.state === 'off').size + " items left"
),
React.createElement(
"ul", { className: "filters" },
filters.map(filter => this.filterRow(filter))
),
!this.props.showMenu && React.createElement(
"a", {
className: "toggle-menu",
href: '#',
onClick: ev => this.handleToggleMenu(ev),
},
"Show menu"
)
)
));
}
}
Polymer({
is: 'ha-panel-react',
properties: {
// Home Assistant object
hass: {
type: Object,
},
// If should render in narrow mode
narrow: {
type: Boolean,
value: false,
},
// If sidebar is currently shown
showMenu: {
type: Boolean,
value: false,
},
// Home Assistant panel info
// panel.config contains config passed to register_panel serverside
panel: {
type: Object,
}
},
// This will make sure we forward changed properties to React
observers: [
'propsChanged(hass, narrow, showMenu, panel)',
],
// Mount React when element attached
attached: function () {
this.mount(this.hass, this.narrow, this.showMenu, this.panel);
},
// Called when properties change
propsChanged: function (hass, narrow, showMenu, panel) {
this.mount(hass, narrow, showMenu, panel);
},
// Render React. Debounce in case multiple properties change.
mount: function (hass, narrow, showMenu, panel) {
this.debounce('mount', function () {
ReactDOM.render(React.createElement(TodoMVC, {
hass: hass,
narrow: narrow,
showMenu: showMenu,
title: panel.config ? panel.config.title : null
}), this.$.mount);
}.bind(this));
},
// Unmount React node when panel no longer in use.
detached: function () {
ReactDOM.unmountComponentAtNode(this.$.mount);
},
});
</script>

BIN
docs/screenshot-components.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -1,4 +1,4 @@
"""Starts home assistant."""
"""Start Home Assistant."""
from __future__ import print_function
import argparse
@@ -20,6 +20,17 @@ from homeassistant.const import (
from homeassistant.util.async import run_callback_threadsafe
def attempt_use_uvloop():
"""Attempt to use uvloop."""
import asyncio
try:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError:
pass
def monkey_patch_asyncio():
"""Replace weakref.WeakSet to address Python 3 bug.
@@ -255,15 +266,18 @@ 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('/__main__.py'):
if sys.argv[0].endswith(os.path.sep + '__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 arg != '--daemon']
return [sys.executable] + [arg for arg in sys.argv if
arg != '--daemon']
else:
return [arg for arg in sys.argv if arg != '--daemon']
def setup_and_run_hass(config_dir: str,
args: argparse.Namespace) -> Optional[int]:
"""Setup HASS and run."""
"""Set up HASS and run."""
from homeassistant import bootstrap
# Run a simple daemon runner process on Windows to handle restarts
@@ -308,8 +322,7 @@ def setup_and_run_hass(config_dir: str,
EVENT_HOMEASSISTANT_START, open_browser
)
hass.start()
return hass.exit_code
return hass.start()
def try_to_restart() -> None:
@@ -356,11 +369,13 @@ def try_to_restart() -> None:
def main() -> int:
"""Start Home Assistant."""
validate_python()
attempt_use_uvloop()
if sys.version_info[:3] < (3, 5, 3):
monkey_patch_asyncio()
validate_python()
args = get_arguments()
if args.script is not None:

View File

@@ -1,318 +1,34 @@
"""Provides methods to bootstrap a home assistant instance."""
"""Provide methods to bootstrap a Home Assistant instance."""
import asyncio
import logging
import logging.handlers
import os
import sys
from time import time
from collections import OrderedDict
from types import ModuleType
from typing import Any, Optional, Dict
import voluptuous as vol
from voluptuous.humanize import humanize_error
import homeassistant.components as core_components
from homeassistant.components import persistent_notification
import homeassistant.config as conf_util
import homeassistant.core as core
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
from homeassistant.setup import async_setup_component
import homeassistant.loader as loader
import homeassistant.util.package as pkg_util
from homeassistant.util.async import (
run_coroutine_threadsafe, run_callback_threadsafe)
from homeassistant.util.logging import AsyncHandler
from homeassistant.util.yaml import clear_secret_cache
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
event_decorators, service, config_per_platform, extract_domain_configs)
from homeassistant.helpers.signal import async_register_signal_handling
_LOGGER = logging.getLogger(__name__)
ATTR_COMPONENT = 'component'
ERROR_LOG_FILENAME = 'home-assistant.log'
_PERSISTENT_ERRORS = {}
HA_COMPONENT_URL = '[{}](https://home-assistant.io/components/{}/)'
def setup_component(hass: core.HomeAssistant, domain: str,
config: Optional[Dict]=None) -> bool:
"""Setup a component and all its dependencies."""
return run_coroutine_threadsafe(
async_setup_component(hass, domain, config), loop=hass.loop).result()
@asyncio.coroutine
def async_setup_component(hass: core.HomeAssistant, domain: str,
config: Optional[Dict]=None) -> bool:
"""Setup a component and all its dependencies.
This method is a coroutine.
"""
if domain in hass.config.components:
_LOGGER.debug('Component %s already set up.', domain)
return True
if not loader.PREPARED:
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
if config is None:
config = {}
components = loader.load_order_component(domain)
# OrderedSet is empty if component or dependencies could not be resolved
if not components:
_async_persistent_notification(hass, domain, True)
return False
for component in components:
res = yield from _async_setup_component(hass, component, config)
if not res:
_LOGGER.error('Component %s failed to setup', component)
_async_persistent_notification(hass, component, True)
return False
return True
def _handle_requirements(hass: core.HomeAssistant, component,
name: str) -> bool:
"""Install the requirements for a component.
This method needs to run in an executor.
"""
if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'):
return True
for req in component.REQUIREMENTS:
if not pkg_util.install_package(req, target=hass.config.path('deps')):
_LOGGER.error('Not initializing %s because could not install '
'dependency %s', name, req)
_async_persistent_notification(hass, name)
return False
return True
@asyncio.coroutine
def _async_setup_component(hass: core.HomeAssistant,
domain: str, config) -> bool:
"""Setup a component for Home Assistant.
This method is a coroutine.
"""
# pylint: disable=too-many-return-statements
if domain in hass.config.components:
return True
setup_lock = hass.data.get('setup_lock')
if setup_lock is None:
setup_lock = hass.data['setup_lock'] = asyncio.Lock(loop=hass.loop)
setup_progress = hass.data.get('setup_progress')
if setup_progress is None:
setup_progress = hass.data['setup_progress'] = []
if domain in setup_progress:
_LOGGER.error('Attempt made to setup %s during setup of %s',
domain, domain)
_async_persistent_notification(hass, domain, True)
return False
try:
# Used to indicate to discovery that a setup is ongoing and allow it
# to wait till it is done.
did_lock = False
if not setup_lock.locked():
yield from setup_lock.acquire()
did_lock = True
setup_progress.append(domain)
config = yield from async_prepare_setup_component(hass, config, domain)
if config is None:
return False
component = loader.get_component(domain)
if component is None:
_async_persistent_notification(hass, domain)
return False
async_comp = hasattr(component, 'async_setup')
try:
_LOGGER.info("Setting up %s", domain)
if async_comp:
result = yield from component.async_setup(hass, config)
else:
result = yield from hass.loop.run_in_executor(
None, component.setup, hass, config)
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error during setup of component %s', domain)
_async_persistent_notification(hass, domain, True)
return False
if result is False:
_LOGGER.error('component %s failed to initialize', domain)
_async_persistent_notification(hass, domain, True)
return False
elif result is not True:
_LOGGER.error('component %s did not return boolean if setup '
'was successful. Disabling component.', domain)
_async_persistent_notification(hass, domain, True)
loader.set_component(domain, None)
return False
hass.config.components.append(component.DOMAIN)
hass.bus.async_fire(
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}
)
return True
finally:
setup_progress.remove(domain)
if did_lock:
setup_lock.release()
def prepare_setup_component(hass: core.HomeAssistant, config: dict,
domain: str):
"""Prepare setup of a component and return processed config."""
return run_coroutine_threadsafe(
async_prepare_setup_component(hass, config, domain), loop=hass.loop
).result()
@asyncio.coroutine
def async_prepare_setup_component(hass: core.HomeAssistant, config: dict,
domain: str):
"""Prepare setup of a component and return processed config.
This method is a coroutine.
"""
# pylint: disable=too-many-return-statements
component = loader.get_component(domain)
missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
if dep not in hass.config.components]
if missing_deps:
_LOGGER.error(
'Not initializing %s because not all dependencies loaded: %s',
domain, ", ".join(missing_deps))
return None
if hasattr(component, 'CONFIG_SCHEMA'):
try:
config = component.CONFIG_SCHEMA(config)
except vol.Invalid as ex:
async_log_exception(ex, domain, config, hass)
return None
elif hasattr(component, 'PLATFORM_SCHEMA'):
platforms = []
for p_name, p_config in config_per_platform(config, domain):
# Validate component specific platform schema
try:
p_validated = component.PLATFORM_SCHEMA(p_config)
except vol.Invalid as ex:
async_log_exception(ex, domain, config, hass)
continue
# Not all platform components follow same pattern for platforms
# So if p_name is None we are not going to validate platform
# (the automation component is one of them)
if p_name is None:
platforms.append(p_validated)
continue
platform = yield from async_prepare_setup_platform(
hass, config, domain, p_name)
if platform is None:
continue
# Validate platform specific schema
if hasattr(platform, 'PLATFORM_SCHEMA'):
try:
# pylint: disable=no-member
p_validated = platform.PLATFORM_SCHEMA(p_validated)
except vol.Invalid as ex:
async_log_exception(ex, '{}.{}'.format(domain, p_name),
p_validated, hass)
continue
platforms.append(p_validated)
# Create a copy of the configuration with all config for current
# component removed and add validated config back in.
filter_keys = extract_domain_configs(config, domain)
config = {key: value for key, value in config.items()
if key not in filter_keys}
config[domain] = platforms
res = yield from hass.loop.run_in_executor(
None, _handle_requirements, hass, component, domain)
if not res:
return None
return config
def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
platform_name: str) -> Optional[ModuleType]:
"""Load a platform and makes sure dependencies are setup."""
return run_coroutine_threadsafe(
async_prepare_setup_platform(hass, config, domain, platform_name),
loop=hass.loop
).result()
@asyncio.coroutine
def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
platform_name: str) \
-> Optional[ModuleType]:
"""Load a platform and makes sure dependencies are setup.
This method is a coroutine.
"""
if not loader.PREPARED:
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
platform = loader.get_platform(domain, platform_name)
# Not found
if platform is None:
_LOGGER.error('Unable to find platform %s', platform_path)
_async_persistent_notification(hass, platform_path)
return None
# Already loaded
elif platform_path in hass.config.components:
return platform
# Load dependencies
for component in getattr(platform, 'DEPENDENCIES', []):
res = yield from async_setup_component(hass, component, config)
if not res:
_LOGGER.error(
'Unable to prepare setup for platform %s because '
'dependency %s could not be initialized', platform_path,
component)
_async_persistent_notification(hass, platform_path, True)
return None
res = yield from hass.loop.run_in_executor(
None, _handle_requirements, hass, platform, platform_path)
if not res:
return None
return platform
FIRST_INIT_COMPONENT = set((
'recorder', 'mqtt', 'mqtt_eventstream', 'logger', 'introduction',
'frontend', 'history'))
def from_config_dict(config: Dict[str, Any],
@@ -334,23 +50,14 @@ def from_config_dict(config: Dict[str, Any],
hass.config.config_dir = config_dir
mount_local_lib_path(config_dir)
@asyncio.coroutine
def _async_init_from_config_dict(future):
try:
re_hass = yield from async_from_config_dict(
config, hass, config_dir, enable_log, verbose, skip_pip,
log_rotate_days)
future.set_result(re_hass)
# pylint: disable=broad-except
except Exception as exc:
future.set_exception(exc)
# run task
future = asyncio.Future(loop=hass.loop)
hass.async_add_job(_async_init_from_config_dict(future))
hass.loop.run_until_complete(future)
hass = hass.loop.run_until_complete(
async_from_config_dict(
config, hass, config_dir, enable_log, verbose, skip_pip,
log_rotate_days)
)
return future.result()
return hass
@asyncio.coroutine
@@ -367,26 +74,20 @@ def async_from_config_dict(config: Dict[str, Any],
Dynamically loads required components and its dependencies.
This method is a coroutine.
"""
hass.async_track_tasks()
setup_lock = hass.data.get('setup_lock')
if setup_lock is None:
setup_lock = hass.data['setup_lock'] = asyncio.Lock(loop=hass.loop)
yield from setup_lock.acquire()
start = time()
core_config = config.get(core.DOMAIN, {})
try:
yield from conf_util.async_process_ha_core_config(hass, core_config)
except vol.Invalid as ex:
async_log_exception(ex, 'homeassistant', core_config, hass)
conf_util.async_log_exception(ex, 'homeassistant', core_config, hass)
return None
yield from hass.loop.run_in_executor(
None, conf_util.process_ha_config_upgrade, hass)
if enable_log:
enable_logging(hass, verbose, log_rotate_days)
async_enable_logging(hass, verbose, log_rotate_days)
hass.config.skip_pip = skip_pip
if skip_pip:
@@ -424,17 +125,24 @@ def async_from_config_dict(config: Dict[str, Any],
_LOGGER.info('Home Assistant core initialized')
# Give event decorators access to HASS
event_decorators.HASS = hass
service.HASS = hass
# stage 1
for component in components:
if component not in FIRST_INIT_COMPONENT:
continue
hass.async_add_job(async_setup_component(hass, component, config))
# Setup the components
for domain in loader.load_order_components(components):
yield from _async_setup_component(hass, domain, config)
yield from hass.async_block_till_done()
setup_lock.release()
# stage 2
for component in components:
if component in FIRST_INIT_COMPONENT:
continue
hass.async_add_job(async_setup_component(hass, component, config))
yield from hass.async_stop_track_tasks()
yield from hass.async_block_till_done()
stop = time()
_LOGGER.info('Home Assistant initialized in %.2fs', stop-start)
async_register_signal_handling(hass)
return hass
@@ -453,22 +161,13 @@ def from_config_file(config_path: str,
if hass is None:
hass = core.HomeAssistant()
@asyncio.coroutine
def _async_init_from_config_file(future):
try:
re_hass = yield from async_from_config_file(
config_path, hass, verbose, skip_pip, log_rotate_days)
future.set_result(re_hass)
# pylint: disable=broad-except
except Exception as exc:
future.set_exception(exc)
# run task
future = asyncio.Future(loop=hass.loop)
hass.loop.create_task(_async_init_from_config_file(future))
hass.loop.run_until_complete(future)
hass = hass.loop.run_until_complete(
async_from_config_file(
config_path, hass, verbose, skip_pip, log_rotate_days)
)
return future.result()
return hass
@asyncio.coroutine
@@ -488,12 +187,13 @@ def async_from_config_file(config_path: str,
yield from hass.loop.run_in_executor(
None, mount_local_lib_path, config_dir)
enable_logging(hass, verbose, log_rotate_days)
async_enable_logging(hass, verbose, log_rotate_days)
try:
config_dict = yield from hass.loop.run_in_executor(
None, conf_util.load_yaml_config_file, config_path)
except HomeAssistantError:
except HomeAssistantError as err:
_LOGGER.error('Error loading %s: %s', config_path, err)
return None
finally:
clear_secret_cache()
@@ -503,22 +203,23 @@ def async_from_config_file(config_path: str,
return hass
def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
log_rotate_days=None) -> None:
"""Setup the logging.
@core.callback
def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
log_rotate_days=None) -> None:
"""Set up the logging.
Async friendly.
This method must be run in the event loop.
"""
logging.basicConfig(level=logging.INFO)
fmt = ("%(asctime)s %(levelname)s (%(threadName)s) "
"[%(name)s] %(message)s")
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
datefmt = '%y-%m-%d %H:%M:%S'
datefmt = '%Y-%m-%d %H:%M:%S'
# suppress overly verbose logs from libraries that aren't helpful
logging.getLogger("requests").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("aiohttp.access").setLevel(logging.WARNING)
# Suppress overly verbose logs from libraries that aren't helpful
logging.getLogger('requests').setLevel(logging.WARNING)
logging.getLogger('urllib3').setLevel(logging.WARNING)
logging.getLogger('aiohttp.access').setLevel(logging.WARNING)
try:
from colorlog import ColoredFormatter
@@ -537,10 +238,6 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
except ImportError:
pass
# AsyncHandler allready exists?
if hass.data.get(core.DATA_ASYNCHANDLER):
return
# Log errors to a file if we have write access to file or config dir
err_log_path = hass.config.path(ERROR_LOG_FILENAME)
err_path_exists = os.path.isfile(err_log_path)
@@ -561,7 +258,15 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
err_handler.setFormatter(logging.Formatter(fmt, datefmt=datefmt))
async_handler = AsyncHandler(hass.loop, err_handler)
hass.data[core.DATA_ASYNCHANDLER] = async_handler
@asyncio.coroutine
def async_stop_async_handler(event):
"""Cleanup async handler."""
logging.getLogger('').removeHandler(async_handler)
yield from async_handler.async_close(blocking=True)
hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_CLOSE, async_stop_async_handler)
logger = logging.getLogger('')
logger.addHandler(async_handler)
@@ -569,58 +274,7 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
else:
_LOGGER.error(
'Unable to setup error log %s (access denied)', err_log_path)
def log_exception(ex, domain, config, hass):
"""Generate log exception for config validation."""
run_callback_threadsafe(
hass.loop, async_log_exception, ex, domain, config, hass).result()
@core.callback
def _async_persistent_notification(hass: core.HomeAssistant, component: str,
link: Optional[bool]=False):
"""Print a persistent notification.
This method must be run in the event loop.
"""
_PERSISTENT_ERRORS[component] = _PERSISTENT_ERRORS.get(component) or link
_lst = [HA_COMPONENT_URL.format(name.replace('_', '-'), name)
if link else name for name, link in _PERSISTENT_ERRORS.items()]
message = ('The following components and platforms could not be set up:\n'
'* ' + '\n* '.join(list(_lst)) + '\nPlease check your config')
persistent_notification.async_create(
hass, message, 'Invalid config', 'invalid_config')
@core.callback
def async_log_exception(ex, domain, config, hass):
"""Generate log exception for config validation.
This method must be run in the event loop.
"""
message = 'Invalid config for [{}]: '.format(domain)
if hass is not None:
_async_persistent_notification(hass, domain, True)
if 'extra keys not allowed' in ex.error_message:
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
.format(ex.path[-1], domain, domain,
'->'.join(str(m) for m in ex.path))
else:
message += '{}.'.format(humanize_error(config, ex))
domain_config = config.get(domain, config)
message += " (See {}, line {}). ".format(
getattr(domain_config, '__config_file__', '?'),
getattr(domain_config, '__line__', '?'))
if domain != 'homeassistant':
message += ('Please check the docs at '
'https://home-assistant.io/components/{}/'.format(domain))
_LOGGER.error(message)
"Unable to setup error log %s (access denied)", err_log_path)
def mount_local_lib_path(config_dir: str) -> str:

View File

@@ -102,10 +102,10 @@ def reload_core_config(hass):
@asyncio.coroutine
def async_setup(hass, config):
"""Setup general services related to Home Assistant."""
"""Set up general services related to Home Assistant."""
@asyncio.coroutine
def async_handle_turn_service(service):
"""Method to handle calls to homeassistant.turn_on/off."""
"""Handle calls to homeassistant.turn_on/off."""
entity_ids = extract_entity_ids(hass, service)
# Generic turn on/off method requires entity id
@@ -156,10 +156,18 @@ def async_setup(hass, config):
return
try:
yield from conf_util.async_check_ha_config_file(hass)
errors = yield from conf_util.async_check_ha_config_file(hass)
except HomeAssistantError:
return
if errors:
notif = get_component('persistent_notification')
_LOGGER.error(errors)
notif.async_create(
hass, "Config error. See dev-info panel for details.",
"Config validating", "{0}.check_config".format(ha.DOMAIN))
return
if call.service == SERVICE_HOMEASSISTANT_RESTART:
hass.async_add_job(hass.async_stop(RESTART_EXIT_CODE))

View File

@@ -113,7 +113,7 @@ def async_setup(hass, config):
if not alarm.should_poll:
continue
update_coro = hass.loop.create_task(
update_coro = hass.async_add_job(
alarm.async_update_ha_state(True))
if hasattr(alarm, 'async_update'):
update_tasks.append(update_coro)

View File

@@ -0,0 +1,116 @@
"""
Support for AlarmDecoder-based alarm control panels (Honeywell/DSC).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.alarmdecoder/
"""
import asyncio
import logging
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
import homeassistant.components.alarm_control_panel as alarm
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)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['alarmdecoder']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up for AlarmDecoder alarm panels."""
_LOGGER.debug("AlarmDecoderAlarmPanel: setup")
device = AlarmDecoderAlarmPanel("Alarm Panel", hass)
async_add_devices([device])
return True
class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
"""Representation of an AlarmDecoder-based alarm panel."""
def __init__(self, name, hass):
"""Initialize the alarm panel."""
self._display = ""
self._name = name
self._state = STATE_UNKNOWN
_LOGGER.debug("Setting up panel")
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_PANEL_MESSAGE, self._message_callback)
@callback
def _message_callback(self, message):
if message.alarm_sounding or message.fire_alarm:
if self._state != STATE_ALARM_TRIGGERED:
self._state = STATE_ALARM_TRIGGERED
self.hass.async_add_job(self.async_update_ha_state())
elif message.armed_away:
if self._state != STATE_ALARM_ARMED_AWAY:
self._state = STATE_ALARM_ARMED_AWAY
self.hass.async_add_job(self.async_update_ha_state())
elif message.armed_home:
if self._state != STATE_ALARM_ARMED_HOME:
self._state = STATE_ALARM_ARMED_HOME
self.hass.async_add_job(self.async_update_ha_state())
else:
if self._state != STATE_ALARM_DISARMED:
self._state = STATE_ALARM_DISARMED
self.hass.async_add_job(self.async_update_ha_state())
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def should_poll(self):
"""Return the polling state."""
return False
@property
def code_format(self):
"""Return the regex for code format or None if no code is required."""
return '^\\d{4,6}$'
@property
def state(self):
"""Return the state of the device."""
return self._state
@asyncio.coroutine
def async_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):
"""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):
"""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))

View File

@@ -5,9 +5,8 @@ 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 voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
@@ -15,10 +14,9 @@ from homeassistant.const import (
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN, CONF_CODE,
CONF_NAME)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
REQUIREMENTS = ['https://github.com/Xorso/pyalarmdotcom'
'/archive/0.1.1.zip'
'#pyalarmdotcom==0.1.1']
REQUIREMENTS = ['pyalarmdotcom==0.3.0']
_LOGGER = logging.getLogger(__name__)
@@ -32,14 +30,17 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup an Alarm.com control panel."""
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up a Alarm.com control panel."""
name = config.get(CONF_NAME)
code = config.get(CONF_CODE)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
add_devices([AlarmDotCom(hass, name, code, username, password)], True)
alarmdotcom = AlarmDotCom(hass, name, code, username, password)
yield from alarmdotcom.async_login()
async_add_devices([alarmdotcom])
class AlarmDotCom(alarm.AlarmControlPanel):
@@ -47,18 +48,30 @@ class AlarmDotCom(alarm.AlarmControlPanel):
def __init__(self, hass, name, code, username, password):
"""Initialize the Alarm.com status."""
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
self._alarm = Alarmdotcom(username, password, timeout=10)
from pyalarmdotcom import Alarmdotcom
_LOGGER.debug('Setting up Alarm.com...')
self._hass = hass
self._name = name
self._code = str(code) if code else None
self._username = username
self._password = password
self._websession = async_get_clientsession(self._hass)
self._state = STATE_UNKNOWN
self._alarm = Alarmdotcom(username,
password,
self._websession,
hass.loop)
def update(self):
@asyncio.coroutine
def async_login(self):
"""Login to Alarm.com."""
yield from self._alarm.async_login()
@asyncio.coroutine
def async_update(self):
"""Fetch the latest state."""
self._state = self._alarm.state
yield from self._alarm.async_update()
return self._alarm.state
@property
def name(self):
@@ -73,45 +86,36 @@ class AlarmDotCom(alarm.AlarmControlPanel):
@property
def state(self):
"""Return the state of the device."""
if self._state == 'Disarmed':
if self._alarm.state.lower() == 'disarmed':
return STATE_ALARM_DISARMED
elif self._state == 'Armed Stay':
elif self._alarm.state.lower() == 'armed stay':
return STATE_ALARM_ARMED_HOME
elif self._state == 'Armed Away':
elif self._alarm.state.lower() == 'armed away':
return STATE_ALARM_ARMED_AWAY
else:
return STATE_UNKNOWN
def alarm_disarm(self, code=None):
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'disarming home'):
return
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
# Open another session to alarm.com to fire off the command
_alarm = Alarmdotcom(self._username, self._password, timeout=10)
_alarm.disarm()
if self._validate_code(code):
yield from self._alarm.async_alarm_disarm()
def alarm_arm_home(self, code=None):
"""Send arm home command."""
if not self._validate_code(code, 'arming home'):
return
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
# Open another session to alarm.com to fire off the command
_alarm = Alarmdotcom(self._username, self._password, timeout=10)
_alarm.arm_stay()
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
"""Send arm hom command."""
if self._validate_code(code):
yield from self._alarm.async_alarm_arm_home()
def alarm_arm_away(self, code=None):
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
if not self._validate_code(code, 'arming home'):
return
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
# Open another session to alarm.com to fire off the command
_alarm = Alarmdotcom(self._username, self._password, timeout=10)
_alarm.arm_away()
if self._validate_code(code):
yield from self._alarm.async_alarm_arm_away()
def _validate_code(self, code, state):
def _validate_code(self, code):
"""Validate given code."""
check = self._code is None or code == self._code
if not check:
_LOGGER.warning('Wrong code entered for %s', state)
_LOGGER.warning('Wrong code entered.')
return check

View File

@@ -51,7 +51,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class Concord232Alarm(alarm.AlarmControlPanel):
"""Represents the Concord232-based alarm panel."""
"""Representation of the Concord232-based alarm panel."""
def __init__(self, hass, url, name):
"""Initialize the Concord232 alarm panel."""
@@ -79,7 +79,7 @@ class Concord232Alarm(alarm.AlarmControlPanel):
@property
def code_format(self):
"""The characters if code is defined."""
"""Return the characters if code is defined."""
return '[0-9]{4}([0-9]{2})?'
@property

View File

@@ -8,7 +8,7 @@ import homeassistant.components.alarm_control_panel.manual as manual
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo alarm control panel platform."""
"""Set up the Demo alarm control panel platform."""
add_devices([
manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10, False),
])

View File

@@ -4,16 +4,20 @@ Support for Envisalink-based alarm control panels (Honeywell/DSC).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.envisalink/
"""
from os import path
import asyncio
import logging
import os
import voluptuous as vol
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 (
EVL_CONTROLLER, EnvisalinkDevice, PARTITION_SCHEMA, CONF_CODE, CONF_PANIC,
CONF_PARTITIONNAME, SIGNAL_PARTITION_UPDATE, SIGNAL_KEYPAD_UPDATE)
DATA_EVL, EnvisalinkDevice, PARTITION_SCHEMA, CONF_CODE, CONF_PANIC,
CONF_PARTITIONNAME, SIGNAL_KEYPAD_UPDATE, SIGNAL_PARTITION_UPDATE)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN, STATE_ALARM_TRIGGERED, STATE_ALARM_PENDING, ATTR_ENTITY_ID)
@@ -22,8 +26,6 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['envisalink']
DEVICES = []
SERVICE_ALARM_KEYPRESS = 'envisalink_alarm_keypress'
ATTR_KEYPRESS = 'keypress'
ALARM_KEYPRESS_SCHEMA = vol.Schema({
@@ -32,70 +34,77 @@ ALARM_KEYPRESS_SCHEMA = vol.Schema({
})
def alarm_keypress_handler(service):
"""Map services to methods on Alarm."""
entity_ids = service.data.get(ATTR_ENTITY_ID)
keypress = service.data.get(ATTR_KEYPRESS)
_target_devices = [device for device in DEVICES
if device.entity_id in entity_ids]
for device in _target_devices:
EnvisalinkAlarm.alarm_keypress(device, keypress)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Perform the setup for Envisalink alarm panels."""
_configured_partitions = discovery_info['partitions']
_code = discovery_info[CONF_CODE]
_panic_type = discovery_info[CONF_PANIC]
for part_num in _configured_partitions:
_device_config_data = PARTITION_SCHEMA(
_configured_partitions[part_num])
_device = EnvisalinkAlarm(
part_num,
_device_config_data[CONF_PARTITIONNAME],
_code,
_panic_type,
EVL_CONTROLLER.alarm_state['partition'][part_num],
EVL_CONTROLLER)
DEVICES.append(_device)
configured_partitions = discovery_info['partitions']
code = discovery_info[CONF_CODE]
panic_type = discovery_info[CONF_PANIC]
add_devices(DEVICES)
devices = []
for part_num in configured_partitions:
device_config_data = PARTITION_SCHEMA(configured_partitions[part_num])
device = EnvisalinkAlarm(
hass,
part_num,
device_config_data[CONF_PARTITIONNAME],
code,
panic_type,
hass.data[DATA_EVL].alarm_state['partition'][part_num],
hass.data[DATA_EVL]
)
devices.append(device)
async_add_devices(devices)
@callback
def alarm_keypress_handler(service):
"""Map services to methods on Alarm."""
entity_ids = service.data.get(ATTR_ENTITY_ID)
keypress = service.data.get(ATTR_KEYPRESS)
target_devices = [device for device in devices
if device.entity_id in entity_ids]
for device in target_devices:
device.async_alarm_keypress(keypress)
# Register Envisalink specific services
descriptions = load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml'))
descriptions = yield from hass.loop.run_in_executor(
None, 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)
hass.services.register(alarm.DOMAIN, SERVICE_ALARM_KEYPRESS,
alarm_keypress_handler,
descriptions.get(SERVICE_ALARM_KEYPRESS),
schema=ALARM_KEYPRESS_SCHEMA)
return True
class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
"""Representation of an Envisalink-based alarm panel."""
def __init__(self, partition_number, alarm_name, code, panic_type, info,
controller):
def __init__(self, hass, partition_number, alarm_name, code, panic_type,
info, controller):
"""Initialize the alarm panel."""
from pydispatch import dispatcher
self._partition_number = partition_number
self._code = code
self._panic_type = panic_type
_LOGGER.debug("Setting up alarm: %s", alarm_name)
EnvisalinkDevice.__init__(self, alarm_name, info, controller)
dispatcher.connect(
self._update_callback, signal=SIGNAL_PARTITION_UPDATE,
sender=dispatcher.Any)
dispatcher.connect(
self._update_callback, signal=SIGNAL_KEYPAD_UPDATE,
sender=dispatcher.Any)
_LOGGER.debug("Setting up alarm: %s", alarm_name)
super().__init__(alarm_name, info, controller)
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_KEYPAD_UPDATE, self._update_callback)
async_dispatcher_connect(
self.hass, SIGNAL_PARTITION_UPDATE, self._update_callback)
@callback
def _update_callback(self, partition):
"""Update HA state, if needed."""
"""Update Home Assistant state, if needed."""
if partition is None or int(partition) == self._partition_number:
self.hass.async_add_job(self.async_update_ha_state())
@@ -126,39 +135,44 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
state = STATE_ALARM_DISARMED
return state
def alarm_disarm(self, code=None):
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
"""Send disarm command."""
if code:
EVL_CONTROLLER.disarm_partition(str(code),
self._partition_number)
self.hass.data[DATA_EVL].disarm_partition(
str(code), self._partition_number)
else:
EVL_CONTROLLER.disarm_partition(str(self._code),
self._partition_number)
self.hass.data[DATA_EVL].disarm_partition(
str(self._code), self._partition_number)
def alarm_arm_home(self, code=None):
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
if code:
EVL_CONTROLLER.arm_stay_partition(str(code),
self._partition_number)
self.hass.data[DATA_EVL].arm_stay_partition(
str(code), self._partition_number)
else:
EVL_CONTROLLER.arm_stay_partition(str(self._code),
self._partition_number)
self.hass.data[DATA_EVL].arm_stay_partition(
str(self._code), self._partition_number)
def alarm_arm_away(self, code=None):
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
if code:
EVL_CONTROLLER.arm_away_partition(str(code),
self._partition_number)
self.hass.data[DATA_EVL].arm_away_partition(
str(code), self._partition_number)
else:
EVL_CONTROLLER.arm_away_partition(str(self._code),
self._partition_number)
self.hass.data[DATA_EVL].arm_away_partition(
str(self._code), self._partition_number)
def alarm_trigger(self, code=None):
@asyncio.coroutine
def async_alarm_trigger(self, code=None):
"""Alarm trigger command. Will be used to trigger a panic alarm."""
EVL_CONTROLLER.panic_alarm(self._panic_type)
self.hass.data[DATA_EVL].panic_alarm(self._panic_type)
def alarm_keypress(self, keypress=None):
@callback
def async_alarm_keypress(self, keypress=None):
"""Send custom keypress."""
if keypress:
EVL_CONTROLLER.keypresses_to_partition(self._partition_number,
keypress)
self.hass.data[DATA_EVL].keypresses_to_partition(
self._partition_number, keypress)

View File

@@ -39,7 +39,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the manual alarm platform."""
"""Set up the manual alarm platform."""
add_devices([ManualAlarm(
hass,
config[CONF_NAME],
@@ -52,7 +52,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class ManualAlarm(alarm.AlarmControlPanel):
"""
Represents an alarm status.
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
@@ -62,7 +62,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
def __init__(self, hass, name, code, pending_time,
trigger_time, disarm_after_trigger):
"""Initalize the manual alarm panel."""
"""Init the manual alarm panel."""
self._state = STATE_ALARM_DISARMED
self._hass = hass
self._name = name
@@ -75,7 +75,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
@property
def should_poll(self):
"""No polling needed."""
"""Return the plling state."""
return False
@property
@@ -166,5 +166,5 @@ class ManualAlarm(alarm.AlarmControlPanel):
"""Validate given code."""
check = self._code is None or code == self._code
if not check:
_LOGGER.warning('Invalid code given for %s', state)
_LOGGER.warning("Invalid code given for %s", state)
return check

View File

@@ -4,10 +4,12 @@ This platform enables the possibility to control a MQTT alarm.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.mqtt/
"""
import asyncio
import logging
import voluptuous as vol
from homeassistant.core import callback
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.components.mqtt as mqtt
from homeassistant.const import (
@@ -41,10 +43,10 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the MQTT platform."""
add_devices([MqttAlarm(
hass,
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the MQTT Alarm Control Panel platform."""
async_add_devices([MqttAlarm(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_COMMAND_TOPIC),
@@ -58,11 +60,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class MqttAlarm(alarm.AlarmControlPanel):
"""Representation of a MQTT alarm status."""
def __init__(self, hass, name, state_topic, command_topic, qos,
payload_disarm, payload_arm_home, payload_arm_away, code):
"""Initalize the MQTT alarm panel."""
def __init__(self, name, state_topic, command_topic, qos, payload_disarm,
payload_arm_home, payload_arm_away, code):
"""Init the MQTT Alarm Control Panel."""
self._state = STATE_UNKNOWN
self._hass = hass
self._name = name
self._state_topic = state_topic
self._command_topic = command_topic
@@ -72,17 +73,24 @@ class MqttAlarm(alarm.AlarmControlPanel):
self._payload_arm_away = payload_arm_away
self._code = code
def async_added_to_hass(self):
"""Subscribe mqtt events.
This method must be run in the event loop and returns a coroutine.
"""
@callback
def message_received(topic, payload, qos):
"""A new MQTT message has been received."""
"""Run when new MQTT message has been received."""
if payload not in (STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_PENDING,
STATE_ALARM_TRIGGERED):
_LOGGER.warning('Received unexpected payload: %s', payload)
_LOGGER.warning("Received unexpected payload: %s", payload)
return
self._state = payload
self.update_ha_state()
self.hass.async_add_job(self.async_update_ha_state())
mqtt.subscribe(hass, self._state_topic, message_received, self._qos)
return mqtt.async_subscribe(
self.hass, self._state_topic, message_received, self._qos)
@property
def should_poll(self):
@@ -104,26 +112,38 @@ class MqttAlarm(alarm.AlarmControlPanel):
"""One or more characters if code is defined."""
return None if self._code is None else '.+'
def alarm_disarm(self, code=None):
"""Send disarm command."""
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
"""Send disarm command.
This method is a coroutine.
"""
if not self._validate_code(code, 'disarming'):
return
mqtt.publish(self.hass, self._command_topic,
self._payload_disarm, self._qos)
mqtt.async_publish(
self.hass, self._command_topic, self._payload_disarm, self._qos)
def alarm_arm_home(self, code=None):
"""Send arm home command."""
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
"""Send arm home command.
This method is a coroutine.
"""
if not self._validate_code(code, 'arming home'):
return
mqtt.publish(self.hass, self._command_topic,
self._payload_arm_home, self._qos)
mqtt.async_publish(
self.hass, self._command_topic, self._payload_arm_home, self._qos)
def alarm_arm_away(self, code=None):
"""Send arm away command."""
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
"""Send arm away command.
This method is a coroutine.
"""
if not self._validate_code(code, 'arming away'):
return
mqtt.publish(self.hass, self._command_topic,
self._payload_arm_away, self._qos)
mqtt.async_publish(
self.hass, self._command_topic, self._payload_arm_away, self._qos)
def _validate_code(self, code, state):
"""Validate given code."""

View File

@@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup nx584 platform."""
"""Set up the nx584 platform."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
@@ -42,15 +42,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
try:
add_devices([NX584Alarm(hass, url, name)])
except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NX584: %s', str(ex))
_LOGGER.error("Unable to connect to NX584: %s", str(ex))
return False
class NX584Alarm(alarm.AlarmControlPanel):
"""Represents the NX584-based alarm panel."""
"""Representation of a NX584-based alarm panel."""
def __init__(self, hass, url, name):
"""Initalize the nx584 alarm panel."""
"""Init the nx584 alarm panel."""
from nx584 import client
self._hass = hass
self._name = name
@@ -69,7 +69,7 @@ class NX584Alarm(alarm.AlarmControlPanel):
@property
def code_format(self):
"""The characters if code is defined."""
"""Return che characters if code is defined."""
return '[0-9]{4}([0-9]{2})?'
@property
@@ -83,20 +83,19 @@ class NX584Alarm(alarm.AlarmControlPanel):
part = self._alarm.list_partitions()[0]
zones = self._alarm.list_zones()
except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to %(host)s: %(reason)s',
_LOGGER.error("Unable to connect to %(host)s: %(reason)s",
dict(host=self._url, reason=ex))
self._state = STATE_UNKNOWN
zones = []
except IndexError:
_LOGGER.error('nx584 reports no partitions')
_LOGGER.error("nx584 reports no partitions")
self._state = STATE_UNKNOWN
zones = []
bypassed = False
for zone in zones:
if zone['bypassed']:
_LOGGER.debug('Zone %(zone)s is bypassed, '
'assuming HOME',
_LOGGER.debug("Zone %(zone)s is bypassed, assuming HOME",
dict(zone=zone['number']))
bypassed = True
break

View File

@@ -12,16 +12,19 @@ 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)
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY,
EVENT_HOMEASSISTANT_STOP)
import homeassistant.helpers.config_validation as cv
import homeassistant.loader as loader
REQUIREMENTS = ['https://github.com/w1ll1am23/simplisafe-python/archive/'
'586fede0e85fd69e56e516aaa8e97eb644ca8866.zip#'
'simplisafe-python==0.0.1']
REQUIREMENTS = ['simplisafe-python==1.0.2']
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'SimpliSafe'
DOMAIN = 'simplisafe'
NOTIFICATION_ID = 'simplisafe_notification'
NOTIFICATION_TITLE = 'SimpliSafe Setup'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_PASSWORD): cv.string,
@@ -33,33 +36,44 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the SimpliSafe platform."""
from simplipy.api import SimpliSafeApiInterface, get_systems
name = config.get(CONF_NAME)
code = config.get(CONF_CODE)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
add_devices([SimpliSafeAlarm(name, username, password, code)])
persistent_notification = loader.get_component('persistent_notification')
simplisafe = SimpliSafeApiInterface()
status = simplisafe.set_credentials(username, password)
if status:
hass.data[DOMAIN] = simplisafe
locations = get_systems(simplisafe)
for location in locations:
add_devices([SimpliSafeAlarm(location, name, code)])
else:
message = 'Failed to log into SimpliSafe. Check credentials.'
_LOGGER.error(message)
persistent_notification.create(
hass, message,
title=NOTIFICATION_TITLE,
notification_id=NOTIFICATION_ID)
return False
def logout(event):
"""Logout of the SimpliSafe API."""
hass.data[DOMAIN].logout()
hass.bus.listen(EVENT_HOMEASSISTANT_STOP, logout)
class SimpliSafeAlarm(alarm.AlarmControlPanel):
"""Representation a SimpliSafe alarm."""
def __init__(self, name, username, password, code):
def __init__(self, simplisafe, name, code):
"""Initialize the SimpliSafe alarm."""
from simplisafe import SimpliSafe
self.simplisafe = SimpliSafe(username, password)
self.simplisafe = simplisafe
self._name = name
self._code = str(code) if code else None
self._id = self.simplisafe.get_id()
status = self.simplisafe.get_state()
if status == 'Off':
self._state = STATE_ALARM_DISARMED
elif status == 'Home':
self._state = STATE_ALARM_ARMED_HOME
elif status == 'Away':
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = STATE_UNKNOWN
@property
def name(self):
@@ -67,7 +81,7 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
if self._name is not None:
return self._name
else:
return 'Alarm {}'.format(self._id)
return 'Alarm {}'.format(self.simplisafe.location_id())
@property
def code_format(self):
@@ -77,46 +91,57 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
@property
def state(self):
"""Return the state of the device."""
return self._state
status = self.simplisafe.state()
if status == 'Off':
state = STATE_ALARM_DISARMED
elif status == 'Home':
state = STATE_ALARM_ARMED_HOME
elif status == 'Away':
state = STATE_ALARM_ARMED_AWAY
else:
state = STATE_UNKNOWN
return state
@property
def device_state_attributes(self):
"""Return the state attributes."""
return {
'temperature': self.simplisafe.temperature(),
'co': self.simplisafe.carbon_monoxide(),
'fire': self.simplisafe.fire(),
'alarm': self.simplisafe.alarm(),
'last_event': self.simplisafe.last_event(),
'flood': self.simplisafe.flood()
}
def update(self):
"""Update alarm status."""
self.simplisafe.get_location()
status = self.simplisafe.get_state()
if status == 'Off':
self._state = STATE_ALARM_DISARMED
elif status == 'Home':
self._state = STATE_ALARM_ARMED_HOME
elif status == 'Away':
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = STATE_UNKNOWN
self.simplisafe.update()
def alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'disarming'):
return
self.simplisafe.set_state('off')
_LOGGER.info('SimpliSafe alarm disarming')
_LOGGER.info("SimpliSafe alarm disarming")
def alarm_arm_home(self, code=None):
"""Send arm home command."""
if not self._validate_code(code, 'arming home'):
return
self.simplisafe.set_state('home')
_LOGGER.info('SimpliSafe alarm arming home')
_LOGGER.info("SimpliSafe alarm arming home")
def alarm_arm_away(self, code=None):
"""Send arm away command."""
if not self._validate_code(code, 'arming away'):
return
self.simplisafe.set_state('away')
_LOGGER.info('SimpliSafe alarm arming away')
_LOGGER.info("SimpliSafe alarm arming away")
def _validate_code(self, code, state):
"""Validate given code."""
check = self._code is None or code == self._code
if not check:
_LOGGER.warning('Wrong code entered for %s', state)
_LOGGER.warning("Wrong code entered for %s", state)
return check

View File

@@ -0,0 +1,92 @@
"""
Interfaces with TotalConnect alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.totalconnect/
"""
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
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_NAME)
REQUIREMENTS = ['total_connect_client==0.7']
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'Total Connect'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
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 a TotalConnect control panel."""
name = config.get(CONF_NAME)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
total_connect = TotalConnect(name, username, password)
add_devices([total_connect], True)
class TotalConnect(alarm.AlarmControlPanel):
"""Represent an TotalConnect status."""
def __init__(self, name, username, password):
"""Initialize the TotalConnect status."""
from total_connect_client import TotalConnectClient
_LOGGER.debug("Setting up TotalConnect...")
self._name = name
self._username = username
self._password = password
self._state = STATE_UNKNOWN
self._client = TotalConnectClient.TotalConnectClient(
username, password)
@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_armed_status()
if status == self._client.DISARMED:
state = STATE_ALARM_DISARMED
elif status == self._client.ARMED_STAY:
state = STATE_ALARM_ARMED_HOME
elif status == self._client.ARMED_AWAY:
state = STATE_ALARM_ARMED_AWAY
else:
state = STATE_UNKNOWN
self._state = state
def alarm_disarm(self, code=None):
"""Send disarm command."""
self._client.disarm()
def alarm_arm_home(self, code=None):
"""Send arm home command."""
self._client.arm_stay()
def alarm_arm_away(self, code=None):
"""Send arm away command."""
self._client.arm_away()

View File

@@ -17,7 +17,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Verisure platform."""
"""Set up the Verisure platform."""
alarms = []
if int(hub.config.get(CONF_ALARM, 1)):
hub.update_alarms()
@@ -29,10 +29,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class VerisureAlarm(alarm.AlarmControlPanel):
"""Represent a Verisure alarm status."""
"""Representation of a Verisure alarm status."""
def __init__(self, device_id):
"""Initalize the Verisure alarm panel."""
"""Initialize the Verisure alarm panel."""
self._id = device_id
self._state = STATE_UNKNOWN
self._digits = hub.config.get(CONF_CODE_DIGITS)
@@ -55,12 +55,12 @@ class VerisureAlarm(alarm.AlarmControlPanel):
@property
def code_format(self):
"""The code format as regex."""
"""Return the code format as regex."""
return '^\\d{%s}$' % self._digits
@property
def changed_by(self):
"""Last change triggered by."""
"""Return the last change triggered by."""
return self._changed_by
def update(self):
@@ -75,24 +75,23 @@ class VerisureAlarm(alarm.AlarmControlPanel):
self._state = STATE_ALARM_ARMED_AWAY
elif hub.alarm_status[self._id].status != 'pending':
_LOGGER.error(
'Unknown alarm state %s',
hub.alarm_status[self._id].status)
"Unknown alarm state %s", hub.alarm_status[self._id].status)
self._changed_by = hub.alarm_status[self._id].name
def alarm_disarm(self, code=None):
"""Send disarm command."""
hub.my_pages.alarm.set(code, 'DISARMED')
_LOGGER.info('verisure alarm disarming')
_LOGGER.info("Verisure alarm disarming")
hub.my_pages.alarm.wait_while_pending()
def alarm_arm_home(self, code=None):
"""Send arm home command."""
hub.my_pages.alarm.set(code, 'ARMED_HOME')
_LOGGER.info('verisure alarm arming home')
_LOGGER.info("Verisure alarm arming home")
hub.my_pages.alarm.wait_while_pending()
def alarm_arm_away(self, code=None):
"""Send arm away command."""
hub.my_pages.alarm.set(code, 'ARMED_AWAY')
_LOGGER.info('verisure alarm arming away')
_LOGGER.info("Verisure alarm arming away")
hub.my_pages.alarm.wait_while_pending()

View File

@@ -16,11 +16,12 @@ from homeassistant.components.wink import WinkDevice, DOMAIN
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['wink']
STATE_ALARM_PRIVACY = 'Private'
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink platform."""
"""Set up the Wink platform."""
import pywink
for camera in pywink.get_cameras():

View File

@@ -0,0 +1,168 @@
"""
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
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
REQUIREMENTS = ['alarmdecoder==0.12.1.0']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'alarmdecoder'
DATA_AD = 'alarmdecoder'
CONF_DEVICE = 'device'
CONF_DEVICE_BAUD = 'baudrate'
CONF_DEVICE_HOST = 'host'
CONF_DEVICE_PATH = 'path'
CONF_DEVICE_PORT = 'port'
CONF_DEVICE_TYPE = 'type'
CONF_PANEL_DISPLAY = 'panel_display'
CONF_ZONE_NAME = 'name'
CONF_ZONE_TYPE = 'type'
CONF_ZONES = 'zones'
DEFAULT_DEVICE_TYPE = 'socket'
DEFAULT_DEVICE_HOST = 'localhost'
DEFAULT_DEVICE_PORT = 10000
DEFAULT_DEVICE_PATH = '/dev/ttyUSB0'
DEFAULT_DEVICE_BAUD = 115200
DEFAULT_PANEL_DISPLAY = False
DEFAULT_ZONE_TYPE = 'opening'
SIGNAL_PANEL_MESSAGE = 'alarmdecoder.panel_message'
SIGNAL_PANEL_ARM_AWAY = 'alarmdecoder.panel_arm_away'
SIGNAL_PANEL_ARM_HOME = 'alarmdecoder.panel_arm_home'
SIGNAL_PANEL_DISARM = 'alarmdecoder.panel_disarm'
SIGNAL_ZONE_FAULT = 'alarmdecoder.zone_fault'
SIGNAL_ZONE_RESTORE = 'alarmdecoder.zone_restore'
DEVICE_SOCKET_SCHEMA = vol.Schema({
vol.Required(CONF_DEVICE_TYPE): 'socket',
vol.Optional(CONF_DEVICE_HOST, default=DEFAULT_DEVICE_HOST): cv.string,
vol.Optional(CONF_DEVICE_PORT, default=DEFAULT_DEVICE_PORT): cv.port})
DEVICE_SERIAL_SCHEMA = vol.Schema({
vol.Required(CONF_DEVICE_TYPE): 'serial',
vol.Optional(CONF_DEVICE_PATH, default=DEFAULT_DEVICE_PATH): cv.string,
vol.Optional(CONF_DEVICE_BAUD, default=DEFAULT_DEVICE_BAUD): cv.string})
DEVICE_USB_SCHEMA = vol.Schema({
vol.Required(CONF_DEVICE_TYPE): 'usb'})
ZONE_SCHEMA = vol.Schema({
vol.Required(CONF_ZONE_NAME): cv.string,
vol.Optional(CONF_ZONE_TYPE, default=DEFAULT_ZONE_TYPE): 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.Optional(CONF_PANEL_DISPLAY,
default=DEFAULT_PANEL_DISPLAY): cv.boolean,
vol.Optional(CONF_ZONES): {vol.Coerce(int): ZONE_SCHEMA},
}),
}, extra=vol.ALLOW_EXTRA)
@asyncio.coroutine
def async_setup(hass, config):
"""Set up for the AlarmDecoder devices."""
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice)
conf = config.get(DOMAIN)
device = conf.get(CONF_DEVICE)
display = conf.get(CONF_PANEL_DISPLAY)
zones = conf.get(CONF_ZONES)
device_type = device.get(CONF_DEVICE_TYPE)
host = DEFAULT_DEVICE_HOST
port = DEFAULT_DEVICE_PORT
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")
controller.close()
@callback
def handle_message(sender, message):
"""Handle message from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message)
def zone_fault_callback(sender, zone):
"""Handle zone fault from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone)
def zone_restore_callback(sender, zone):
"""Handle zone restore from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_RESTORE, zone)
controller = False
if device_type == 'socket':
host = device.get(CONF_DEVICE_HOST)
port = device.get(CONF_DEVICE_PORT)
controller = AlarmDecoder(SocketDevice(interface=(host, port)))
elif device_type == 'serial':
path = device.get(CONF_DEVICE_PATH)
baud = device.get(CONF_DEVICE_BAUD)
controller = AlarmDecoder(SerialDevice(interface=path))
elif device_type == 'usb':
AlarmDecoder(USBDevice.find())
return False
controller.on_open += handle_open
controller.on_message += handle_message
controller.on_zone_fault += zone_fault_callback
controller.on_zone_restore += zone_restore_callback
hass.data[DATA_AD] = controller
controller.open(baud)
result = yield from sync_connect
if not result:
return False
hass.async_add_job(
async_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))
if display:
hass.async_add_job(async_load_platform(
hass, 'sensor', DOMAIN, conf, config))
return True

View File

@@ -13,13 +13,11 @@ 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)
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)
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.helpers import service, event
from homeassistant.util.async import run_callback_threadsafe
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
@@ -32,13 +30,16 @@ CONF_NOTIFIERS = 'notifiers'
CONF_REPEAT = 'repeat'
CONF_SKIP_FIRST = 'skip_first'
DEFAULT_CAN_ACK = True
DEFAULT_SKIP_FIRST = False
ALERT_SCHEMA = vol.Schema({
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_STATE, default=STATE_ON): cv.string,
vol.Required(CONF_REPEAT): vol.All(cv.ensure_list, [vol.Coerce(float)]),
vol.Required(CONF_CAN_ACK, default=True): cv.boolean,
vol.Required(CONF_SKIP_FIRST, default=False): cv.boolean,
vol.Required(CONF_CAN_ACK, default=DEFAULT_CAN_ACK): cv.boolean,
vol.Required(CONF_SKIP_FIRST, default=DEFAULT_SKIP_FIRST): cv.boolean,
vol.Required(CONF_NOTIFIERS): cv.ensure_list})
CONFIG_SCHEMA = vol.Schema({
@@ -60,7 +61,7 @@ def is_on(hass, entity_id):
def turn_on(hass, entity_id):
"""Reset the alert."""
run_callback_threadsafe(hass.loop, async_turn_on, hass, entity_id)
hass.add_job(async_turn_on, hass, entity_id)
@callback
@@ -73,7 +74,7 @@ def async_turn_on(hass, entity_id):
def turn_off(hass, entity_id):
"""Acknowledge alert."""
run_callback_threadsafe(hass.loop, async_turn_off, hass, entity_id)
hass.add_job(async_turn_off, hass, entity_id)
@callback
@@ -86,7 +87,7 @@ def async_turn_off(hass, entity_id):
def toggle(hass, entity_id):
"""Toggle acknowledgement of alert."""
run_callback_threadsafe(hass.loop, async_toggle, hass, entity_id)
hass.add_job(async_toggle, hass, entity_id)
@callback
@@ -99,7 +100,7 @@ def async_toggle(hass, entity_id):
@asyncio.coroutine
def async_setup(hass, config):
"""Setup alert component."""
"""Set up the Alert component."""
alerts = config.get(DOMAIN)
all_alerts = {}
@@ -117,7 +118,7 @@ def async_setup(hass, config):
else:
yield from alert.async_turn_off()
# setup alerts
# Setup alerts
for entity_id, alert in alerts.items():
entity = Alert(hass, entity_id,
alert[CONF_NAME], alert[CONF_ENTITY_ID],
@@ -126,13 +127,13 @@ def async_setup(hass, config):
alert[CONF_CAN_ACK])
all_alerts[entity.entity_id] = entity
# read descriptions
# Read descriptions
descriptions = yield from hass.loop.run_in_executor(
None, load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
descriptions = descriptions.get(DOMAIN, {})
# setup service calls
# Setup service calls
hass.services.async_register(
DOMAIN, SERVICE_TURN_OFF, async_handle_alert_service,
descriptions.get(SERVICE_TURN_OFF), schema=ALERT_SERVICE_SCHEMA)
@@ -171,8 +172,8 @@ class Alert(ToggleEntity):
self._cancel = None
self.entity_id = ENTITY_ID_FORMAT.format(entity_id)
event.async_track_state_change(hass, watched_entity_id,
self.watched_entity_change)
event.async_track_state_change(
hass, watched_entity_id, self.watched_entity_change)
@property
def name(self):
@@ -201,7 +202,7 @@ class Alert(ToggleEntity):
@asyncio.coroutine
def watched_entity_change(self, entity, from_state, to_state):
"""Determine if the alert should start or stop."""
_LOGGER.debug('Watched entity (%s) has changed.', entity)
_LOGGER.debug("Watched entity (%s) has changed", entity)
if to_state.state == self._alert_state and not self._firing:
yield from self.begin_alerting()
if to_state.state != self._alert_state and self._firing:
@@ -210,7 +211,7 @@ class Alert(ToggleEntity):
@asyncio.coroutine
def begin_alerting(self):
"""Begin the alert procedures."""
_LOGGER.debug('Beginning Alert: %s', self._name)
_LOGGER.debug("Beginning Alert: %s", self._name)
self._ack = False
self._firing = True
self._next_delay = 0
@@ -225,7 +226,7 @@ class Alert(ToggleEntity):
@asyncio.coroutine
def end_alerting(self):
"""End the alert procedures."""
_LOGGER.debug('Ending Alert: %s', self._name)
_LOGGER.debug("Ending Alert: %s", self._name)
self._cancel()
self._ack = False
self._firing = False
@@ -247,7 +248,7 @@ class Alert(ToggleEntity):
return
if not self._ack:
_LOGGER.info('Alerting: %s', self._name)
_LOGGER.info("Alerting: %s", self._name)
for target in self._notifiers:
yield from self.hass.services.async_call(
'notify', target, {'message': self._name})
@@ -256,14 +257,14 @@ class Alert(ToggleEntity):
@asyncio.coroutine
def async_turn_on(self):
"""Async Unacknowledge alert."""
_LOGGER.debug('Reset Alert: %s', self._name)
_LOGGER.debug("Reset Alert: %s", self._name)
self._ack = False
yield from self.async_update_ha_state()
@asyncio.coroutine
def async_turn_off(self):
"""Async Acknowledge alert."""
_LOGGER.debug('Acknowledged Alert: %s', self._name)
_LOGGER.debug("Acknowledged Alert: %s", self._name)
self._ack = True
yield from self.async_update_ha_state()

View File

@@ -0,0 +1,293 @@
"""
Support for IP Webcam, an Android app that acts as a full-featured webcam.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/android_ip_webcam/
"""
import asyncio
import logging
from datetime import timedelta
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import (
CONF_NAME, CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD,
CONF_SENSORS, CONF_SWITCHES, CONF_TIMEOUT, CONF_SCAN_INTERVAL,
CONF_PLATFORM)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import (
async_dispatcher_send, async_dispatcher_connect)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.util.dt import utcnow
from homeassistant.components.camera.mjpeg import (
CONF_MJPEG_URL, CONF_STILL_IMAGE_URL)
REQUIREMENTS = ['pydroid-ipcam==0.8']
_LOGGER = logging.getLogger(__name__)
ATTR_AUD_CONNS = 'Audio Connections'
ATTR_HOST = 'host'
ATTR_VID_CONNS = 'Video Connections'
CONF_MOTION_SENSOR = 'motion_sensor'
DATA_IP_WEBCAM = 'android_ip_webcam'
DEFAULT_NAME = 'IP Webcam'
DEFAULT_PORT = 8080
DEFAULT_TIMEOUT = 10
DOMAIN = 'android_ip_webcam'
SCAN_INTERVAL = timedelta(seconds=10)
SIGNAL_UPDATE_DATA = 'android_ip_webcam_update'
KEY_MAP = {
'audio_connections': 'Audio Connections',
'adet_limit': 'Audio Trigger Limit',
'antibanding': 'Anti-banding',
'audio_only': 'Audio Only',
'battery_level': 'Battery Level',
'battery_temp': 'Battery Temperature',
'battery_voltage': 'Battery Voltage',
'coloreffect': 'Color Effect',
'exposure': 'Exposure Level',
'exposure_lock': 'Exposure Lock',
'ffc': 'Front-facing Camera',
'flashmode': 'Flash Mode',
'focus': 'Focus',
'focus_homing': 'Focus Homing',
'focus_region': 'Focus Region',
'focusmode': 'Focus Mode',
'gps_active': 'GPS Active',
'idle': 'Idle',
'ip_address': 'IPv4 Address',
'ipv6_address': 'IPv6 Address',
'ivideon_streaming': 'Ivideon Streaming',
'light': 'Light Level',
'mirror_flip': 'Mirror Flip',
'motion': 'Motion',
'motion_active': 'Motion Active',
'motion_detect': 'Motion Detection',
'motion_event': 'Motion Event',
'motion_limit': 'Motion Limit',
'night_vision': 'Night Vision',
'night_vision_average': 'Night Vision Average',
'night_vision_gain': 'Night Vision Gain',
'orientation': 'Orientation',
'overlay': 'Overlay',
'photo_size': 'Photo Size',
'pressure': 'Pressure',
'proximity': 'Proximity',
'quality': 'Quality',
'scenemode': 'Scene Mode',
'sound': 'Sound',
'sound_event': 'Sound Event',
'sound_timeout': 'Sound Timeout',
'torch': 'Torch',
'video_connections': 'Video Connections',
'video_chunk_len': 'Video Chunk Length',
'video_recording': 'Video Recording',
'video_size': 'Video Size',
'whitebalance': 'White Balance',
'whitebalance_lock': 'White Balance Lock',
'zoom': 'Zoom'
}
ICON_MAP = {
'audio_connections': 'mdi:speaker',
'battery_level': 'mdi:battery',
'battery_temp': 'mdi:thermometer',
'battery_voltage': 'mdi:battery-charging-100',
'exposure_lock': 'mdi:camera',
'ffc': 'mdi:camera-front-variant',
'focus': 'mdi:image-filter-center-focus',
'gps_active': 'mdi:crosshairs-gps',
'light': 'mdi:flashlight',
'motion': 'mdi:run',
'night_vision': 'mdi:weather-night',
'overlay': 'mdi:monitor',
'pressure': 'mdi:gauge',
'proximity': 'mdi:map-marker-radius',
'quality': 'mdi:quality-high',
'sound': 'mdi:speaker',
'sound_event': 'mdi:speaker',
'sound_timeout': 'mdi:speaker',
'torch': 'mdi:white-balance-sunny',
'video_chunk_len': 'mdi:video',
'video_connections': 'mdi:eye',
'video_recording': 'mdi:record-rec',
'whitebalance_lock': 'mdi:white-balance-auto'
}
SWITCHES = ['exposure_lock', 'ffc', 'focus', 'gps_active', 'night_vision',
'overlay', 'torch', 'whitebalance_lock', 'video_recording']
SENSORS = ['audio_connections', 'battery_level', 'battery_temp',
'battery_voltage', 'light', 'motion', 'pressure', 'proximity',
'sound', 'video_connections']
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.All(cv.ensure_list, [vol.Schema({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
vol.Optional(CONF_SCAN_INTERVAL, default=SCAN_INTERVAL):
cv.time_period,
vol.Inclusive(CONF_USERNAME, 'authentication'): cv.string,
vol.Inclusive(CONF_PASSWORD, 'authentication'): cv.string,
vol.Optional(CONF_SWITCHES, default=None):
vol.All(cv.ensure_list, [vol.In(SWITCHES)]),
vol.Optional(CONF_SENSORS, default=None):
vol.All(cv.ensure_list, [vol.In(SENSORS)]),
vol.Optional(CONF_MOTION_SENSOR, default=None): cv.boolean,
})])
}, extra=vol.ALLOW_EXTRA)
@asyncio.coroutine
def async_setup(hass, config):
"""Set up the IP Webcam component."""
from pydroid_ipcam import PyDroidIPCam
webcams = hass.data[DATA_IP_WEBCAM] = {}
websession = async_get_clientsession(hass)
@asyncio.coroutine
def async_setup_ipcamera(cam_config):
"""Set up an IP camera."""
host = cam_config[CONF_HOST]
username = cam_config.get(CONF_USERNAME)
password = cam_config.get(CONF_PASSWORD)
name = cam_config[CONF_NAME]
interval = cam_config[CONF_SCAN_INTERVAL]
switches = cam_config[CONF_SWITCHES]
sensors = cam_config[CONF_SENSORS]
motion = cam_config[CONF_MOTION_SENSOR]
# Init ip webcam
cam = PyDroidIPCam(
hass.loop, websession, host, cam_config[CONF_PORT],
username=username, password=password,
timeout=cam_config[CONF_TIMEOUT]
)
if switches is None:
switches = [setting for setting in cam.enabled_settings
if setting in SWITCHES]
if sensors is None:
sensors = [sensor for sensor in cam.enabled_sensors
if sensor in SENSORS]
sensors.extend(['audio_connections', 'video_connections'])
if motion is None:
motion = 'motion_active' in cam.enabled_sensors
@asyncio.coroutine
def async_update_data(now):
"""Update data from IP camera in SCAN_INTERVAL."""
yield from cam.update()
async_dispatcher_send(hass, SIGNAL_UPDATE_DATA, host)
async_track_point_in_utc_time(
hass, async_update_data, utcnow() + interval)
yield from async_update_data(None)
# Load platforms
webcams[host] = cam
mjpeg_camera = {
CONF_PLATFORM: 'mjpeg',
CONF_MJPEG_URL: cam.mjpeg_url,
CONF_STILL_IMAGE_URL: cam.image_url,
CONF_NAME: name,
}
if username and password:
mjpeg_camera.update({
CONF_USERNAME: username,
CONF_PASSWORD: password
})
hass.async_add_job(discovery.async_load_platform(
hass, 'camera', 'mjpeg', mjpeg_camera, config))
if sensors:
hass.async_add_job(discovery.async_load_platform(
hass, 'sensor', DOMAIN, {
CONF_NAME: name,
CONF_HOST: host,
CONF_SENSORS: sensors,
}, config))
if switches:
hass.async_add_job(discovery.async_load_platform(
hass, 'switch', DOMAIN, {
CONF_NAME: name,
CONF_HOST: host,
CONF_SWITCHES: switches,
}, config))
if motion:
hass.async_add_job(discovery.async_load_platform(
hass, 'binary_sensor', DOMAIN, {
CONF_HOST: host,
CONF_NAME: name,
}, config))
tasks = [async_setup_ipcamera(conf) for conf in config[DOMAIN]]
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
return True
class AndroidIPCamEntity(Entity):
"""The Android device running IP Webcam."""
def __init__(self, host, ipcam):
"""Initialize the data oject."""
self._host = host
self._ipcam = ipcam
@asyncio.coroutine
def async_added_to_hass(self):
"""Register update dispatcher."""
@callback
def async_ipcam_update(host):
"""Update callback."""
if self._host != host:
return
self.hass.async_add_job(self.async_update_ha_state(True))
async_dispatcher_connect(
self.hass, SIGNAL_UPDATE_DATA, async_ipcam_update)
@property
def should_poll(self):
"""Return True if entity has to be polled for state."""
return False
@property
def available(self):
"""Return True if entity is available."""
return self._ipcam.available
@property
def device_state_attributes(self):
"""Return the state attributes."""
state_attr = {ATTR_HOST: self._host}
if self._ipcam.status_data is None:
return state_attr
state_attr[ATTR_VID_CONNS] = \
self._ipcam.status_data.get('video_connections')
state_attr[ATTR_AUD_CONNS] = \
self._ipcam.status_data.get('audio_connections')
return state_attr

View File

@@ -17,9 +17,9 @@ from homeassistant.bootstrap import ERROR_LOG_FILENAME
from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED,
HTTP_BAD_REQUEST, HTTP_CREATED, HTTP_NOT_FOUND,
HTTP_UNPROCESSABLE_ENTITY, MATCH_ALL, URL_API, URL_API_COMPONENTS,
MATCH_ALL, URL_API, URL_API_COMPONENTS,
URL_API_CONFIG, URL_API_DISCOVERY_INFO, URL_API_ERROR_LOG,
URL_API_EVENT_FORWARD, URL_API_EVENTS, URL_API_SERVICES,
URL_API_EVENTS, URL_API_SERVICES,
URL_API_STATES, URL_API_STATES_ENTITY, URL_API_STREAM, URL_API_TEMPLATE,
__version__)
from homeassistant.exceptions import TemplateError
@@ -48,11 +48,12 @@ def setup(hass, config):
hass.http.register_view(APIEventView)
hass.http.register_view(APIServicesView)
hass.http.register_view(APIDomainServicesView)
hass.http.register_view(APIEventForwardingView)
hass.http.register_view(APIComponentsView)
hass.http.register_view(APIErrorLogView)
hass.http.register_view(APITemplateView)
hass.http.register_static_path(
URL_API_ERROR_LOG, hass.config.path(ERROR_LOG_FILENAME), False)
return True
@@ -317,77 +318,6 @@ class APIDomainServicesView(HomeAssistantView):
return self.json(changed_states)
class APIEventForwardingView(HomeAssistantView):
"""View to handle EventForwarding requests."""
url = URL_API_EVENT_FORWARD
name = "api:event-forward"
event_forwarder = None
@asyncio.coroutine
def post(self, request):
"""Setup an event forwarder."""
hass = request.app['hass']
try:
data = yield from request.json()
except ValueError:
return self.json_message("No data received.", HTTP_BAD_REQUEST)
try:
host = data['host']
api_password = data['api_password']
except KeyError:
return self.json_message("No host or api_password received.",
HTTP_BAD_REQUEST)
try:
port = int(data['port']) if 'port' in data else None
except ValueError:
return self.json_message("Invalid value received for port.",
HTTP_UNPROCESSABLE_ENTITY)
api = rem.API(host, api_password, port)
valid = yield from hass.loop.run_in_executor(
None, api.validate_api)
if not valid:
return self.json_message("Unable to validate API.",
HTTP_UNPROCESSABLE_ENTITY)
if self.event_forwarder is None:
self.event_forwarder = rem.EventForwarder(hass)
self.event_forwarder.async_connect(api)
return self.json_message("Event forwarding setup.")
@asyncio.coroutine
def delete(self, request):
"""Remove event forwarder."""
try:
data = yield from request.json()
except ValueError:
return self.json_message("No data received.", HTTP_BAD_REQUEST)
try:
host = data['host']
except KeyError:
return self.json_message("No host received.", HTTP_BAD_REQUEST)
try:
port = int(data['port']) if 'port' in data else None
except ValueError:
return self.json_message("Invalid value received for port.",
HTTP_UNPROCESSABLE_ENTITY)
if self.event_forwarder is not None:
api = rem.API(host, None, port)
self.event_forwarder.async_disconnect(api)
return self.json_message("Event forwarding cancelled.")
class APIComponentsView(HomeAssistantView):
"""View to handle Components requests."""
@@ -400,20 +330,6 @@ class APIComponentsView(HomeAssistantView):
return self.json(request.app['hass'].config.components)
class APIErrorLogView(HomeAssistantView):
"""View to handle ErrorLog requests."""
url = URL_API_ERROR_LOG
name = "api:error-log"
@asyncio.coroutine
def get(self, request):
"""Serve error log."""
resp = yield from self.file(
request, request.app['hass'].config.path(ERROR_LOG_FILENAME))
return resp
class APITemplateView(HomeAssistantView):
"""View to handle requests."""

View File

@@ -77,14 +77,14 @@ class ApiaiIntentsView(HomeAssistantView):
"""Handle API.AI."""
data = yield from request.json()
_LOGGER.debug('Received Apiai request: %s', data)
_LOGGER.debug("Received api.ai request: %s", data)
req = data.get('result')
if req is None:
_LOGGER.error('Received invalid data from Apiai: %s', data)
return self.json_message('Expected result value not received',
HTTP_BAD_REQUEST)
_LOGGER.error("Received invalid data from api.ai: %s", data)
return self.json_message(
"Expected result value not received", HTTP_BAD_REQUEST)
action_incomplete = req['actionIncomplete']
@@ -106,7 +106,7 @@ class ApiaiIntentsView(HomeAssistantView):
# return self.json(response)
if intent == "":
_LOGGER.warning('Received intent with empty action')
_LOGGER.warning("Received intent with empty action")
response.add_speech(
"You have not defined an action in your api.ai intent.")
return self.json(response)
@@ -114,7 +114,7 @@ class ApiaiIntentsView(HomeAssistantView):
config = self.intents.get(intent)
if config is None:
_LOGGER.warning('Received unknown intent %s', intent)
_LOGGER.warning("Received unknown intent %s", intent)
response.add_speech(
"Intent '%s' is not yet configured within Home Assistant." %
intent)

View File

@@ -13,7 +13,7 @@ from homeassistant.const import (
from homeassistant.const import CONF_PORT
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['PyMata==2.13']
REQUIREMENTS = ['PyMata==2.14']
_LOGGER = logging.getLogger(__name__)
@@ -29,18 +29,25 @@ CONFIG_SCHEMA = vol.Schema({
def setup(hass, config):
"""Setup the Arduino component."""
"""Set up the Arduino component."""
import serial
port = config[DOMAIN][CONF_PORT]
global BOARD
try:
BOARD = ArduinoBoard(config[DOMAIN][CONF_PORT])
BOARD = ArduinoBoard(port)
except (serial.serialutil.SerialException, FileNotFoundError):
_LOGGER.exception("Your port is not accessible.")
_LOGGER.error("Your port %s is not accessible", port)
return False
if BOARD.get_firmata()[1] <= 2:
_LOGGER.error("The StandardFirmata sketch should be 2.2 or newer.")
return False
try:
if BOARD.get_firmata()[1] <= 2:
_LOGGER.error("The StandardFirmata sketch should be 2.2 or newer")
return False
except IndexError:
_LOGGER.warning("The version of the StandardFirmata sketch was not"
"detected. This may lead to side effects")
def stop_arduino(event):
"""Stop the Arduino service."""
@@ -67,25 +74,20 @@ class ArduinoBoard(object):
def set_mode(self, pin, direction, mode):
"""Set the mode and the direction of a given pin."""
if mode == 'analog' and direction == 'in':
self._board.set_pin_mode(pin,
self._board.INPUT,
self._board.ANALOG)
self._board.set_pin_mode(
pin, self._board.INPUT, self._board.ANALOG)
elif mode == 'analog' and direction == 'out':
self._board.set_pin_mode(pin,
self._board.OUTPUT,
self._board.ANALOG)
self._board.set_pin_mode(
pin, self._board.OUTPUT, self._board.ANALOG)
elif mode == 'digital' and direction == 'in':
self._board.set_pin_mode(pin,
self._board.INPUT,
self._board.DIGITAL)
self._board.set_pin_mode(
pin, self._board.INPUT, self._board.DIGITAL)
elif mode == 'digital' and direction == 'out':
self._board.set_pin_mode(pin,
self._board.OUTPUT,
self._board.DIGITAL)
self._board.set_pin_mode(
pin, self._board.OUTPUT, self._board.DIGITAL)
elif mode == 'pwm':
self._board.set_pin_mode(pin,
self._board.OUTPUT,
self._board.PWM)
self._board.set_pin_mode(
pin, self._board.OUTPUT, self._board.PWM)
def get_analog_inputs(self):
"""Get the values from the pins."""

View File

@@ -11,16 +11,18 @@ import os
import voluptuous as vol
from homeassistant.bootstrap import async_prepare_setup_platform
from homeassistant.setup import async_prepare_setup_platform
from homeassistant.core import CoreState
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_TOGGLE, SERVICE_RELOAD, EVENT_HOMEASSISTANT_START)
from homeassistant.components import logbook
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import extract_domain_configs, script, condition
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.restore_state import async_get_last_state
from homeassistant.loader import get_platform
from homeassistant.util.dt import utcnow
import homeassistant.helpers.config_validation as cv
@@ -28,8 +30,6 @@ import homeassistant.helpers.config_validation as cv
DOMAIN = 'automation'
ENTITY_ID_FORMAT = DOMAIN + '.{}'
DEPENDENCIES = ['group']
GROUP_NAME_ALL_AUTOMATIONS = 'all automations'
CONF_ALIAS = 'alias'
@@ -52,7 +52,6 @@ DEFAULT_INITIAL_STATE = True
ATTR_LAST_TRIGGERED = 'last_triggered'
ATTR_VARIABLES = 'variables'
SERVICE_TRIGGER = 'trigger'
SERVICE_RELOAD = 'reload'
_LOGGER = logging.getLogger(__name__)
@@ -83,8 +82,7 @@ _CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA])
PLATFORM_SCHEMA = vol.Schema({
CONF_ALIAS: cv.string,
vol.Optional(CONF_INITIAL_STATE,
default=DEFAULT_INITIAL_STATE): cv.boolean,
vol.Optional(CONF_INITIAL_STATE): cv.boolean,
vol.Optional(CONF_HIDE_ENTITY, default=DEFAULT_HIDE_ENTITY): cv.boolean,
vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA,
vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA,
@@ -103,15 +101,13 @@ TRIGGER_SERVICE_SCHEMA = vol.Schema({
RELOAD_SERVICE_SCHEMA = vol.Schema({})
def is_on(hass, entity_id=None):
def is_on(hass, entity_id):
"""
Return true if specified automation entity_id is on.
Check all automation if no entity_id specified.
Async friendly.
"""
entity_ids = [entity_id] if entity_id else hass.states.entity_ids(DOMAIN)
return any(hass.states.is_state(entity_id, STATE_ON)
for entity_id in entity_ids)
return hass.states.is_state(entity_id, STATE_ON)
def turn_on(hass, entity_id=None):
@@ -145,7 +141,7 @@ def reload(hass):
@asyncio.coroutine
def async_setup(hass, config):
"""Setup the automation."""
"""Set up the automation."""
component = EntityComponent(_LOGGER, DOMAIN, hass,
group_name=GROUP_NAME_ALL_AUTOMATIONS)
@@ -226,16 +222,16 @@ class AutomationEntity(ToggleEntity):
"""Entity to show status of entity."""
def __init__(self, name, async_attach_triggers, cond_func, async_action,
hidden):
hidden, initial_state):
"""Initialize an automation entity."""
self._name = name
self._async_attach_triggers = async_attach_triggers
self._async_detach_triggers = None
self._cond_func = cond_func
self._async_action = async_action
self._enabled = False
self._last_triggered = None
self._hidden = hidden
self._initial_state = initial_state
@property
def name(self):
@@ -262,26 +258,62 @@ class AutomationEntity(ToggleEntity):
@property
def is_on(self) -> bool:
"""Return True if entity is on."""
return self._enabled
return self._async_detach_triggers is not None
@asyncio.coroutine
def async_added_to_hass(self) -> None:
"""Startup with initial state or previous state."""
if self._initial_state is not None:
enable_automation = self._initial_state
_LOGGER.debug("Automation %s initial state %s from config "
"initial_state", self.entity_id, enable_automation)
else:
state = yield from async_get_last_state(self.hass, self.entity_id)
if state:
enable_automation = state.state == STATE_ON
self._last_triggered = state.attributes.get('last_triggered')
_LOGGER.debug("Automation %s initial state %s from recorder "
"last state %s", self.entity_id,
enable_automation, state)
else:
enable_automation = DEFAULT_INITIAL_STATE
_LOGGER.debug("Automation %s initial state %s from default "
"initial state", self.entity_id,
enable_automation)
if not enable_automation:
return
# HomeAssistant is starting up
elif self.hass.state == CoreState.not_running:
@asyncio.coroutine
def async_enable_automation(event):
"""Start automation on startup."""
yield from self.async_enable()
self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, async_enable_automation)
# HomeAssistant is running
else:
yield from self.async_enable()
@asyncio.coroutine
def async_turn_on(self, **kwargs) -> None:
"""Turn the entity on and update the state."""
if self._enabled:
if self.is_on:
return
yield from self.async_enable()
yield from self.async_update_ha_state()
@asyncio.coroutine
def async_turn_off(self, **kwargs) -> None:
"""Turn the entity off."""
if not self._enabled:
if not self.is_on:
return
self._async_detach_triggers()
self._async_detach_triggers = None
self._enabled = False
yield from self.async_update_ha_state()
@asyncio.coroutine
@@ -307,12 +339,12 @@ class AutomationEntity(ToggleEntity):
This method is a coroutine.
"""
if self._enabled:
if self.is_on:
return
self._async_detach_triggers = yield from self._async_attach_triggers(
self.async_trigger)
self._enabled = True
yield from self.async_update_ha_state()
@asyncio.coroutine
@@ -322,7 +354,6 @@ def _async_process_config(hass, config, component):
This method is a coroutine.
"""
entities = []
tasks = []
for config_key in extract_domain_configs(config, DOMAIN):
conf = config[config_key]
@@ -332,6 +363,7 @@ def _async_process_config(hass, config, component):
list_no)
hidden = config_block[CONF_HIDE_ENTITY]
initial_state = config_block.get(CONF_INITIAL_STATE)
action = _async_get_action(hass, config_block.get(CONF_ACTION, {}),
name)
@@ -348,15 +380,14 @@ def _async_process_config(hass, config, component):
async_attach_triggers = partial(
_async_process_trigger, hass, config,
config_block.get(CONF_TRIGGER, []), name)
entity = AutomationEntity(name, async_attach_triggers, cond_func,
action, hidden)
if config_block[CONF_INITIAL_STATE]:
tasks.append(entity.async_enable())
config_block.get(CONF_TRIGGER, []), name
)
entity = AutomationEntity(
name, async_attach_triggers, cond_func, action, hidden,
initial_state)
entities.append(entity)
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
if entities:
yield from component.async_add_entities(entities)
@@ -369,7 +400,7 @@ def _async_get_action(hass, config, name):
@asyncio.coroutine
def action(entity_id, variables):
"""Action to be executed."""
"""Execute an action."""
_LOGGER.info('Executing %s', name)
logbook.async_log_entry(
hass, name, 'has been triggered', DOMAIN, entity_id)
@@ -399,7 +430,7 @@ def _async_process_if(hass, config, p_config):
@asyncio.coroutine
def _async_process_trigger(hass, config, trigger_configs, name, action):
"""Setup the triggers.
"""Set up the triggers.
This method is a coroutine.
"""
@@ -412,7 +443,7 @@ def _async_process_trigger(hass, config, trigger_configs, name, action):
if platform is None:
return None
remove = platform.async_trigger(hass, conf, action)
remove = yield from platform.async_trigger(hass, conf, action)
if not remove:
_LOGGER.error("Error setting up trigger %s", name)

View File

@@ -2,18 +2,19 @@
Offer event listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#event-trigger
at https://home-assistant.io/docs/automation/trigger/#event-trigger
"""
import asyncio
import logging
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import CONF_PLATFORM
from homeassistant.core import callback, CoreState
from homeassistant.const import CONF_PLATFORM, EVENT_HOMEASSISTANT_START
from homeassistant.helpers import config_validation as cv
CONF_EVENT_TYPE = "event_type"
CONF_EVENT_DATA = "event_data"
CONF_EVENT_TYPE = 'event_type'
CONF_EVENT_DATA = 'event_data'
_LOGGER = logging.getLogger(__name__)
@@ -24,11 +25,25 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
event_type = config.get(CONF_EVENT_TYPE)
event_data = config.get(CONF_EVENT_DATA)
if (event_type == EVENT_HOMEASSISTANT_START and
hass.state == CoreState.starting):
_LOGGER.warning('Deprecation: Automations should not listen to event '
"'homeassistant_start'. Use platform 'homeassistant' "
'instead. Feature will be removed in 0.45')
hass.async_run_job(action, {
'trigger': {
'platform': 'event',
'event': None,
},
})
return lambda: None
@callback
def handle_event(event):
"""Listen for events and calls the action when data matches."""

View File

@@ -0,0 +1,55 @@
"""
Offer Home Assistant core automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#homeassistant-trigger
"""
import asyncio
import logging
import voluptuous as vol
from homeassistant.core import callback, CoreState
from homeassistant.const import (
CONF_PLATFORM, CONF_EVENT, EVENT_HOMEASSISTANT_STOP)
EVENT_START = 'start'
EVENT_SHUTDOWN = 'shutdown'
_LOGGER = logging.getLogger(__name__)
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'homeassistant',
vol.Required(CONF_EVENT): vol.Any(EVENT_START, EVENT_SHUTDOWN),
})
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
event = config.get(CONF_EVENT)
if event == EVENT_SHUTDOWN:
@callback
def hass_shutdown(event):
"""Execute when Home Assistant is shutting down."""
hass.async_run_job(action, {
'trigger': {
'platform': 'homeassistant',
'event': event,
},
})
return hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP,
hass_shutdown)
# Automation are enabled while hass is starting up, fire right away
# Check state because a config reload shouldn't trigger it.
elif hass.state == CoreState.starting:
hass.async_run_job(action, {
'trigger': {
'platform': 'homeassistant',
'event': event,
},
})
return lambda: None

View File

@@ -4,6 +4,7 @@ Trigger an automation when a LiteJet switch is released.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/automation.litejet/
"""
import asyncio
import logging
import voluptuous as vol
@@ -32,6 +33,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for events based on configuration."""
number = config.get(CONF_NUMBER)
@@ -68,7 +70,7 @@ def async_trigger(hass, config, action):
nonlocal held_less_than, held_more_than
pressed_time = dt_util.utcnow()
if held_more_than is None and held_less_than is None:
call_action()
hass.add_job(call_action)
if held_more_than is not None and held_less_than is None:
cancel_pressed_more_than = track_point_in_utc_time(
hass,
@@ -86,7 +88,7 @@ def async_trigger(hass, config, action):
held_time = dt_util.utcnow() - pressed_time
if held_less_than is not None and held_time < held_less_than:
if held_more_than is None or held_time > held_more_than:
call_action()
hass.add_job(call_action)
hass.data['litejet_system'].on_switch_pressed(number, pressed)
hass.data['litejet_system'].on_switch_released(number, released)

View File

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

View File

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

View File

@@ -2,8 +2,9 @@
Offer state listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#state-trigger
at https://home-assistant.io/docs/automation/trigger/#state-trigger
"""
import asyncio
import voluptuous as vol
from homeassistant.core import callback
@@ -13,11 +14,11 @@ from homeassistant.helpers.event import (
async_track_state_change, async_track_point_in_utc_time)
import homeassistant.helpers.config_validation as cv
CONF_ENTITY_ID = "entity_id"
CONF_FROM = "from"
CONF_TO = "to"
CONF_STATE = "state"
CONF_FOR = "for"
CONF_ENTITY_ID = 'entity_id'
CONF_FROM = 'from'
CONF_TO = 'to'
CONF_STATE = 'state'
CONF_FOR = 'for'
TRIGGER_SCHEMA = vol.All(
vol.Schema({
@@ -34,6 +35,7 @@ TRIGGER_SCHEMA = vol.All(
)
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
@@ -43,6 +45,19 @@ def async_trigger(hass, config, action):
async_remove_state_for_cancel = None
async_remove_state_for_listener = None
@callback
def clear_listener():
"""Clear all unsub listener."""
nonlocal async_remove_state_for_cancel, async_remove_state_for_listener
# pylint: disable=not-callable
if async_remove_state_for_listener is not None:
async_remove_state_for_listener()
async_remove_state_for_listener = None
if async_remove_state_for_cancel is not None:
async_remove_state_for_cancel()
async_remove_state_for_cancel = None
@callback
def state_automation_listener(entity, from_s, to_s):
"""Listen for state changes and calls action."""
@@ -64,18 +79,11 @@ def async_trigger(hass, config, action):
call_action()
return
@callback
def clear_listener():
"""Clear all unsub listener."""
nonlocal async_remove_state_for_cancel
nonlocal async_remove_state_for_listener
async_remove_state_for_listener = None
async_remove_state_for_cancel = None
@callback
def state_for_listener(now):
"""Fire on state changes after a delay and calls action."""
async_remove_state_for_cancel()
nonlocal async_remove_state_for_listener
async_remove_state_for_listener = None
clear_listener()
call_action()
@@ -84,10 +92,11 @@ def async_trigger(hass, config, action):
"""Fire on changes and cancel for listener if changed."""
if inner_to_s.state == to_s.state:
return
async_remove_state_for_listener()
async_remove_state_for_cancel()
clear_listener()
# cleanup previous listener
clear_listener()
async_remove_state_for_listener = async_track_point_in_utc_time(
hass, state_for_listener, dt_util.utcnow() + time_delta)
@@ -97,14 +106,10 @@ def async_trigger(hass, config, action):
unsub = async_track_state_change(
hass, entity_id, state_automation_listener, from_state, to_state)
@callback
def async_remove():
"""Remove state listeners async."""
unsub()
# pylint: disable=not-callable
if async_remove_state_for_cancel is not None:
async_remove_state_for_cancel()
if async_remove_state_for_listener is not None:
async_remove_state_for_listener()
clear_listener()
return async_remove

View File

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

View File

@@ -2,16 +2,16 @@
Offer template automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#template-trigger
at https://home-assistant.io/docs/automation/trigger/#template-trigger
"""
import asyncio
import logging
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import CONF_VALUE_TEMPLATE, CONF_PLATFORM
from homeassistant.helpers import condition
from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers.event import async_track_template
import homeassistant.helpers.config_validation as cv
@@ -23,33 +23,22 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
value_template = config.get(CONF_VALUE_TEMPLATE)
value_template.hass = hass
# Local variable to keep track of if the action has already been triggered
already_triggered = False
@callback
def state_changed_listener(entity_id, from_s, to_s):
def template_listener(entity_id, from_s, to_s):
"""Listen for state changes and calls action."""
nonlocal already_triggered
template_result = condition.async_template(hass, value_template)
hass.async_run_job(action, {
'trigger': {
'platform': 'template',
'entity_id': entity_id,
'from_state': from_s,
'to_state': to_s,
},
})
# Check to see if template returns true
if template_result and not already_triggered:
already_triggered = True
hass.async_run_job(action, {
'trigger': {
'platform': 'template',
'entity_id': entity_id,
'from_state': from_s,
'to_state': to_s,
},
})
elif not template_result:
already_triggered = False
return async_track_state_change(hass, value_template.extract_entities(),
state_changed_listener)
return async_track_template(hass, value_template, template_listener)

View File

@@ -2,8 +2,9 @@
Offer time listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#time-trigger
at https://home-assistant.io/docs/automation/trigger/#time-trigger
"""
import asyncio
import logging
import voluptuous as vol
@@ -13,9 +14,9 @@ from homeassistant.const import CONF_AFTER, CONF_PLATFORM
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import async_track_time_change
CONF_HOURS = "hours"
CONF_MINUTES = "minutes"
CONF_SECONDS = "seconds"
CONF_HOURS = 'hours'
CONF_MINUTES = 'minutes'
CONF_SECONDS = 'seconds'
_LOGGER = logging.getLogger(__name__)
@@ -29,6 +30,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({
CONF_SECONDS, CONF_AFTER))
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
if CONF_AFTER in config:

View File

@@ -2,8 +2,9 @@
Offer zone automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#zone-trigger
at https://home-assistant.io/docs/automation/trigger/#zone-trigger
"""
import asyncio
import voluptuous as vol
from homeassistant.core import callback
@@ -13,8 +14,8 @@ from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers import (
condition, config_validation as cv, location)
EVENT_ENTER = "enter"
EVENT_LEAVE = "leave"
EVENT_ENTER = 'enter'
EVENT_LEAVE = 'leave'
DEFAULT_EVENT = EVENT_ENTER
TRIGGER_SCHEMA = vol.Schema({
@@ -26,6 +27,7 @@ TRIGGER_SCHEMA = vol.Schema({
})
@asyncio.coroutine
def async_trigger(hass, config, action):
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)

View File

@@ -37,14 +37,14 @@ def setup(hass, config):
# noqa: F821
def setup_output(pin):
"""Setup a GPIO as output."""
"""Set up a GPIO as output."""
# pylint: disable=import-error,undefined-variable
import Adafruit_BBIO.GPIO as GPIO
GPIO.setup(pin, GPIO.OUT)
def setup_input(pin, pull_mode):
"""Setup a GPIO as input."""
"""Set up a GPIO as input."""
# pylint: disable=import-error,undefined-variable
import Adafruit_BBIO.GPIO as GPIO
GPIO.setup(pin, GPIO.IN, # noqa: F821

View File

@@ -14,13 +14,13 @@ from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity import Entity
from homeassistant.const import (STATE_ON, STATE_OFF)
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
from homeassistant.helpers.deprecation import deprecated_substitute
DOMAIN = 'binary_sensor'
SCAN_INTERVAL = timedelta(seconds=30)
ENTITY_ID_FORMAT = DOMAIN + '.{}'
SENSOR_CLASSES = [
None, # Generic on/off
DEVICE_CLASSES = [
'cold', # On means cold (or too cold)
'connectivity', # On means connection present, Off = no connection
'gas', # CO, CO2, etc.
@@ -38,7 +38,7 @@ SENSOR_CLASSES = [
'vibration', # On means vibration detected, Off means no vibration
]
SENSOR_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(SENSOR_CLASSES))
DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(DEVICE_CLASSES))
@asyncio.coroutine
@@ -57,7 +57,7 @@ class BinarySensorDevice(Entity):
@property
def is_on(self):
"""Return True if the binary sensor is on."""
"""Return true if the binary sensor is on."""
return None
@property
@@ -66,16 +66,7 @@ class BinarySensorDevice(Entity):
return STATE_ON if self.is_on else STATE_OFF
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
@deprecated_substitute('sensor_class')
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return None
@property
def state_attributes(self):
"""Return device specific state attributes."""
attr = {}
if self.sensor_class is not None:
attr['sensor_class'] = self.sensor_class
return attr

View File

@@ -0,0 +1,112 @@
"""
Support for AlarmDecoder zone states- represented as binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.alarmdecoder/
"""
import asyncio
import logging
from homeassistant.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)
DEPENDENCIES = ['alarmdecoder']
_LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_setup_platform(hass, config, async_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]
device = AlarmDecoderBinarySensor(
hass, zone_num, zone_name, zone_type)
devices.append(device)
async_add_devices(devices)
return True
class AlarmDecoderBinarySensor(BinarySensorDevice):
"""Representation of an AlarmDecoder binary sensor."""
def __init__(self, hass, zone_number, zone_name, zone_type):
"""Initialize the binary_sensor."""
self._zone_number = zone_number
self._zone_type = zone_type
self._state = 0
self._name = zone_name
self._type = zone_type
_LOGGER.debug("Setup up zone: %s", self._name)
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_FAULT, self._fault_callback)
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_RESTORE, self._restore_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 is_on(self):
"""Return true if sensor is on."""
return self._state == 1
@property
def device_class(self):
"""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.hass.async_add_job(self.async_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.hass.async_add_job(self.async_update_ha_state())

View File

@@ -0,0 +1,62 @@
"""
Support for IP Webcam binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.android_ip_webcam/
"""
import asyncio
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.android_ip_webcam import (
KEY_MAP, DATA_IP_WEBCAM, AndroidIPCamEntity, CONF_HOST, CONF_NAME)
DEPENDENCIES = ['android_ip_webcam']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the IP Webcam binary sensors."""
if discovery_info is None:
return
host = discovery_info[CONF_HOST]
name = discovery_info[CONF_NAME]
ipcam = hass.data[DATA_IP_WEBCAM][host]
async_add_devices(
[IPWebcamBinarySensor(name, host, ipcam, 'motion_active')], True)
class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice):
"""Representation of an IP Webcam binary sensor."""
def __init__(self, name, host, ipcam, sensor):
"""Initialize the binary sensor."""
super().__init__(host, ipcam)
self._sensor = sensor
self._mapped_name = KEY_MAP.get(self._sensor, self._sensor)
self._name = '{} {}'.format(name, self._mapped_name)
self._state = None
self._unit = None
@property
def name(self):
"""Return the name of the binary sensor, if any."""
return self._name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@asyncio.coroutine
def async_update(self):
"""Retrieve latest state."""
state, _ = self._ipcam.export_sensor(self._sensor)
self._state = state == 1.0
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return 'motion'

View File

@@ -21,7 +21,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup an Online Status binary sensor."""
"""Set up an Online Status binary sensor."""
add_entities((OnlineStatus(config, apcupsd.DATA),))

View File

@@ -11,11 +11,12 @@ import requests
import voluptuous as vol
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA)
BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
CONF_RESOURCE, CONF_PIN, CONF_NAME, CONF_SENSOR_CLASS)
CONF_RESOURCE, CONF_PIN, CONF_NAME, CONF_SENSOR_CLASS, CONF_DEVICE_CLASS)
from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
_LOGGER = logging.getLogger(__name__)
@@ -25,7 +26,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_RESOURCE): cv.url,
vol.Optional(CONF_NAME): cv.string,
vol.Required(CONF_PIN): cv.string,
vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA,
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
@@ -33,7 +35,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the aREST binary sensor."""
resource = config.get(CONF_RESOURCE)
pin = config.get(CONF_PIN)
sensor_class = config.get(CONF_SENSOR_CLASS)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
try:
response = requests.get(resource, timeout=10).json()
@@ -49,18 +51,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
add_devices([ArestBinarySensor(
arest, resource, config.get(CONF_NAME, response[CONF_NAME]),
sensor_class, pin)])
device_class, pin)])
class ArestBinarySensor(BinarySensorDevice):
"""Implement an aREST binary sensor for a pin."""
def __init__(self, arest, resource, name, sensor_class, pin):
def __init__(self, arest, resource, name, device_class, pin):
"""Initialize the aREST device."""
self.arest = arest
self._resource = resource
self._name = name
self._sensor_class = sensor_class
self._device_class = device_class
self._pin = pin
self.update()
@@ -81,9 +83,9 @@ class ArestBinarySensor(BinarySensorDevice):
return bool(self.arest.data.get('state'))
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return self._sensor_class
return self._device_class
def update(self):
"""Get the latest data from aREST API."""

View File

@@ -0,0 +1,148 @@
"""
Support for aurora forecast data sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.aurora/
"""
from datetime import timedelta
import logging
import requests
import voluptuous as vol
from homeassistant.components.binary_sensor \
import (BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_NAME)
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle
CONF_THRESHOLD = "forecast_threshold"
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'Aurora Visibility'
DEFAULT_DEVICE_CLASS = "visible"
DEFAULT_THRESHOLD = 75
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_THRESHOLD, default=DEFAULT_THRESHOLD): cv.positive_int,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the aurora sensor."""
if None in (hass.config.latitude, hass.config.longitude):
_LOGGER.error("Lat. or long. not set in Home Assistant config")
return False
name = config.get(CONF_NAME)
threshold = config.get(CONF_THRESHOLD)
try:
aurora_data = AuroraData(
hass.config.latitude,
hass.config.longitude,
threshold
)
aurora_data.update()
except requests.exceptions.HTTPError as error:
_LOGGER.error(
"Connection to aurora forecast service failed: %s", error)
return False
add_devices([AuroraSensor(aurora_data, name)], True)
class AuroraSensor(BinarySensorDevice):
"""Implementation of an aurora sensor."""
def __init__(self, aurora_data, name):
"""Initialize the sensor."""
self.aurora_data = aurora_data
self._name = name
@property
def name(self):
"""Return the name of the sensor."""
return '{}'.format(self._name)
@property
def is_on(self):
"""Return true if aurora is visible."""
return self.aurora_data.is_visible if self.aurora_data else False
@property
def device_class(self):
"""Return the class of this device."""
return DEFAULT_DEVICE_CLASS
@property
def device_state_attributes(self):
"""Return the state attributes."""
attrs = {}
if self.aurora_data:
attrs["visibility_level"] = self.aurora_data.visibility_level
attrs["message"] = self.aurora_data.is_visible_text
return attrs
def update(self):
"""Get the latest data from Aurora API and updates the states."""
self.aurora_data.update()
class AuroraData(object):
"""Get aurora forecast."""
def __init__(self, latitude, longitude, threshold):
"""Initialize the data object."""
self.latitude = latitude
self.longitude = longitude
self.number_of_latitude_intervals = 513
self.number_of_longitude_intervals = 1024
self.api_url = \
"http://services.swpc.noaa.gov/text/aurora-nowcast-map.txt"
self.headers = {"User-Agent": "Home Assistant Aurora Tracker v.0.1.0"}
self.threshold = int(threshold)
self.is_visible = None
self.is_visible_text = None
self.visibility_level = None
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Get the latest data from the Aurora service."""
try:
self.visibility_level = self.get_aurora_forecast()
if int(self.visibility_level) > self.threshold:
self.is_visible = True
self.is_visible_text = "visible!"
else:
self.is_visible = False
self.is_visible_text = "nothing's out"
except requests.exceptions.HTTPError as error:
_LOGGER.error(
"Connection to aurora forecast service failed: %s", error)
return False
def get_aurora_forecast(self):
"""Get forecast data and parse for given long/lat."""
raw_data = requests.get(self.api_url, headers=self.headers).text
forecast_table = [
row.strip(" ").split(" ")
for row in raw_data.split("\n")
if not row.startswith("#")
]
# convert lat and long for data points in table
converted_latitude = round((self.latitude / 180)
* self.number_of_latitude_intervals)
converted_longitude = round((self.longitude / 360)
* self.number_of_longitude_intervals)
return forecast_table[converted_latitude][converted_longitude]

View File

@@ -42,7 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Beaglebone Black GPIO devices."""
"""Set up the Beaglebone Black GPIO devices."""
pins = config.get(CONF_PINS)
binary_sensors = []
@@ -53,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class BBBGPIOBinarySensor(BinarySensorDevice):
"""Represent a binary sensor that uses Beaglebone Black GPIO."""
"""Representation of a binary sensor that uses Beaglebone Black GPIO."""
def __init__(self, pin, params):
"""Initialize the Beaglebone Black binary sensor."""

View File

@@ -0,0 +1,74 @@
"""
Support for Blink system camera control.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.blink/
"""
from homeassistant.components.blink import DOMAIN
from homeassistant.components.binary_sensor import BinarySensorDevice
DEPENDENCIES = ['blink']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the blink binary sensors."""
if discovery_info is None:
return
data = hass.data[DOMAIN].blink
devs = list()
for name in data.cameras:
devs.append(BlinkCameraMotionSensor(name, data))
devs.append(BlinkSystemSensor(data))
add_devices(devs, True)
class BlinkCameraMotionSensor(BinarySensorDevice):
"""Representation of a Blink binary sensor."""
def __init__(self, name, data):
"""Initialize the sensor."""
self._name = 'blink_' + name + '_motion_enabled'
self._camera_name = name
self.data = data
self._state = self.data.cameras[self._camera_name].armed
@property
def name(self):
"""Return the name of the blink sensor."""
return self._name
@property
def is_on(self):
"""Return the status of the sensor."""
return self._state
def update(self):
"""Update sensor state."""
self.data.refresh()
self._state = self.data.cameras[self._camera_name].armed
class BlinkSystemSensor(BinarySensorDevice):
"""A representation of a Blink system sensor."""
def __init__(self, data):
"""Initialize the sensor."""
self._name = 'blink armed status'
self.data = data
self._state = self.data.arm
@property
def name(self):
"""Return the name of the blink sensor."""
return self._name.replace(" ", "_")
@property
def is_on(self):
"""Return the status of the sensor."""
return self._state
def update(self):
"""Update sensor state."""
self.data.refresh()
self._state = self.data.arm

View File

@@ -18,7 +18,6 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['bloomsky']
# These are the available sensors mapped to binary_sensor class
SENSOR_TYPES = {
'Rain': 'moisture',
'Night': None,
@@ -31,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the available BloomSky weather binary sensors."""
"""Set up the available BloomSky weather binary sensors."""
bloomsky = get_component('bloomsky')
# Default needed in case of discovery
sensors = config.get(CONF_MONITORED_CONDITIONS, SENSOR_TYPES)
@@ -42,7 +41,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class BloomSkySensor(BinarySensorDevice):
"""Represent a single binary sensor in a BloomSky device."""
"""Representation of a single binary sensor in a BloomSky device."""
def __init__(self, bs, device, sensor_name):
"""Initialize a BloomSky binary sensor."""
@@ -55,7 +54,7 @@ class BloomSkySensor(BinarySensorDevice):
@property
def name(self):
"""The name of the BloomSky device and this sensor."""
"""Return the name of the BloomSky device and this sensor."""
return self._name
@property
@@ -64,8 +63,8 @@ class BloomSkySensor(BinarySensorDevice):
return self._unique_id
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return SENSOR_TYPES.get(self._sensor_name)
@property

View File

@@ -10,12 +10,13 @@ import logging
import voluptuous as vol
from homeassistant.components.binary_sensor import (
BinarySensorDevice, SENSOR_CLASSES_SCHEMA, PLATFORM_SCHEMA)
BinarySensorDevice, DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA)
from homeassistant.components.sensor.command_line import CommandSensorData
from homeassistant.const import (
CONF_PAYLOAD_OFF, CONF_PAYLOAD_ON, CONF_NAME, CONF_VALUE_TEMPLATE,
CONF_SENSOR_CLASS, CONF_COMMAND)
CONF_SENSOR_CLASS, CONF_COMMAND, CONF_DEVICE_CLASS)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
_LOGGER = logging.getLogger(__name__)
@@ -30,39 +31,40 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
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_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA,
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
})
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Command line Binary Sensor."""
"""Set up the Command line Binary Sensor."""
name = config.get(CONF_NAME)
command = config.get(CONF_COMMAND)
payload_off = config.get(CONF_PAYLOAD_OFF)
payload_on = config.get(CONF_PAYLOAD_ON)
sensor_class = config.get(CONF_SENSOR_CLASS)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = hass
data = CommandSensorData(command)
add_devices([CommandBinarySensor(
hass, data, name, sensor_class, payload_on, payload_off,
hass, data, name, device_class, payload_on, payload_off,
value_template)])
class CommandBinarySensor(BinarySensorDevice):
"""Represent a command line binary sensor."""
"""Representation of a command line binary sensor."""
def __init__(self, hass, data, name, sensor_class, payload_on,
def __init__(self, hass, data, name, device_class, payload_on,
payload_off, value_template):
"""Initialize the Command line binary sensor."""
self._hass = hass
self.data = data
self._name = name
self._sensor_class = sensor_class
self._device_class = device_class
self._state = False
self._payload_on = payload_on
self._payload_off = payload_off
@@ -80,9 +82,9 @@ class CommandBinarySensor(BinarySensorDevice):
return self._state
@ property
def sensor_class(self):
def device_class(self):
"""Return the class of the binary sensor."""
return self._sensor_class
return self._device_class
def update(self):
"""Get the latest data and updates the state."""

View File

@@ -11,7 +11,7 @@ import requests
import voluptuous as vol
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES)
BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES)
from homeassistant.const import (CONF_HOST, CONF_PORT)
import homeassistant.helpers.config_validation as cv
@@ -30,7 +30,7 @@ DEFAULT_SSL = False
SCAN_INTERVAL = datetime.timedelta(seconds=1)
ZONE_TYPES_SCHEMA = vol.Schema({
cv.positive_int: vol.In(SENSOR_CLASSES),
cv.positive_int: vol.In(DEVICE_CLASSES),
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@@ -67,8 +67,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if zone['number'] not in exclude:
sensors.append(
Concord232ZoneSensor(
hass, client, zone, zone_types.get(zone['number'],
get_opening_type(zone)))
hass, client, zone, zone_types.get(
zone['number'], get_opening_type(zone))
)
)
add_devices(sensors)
@@ -77,7 +78,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
def get_opening_type(zone):
"""Helper function to try to guess sensor type from name."""
"""Return the result of the type guessing from name."""
if 'MOTION' in zone['name']:
return 'motion'
if 'KEY' in zone['name']:
@@ -102,8 +103,8 @@ class Concord232ZoneSensor(BinarySensorDevice):
self.update()
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return self._zone_type
@property
@@ -123,7 +124,7 @@ class Concord232ZoneSensor(BinarySensorDevice):
return bool(self._zone['state'] == 'Normal')
def update(self):
""""Get updated stats from API."""
"""Get updated stats from API."""
last_update = datetime.datetime.now() - self._client.last_zone_update
_LOGGER.debug("Zone: %s ", self._zone)
if last_update > datetime.timedelta(seconds=1):

View File

@@ -8,7 +8,7 @@ from homeassistant.components.binary_sensor import BinarySensorDevice
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo binary sensor platform."""
"""Set up the Demo binary sensor platform."""
add_devices([
DemoBinarySensor('Basement Floor Wet', False, 'moisture'),
DemoBinarySensor('Movement Backyard', True, 'motion'),
@@ -16,16 +16,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class DemoBinarySensor(BinarySensorDevice):
"""A Demo binary sensor."""
"""representation of a Demo binary sensor."""
def __init__(self, name, state, sensor_class):
def __init__(self, name, state, device_class):
"""Initialize the demo sensor."""
self._name = name
self._state = state
self._sensor_type = sensor_class
self._sensor_type = device_class
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return self._sensor_type

View File

@@ -36,6 +36,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
dev = []
for droplet in droplets:
droplet_id = digital_ocean.DIGITAL_OCEAN.get_droplet_id(droplet)
if droplet_id is None:
_LOGGER.error("Droplet %s is not available", droplet)
return False
dev.append(DigitalOceanBinarySensor(
digital_ocean.DIGITAL_OCEAN, droplet_id))
@@ -63,7 +66,7 @@ class DigitalOceanBinarySensor(BinarySensorDevice):
return self.data.status == 'active'
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return DEFAULT_SENSOR_CLASS

View File

@@ -13,7 +13,7 @@ ECOBEE_CONFIG_FILE = 'ecobee.conf'
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Ecobee sensors."""
"""Set up the Ecobee sensors."""
if discovery_info is None:
return
data = ecobee.NETWORK
@@ -38,7 +38,7 @@ class EcobeeBinarySensor(BinarySensorDevice):
self.sensor_name = sensor_name
self.index = sensor_index
self._state = None
self._sensor_class = 'occupancy'
self._device_class = 'occupancy'
self.update()
@property
@@ -57,9 +57,9 @@ class EcobeeBinarySensor(BinarySensorDevice):
return "binary_sensor_ecobee_{}_{}".format(self._name, self.index)
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return self._sensor_class
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return self._device_class
def update(self):
"""Get the latest state of the sensor."""

View File

@@ -0,0 +1,69 @@
"""
Support for Eight Sleep binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.eight_sleep/
"""
import logging
import asyncio
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.eight_sleep import (
DATA_EIGHT, EightSleepHeatEntity, CONF_BINARY_SENSORS, NAME_MAP)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['eight_sleep']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the eight sleep binary sensor."""
if discovery_info is None:
return
name = 'Eight'
sensors = discovery_info[CONF_BINARY_SENSORS]
eight = hass.data[DATA_EIGHT]
all_sensors = []
for sensor in sensors:
all_sensors.append(EightHeatSensor(name, eight, sensor))
async_add_devices(all_sensors, True)
class EightHeatSensor(EightSleepHeatEntity, BinarySensorDevice):
"""Representation of a Eight Sleep heat-based sensor."""
def __init__(self, name, eight, sensor):
"""Initialize the sensor."""
super().__init__(eight)
self._sensor = sensor
self._mapped_name = NAME_MAP.get(self._sensor, self._sensor)
self._name = '{} {}'.format(name, self._mapped_name)
self._state = None
self._side = self._sensor.split('_')[0]
self._userid = self._eight.fetch_userid(self._side)
self._usrobj = self._eight.users[self._userid]
_LOGGER.debug("Presence Sensor: %s, Side: %s, User: %s",
self._sensor, self._side, self._userid)
@property
def name(self):
"""Return the name of the sensor, if any."""
return self._name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@asyncio.coroutine
def async_update(self):
"""Retrieve latest state."""
self._state = self._usrobj.bed_presence

View File

@@ -9,10 +9,12 @@ import logging
import voluptuous as vol
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA)
BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA)
from homeassistant.components import enocean
from homeassistant.const import (CONF_NAME, CONF_ID, CONF_SENSOR_CLASS)
from homeassistant.const import (
CONF_NAME, CONF_ID, CONF_SENSOR_CLASS, CONF_DEVICE_CLASS)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
_LOGGER = logging.getLogger(__name__)
@@ -22,41 +24,42 @@ DEFAULT_NAME = 'EnOcean binary sensor'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA,
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Binary Sensor platform fo EnOcean."""
"""Set up the Binary Sensor platform for EnOcean."""
dev_id = config.get(CONF_ID)
devname = config.get(CONF_NAME)
sensor_class = config.get(CONF_SENSOR_CLASS)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
add_devices([EnOceanBinarySensor(dev_id, devname, sensor_class)])
add_devices([EnOceanBinarySensor(dev_id, devname, device_class)])
class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
"""Representation of EnOcean binary sensors such as wall switches."""
def __init__(self, dev_id, devname, sensor_class):
def __init__(self, dev_id, devname, device_class):
"""Initialize the EnOcean binary sensor."""
enocean.EnOceanDevice.__init__(self)
self.stype = "listener"
self.stype = 'listener'
self.dev_id = dev_id
self.which = -1
self.onoff = -1
self.devname = devname
self._sensor_class = sensor_class
self._device_class = device_class
@property
def name(self):
"""The default name for the binary sensor."""
"""Return the default name for the binary sensor."""
return self.devname
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return self._sensor_class
return self._device_class
def value_changed(self, value, value2):
"""Fire an event with the data that have changed.
@@ -64,7 +67,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
This method is called when there is an incoming packet associated
with this platform.
"""
self.update_ha_state()
self.schedule_update_ha_state()
if value2 == 0x70:
self.which = 0
self.onoff = 0
@@ -77,7 +80,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
elif value2 == 0x10:
self.which = 1
self.onoff = 1
self.hass.bus.fire('button_pressed', {"id": self.dev_id,
self.hass.bus.fire('button_pressed', {'id': self.dev_id,
'pushed': value,
'which': self.which,
'onoff': self.onoff})

View File

@@ -4,48 +4,60 @@ Support for Envisalink zone states- represented as binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.envisalink/
"""
import asyncio
import logging
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.envisalink import (EVL_CONTROLLER,
ZONE_SCHEMA,
CONF_ZONENAME,
CONF_ZONETYPE,
EnvisalinkDevice,
SIGNAL_ZONE_UPDATE)
from homeassistant.components.envisalink import (
DATA_EVL, ZONE_SCHEMA, CONF_ZONENAME, CONF_ZONETYPE, EnvisalinkDevice,
SIGNAL_ZONE_UPDATE)
from homeassistant.const import ATTR_LAST_TRIP_TIME
DEPENDENCIES = ['envisalink']
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['envisalink']
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup Envisalink binary sensor devices."""
_configured_zones = discovery_info['zones']
for zone_num in _configured_zones:
_device_config_data = ZONE_SCHEMA(_configured_zones[zone_num])
_device = EnvisalinkBinarySensor(
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Envisalink binary sensor devices."""
configured_zones = discovery_info['zones']
devices = []
for zone_num in configured_zones:
device_config_data = ZONE_SCHEMA(configured_zones[zone_num])
device = EnvisalinkBinarySensor(
hass,
zone_num,
_device_config_data[CONF_ZONENAME],
_device_config_data[CONF_ZONETYPE],
EVL_CONTROLLER.alarm_state['zone'][zone_num],
EVL_CONTROLLER)
add_devices_callback([_device])
device_config_data[CONF_ZONENAME],
device_config_data[CONF_ZONETYPE],
hass.data[DATA_EVL].alarm_state['zone'][zone_num],
hass.data[DATA_EVL]
)
devices.append(device)
async_add_devices(devices)
class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
"""Representation of an Envisalink binary sensor."""
def __init__(self, zone_number, zone_name, zone_type, info, controller):
def __init__(self, hass, zone_number, zone_name, zone_type, info,
controller):
"""Initialize the binary_sensor."""
from pydispatch import dispatcher
self._zone_type = zone_type
self._zone_number = zone_number
_LOGGER.debug('Setting up zone: ' + zone_name)
EnvisalinkDevice.__init__(self, zone_name, info, controller)
dispatcher.connect(self._update_callback,
signal=SIGNAL_ZONE_UPDATE,
sender=dispatcher.Any)
super().__init__(zone_name, info, controller)
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_UPDATE, self._update_callback)
@property
def device_state_attributes(self):
@@ -60,11 +72,12 @@ class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
return self._info['status']['open']
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return self._zone_type
@callback
def _update_callback(self, zone):
"""Update the zone's state, if needed."""
if zone is None or int(zone) == self._zone_number:
self.hass.async_add_job(self.update_ha_state)
self.hass.async_add_job(self.async_update_ha_state())

View File

@@ -48,26 +48,21 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Create the binary sensor."""
"""Set up the FFmpeg binary moition sensor."""
manager = hass.data[DATA_FFMPEG]
# check source
if not manager.async_run_test(config.get(CONF_INPUT)):
return
# generate sensor object
entity = FFmpegMotion(hass, manager, config)
# add to system
manager.async_register_device(entity)
yield from async_add_devices([entity])
async_add_devices([entity])
class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
"""A binary sensor which use ffmpeg for noise detection."""
"""A binary sensor which use FFmpeg for noise detection."""
def __init__(self, hass, config):
"""Constructor for binary sensor noise detection."""
def __init__(self, config):
"""Init for the binary sensor noise detection."""
super().__init__(config.get(CONF_INITIAL_STATE))
self._state = False
@@ -82,7 +77,7 @@ class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
@property
def is_on(self):
"""True if the binary sensor is on."""
"""Return true if the binary sensor is on."""
return self._state
@property
@@ -92,21 +87,25 @@ class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
class FFmpegMotion(FFmpegBinarySensor):
"""A binary sensor which use ffmpeg for noise detection."""
"""A binary sensor which use FFmpeg for noise detection."""
def __init__(self, hass, manager, config):
"""Initialize ffmpeg motion binary sensor."""
"""Initialize FFmpeg motion binary sensor."""
from haffmpeg import SensorMotion
super().__init__(hass, config)
super().__init__(config)
self.ffmpeg = SensorMotion(
manager.binary, hass.loop, self._async_callback)
def async_start_ffmpeg(self):
@asyncio.coroutine
def _async_start_ffmpeg(self, entity_ids):
"""Start a FFmpeg instance.
This method must be run in the event loop and returns a coroutine.
This method is a coroutine.
"""
if entity_ids is not None and self.entity_id not in entity_ids:
return
# init config
self.ffmpeg.set_options(
time_reset=self._config.get(CONF_RESET),
@@ -116,12 +115,12 @@ class FFmpegMotion(FFmpegBinarySensor):
)
# run
return self.ffmpeg.open_sensor(
yield from self.ffmpeg.open_sensor(
input_source=self._config.get(CONF_INPUT),
extra_cmd=self._config.get(CONF_EXTRA_ARGUMENTS),
)
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return "motion"
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return 'motion'

View File

@@ -45,52 +45,49 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Create the binary sensor."""
"""Set up the FFmpeg noise binary sensor."""
manager = hass.data[DATA_FFMPEG]
# check source
if not manager.async_run_test(config.get(CONF_INPUT)):
return
# generate sensor object
entity = FFmpegNoise(hass, manager, config)
# add to system
manager.async_register_device(entity)
yield from async_add_devices([entity])
async_add_devices([entity])
class FFmpegNoise(FFmpegBinarySensor):
"""A binary sensor which use ffmpeg for noise detection."""
"""A binary sensor which use FFmpeg for noise detection."""
def __init__(self, hass, manager, config):
"""Initialize ffmpeg noise binary sensor."""
"""Initialize FFmpeg noise binary sensor."""
from haffmpeg import SensorNoise
super().__init__(hass, config)
super().__init__(config)
self.ffmpeg = SensorNoise(
manager.binary, hass.loop, self._async_callback)
def async_start_ffmpeg(self):
@asyncio.coroutine
def _async_start_ffmpeg(self, entity_ids):
"""Start a FFmpeg instance.
This method must be run in the event loop and returns a coroutine.
This method is a coroutine.
"""
# init config
if entity_ids is not None and self.entity_id not in entity_ids:
return
self.ffmpeg.set_options(
time_duration=self._config.get(CONF_DURATION),
time_reset=self._config.get(CONF_RESET),
peak=self._config.get(CONF_PEAK),
)
# run
return self.ffmpeg.open_sensor(
yield from self.ffmpeg.open_sensor(
input_source=self._config.get(CONF_INPUT),
output_dest=self._config.get(CONF_OUTPUT),
extra_cmd=self._config.get(CONF_EXTRA_ARGUMENTS),
)
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return "sound"
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return 'sound'

View File

@@ -1,4 +1,9 @@
"""Contains functionality to use flic buttons as a binary sensor."""
"""
Support to use flic buttons as a binary sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.flic/
"""
import logging
import threading
@@ -11,39 +16,40 @@ from homeassistant.const import (
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
REQUIREMENTS = ['https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4']
_LOGGER = logging.getLogger(__name__)
DEFAULT_TIMEOUT = 3
CLICK_TYPE_SINGLE = "single"
CLICK_TYPE_DOUBLE = "double"
CLICK_TYPE_HOLD = "hold"
CLICK_TYPE_SINGLE = 'single'
CLICK_TYPE_DOUBLE = 'double'
CLICK_TYPE_HOLD = 'hold'
CLICK_TYPES = [CLICK_TYPE_SINGLE, CLICK_TYPE_DOUBLE, CLICK_TYPE_HOLD]
CONF_IGNORED_CLICK_TYPES = "ignored_click_types"
CONF_IGNORED_CLICK_TYPES = 'ignored_click_types'
EVENT_NAME = "flic_click"
EVENT_DATA_NAME = "button_name"
EVENT_DATA_ADDRESS = "button_address"
EVENT_DATA_TYPE = "click_type"
EVENT_DATA_QUEUED_TIME = "queued_time"
DEFAULT_HOST = 'localhost'
DEFAULT_PORT = 5551
EVENT_NAME = 'flic_click'
EVENT_DATA_NAME = 'button_name'
EVENT_DATA_ADDRESS = 'button_address'
EVENT_DATA_TYPE = 'click_type'
EVENT_DATA_QUEUED_TIME = 'queued_time'
# Validation of the user's configuration
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_HOST, default='localhost'): cv.string,
vol.Optional(CONF_PORT, default=5551): cv.port,
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_DISCOVERY, default=True): cv.boolean,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
vol.Optional(CONF_IGNORED_CLICK_TYPES): vol.All(cv.ensure_list,
[vol.In(CLICK_TYPES)])
vol.Optional(CONF_IGNORED_CLICK_TYPES):
vol.All(cv.ensure_list, [vol.In(CLICK_TYPES)])
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup the flic platform."""
"""Set up the flic platform."""
import pyflic
# Initialize flic client responsible for
@@ -55,11 +61,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
try:
client = pyflic.FlicClient(host, port)
except ConnectionRefusedError:
_LOGGER.error("Failed to connect to flic server.")
_LOGGER.error("Failed to connect to flic server")
return
def new_button_callback(address):
"""Setup newly verified button as device in home assistant."""
"""Set up newly verified button as device in Home Assistant."""
setup_button(hass, config, add_entities, client, address)
client.on_new_verified_button = new_button_callback
@@ -74,7 +80,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
def get_info_callback(items):
"""Add entities for already verified buttons."""
addresses = items["bd_addr_of_verified_buttons"] or []
addresses = items['bd_addr_of_verified_buttons'] or []
for address in addresses:
setup_button(hass, config, add_entities, client, address)
@@ -83,7 +89,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
def start_scanning(config, add_entities, client):
"""Start a new flic client for scanning & connceting to new buttons."""
"""Start a new flic client for scanning and connecting to new buttons."""
import pyflic
scan_wizard = pyflic.ScanWizard()
@@ -91,10 +97,10 @@ def start_scanning(config, add_entities, client):
def scan_completed_callback(scan_wizard, result, address, name):
"""Restart scan wizard to constantly check for new buttons."""
if result == pyflic.ScanWizardResult.WizardSuccess:
_LOGGER.info("Found new button (%s)", address)
_LOGGER.info("Found new button %s", address)
elif result != pyflic.ScanWizardResult.WizardFailedTimeout:
_LOGGER.warning("Failed to connect to button (%s). Reason: %s",
address, result)
_LOGGER.warning(
"Failed to connect to button %s. Reason: %s", address, result)
# Restart scan wizard
start_scanning(config, add_entities, client)
@@ -104,11 +110,11 @@ def start_scanning(config, add_entities, client):
def setup_button(hass, config, add_entities, client, address):
"""Setup single button device."""
"""Set up a single button device."""
timeout = config.get(CONF_TIMEOUT)
ignored_click_types = config.get(CONF_IGNORED_CLICK_TYPES)
button = FlicButton(hass, client, address, timeout, ignored_click_types)
_LOGGER.info("Connected to button (%s)", address)
_LOGGER.info("Connected to button %s", address)
add_entities([button])
@@ -161,7 +167,7 @@ class FlicButton(BinarySensorDevice):
@property
def name(self):
"""Return the name of the device."""
return "flic_%s" % self.address.replace(":", "")
return 'flic_{}'.format(self.address.replace(':', ''))
@property
def address(self):
@@ -179,26 +185,23 @@ class FlicButton(BinarySensorDevice):
return False
@property
def state_attributes(self):
def device_state_attributes(self):
"""Return device specific state attributes."""
attr = super(FlicButton, self).state_attributes
attr["address"] = self.address
return attr
return {'address': self.address}
def _queued_event_check(self, click_type, time_diff):
"""Generate a log message and returns true if timeout exceeded."""
time_string = "{:d} {}".format(
time_diff, "second" if time_diff == 1 else "seconds")
time_diff, 'second' if time_diff == 1 else 'seconds')
if time_diff > self._timeout:
_LOGGER.warning(
"Queued %s dropped for %s. Time in queue was %s.",
"Queued %s dropped for %s. Time in queue was %s",
click_type, self.address, time_string)
return True
else:
_LOGGER.info(
"Queued %s allowed for %s. Time in queue was %s.",
"Queued %s allowed for %s. Time in queue was %s",
click_type, self.address, time_string)
return False
@@ -230,8 +233,8 @@ class FlicButton(BinarySensorDevice):
EVENT_DATA_TYPE: hass_click_type
})
def _connection_status_changed(self, channel,
connection_status, disconnect_reason):
def _connection_status_changed(
self, channel, connection_status, disconnect_reason):
"""Remove device, if button disconnects."""
import pyflic

View File

@@ -15,9 +15,10 @@ from homeassistant.components.binary_sensor import (
import homeassistant.helpers.config_validation as cv
from homeassistant.const import (
CONF_HOST, CONF_PORT, CONF_NAME, CONF_USERNAME, CONF_PASSWORD,
CONF_SSL, EVENT_HOMEASSISTANT_STOP, ATTR_LAST_TRIP_TIME, CONF_CUSTOMIZE)
CONF_SSL, EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_START,
ATTR_LAST_TRIP_TIME, CONF_CUSTOMIZE)
REQUIREMENTS = ['pyhik==0.0.7', 'pydispatcher==2.0.5']
REQUIREMENTS = ['pyhik==0.1.2']
_LOGGER = logging.getLogger(__name__)
CONF_IGNORED = 'ignored'
@@ -29,10 +30,9 @@ DEFAULT_DELAY = 0
ATTR_DELAY = 'delay'
SENSOR_CLASS_MAP = {
DEVICE_CLASS_MAP = {
'Motion': 'motion',
'Line Crossing': 'motion',
'IO Trigger': None,
'Field Detection': 'motion',
'Video Loss': None,
'Tamper Detection': 'motion',
@@ -46,6 +46,7 @@ SENSOR_CLASS_MAP = {
'Bad Video': None,
'PIR Alarm': 'motion',
'Face Detection': 'motion',
'Scene Change Detection': 'motion',
}
CUSTOMIZE_SCHEMA = vol.Schema({
@@ -66,7 +67,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup Hikvision binary sensor devices."""
"""Set up the Hikvision binary sensor devices."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
@@ -76,38 +77,44 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
customize = config.get(CONF_CUSTOMIZE)
if config.get(CONF_SSL):
protocol = "https"
protocol = 'https'
else:
protocol = "http"
protocol = 'http'
url = '{}://{}'.format(protocol, host)
data = HikvisionData(hass, url, port, name, username, password)
if data.sensors is None:
_LOGGER.error('Hikvision event stream has no data, unable to setup.')
_LOGGER.error("Hikvision event stream has no data, unable to setup")
return False
entities = []
for sensor in data.sensors:
# Build sensor name, then parse customize config.
sensor_name = sensor.replace(' ', '_')
for sensor, channel_list in data.sensors.items():
for channel in channel_list:
# Build sensor name, then parse customize config.
if data.type == 'NVR':
sensor_name = '{}_{}'.format(
sensor.replace(' ', '_'), channel[1])
else:
sensor_name = sensor.replace(' ', '_')
custom = customize.get(sensor_name.lower(), {})
ignore = custom.get(CONF_IGNORED)
delay = custom.get(CONF_DELAY)
custom = customize.get(sensor_name.lower(), {})
ignore = custom.get(CONF_IGNORED)
delay = custom.get(CONF_DELAY)
_LOGGER.debug('Entity: %s - %s, Options - Ignore: %s, Delay: %s',
data.name, sensor_name, ignore, delay)
if not ignore:
entities.append(HikvisionBinarySensor(hass, sensor, data, delay))
_LOGGER.debug("Entity: %s - %s, Options - Ignore: %s, Delay: %s",
data.name, sensor_name, ignore, delay)
if not ignore:
entities.append(HikvisionBinarySensor(
hass, sensor, channel[1], data, delay))
add_entities(entities)
class HikvisionData(object):
"""Hikvision camera event stream object."""
"""Hikvision device event stream object."""
def __init__(self, hass, url, port, name, username, password):
"""Initialize the data oject."""
@@ -119,49 +126,64 @@ class HikvisionData(object):
self._password = password
# Establish camera
self._cam = HikCamera(self._url, self._port,
self._username, self._password)
self.camdata = HikCamera(
self._url, self._port, self._username, self._password)
if self._name is None:
self._name = self._cam.get_name
# Start event stream
self._cam.start_stream()
self._name = self.camdata.get_name
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self.stop_hik)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, self.start_hik)
def stop_hik(self, event):
"""Shutdown Hikvision subscriptions and subscription thread on exit."""
self._cam.disconnect()
self.camdata.disconnect()
def start_hik(self, event):
"""Start Hikvision event stream thread."""
self.camdata.start_stream()
@property
def sensors(self):
"""Return list of available sensors and their states."""
return self._cam.current_event_states
return self.camdata.current_event_states
@property
def cam_id(self):
"""Return camera id."""
return self._cam.get_id
"""Return device id."""
return self.camdata.get_id
@property
def name(self):
"""Return camera name."""
"""Return device name."""
return self._name
@property
def type(self):
"""Return device type."""
return self.camdata.get_type
def get_attributes(self, sensor, channel):
"""Return attribute list for sensor/channel."""
return self.camdata.fetch_attributes(sensor, channel)
class HikvisionBinarySensor(BinarySensorDevice):
"""Representation of a Hikvision binary sensor."""
def __init__(self, hass, sensor, cam, delay):
def __init__(self, hass, sensor, channel, cam, delay):
"""Initialize the binary_sensor."""
from pydispatch import dispatcher
self._hass = hass
self._cam = cam
self._name = self._cam.name + ' ' + sensor
self._id = self._cam.cam_id + '.' + sensor
self._sensor = sensor
self._channel = channel
if self._cam.type == 'NVR':
self._name = '{} {} {}'.format(self._cam.name, sensor, channel)
else:
self._name = '{} {}'.format(self._cam.name, sensor)
self._id = '{}.{}.{}'.format(self._cam.cam_id, sensor, channel)
if delay is None:
self._delay = 0
@@ -170,20 +192,16 @@ class HikvisionBinarySensor(BinarySensorDevice):
self._timer = None
# Form signal for dispatcher
signal = 'ValueChanged.{}'.format(self._cam.cam_id)
dispatcher.connect(self._update_callback,
signal=signal,
sender=self._sensor)
# Register callback function with pyHik
self._cam.camdata.add_update_callback(self._update_callback, self._id)
def _sensor_state(self):
"""Extract sensor state."""
return self._cam.sensors[self._sensor][0]
return self._cam.get_attributes(self._sensor, self._channel)[0]
def _sensor_last_update(self):
"""Extract sensor last update time."""
return self._cam.sensors[self._sensor][3]
return self._cam.get_attributes(self._sensor, self._channel)[3]
@property
def name(self):
@@ -201,10 +219,10 @@ class HikvisionBinarySensor(BinarySensorDevice):
return self._sensor_state()
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
try:
return SENSOR_CLASS_MAP[self._sensor]
return DEVICE_CLASS_MAP[self._sensor]
except KeyError:
# Sensor must be unknown to us, add as generic
return None
@@ -225,19 +243,15 @@ class HikvisionBinarySensor(BinarySensorDevice):
return attr
def _update_callback(self, signal, sender):
def _update_callback(self, msg):
"""Update the sensor's state, if needed."""
_LOGGER.debug('Dispatcher callback, signal: %s, sender: %s',
signal, sender)
if sender is not self._sensor:
return
_LOGGER.debug('Callback signal from: %s', msg)
if self._delay > 0 and not self.is_on:
# Set timer to wait until updating the state
def _delay_update(now):
"""Timer callback for sensor update."""
_LOGGER.debug('%s Called delayed (%ssec) update.',
_LOGGER.debug("%s Called delayed (%ssec) update",
self._name, self._delay)
self.schedule_update_ha_state()
self._timer = None

View File

@@ -7,40 +7,39 @@ https://home-assistant.io/components/binary_sensor.homematic/
import logging
from homeassistant.const import STATE_UNKNOWN
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.homematic import HMDevice
from homeassistant.loader import get_component
from homeassistant.components.homematic import HMDevice, ATTR_DISCOVER_DEVICES
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['homematic']
SENSOR_TYPES_CLASS = {
"Remote": None,
"ShutterContact": "opening",
"MaxShutterContact": "opening",
"IPShutterContact": "opening",
"Smoke": "smoke",
"SmokeV2": "smoke",
"Motion": "motion",
"MotionV2": "motion",
"RemoteMotion": None,
"WeatherSensor": None,
"TiltSensor": None,
'Remote': None,
'ShutterContact': 'opening',
'MaxShutterContact': 'opening',
'IPShutterContact': 'opening',
'Smoke': 'smoke',
'SmokeV2': 'smoke',
'Motion': 'motion',
'MotionV2': 'motion',
'RemoteMotion': None,
'WeatherSensor': None,
'TiltSensor': None,
}
def setup_platform(hass, config, add_callback_devices, discovery_info=None):
"""Setup the Homematic binary sensor platform."""
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Homematic binary sensor platform."""
if discovery_info is None:
return
homematic = get_component("homematic")
return homematic.setup_hmdevice_discovery_helper(
hass,
HMBinarySensor,
discovery_info,
add_callback_devices
)
devices = []
for config in discovery_info[ATTR_DISCOVER_DEVICES]:
new_device = HMBinarySensor(hass, config)
new_device.link_homematic()
devices.append(new_device)
add_devices(devices)
class HMBinarySensor(HMDevice, BinarySensorDevice):
@@ -54,14 +53,11 @@ class HMBinarySensor(HMDevice, BinarySensorDevice):
return bool(self._hm_get_state())
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
if not self.available:
return None
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
# If state is MOTION (RemoteMotion works only)
if self._state == "MOTION":
return "motion"
if self._state == 'MOTION':
return 'motion'
return SENSOR_TYPES_CLASS.get(self._hmdevice.__class__.__name__, None)
def _init_data_struct(self):

View File

@@ -0,0 +1,87 @@
"""
Support for INSTEON dimmers via PowerLinc Modem.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/insteon_plm/
"""
import logging
import asyncio
from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.loader import get_component
DEPENDENCIES = ['insteon_plm']
_LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the INSTEON PLM device class for the hass platform."""
plm = hass.data['insteon_plm']
device_list = []
for device in discovery_info:
name = device.get('address')
address = device.get('address_hex')
_LOGGER.info('Registered %s with binary_sensor platform.', name)
device_list.append(
InsteonPLMBinarySensorDevice(hass, plm, address, name)
)
async_add_devices(device_list)
class InsteonPLMBinarySensorDevice(BinarySensorDevice):
"""A Class for an Insteon device."""
def __init__(self, hass, plm, address, name):
"""Initialize the binarysensor."""
self._hass = hass
self._plm = plm.protocol
self._address = address
self._name = name
self._plm.add_update_callback(
self.async_binarysensor_update, {'address': self._address})
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def address(self):
"""Return the the address of the node."""
return self._address
@property
def name(self):
"""Return the the name of the node."""
return self._name
@property
def is_on(self):
"""Return the boolean response if the node is on."""
sensorstate = self._plm.get_device_attr(self._address, 'sensorstate')
_LOGGER.info("Sensor state for %s is %s", self._address, sensorstate)
return bool(sensorstate)
@property
def device_state_attributes(self):
"""Provide attributes for display on device card."""
insteon_plm = get_component('insteon_plm')
return insteon_plm.common_attributes(self)
def get_attr(self, key):
"""Return specified attribute for this device."""
return self._plm.get_device_attr(self.address, key)
@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)
self._hass.async_add_job(self.async_update_ha_state())

View File

@@ -26,7 +26,7 @@ ATTR_ISS_NUMBER_PEOPLE_SPACE = 'number_of_people_in_space'
CONF_SHOW_ON_MAP = 'show_on_map'
DEFAULT_NAME = 'ISS'
DEFAULT_SENSOR_CLASS = 'visible'
DEFAULT_DEVICE_CLASS = 'visible'
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
@@ -77,9 +77,9 @@ class IssBinarySensor(BinarySensorDevice):
return self.iss_data.is_above if self.iss_data else False
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return DEFAULT_SENSOR_CLASS
return DEFAULT_DEVICE_CLASS
@property
def device_state_attributes(self):

View File

@@ -12,7 +12,6 @@ import homeassistant.components.isy994 as isy
from homeassistant.const import STATE_ON, STATE_OFF
from homeassistant.helpers.typing import ConfigType
_LOGGER = logging.getLogger(__name__)
VALUE_TO_STATE = {
@@ -27,9 +26,9 @@ 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):
"""Setup the ISY994 binary sensor platform."""
"""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.')
_LOGGER.error("A connection has not been made to the ISY controller")
return False
devices = []

View File

@@ -11,7 +11,7 @@ DEPENDENCIES = ['knx']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the KNX binary sensor platform."""
"""Set up the KNX binary sensor platform."""
add_devices([KNXSwitch(hass, KNXConfig(config))])

View File

@@ -0,0 +1,68 @@
"""
Support for MAX! Window Shutter via MAX! Cube.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/maxcube/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.maxcube import MAXCUBE_HANDLE
from homeassistant.const import STATE_UNKNOWN
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Iterate through all MAX! Devices and add window shutters."""
cube = hass.data[MAXCUBE_HANDLE].cube
devices = []
for device in cube.devices:
name = "{} {}".format(
cube.room_by_id(device.room_id).name, device.name)
# Only add Window Shutters
if cube.is_windowshutter(device):
devices.append(MaxCubeShutter(hass, name, device.rf_address))
if devices:
add_devices(devices)
class MaxCubeShutter(BinarySensorDevice):
"""Representation of a MAX! Cube Binary Sensor device."""
def __init__(self, hass, name, rf_address):
"""Initialize MAX! Cube BinarySensorDevice."""
self._name = name
self._sensor_type = 'opening'
self._rf_address = rf_address
self._cubehandle = hass.data[MAXCUBE_HANDLE]
self._state = STATE_UNKNOWN
@property
def should_poll(self):
"""Return the polling state."""
return True
@property
def name(self):
"""Return the name of the BinarySensorDevice."""
return self._name
@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 update(self):
"""Get latest data from MAX! Cube."""
self._cubehandle.update()
device = self._cubehandle.cube.device_by_rf(self._rf_address)
self._state = device.is_open

View File

@@ -16,9 +16,9 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['modbus']
CONF_COIL = "coil"
CONF_COILS = "coils"
CONF_SLAVE = "slave"
CONF_COIL = 'coil'
CONF_COILS = 'coils'
CONF_SLAVE = 'slave'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_COILS): [{
@@ -30,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Modbus binary sensors."""
"""Set up the Modbus binary sensors."""
sensors = []
for coil in config.get(CONF_COILS):
sensors.append(ModbusCoilSensor(

View File

@@ -4,6 +4,7 @@ Support for MQTT binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mqtt/
"""
import asyncio
import logging
import voluptuous as vol
@@ -11,12 +12,13 @@ import voluptuous as vol
from homeassistant.core import callback
import homeassistant.components.mqtt as mqtt
from homeassistant.components.binary_sensor import (
BinarySensorDevice, SENSOR_CLASSES)
BinarySensorDevice, DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON, CONF_PAYLOAD_OFF,
CONF_SENSOR_CLASS)
CONF_SENSOR_CLASS, CONF_DEVICE_CLASS)
from homeassistant.components.mqtt import (CONF_STATE_TOPIC, CONF_QOS)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
_LOGGER = logging.getLogger(__name__)
@@ -29,13 +31,13 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
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_SENSOR_CLASS, default=None):
vol.Any(vol.In(SENSOR_CLASSES), vol.SetTo(None)),
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the MQTT binary sensor."""
if discovery_info is not None:
config = PLATFORM_SCHEMA(discovery_info)
@@ -43,11 +45,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = hass
add_devices([MqttBinarySensor(
hass,
async_add_devices([MqttBinarySensor(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_SENSOR_CLASS),
get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS),
config.get(CONF_QOS),
config.get(CONF_PAYLOAD_ON),
config.get(CONF_PAYLOAD_OFF),
@@ -58,36 +60,42 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class MqttBinarySensor(BinarySensorDevice):
"""Representation a binary sensor that is updated by MQTT."""
def __init__(self, hass, name, state_topic, sensor_class, qos, payload_on,
def __init__(self, name, state_topic, device_class, qos, payload_on,
payload_off, value_template):
"""Initialize the MQTT binary sensor."""
self._hass = hass
self._name = name
self._state = False
self._state_topic = state_topic
self._sensor_class = sensor_class
self._device_class = device_class
self._payload_on = payload_on
self._payload_off = payload_off
self._qos = qos
self._template = value_template
def async_added_to_hass(self):
"""Subscribe mqtt events.
This method must be run in the event loop and returns a coroutine.
"""
@callback
def message_received(topic, payload, qos):
"""A new MQTT message has been received."""
if value_template is not None:
payload = value_template.async_render_with_possible_json_value(
"""Handle a new received MQTT message."""
if self._template is not None:
payload = self._template.async_render_with_possible_json_value(
payload)
if payload == self._payload_on:
self._state = True
hass.async_add_job(self.async_update_ha_state())
elif payload == self._payload_off:
self._state = False
hass.async_add_job(self.async_update_ha_state())
mqtt.subscribe(hass, self._state_topic, message_received, self._qos)
self.hass.async_add_job(self.async_update_ha_state())
return mqtt.async_subscribe(
self.hass, self._state_topic, message_received, self._qos)
@property
def should_poll(self):
"""No polling needed."""
"""Return the polling state."""
return False
@property
@@ -101,6 +109,6 @@ class MqttBinarySensor(BinarySensorDevice):
return self._state
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return self._sensor_class
return self._device_class

View File

@@ -7,7 +7,7 @@ https://home-assistant.io/components/binary_sensor.mysensors/
import logging
from homeassistant.components import mysensors
from homeassistant.components.binary_sensor import (SENSOR_CLASSES,
from homeassistant.components.binary_sensor import (DEVICE_CLASSES,
BinarySensorDevice)
from homeassistant.const import STATE_ON
@@ -16,7 +16,7 @@ DEPENDENCIES = []
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the mysensors platform for sensors."""
"""Set up the MySensors platform for sensors."""
# Only act if loaded via mysensors by discovery event.
# Otherwise gateway is not setup.
if discovery_info is None:
@@ -62,8 +62,8 @@ class MySensorsBinarySensor(
return False
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
pres = self.gateway.const.Presentation
class_map = {
pres.S_DOOR: 'opening',
@@ -78,5 +78,5 @@ class MySensorsBinarySensor(
pres.S_VIBRATION: 'vibration',
pres.S_MOISTURE: 'moisture',
})
if class_map.get(self.child_type) in SENSOR_CLASSES:
if class_map.get(self.child_type) in DEVICE_CLASSES:
return class_map.get(self.child_type)

View File

@@ -16,15 +16,18 @@ DEPENDENCIES = ['nest']
BINARY_TYPES = ['online']
CLIMATE_BINARY_TYPES = ['fan',
'is_using_emergency_heat',
'is_locked',
'has_leaf']
CLIMATE_BINARY_TYPES = [
'fan',
'is_using_emergency_heat',
'is_locked',
'has_leaf',
]
CAMERA_BINARY_TYPES = [
'motion_detected',
'sound_detected',
'person_detected']
'person_detected',
]
_BINARY_TYPES_DEPRECATED = [
'hvac_ac_state',
@@ -34,7 +37,8 @@ _BINARY_TYPES_DEPRECATED = [
'hvac_heat_x3_state',
'hvac_alt_heat_state',
'hvac_alt_heat_x2_state',
'hvac_emer_heat_state']
'hvac_emer_heat_state',
]
_VALID_BINARY_SENSOR_TYPES = BINARY_TYPES + CLIMATE_BINARY_TYPES \
+ CAMERA_BINARY_TYPES
@@ -43,7 +47,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Nest binary sensors."""
"""Set up the Nest binary sensors."""
if discovery_info is None:
return
@@ -93,7 +97,7 @@ class NestBinarySensor(NestSensor, BinarySensorDevice):
@property
def is_on(self):
"""True if the binary sensor is on."""
"""Return true if the binary sensor is on."""
return self._state
def update(self):

View File

@@ -7,6 +7,7 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.netatmo/.
"""
import logging
import voluptuous as vol
from homeassistant.components.binary_sensor import (
@@ -16,10 +17,9 @@ from homeassistant.loader import get_component
from homeassistant.const import CONF_TIMEOUT, CONF_OFFSET
from homeassistant.helpers import config_validation as cv
DEPENDENCIES = ["netatmo"]
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['netatmo']
# These are the available sensors mapped to binary_sensor class
WELCOME_SENSOR_TYPES = {
@@ -34,8 +34,8 @@ PRESENCE_SENSOR_TYPES = {
"Outdoor vehicle": "motion"
}
TAG_SENSOR_TYPES = {
"Tag Vibration": 'vibration',
"Tag Open": 'opening'
"Tag Vibration": "vibration",
"Tag Open": "opening"
}
CONF_HOME = 'home'
@@ -61,7 +61,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup access to Netatmo binary sensor."""
"""Set up the access to Netatmo binary sensor."""
netatmo = get_component('netatmo')
home = config.get(CONF_HOME, None)
timeout = config.get(CONF_TIMEOUT, 15)
@@ -85,35 +85,31 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
for camera_name in data.get_camera_names():
camera_type = data.get_camera_type(camera=camera_name, home=home)
if camera_type == "NACamera":
if camera_type == 'NACamera':
if CONF_CAMERAS in config:
if config[CONF_CAMERAS] != [] and \
camera_name not in config[CONF_CAMERAS]:
continue
for variable in welcome_sensors:
add_devices([NetatmoBinarySensor(data, camera_name,
module_name, home, timeout,
offset, camera_type,
variable)])
if camera_type == "NOC":
add_devices([NetatmoBinarySensor(
data, camera_name, module_name, home, timeout,
offset, camera_type, variable)])
if camera_type == 'NOC':
if CONF_CAMERAS in config:
if config[CONF_CAMERAS] != [] and \
camera_name not in config[CONF_CAMERAS]:
continue
for variable in presence_sensors:
add_devices([NetatmoBinarySensor(data, camera_name,
module_name, home, timeout,
offset, camera_type,
variable)])
add_devices([NetatmoBinarySensor(
data, camera_name, module_name, home, timeout, offset,
camera_type, variable)])
for module_name in data.get_module_names(camera_name):
for variable in tag_sensors:
camera_type = None
add_devices([NetatmoBinarySensor(data, camera_name,
module_name, home,
timeout, offset,
camera_type,
variable)])
add_devices([NetatmoBinarySensor(
data, camera_name, module_name, home, timeout, offset,
camera_type, variable)])
class NetatmoBinarySensor(BinarySensorDevice):
@@ -121,7 +117,7 @@ class NetatmoBinarySensor(BinarySensorDevice):
def __init__(self, data, camera_name, module_name, home,
timeout, offset, camera_type, sensor):
"""Setup for access to the Netatmo camera events."""
"""Set up for access to the Netatmo camera events."""
self._data = data
self._camera_name = camera_name
self._module_name = module_name
@@ -129,23 +125,23 @@ class NetatmoBinarySensor(BinarySensorDevice):
self._timeout = timeout
self._offset = offset
if home:
self._name = home + ' / ' + camera_name
self._name = '{} / {}'.format(home, camera_name)
else:
self._name = camera_name
if module_name:
self._name += ' / ' + module_name
self._sensor_name = sensor
self._name += ' ' + sensor
camera_id = data.camera_data.cameraByName(camera=camera_name,
home=home)['id']
self._unique_id = "Netatmo_binary_sensor {0} - {1}".format(self._name,
camera_id)
camera_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.update()
@property
def name(self):
"""The name of the Netatmo device and this sensor."""
"""Return the name of the Netatmo device and this sensor."""
return self._name
@property
@@ -154,11 +150,11 @@ class NetatmoBinarySensor(BinarySensorDevice):
return self._unique_id
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
if self._cameratype == "NACamera":
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
if self._cameratype == 'NACamera':
return WELCOME_SENSOR_TYPES.get(self._sensor_name)
elif self._cameratype == "NOC":
elif self._cameratype == 'NOC':
return PRESENCE_SENSOR_TYPES.get(self._sensor_name)
else:
return TAG_SENSOR_TYPES.get(self._sensor_name)
@@ -173,51 +169,44 @@ class NetatmoBinarySensor(BinarySensorDevice):
self._data.update()
self._data.update_event()
if self._cameratype == "NACamera":
if self._cameratype == 'NACamera':
if self._sensor_name == "Someone known":
self._state =\
self._data.camera_data.someoneKnownSeen(self._home,
self._camera_name,
self._timeout*60)
self._data.camera_data.someoneKnownSeen(
self._home, self._camera_name, self._timeout*60)
elif self._sensor_name == "Someone unknown":
self._state =\
self._data.camera_data.someoneUnknownSeen(
self._home, self._camera_name, self._timeout*60)
elif self._sensor_name == "Motion":
self._state =\
self._data.camera_data.motionDetected(self._home,
self._camera_name,
self._timeout*60)
elif self._cameratype == "NOC":
self._data.camera_data.motionDetected(
self._home, self._camera_name, self._timeout*60)
elif self._cameratype == 'NOC':
if self._sensor_name == "Outdoor motion":
self._state =\
self._data.camera_data.outdoormotionDetected(
self._home, self._camera_name, self._offset)
elif self._sensor_name == "Outdoor human":
self._state =\
self._data.camera_data.humanDetected(self._home,
self._camera_name,
self._offset)
self._data.camera_data.humanDetected(
self._home, self._camera_name, self._offset)
elif self._sensor_name == "Outdoor animal":
self._state =\
self._data.camera_data.animalDetected(self._home,
self._camera_name,
self._offset)
self._data.camera_data.animalDetected(
self._home, self._camera_name, self._offset)
elif self._sensor_name == "Outdoor vehicle":
self._state =\
self._data.camera_data.carDetected(self._home,
self._camera_name,
self._offset)
self._data.camera_data.carDetected(
self._home, self._camera_name, self._offset)
if self._sensor_name == "Tag Vibration":
self._state =\
self._data.camera_data.moduleMotionDetected(self._home,
self._module_name,
self._camera_name,
self._timeout*60)
self._data.camera_data.moduleMotionDetected(
self._home, self._module_name, self._camera_name,
self._timeout*60)
elif self._sensor_name == "Tag Open":
self._state =\
self._data.camera_data.moduleOpened(self._home,
self._module_name,
self._camera_name)
self._data.camera_data.moduleOpened(
self._home, self._module_name, self._camera_name)
else:
return None

View File

@@ -12,7 +12,7 @@ import requests
import voluptuous as vol
from homeassistant.components.binary_sensor import (
SENSOR_CLASSES, BinarySensorDevice, PLATFORM_SCHEMA)
DEVICE_CLASSES, BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_HOST, CONF_PORT)
import homeassistant.helpers.config_validation as cv
@@ -28,7 +28,7 @@ DEFAULT_PORT = '5007'
DEFAULT_SSL = False
ZONE_TYPES_SCHEMA = vol.Schema({
cv.positive_int: vol.In(SENSOR_CLASSES),
cv.positive_int: vol.In(DEVICE_CLASSES),
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@@ -41,7 +41,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the NX584 binary sensor platform."""
"""Set up the NX584 binary sensor platform."""
from nx584 import client as nx584_client
host = config.get(CONF_HOST)
@@ -53,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
client = nx584_client.Client('http://{}:{}'.format(host, port))
zones = client.list_zones()
except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NX584: %s', str(ex))
_LOGGER.error("Unable to connect to NX584: %s", str(ex))
return False
version = [int(v) for v in client.get_version().split('.')]
@@ -85,8 +85,8 @@ class NX584ZoneSensor(BinarySensorDevice):
self._zone_type = zone_type
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return self._zone_type
@property

View File

@@ -9,14 +9,12 @@ import logging
import requests
import voluptuous as vol
from homeassistant.const import (
CONF_NAME, STATE_ON, STATE_OFF, CONF_MONITORED_CONDITIONS)
from homeassistant.const import CONF_NAME, CONF_MONITORED_CONDITIONS
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.loader import get_component
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['octoprint']
@@ -38,22 +36,18 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the available OctoPrint binary sensors."""
"""Set up the available OctoPrint binary sensors."""
octoprint = get_component('octoprint')
name = config.get(CONF_NAME)
monitored_conditions = config.get(CONF_MONITORED_CONDITIONS,
SENSOR_TYPES.keys())
monitored_conditions = config.get(
CONF_MONITORED_CONDITIONS, SENSOR_TYPES.keys())
devices = []
for octo_type in monitored_conditions:
new_sensor = OctoPrintBinarySensor(octoprint.OCTOPRINT,
octo_type,
SENSOR_TYPES[octo_type][2],
name,
SENSOR_TYPES[octo_type][3],
SENSOR_TYPES[octo_type][0],
SENSOR_TYPES[octo_type][1],
'flags')
new_sensor = OctoPrintBinarySensor(
octoprint.OCTOPRINT, octo_type, SENSOR_TYPES[octo_type][2],
name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
SENSOR_TYPES[octo_type][1], 'flags')
devices.append(new_sensor)
add_devices(devices)
@@ -85,31 +79,22 @@ class OctoPrintBinarySensor(BinarySensorDevice):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
return self.is_on
@property
def is_on(self):
"""Return true if binary sensor is on."""
if self._state:
return STATE_ON
else:
return STATE_OFF
return bool(self._state)
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return None
def update(self):
"""Update state of sensor."""
try:
self._state = self.api.update(self.sensor_type,
self.api_endpoint,
self.api_group,
self.api_tool)
self._state = self.api.update(
self.sensor_type, self.api_endpoint, self.api_group,
self.api_tool)
except requests.exceptions.ConnectionError:
# Error calling the api, already logged in api.update()
return

View File

@@ -0,0 +1,186 @@
"""
Support for Pilight binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.pilight/
"""
import datetime
import logging
import voluptuous as vol
from homeassistant.components import pilight
from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA,
BinarySensorDevice,
)
from homeassistant.const import (
CONF_DISARM_AFTER_TRIGGER,
CONF_NAME,
CONF_PAYLOAD,
CONF_PAYLOAD_OFF,
CONF_PAYLOAD_ON
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import track_point_in_time
from homeassistant.util import dt as dt_util
_LOGGER = logging.getLogger(__name__)
CONF_VARIABLE = 'variable'
DEFAULT_NAME = 'Pilight Binary Sensor'
DEPENDENCIES = ['pilight']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_VARIABLE): cv.string,
vol.Required(CONF_PAYLOAD): vol.Schema(dict),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PAYLOAD_ON, default='on'): cv.string,
vol.Optional(CONF_PAYLOAD_OFF, default='off'): cv.string,
vol.Optional(CONF_DISARM_AFTER_TRIGGER, default=False): cv.boolean
})
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Pilight Binary Sensor."""
disarm = config.get(CONF_DISARM_AFTER_TRIGGER)
if disarm:
add_devices([PilightTriggerSensor(
hass=hass,
name=config.get(CONF_NAME),
variable=config.get(CONF_VARIABLE),
payload=config.get(CONF_PAYLOAD),
on_value=config.get(CONF_PAYLOAD_ON),
off_value=config.get(CONF_PAYLOAD_OFF),
)])
else:
add_devices([PilightBinarySensor(
hass=hass,
name=config.get(CONF_NAME),
variable=config.get(CONF_VARIABLE),
payload=config.get(CONF_PAYLOAD),
on_value=config.get(CONF_PAYLOAD_ON),
off_value=config.get(CONF_PAYLOAD_OFF),
)])
class PilightBinarySensor(BinarySensorDevice):
"""Representation of a binary sensor that can be updated using Pilight."""
def __init__(self, hass, name, variable, payload, on_value, off_value):
"""Initialize the sensor."""
self._state = False
self._hass = hass
self._name = name
self._variable = variable
self._payload = payload
self._on_value = on_value
self._off_value = off_value
hass.bus.listen(pilight.EVENT, self._handle_code)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._state
def _handle_code(self, call):
"""Handle received code by the pilight-daemon.
If the code matches the defined playload
of this sensor the sensor state is changed accordingly.
"""
# Check if received code matches defined playoad
# True if payload is contained in received code dict
payload_ok = True
for key in self._payload:
if key not in call.data:
payload_ok = False
continue
if self._payload[key] != call.data[key]:
payload_ok = False
# Read out variable if payload ok
if payload_ok:
if self._variable not in call.data:
return
value = call.data[self._variable]
self._state = (value == self._on_value)
self.schedule_update_ha_state()
class PilightTriggerSensor(BinarySensorDevice):
"""Representation of a binary sensor that can be updated using Pilight."""
def __init__(
self,
hass,
name,
variable,
payload,
on_value,
off_value,
rst_dly_sec=30):
"""Initialize the sensor."""
self._state = False
self._hass = hass
self._name = name
self._variable = variable
self._payload = payload
self._on_value = on_value
self._off_value = off_value
self._reset_delay_sec = rst_dly_sec
self._delay_after = None
self._hass = hass
hass.bus.listen(pilight.EVENT, self._handle_code)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._state
def _reset_state(self, call):
self._state = False
self._delay_after = None
self.schedule_update_ha_state()
def _handle_code(self, call):
"""Handle received code by the pilight-daemon.
If the code matches the defined playload
of this sensor the sensor state is changed accordingly.
"""
# Check if received code matches defined playoad
# True if payload is contained in received code dict
payload_ok = True
for key in self._payload:
if key not in call.data:
payload_ok = False
continue
if self._payload[key] != call.data[key]:
payload_ok = False
# Read out variable if payload ok
if payload_ok:
if self._variable not in call.data:
return
value = call.data[self._variable]
self._state = (value == self._on_value)
if self._delay_after is None:
self._delay_after = dt_util.utcnow() + datetime.timedelta(
seconds=self._reset_delay_sec)
track_point_in_time(
self._hass, self._reset_state,
self._delay_after)
self.schedule_update_ha_state()

View File

@@ -0,0 +1,143 @@
"""
Tracks the latency of a host by sending ICMP echo requests (ping).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.ping/
"""
import logging
import subprocess
import re
import sys
from datetime import timedelta
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME, CONF_HOST
_LOGGER = logging.getLogger(__name__)
ATTR_ROUND_TRIP_TIME_AVG = 'round_trip_time_avg'
ATTR_ROUND_TRIP_TIME_MAX = 'round_trip_time_max'
ATTR_ROUND_TRIP_TIME_MDEV = 'round_trip_time_mdev'
ATTR_ROUND_TRIP_TIME_MIN = 'round_trip_time_min'
CONF_PING_COUNT = 'count'
DEFAULT_NAME = 'Ping Binary sensor'
DEFAULT_PING_COUNT = 5
DEFAULT_SENSOR_CLASS = 'connectivity'
SCAN_INTERVAL = timedelta(minutes=5)
PING_MATCHER = re.compile(
r'(?P<min>\d+.\d+)\/(?P<avg>\d+.\d+)\/(?P<max>\d+.\d+)\/(?P<mdev>\d+.\d+)')
WIN32_PING_MATCHER = re.compile(
r'(?P<min>\d+)ms.+(?P<max>\d+)ms.+(?P<avg>\d+)ms')
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PING_COUNT, default=DEFAULT_PING_COUNT): cv.positive_int,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Ping Binary sensor."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
count = config.get(CONF_PING_COUNT)
add_devices([PingBinarySensor(name, PingData(host, count))], True)
class PingBinarySensor(BinarySensorDevice):
"""Representation of a Ping Binary sensor."""
def __init__(self, name, ping):
"""Initialize the Ping Binary sensor."""
self._name = name
self.ping = ping
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def device_class(self):
"""Return the class of this sensor."""
return DEFAULT_SENSOR_CLASS
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self.ping.available
@property
def device_state_attributes(self):
"""Return the state attributes of the ICMP checo request."""
if self.ping.data is not False:
return {
ATTR_ROUND_TRIP_TIME_AVG: self.ping.data['avg'],
ATTR_ROUND_TRIP_TIME_MAX: self.ping.data['max'],
ATTR_ROUND_TRIP_TIME_MDEV: self.ping.data['mdev'],
ATTR_ROUND_TRIP_TIME_MIN: self.ping.data['min'],
}
def update(self):
"""Get the latest data."""
self.ping.update()
class PingData(object):
"""The Class for handling the data retrieval."""
def __init__(self, host, count):
"""Initialize the data object."""
self._ip_address = host
self._count = count
self.data = {}
self.available = False
if sys.platform == 'win32':
self._ping_cmd = [
'ping', '-n', str(self._count), '-w', '1000', self._ip_address]
else:
self._ping_cmd = [
'ping', '-n', '-q', '-c', str(self._count), '-W1',
self._ip_address]
def ping(self):
"""Send ICMP echo request and return details if success."""
pinger = subprocess.Popen(
self._ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
try:
out = pinger.communicate()
_LOGGER.debug("Output is %s", str(out))
if sys.platform == 'win32':
match = WIN32_PING_MATCHER.search(str(out).split('\n')[-1])
rtt_min, rtt_avg, rtt_max = match.groups()
return {
'min': rtt_min,
'avg': rtt_avg,
'max': rtt_max,
'mdev': ''}
else:
match = PING_MATCHER.search(str(out).split('\n')[-1])
rtt_min, rtt_avg, rtt_max, rtt_mdev = match.groups()
return {
'min': rtt_min,
'avg': rtt_avg,
'max': rtt_max,
'mdev': rtt_mdev}
except (subprocess.CalledProcessError, AttributeError):
return False
def update(self):
"""Retrieve the latest details from the host."""
self.data = self.ping()
self.available = bool(self.data)

View File

@@ -10,14 +10,15 @@ import voluptuous as vol
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
from homeassistant.components.binary_sensor import (
BinarySensorDevice, SENSOR_CLASSES_SCHEMA, PLATFORM_SCHEMA)
BinarySensorDevice, DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA)
from homeassistant.components.sensor.rest import RestData
from homeassistant.const import (
CONF_PAYLOAD, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_METHOD, CONF_RESOURCE,
CONF_SENSOR_CLASS, CONF_VERIFY_SSL, CONF_USERNAME, CONF_PASSWORD,
CONF_HEADERS, CONF_AUTHENTICATION, HTTP_BASIC_AUTHENTICATION,
HTTP_DIGEST_AUTHENTICATION)
HTTP_DIGEST_AUTHENTICATION, CONF_DEVICE_CLASS)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
_LOGGER = logging.getLogger(__name__)
@@ -34,7 +35,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_PAYLOAD): cv.string,
vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA,
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
@@ -42,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the REST binary sensor."""
"""Set up the REST binary sensor."""
name = config.get(CONF_NAME)
resource = config.get(CONF_RESOURCE)
method = config.get(CONF_METHOD)
@@ -51,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
headers = config.get(CONF_HEADERS)
sensor_class = config.get(CONF_SENSOR_CLASS)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = hass
@@ -72,18 +74,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
return False
add_devices([RestBinarySensor(
hass, rest, name, sensor_class, value_template)])
hass, rest, name, device_class, value_template)])
class RestBinarySensor(BinarySensorDevice):
"""Representation of a REST binary sensor."""
def __init__(self, hass, rest, name, sensor_class, value_template):
def __init__(self, hass, rest, name, device_class, value_template):
"""Initialize a REST binary sensor."""
self._hass = hass
self.rest = rest
self._name = name
self._sensor_class = sensor_class
self._device_class = device_class
self._state = False
self._previous_data = None
self._value_template = value_template
@@ -95,9 +97,9 @@ class RestBinarySensor(BinarySensorDevice):
return self._name
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return self._sensor_class
return self._device_class
@property
def is_on(self):
@@ -112,8 +114,8 @@ class RestBinarySensor(BinarySensorDevice):
try:
return bool(int(response))
except ValueError:
return {"true": True, "on": True, "open": True,
"yes": True}.get(response.lower(), False)
return {'true': True, 'on': True, 'open': True,
'yes': True}.get(response.lower(), False)
def update(self):
"""Get the latest data from REST API and updates the state."""

View File

@@ -0,0 +1,109 @@
"""
This component provides HA sensor support for Ring Door Bell/Chimes.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.ring/
"""
import logging
from datetime import timedelta
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.ring import (
CONF_ATTRIBUTION, DEFAULT_ENTITY_NAMESPACE)
from homeassistant.const import (
ATTR_ATTRIBUTION, CONF_ENTITY_NAMESPACE, CONF_MONITORED_CONDITIONS)
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
DEPENDENCIES = ['ring']
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=5)
# Sensor types: Name, category, device_class
SENSOR_TYPES = {
'ding': ['Ding', ['doorbell'], 'occupancy'],
'motion': ['Motion', ['doorbell'], 'motion'],
}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_ENTITY_NAMESPACE, default=DEFAULT_ENTITY_NAMESPACE):
cv.string,
vol.Required(CONF_MONITORED_CONDITIONS, default=[]):
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up a sensor for a Ring device."""
ring = hass.data.get('ring')
sensors = []
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
for device in ring.doorbells:
if 'doorbell' in SENSOR_TYPES[sensor_type][1]:
sensors.append(RingBinarySensor(hass,
device,
sensor_type))
add_devices(sensors, True)
return True
class RingBinarySensor(BinarySensorDevice):
"""A binary sensor implementation for Ring device."""
def __init__(self, hass, data, sensor_type):
"""Initialize a sensor for Ring device."""
super(RingBinarySensor, self).__init__()
self._sensor_type = sensor_type
self._data = data
self._name = "{0} {1}".format(self._data.name,
SENSOR_TYPES.get(self._sensor_type)[0])
self._device_class = SENSOR_TYPES.get(self._sensor_type)[2]
self._state = None
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._state
@property
def device_class(self):
"""Return the class of the binary sensor."""
return self._device_class
@property
def device_state_attributes(self):
"""Return the state attributes."""
attrs = {}
attrs[ATTR_ATTRIBUTION] = CONF_ATTRIBUTION
attrs['device_id'] = self._data.id
attrs['firmware'] = self._data.firmware
attrs['timezone'] = self._data.timezone
if self._data.alert and self._data.alert_expires_at:
attrs['expires_at'] = self._data.alert_expires_at
attrs['state'] = self._data.alert.get('state')
return attrs
def update(self):
"""Get the latest data and updates the state."""
self._data.check_alerts()
if self._data.alert:
self._state = (self._sensor_type ==
self._data.alert.get('kind'))
else:
self._state = False

View File

@@ -41,10 +41,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Raspberry PI GPIO devices."""
pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE)
bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME)
invert_logic = config.get('invert_logic', DEFAULT_INVERT_LOGIC)
"""Set up the Raspberry PI GPIO devices."""
pull_mode = config.get(CONF_PULL_MODE)
bouncetime = config.get(CONF_BOUNCETIME)
invert_logic = config.get(CONF_INVERT_LOGIC)
binary_sensors = []
ports = config.get('ports')

View File

@@ -11,7 +11,7 @@ DEPENDENCIES = ['sleepiq']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the SleepIQ sensors."""
"""Set up the SleepIQ sensors."""
if discovery_info is None:
return
@@ -42,7 +42,7 @@ class IsInBedBinarySensor(sleepiq.SleepIQSensor, BinarySensorDevice):
return self._state is True
@property
def sensor_class(self):
def device_class(self):
"""Return the class of this sensor."""
return "occupancy"

View File

@@ -27,5 +27,5 @@ class TcpBinarySensor(BinarySensorDevice, TcpSensor):
@property
def is_on(self):
"""True if the binary sensor is on."""
"""Return true if the binary sensor is on."""
return self._state == self._config[CONF_VALUE_ON]

View File

@@ -12,14 +12,17 @@ import voluptuous as vol
from homeassistant.core import callback
from homeassistant.components.binary_sensor import (
BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA,
SENSOR_CLASSES_SCHEMA)
DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, CONF_VALUE_TEMPLATE,
CONF_SENSOR_CLASS, CONF_SENSORS)
CONF_SENSOR_CLASS, CONF_SENSORS, CONF_DEVICE_CLASS,
EVENT_HOMEASSISTANT_START, STATE_ON)
from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
from homeassistant.helpers.entity import async_generate_entity_id
from homeassistant.helpers.event import async_track_state_change
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.restore_state import async_get_last_state
_LOGGER = logging.getLogger(__name__)
@@ -27,7 +30,8 @@ SENSOR_SCHEMA = vol.Schema({
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@@ -37,7 +41,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup template binary sensors."""
"""Set up template binary sensors."""
sensors = []
for device, device_config in config[CONF_SENSORS].items():
@@ -45,49 +49,62 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
entity_ids = (device_config.get(ATTR_ENTITY_ID) or
value_template.extract_entities())
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
sensor_class = device_config.get(CONF_SENSOR_CLASS)
device_class = get_deprecated(
device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
if value_template is not None:
value_template.hass = hass
sensors.append(
BinarySensorTemplate(
hass,
device,
friendly_name,
sensor_class,
value_template,
hass, device, friendly_name, device_class, value_template,
entity_ids)
)
if not sensors:
_LOGGER.error('No sensors added')
_LOGGER.error("No sensors added")
return False
yield from async_add_devices(sensors, True)
async_add_devices(sensors, True)
return True
class BinarySensorTemplate(BinarySensorDevice):
"""A virtual binary sensor that triggers from another sensor."""
def __init__(self, hass, device, friendly_name, sensor_class,
def __init__(self, hass, device, friendly_name, device_class,
value_template, entity_ids):
"""Initialize the Template binary sensor."""
self.hass = hass
self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device,
hass=hass)
self.entity_id = async_generate_entity_id(
ENTITY_ID_FORMAT, device, hass=hass)
self._name = friendly_name
self._sensor_class = sensor_class
self._device_class = device_class
self._template = value_template
self._state = None
self._entities = entity_ids
@asyncio.coroutine
def async_added_to_hass(self):
"""Register callbacks."""
state = yield from async_get_last_state(self.hass, self.entity_id)
if state:
self._state = state.state == STATE_ON
@callback
def template_bsensor_state_listener(entity, old_state, new_state):
"""Called when the target device changes state."""
hass.async_add_job(self.async_update_ha_state, True)
"""Handle the target device state changes."""
self.hass.async_add_job(self.async_update_ha_state(True))
async_track_state_change(
hass, entity_ids, template_bsensor_state_listener)
@callback
def template_bsensor_startup(event):
"""Update template on startup."""
async_track_state_change(
self.hass, self._entities, template_bsensor_state_listener)
self.hass.async_add_job(self.async_update_ha_state(True))
self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, template_bsensor_startup)
@property
def name(self):
@@ -100,9 +117,9 @@ class BinarySensorTemplate(BinarySensorDevice):
return self._state
@property
def sensor_class(self):
def device_class(self):
"""Return the sensor class of the sensor."""
return self._sensor_class
return self._device_class
@property
def should_poll(self):
@@ -118,8 +135,8 @@ class BinarySensorTemplate(BinarySensorDevice):
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 template %s,'
' the state is unknown.', self._name)
_LOGGER.warning("Could not render template %s, "
"the state is unknown", self._name)
return
_LOGGER.error('Could not render template %s: %s', self._name, ex)
_LOGGER.error("Could not render template %s: %s", self._name, ex)
self._state = False

View File

@@ -11,11 +11,12 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA)
BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
CONF_NAME, CONF_ENTITY_ID, CONF_TYPE, STATE_UNKNOWN, CONF_SENSOR_CLASS,
ATTR_ENTITY_ID)
ATTR_ENTITY_ID, CONF_DEVICE_CLASS)
from homeassistant.core import callback
from homeassistant.helpers.deprecation import get_deprecated
from homeassistant.helpers.event import async_track_state_change
_LOGGER = logging.getLogger(__name__)
@@ -37,7 +38,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_THRESHOLD): vol.Coerce(float),
vol.Required(CONF_TYPE): vol.In(SENSOR_TYPES),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA,
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
@@ -48,11 +50,11 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
name = config.get(CONF_NAME)
threshold = config.get(CONF_THRESHOLD)
limit_type = config.get(CONF_TYPE)
sensor_class = config.get(CONF_SENSOR_CLASS)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
yield from async_add_devices(
async_add_devices(
[ThresholdSensor(hass, entity_id, name, threshold, limit_type,
sensor_class)], True)
device_class)], True)
return True
@@ -60,14 +62,14 @@ class ThresholdSensor(BinarySensorDevice):
"""Representation of a Threshold sensor."""
def __init__(self, hass, entity_id, name, threshold, limit_type,
sensor_class):
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._sensor_class = sensor_class
self._device_class = device_class
self._deviation = False
self.sensor_value = 0
@@ -75,7 +77,7 @@ class ThresholdSensor(BinarySensorDevice):
# pylint: disable=invalid-name
def async_threshold_sensor_state_listener(
entity, old_state, new_state):
"""Called when the sensor changes state."""
"""Handle sensor state changes."""
if new_state.state == STATE_UNKNOWN:
return
@@ -105,9 +107,9 @@ class ThresholdSensor(BinarySensorDevice):
return False
@property
def sensor_class(self):
def device_class(self):
"""Return the sensor class of the sensor."""
return self._sensor_class
return self._device_class
@property
def device_state_attributes(self):

View File

@@ -6,21 +6,19 @@ https://home-assistant.io/components/sensor.trend/
"""
import asyncio
import logging
import voluptuous as vol
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import (
BinarySensorDevice,
ENTITY_ID_FORMAT,
PLATFORM_SCHEMA,
SENSOR_CLASSES_SCHEMA)
BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA,
DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
ATTR_FRIENDLY_NAME,
ATTR_ENTITY_ID,
CONF_SENSOR_CLASS,
STATE_UNKNOWN,)
ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, CONF_SENSOR_CLASS,
CONF_DEVICE_CLASS, STATE_UNKNOWN,)
from homeassistant.helpers.deprecation import get_deprecated
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.event import track_state_change
@@ -34,8 +32,8 @@ SENSOR_SCHEMA = vol.Schema({
vol.Optional(CONF_ATTRIBUTE): cv.string,
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
vol.Optional(CONF_INVERT, default=False): cv.boolean,
vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA
vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@@ -45,25 +43,21 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the trend sensors."""
"""Set up the trend sensors."""
sensors = []
for device, device_config in config[CONF_SENSORS].items():
entity_id = device_config[ATTR_ENTITY_ID]
attribute = device_config.get(CONF_ATTRIBUTE)
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
sensor_class = device_config[CONF_SENSOR_CLASS]
device_class = get_deprecated(
device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
invert = device_config[CONF_INVERT]
sensors.append(
SensorTrend(
hass,
device,
friendly_name,
entity_id,
attribute,
sensor_class,
invert)
hass, device, friendly_name, entity_id, attribute,
device_class, invert)
)
if not sensors:
_LOGGER.error("No sensors added")
@@ -76,15 +70,15 @@ class SensorTrend(BinarySensorDevice):
"""Representation of a trend Sensor."""
def __init__(self, hass, device_id, friendly_name,
target_entity, attribute, sensor_class, invert):
target_entity, attribute, device_class, invert):
"""Initialize the sensor."""
self._hass = hass
self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
hass=hass)
self.entity_id = generate_entity_id(
ENTITY_ID_FORMAT, device_id, hass=hass)
self._name = friendly_name
self._target_entity = target_entity
self._attribute = attribute
self._sensor_class = sensor_class
self._device_class = device_class
self._invert = invert
self._state = None
self.from_state = None
@@ -92,7 +86,7 @@ class SensorTrend(BinarySensorDevice):
@callback
def trend_sensor_state_listener(entity, old_state, new_state):
"""Called when the target device changes state."""
"""Handle the target device state changes."""
self.from_state = old_state
self.to_state = new_state
hass.async_add_job(self.async_update_ha_state(True))
@@ -111,9 +105,9 @@ class SensorTrend(BinarySensorDevice):
return self._state
@property
def sensor_class(self):
def device_class(self):
"""Return the sensor class of the sensor."""
return self._sensor_class
return self._device_class
@property
def should_poll(self):

View File

@@ -7,9 +7,9 @@ https://home-assistant.io/components/binary_sensor.vera/
import logging
from homeassistant.components.binary_sensor import (
BinarySensorDevice)
BinarySensorDevice, ENTITY_ID_FORMAT)
from homeassistant.components.vera import (
VeraDevice, VERA_DEVICES, VERA_CONTROLLER)
VERA_CONTROLLER, VERA_DEVICES, VeraDevice)
DEPENDENCIES = ['vera']
@@ -30,6 +30,7 @@ class VeraBinarySensor(VeraDevice, BinarySensorDevice):
"""Initialize the binary_sensor."""
self._state = False
VeraDevice.__init__(self, vera_device, controller)
self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id)
@property
def is_on(self):

View File

@@ -0,0 +1,39 @@
"""
Support for VOC.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.volvooncall/
"""
import logging
from homeassistant.components.volvooncall import VolvoEntity
from homeassistant.components.binary_sensor import BinarySensorDevice
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Volvo sensors."""
if discovery_info is None:
return
add_devices([VolvoSensor(hass, *discovery_info)])
class VolvoSensor(VolvoEntity, BinarySensorDevice):
"""Representation of a Volvo sensor."""
@property
def is_on(self):
"""Return True if the binary sensor is on."""
val = getattr(self.vehicle, self._attribute)
if self._attribute == 'bulb_failures':
return bool(val)
elif self._attribute in ['doors', 'windows']:
return any([val[key] for key in val if 'Open' in key])
else:
return val != 'Normal'
@property
def device_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return 'safety'

View File

@@ -20,8 +20,8 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
import pywemo.discovery as discovery
if discovery_info is not None:
location = discovery_info[2]
mac = discovery_info[3]
location = discovery_info['ssdp_description']
mac = discovery_info['mac_address']
device = discovery.device_from_description(location, mac)
if device:
@@ -29,7 +29,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
class WemoBinarySensor(BinarySensorDevice):
"""Represents a WeMo binary sensor."""
"""Representation a WeMo binary sensor."""
def __init__(self, device):
"""Initialize the WeMo sensor."""
@@ -40,12 +40,12 @@ class WemoBinarySensor(BinarySensorDevice):
wemo.SUBSCRIPTION_REGISTRY.register(self.wemo)
wemo.SUBSCRIPTION_REGISTRY.on(self.wemo, None, self._update_callback)
def _update_callback(self, _device, _params):
"""Called by the wemo device callback to update state."""
_LOGGER.info(
'Subscription update for %s',
_device)
self.update()
def _update_callback(self, _device, _type, _params):
"""Handle state changes."""
_LOGGER.info("Subscription update for %s", _device)
updated = self.wemo.subscription_update(_type, _params)
self._update(force_update=(not updated))
if not hasattr(self, 'hass'):
return
self.schedule_update_ha_state()
@@ -58,7 +58,7 @@ class WemoBinarySensor(BinarySensorDevice):
@property
def unique_id(self):
"""Return the id of this WeMo device."""
return "{}.{}".format(self.__class__, self.wemo.serialnumber)
return '{}.{}'.format(self.__class__, self.wemo.serialnumber)
@property
def name(self):
@@ -67,12 +67,16 @@ class WemoBinarySensor(BinarySensorDevice):
@property
def is_on(self):
"""True if sensor is on."""
"""Return true if sensor is on."""
return self._state
def update(self):
"""Update WeMo state."""
self._update(force_update=True)
def _update(self, force_update=True):
try:
self._state = self.wemo.get_state(True)
except AttributeError:
_LOGGER.warning('Could not update status for %s', self.name)
self._state = self.wemo.get_state(force_update)
except AttributeError as err:
_LOGGER.warning(
"Could not update status for %s (%s)", self.name, err)

View File

@@ -16,23 +16,23 @@ 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",
"co_detected": "gas",
"smoke_detected": "smoke",
"capturing_video": None
'opened': 'opening',
'brightness': 'light',
'vibration': 'vibration',
'loudness': 'sound',
'noise': 'sound',
'capturing_audio': 'sound',
'liquid_detected': 'moisture',
'motion': 'motion',
'presence': 'occupancy',
'co_detected': 'gas',
'smoke_detected': 'smoke',
'capturing_video': None
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink binary sensor platform."""
"""Set up the Wink binary sensor platform."""
import pywink
for sensor in pywink.get_sensors():
@@ -83,7 +83,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if camera_sensor.capability() in SENSOR_TYPES:
add_devices([WinkBinarySensorDevice(camera_sensor, hass)])
except AttributeError:
_LOGGER.info("Device isn't a sensor, skipping.")
_LOGGER.info("Device isn't a sensor, skipping")
class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
@@ -92,13 +92,13 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
def __init__(self, wink, hass):
"""Initialize the Wink binary sensor."""
super().__init__(wink, hass)
try:
if hasattr(self.wink, 'unit'):
self._unit_of_measurement = self.wink.unit()
except AttributeError:
else:
self._unit_of_measurement = None
try:
if hasattr(self.wink, 'capability'):
self.capability = self.wink.capability()
except AttributeError:
else:
self.capability = None
@property
@@ -107,8 +107,8 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
return self.wink.state()
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return SENSOR_TYPES.get(self.capability)
@@ -161,8 +161,8 @@ class WinkRemote(WinkBinarySensorDevice):
}
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return None

View File

@@ -0,0 +1,152 @@
"""
Sensor to indicate whether the current day is a workday.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.workday/
"""
import asyncio
import logging
import datetime
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME, WEEKDAYS
import homeassistant.util.dt as dt_util
from homeassistant.components.binary_sensor import BinarySensorDevice
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['holidays==0.8.1']
# 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']
CONF_COUNTRY = 'country'
CONF_PROVINCE = 'province'
CONF_WORKDAYS = 'workdays'
# By default, Monday - Friday are workdays
DEFAULT_WORKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri']
CONF_EXCLUDES = 'excludes'
# By default, public holidays, Saturdays and Sundays are excluded from workdays
DEFAULT_EXCLUDES = ['sat', 'sun', 'holiday']
DEFAULT_NAME = 'Workday Sensor'
ALLOWED_DAYS = WEEKDAYS + ['holiday']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_COUNTRY): vol.In(ALL_COUNTRIES),
vol.Optional(CONF_PROVINCE, default=None): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_WORKDAYS, default=DEFAULT_WORKDAYS):
vol.All(cv.ensure_list, [vol.In(ALLOWED_DAYS)]),
vol.Optional(CONF_EXCLUDES, default=DEFAULT_EXCLUDES):
vol.All(cv.ensure_list, [vol.In(ALLOWED_DAYS)]),
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Workday sensor."""
import holidays
sensor_name = config.get(CONF_NAME)
country = config.get(CONF_COUNTRY)
province = config.get(CONF_PROVINCE)
workdays = config.get(CONF_WORKDAYS)
excludes = config.get(CONF_EXCLUDES)
year = datetime.datetime.now().year
obj_holidays = getattr(holidays, country)(years=year)
if province:
# 'state' and 'prov' are not interchangeable, so need to make
# sure we use the right one
if (hasattr(obj_holidays, "PROVINCES") and
province in obj_holidays.PROVINCES):
obj_holidays = getattr(holidays, country)(prov=province,
years=year)
elif (hasattr(obj_holidays, "STATES") and
province in obj_holidays.STATES):
obj_holidays = getattr(holidays, country)(state=province,
years=year)
else:
_LOGGER.error("There is no province/state %s in country %s",
province, country)
return False
_LOGGER.debug("Found the following holidays for your configuration:")
for date, name in sorted(obj_holidays.items()):
_LOGGER.debug("%s %s", date, name)
add_devices([IsWorkdaySensor(
obj_holidays, workdays, excludes, sensor_name)], True)
def day_to_string(day):
"""Convert day index 0 - 7 to string."""
try:
return ALLOWED_DAYS[day]
except IndexError:
return None
class IsWorkdaySensor(BinarySensorDevice):
"""Implementation of a Workday sensor."""
def __init__(self, obj_holidays, workdays, excludes, name):
"""Initialize the Workday sensor."""
self._name = name
self._obj_holidays = obj_holidays
self._workdays = workdays
self._excludes = excludes
self._state = None
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return the state of the device."""
return self._state
def is_include(self, day, now):
"""Check if given day is in the includes list."""
if day in self._workdays:
return True
elif 'holiday' in self._workdays and now in self._obj_holidays:
return True
return False
def is_exclude(self, day, now):
"""Check if given day is in the excludes list."""
if day in self._excludes:
return True
elif 'holiday' in self._excludes and now in self._obj_holidays:
return True
return False
@asyncio.coroutine
def async_update(self):
"""Get date and look whether it is a holiday."""
# Default is no workday
self._state = False
# Get iso day of the week (1 = Monday, 7 = Sunday)
day = datetime.datetime.today().isoweekday() - 1
day_of_week = day_to_string(day)
if self.is_include(day_of_week, dt_util.now()):
self._state = True
if self.is_exclude(day_of_week, dt_util.now()):
self._state = False

View File

@@ -0,0 +1,89 @@
"""
Binary sensors on Zigbee Home Automation networks.
For more details on this platform, please refer to the documentation
at https://home-assistant.io/components/binary_sensor.zha/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import DOMAIN, BinarySensorDevice
from homeassistant.components import zha
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['zha']
# ZigBee Cluster Library Zone Type to Home Assistant device class
CLASS_MAPPING = {
0x000d: 'motion',
0x0015: 'opening',
0x0028: 'smoke',
0x002a: 'moisture',
0x002b: 'gas',
0x002d: 'vibration',
}
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Zigbee Home Automation binary sensors."""
discovery_info = zha.get_discovery_info(hass, discovery_info)
if discovery_info is None:
return
from bellows.zigbee.zcl.clusters.security import IasZone
clusters = discovery_info['clusters']
device_class = None
cluster = [c for c in clusters if isinstance(c, IasZone)][0]
if discovery_info['new_join']:
yield from cluster.bind()
ieee = cluster.endpoint.device.application.ieee
yield from cluster.write_attributes({'cie_addr': ieee})
try:
zone_type = yield from cluster['zone_type']
device_class = CLASS_MAPPING.get(zone_type, None)
except Exception: # pylint: disable=broad-except
# If we fail to read from the device, use a non-specific class
pass
sensor = BinarySensor(device_class, **discovery_info)
async_add_devices([sensor])
class BinarySensor(zha.Entity, BinarySensorDevice):
"""THe ZHA Binary Sensor."""
_domain = DOMAIN
def __init__(self, device_class, **kwargs):
"""Initialize the ZHA binary sensor."""
super().__init__(**kwargs)
self._device_class = device_class
from bellows.zigbee.zcl.clusters.security import IasZone
self._ias_zone_cluster = self._clusters[IasZone.cluster_id]
@property
def is_on(self) -> bool:
"""Return True if entity is on."""
if self._state == 'unknown':
return False
return bool(self._state)
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return self._device_class
def cluster_command(self, aps_frame, tsn, command_id, args):
"""Handle commands received to this cluster."""
if command_id == 0:
self._state = args[0] & 3
_LOGGER.debug("Updated alarm state: %s", self._state)
self.schedule_update_ha_state()
elif command_id == 1:
_LOGGER.debug("Enroll requested")
self.hass.add_job(self._ias_zone_cluster.enroll_response(0, 0))

View File

@@ -23,8 +23,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the ZigBee binary sensor platform."""
add_devices([ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))])
"""Set up the ZigBee binary sensor platform."""
add_devices(
[ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))], True)
class ZigBeeBinarySensor(ZigBeeDigitalIn, BinarySensorDevice):

View File

@@ -10,6 +10,7 @@ import homeassistant.util.dt as dt_util
from homeassistant.helpers.event import track_point_in_time
from homeassistant.components import zwave
from homeassistant.components.zwave import workaround
from homeassistant.components.zwave import async_setup_platform # noqa # pylint: disable=unused-import
from homeassistant.components.binary_sensor import (
DOMAIN,
BinarySensorDevice)
@@ -18,88 +19,71 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = []
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Z-Wave platform for binary sensors."""
if discovery_info is None or zwave.NETWORK is None:
return
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
value.set_change_verified(False)
device_mapping = workaround.get_device_mapping(value)
def get_device(values, **kwargs):
"""Create Z-Wave entity device."""
device_mapping = workaround.get_device_mapping(values.primary)
if device_mapping == workaround.WORKAROUND_NO_OFF_EVENT:
# Default the multiplier to 4
re_arm_multiplier = (zwave.get_config_value(value.node, 9) or 4)
add_devices([
ZWaveTriggerSensor(value, "motion",
hass, re_arm_multiplier * 8)
])
return
re_arm_multiplier = zwave.get_config_value(values.primary.node, 9) or 4
return ZWaveTriggerSensor(values, "motion", re_arm_multiplier * 8)
if workaround.get_device_component_mapping(value) == DOMAIN:
add_devices([ZWaveBinarySensor(value, None)])
return
if workaround.get_device_component_mapping(values.primary) == DOMAIN:
return ZWaveBinarySensor(values, None)
if value.command_class == zwave.const.COMMAND_CLASS_SENSOR_BINARY:
add_devices([ZWaveBinarySensor(value, None)])
if values.primary.command_class == zwave.const.COMMAND_CLASS_SENSOR_BINARY:
return ZWaveBinarySensor(values, None)
return None
class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity):
"""Representation of a binary sensor within Z-Wave."""
def __init__(self, value, sensor_class):
def __init__(self, values, device_class):
"""Initialize the sensor."""
self._sensor_type = sensor_class
zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
zwave.ZWaveDeviceEntity.__init__(self, values, DOMAIN)
self._sensor_type = device_class
self._state = self.values.primary.data
def update_properties(self):
"""Handle data changes for node values."""
self._state = self.values.primary.data
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._value.data
"""Return true if the binary sensor is on."""
return self._state
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return self._sensor_type
@property
def should_poll(self):
"""No polling needed."""
return False
class ZWaveTriggerSensor(ZWaveBinarySensor):
"""Representation of a stateless sensor within Z-Wave."""
def __init__(self, value, sensor_class, hass, re_arm_sec=60):
def __init__(self, values, device_class, re_arm_sec=60):
"""Initialize the sensor."""
super(ZWaveTriggerSensor, self).__init__(value, sensor_class)
self._hass = hass
super(ZWaveTriggerSensor, self).__init__(values, device_class)
self.re_arm_sec = re_arm_sec
self.invalidate_after = None
def update_properties(self):
"""Handle value changes for this entity's node."""
self._state = self.values.primary.data
# only allow this value to be true for re_arm secs
if not self.hass:
return
self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
seconds=self.re_arm_sec)
# If it's active make sure that we set the timeout tracker
if value.data:
track_point_in_time(
self._hass, self.async_update_ha_state,
self.invalidate_after)
def value_changed(self, value):
"""Called when a value for this entity's node has changed."""
if self._value.value_id == value.value_id:
self.schedule_update_ha_state()
if value.data:
# only allow this value to be true for re_arm secs
self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
seconds=self.re_arm_sec)
track_point_in_time(
self._hass, self.async_update_ha_state,
self.invalidate_after)
track_point_in_time(
self.hass, self.async_update_ha_state,
self.invalidate_after)
@property
def is_on(self):
"""Return True if movement has happened within the rearm time."""
return self._value.data and \
"""Return true if movement has happened within the rearm time."""
return self._state and \
(self.invalidate_after is None or
self.invalidate_after > dt_util.utcnow())

View File

@@ -0,0 +1,89 @@
"""
Support for Blink Home Camera System.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/blink/
"""
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.const import (
CONF_USERNAME, CONF_PASSWORD, ATTR_FRIENDLY_NAME, ATTR_ARMED)
from homeassistant.helpers import discovery
REQUIREMENTS = ['blinkpy==0.5.2']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'blink'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string
})
}, extra=vol.ALLOW_EXTRA)
ARM_SYSTEM_SCHEMA = vol.Schema({
vol.Optional(ATTR_ARMED): cv.boolean
})
ARM_CAMERA_SCHEMA = vol.Schema({
vol.Required(ATTR_FRIENDLY_NAME): cv.string,
vol.Optional(ATTR_ARMED): cv.boolean
})
SNAP_PICTURE_SCHEMA = vol.Schema({
vol.Required(ATTR_FRIENDLY_NAME): cv.string
})
class BlinkSystem(object):
"""Blink System class."""
def __init__(self, config_info):
"""Initialize the system."""
import blinkpy
self.blink = blinkpy.Blink(username=config_info[DOMAIN][CONF_USERNAME],
password=config_info[DOMAIN][CONF_PASSWORD])
self.blink.setup_system()
def setup(hass, config):
"""Set up Blink System."""
hass.data[DOMAIN] = BlinkSystem(config)
discovery.load_platform(hass, 'camera', DOMAIN, {}, config)
discovery.load_platform(hass, 'sensor', DOMAIN, {}, config)
discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config)
def snap_picture(call):
"""Take a picture."""
cameras = hass.data[DOMAIN].blink.cameras
name = call.data.get(ATTR_FRIENDLY_NAME, '')
if name in cameras:
cameras[name].snap_picture()
def arm_camera(call):
"""Arm a camera."""
cameras = hass.data[DOMAIN].blink.cameras
name = call.data.get(ATTR_FRIENDLY_NAME, '')
value = call.data.get(ATTR_ARMED, True)
if name in cameras:
cameras[name].set_motion_detect(value)
def arm_system(call):
"""Arm the system."""
value = call.data.get(ATTR_ARMED, True)
hass.data[DOMAIN].blink.arm = value
hass.data[DOMAIN].blink.refresh()
hass.services.register(
DOMAIN, 'snap_picture', snap_picture, schema=SNAP_PICTURE_SCHEMA)
hass.services.register(
DOMAIN, 'arm_camera', arm_camera, schema=ARM_CAMERA_SCHEMA)
hass.services.register(
DOMAIN, 'arm_system', arm_system, schema=ARM_SYSTEM_SCHEMA)
return True

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