Compare commits

...

203 Commits
0.43 ... 0.44.1

Author SHA1 Message Date
Paulus Schoutsen
ab9c394e93 Version bump to 0.44.1 2017-05-07 15:09:53 -07:00
Paulus Schoutsen
5d13f36a4b Merge pull request #7482 from home-assistant/release-0-44-1
0.44.1
2017-05-07 15:08:37 -07:00
Caleb
4165629f97 Update to pyunifi 2.12 (#7468)
* Update to pyunifi 2.12

* Update requirements_all.txt
2017-05-07 14:03:39 -07:00
Marc Egli
f87b9b7b85 Fix plant MIN_TEMPERATURE, MAX_TEMPERATURE validation (#7476)
* Fix plant MIN_TEMPERATURE, MAX_TEMPERATURE validation

small_float only allows values from 0 to 1 so we should use float instead

* Do not use vol.All for a single validation
2017-05-07 14:03:14 -07:00
Martin Hjelmare
2ab45441a8 Upgrade pymysensors to 0.10.0 (#7469) 2017-05-07 14:02:53 -07:00
pezinek
fcdfebefd9 Forecasts for weather underground (#7062) 2017-05-07 13:56:19 -07:00
Brian Cribbs
9b920b3b40 fixing nits 2017-05-07 13:56:05 -07:00
Brian Cribbs
0c94df9fcf fixing documentation 2017-05-07 13:56:05 -07:00
Brian Cribbs
1ba4435693 repairing functionality for non-zero based ranges 2017-05-07 13:56:05 -07:00
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
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
40f480c24e tradfri: Improve color temp support detection (#7211) 2017-04-21 23:32:51 -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
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
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
0acc52b23b HassIO API v2 (#7201)
Add an optional extended description…
2017-04-21 12:20:19 +02: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
717 changed files with 11150 additions and 6155 deletions

View File

@@ -77,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
@@ -154,6 +157,13 @@ omit =
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
@@ -165,6 +175,7 @@ omit =
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
@@ -182,15 +193,18 @@ omit =
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
@@ -201,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
@@ -222,10 +237,13 @@ 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
@@ -238,6 +256,7 @@ omit =
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
@@ -335,6 +354,7 @@ 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
@@ -350,6 +370,7 @@ omit =
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
@@ -391,6 +412,7 @@ omit =
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

View File

@@ -27,4 +27,4 @@ RUN pip3 install --no-cache-dir -r requirements_all.txt && \
# Copy source
COPY . .
CMD [ "python", "-m", "homeassistant", "--config", "/config" ]
CMD [ "python", "-m", "homeassistant", "--config", "/config" ]

View File

@@ -1,4 +1,4 @@
"""Starts home assistant."""
"""Start Home Assistant."""
from __future__ import print_function
import argparse
@@ -277,7 +277,7 @@ def cmdline() -> List[str]:
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

View File

@@ -1,4 +1,4 @@
"""Provides methods to bootstrap a home assistant instance."""
"""Provide methods to bootstrap a Home Assistant instance."""
import asyncio
import logging
import logging.handlers
@@ -206,7 +206,7 @@ def async_from_config_file(config_path: str,
@core.callback
def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
log_rotate_days=None) -> None:
"""Setup the logging.
"""Set up the logging.
This method must be run in the event loop.
"""
@@ -214,12 +214,12 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
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
@@ -274,7 +274,7 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
else:
_LOGGER.error(
'Unable to setup error log %s (access denied)', err_log_path)
"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

View File

@@ -25,7 +25,7 @@ DEPENDENCIES = ['alarmdecoder']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Perform the setup for AlarmDecoder alarm panels."""
"""Set up for AlarmDecoder alarm panels."""
_LOGGER.debug("AlarmDecoderAlarmPanel: setup")
device = AlarmDecoderAlarmPanel("Alarm Panel", hass)
@@ -44,7 +44,7 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
self._name = name
self._state = STATE_UNKNOWN
_LOGGER.debug("AlarmDecoderAlarm: Setting up panel")
_LOGGER.debug("Setting up panel")
@asyncio.coroutine
def async_added_to_hass(self):
@@ -78,12 +78,12 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
@property
def should_poll(self):
"""No polling needed."""
"""Return the polling state."""
return False
@property
def code_format(self):
"""Regex for code format or None if no code is required."""
"""Return the regex for code format or None if no code is required."""
return '^\\d{4,6}$'
@property
@@ -94,26 +94,23 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
"""Send disarm command."""
_LOGGER.debug("AlarmDecoderAlarm::alarm_disarm: %s", code)
_LOGGER.debug("alarm_disarm: %s", code)
if code:
_LOGGER.debug("AlarmDecoderAlarm::alarm_disarm: sending %s1",
str(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("AlarmDecoderAlarm::alarm_arm_away: %s", code)
_LOGGER.debug("alarm_arm_away: %s", code)
if code:
_LOGGER.debug("AlarmDecoderAlarm::alarm_arm_away: sending %s2",
str(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("AlarmDecoderAlarm::alarm_arm_home: %s", code)
_LOGGER.debug("alarm_arm_home: %s", code)
if code:
_LOGGER.debug("AlarmDecoderAlarm::alarm_arm_home: sending %s3",
str(code))
_LOGGER.debug("alarm_arm_home: sending %s3", str(code))
self.hass.data[DATA_AD].send("{!s}3".format(code))

View File

@@ -1,5 +1,4 @@
"""
Interfaces with Alarm.com alarm control panels.
For more details about this platform, please refer to the documentation at
@@ -33,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a Alarm.com control panel."""
"""Set up a Alarm.com control panel."""
name = config.get(CONF_NAME)
code = config.get(CONF_CODE)
username = config.get(CONF_USERNAME)

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

@@ -104,7 +104,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
@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())

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

@@ -45,7 +45,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the MQTT platform."""
"""Set up the MQTT Alarm Control Panel platform."""
async_add_devices([MqttAlarm(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
@@ -62,7 +62,7 @@ class MqttAlarm(alarm.AlarmControlPanel):
def __init__(self, name, state_topic, command_topic, qos, payload_disarm,
payload_arm_home, payload_arm_away, code):
"""Initalize the MQTT alarm panel."""
"""Init the MQTT Alarm Control Panel."""
self._state = STATE_UNKNOWN
self._name = name
self._state_topic = state_topic
@@ -80,11 +80,11 @@ class MqttAlarm(alarm.AlarmControlPanel):
"""
@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.hass.async_add_job(self.async_update_ha_state())

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

@@ -123,25 +123,25 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
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

@@ -1,15 +1,20 @@
"""Interfaces with TotalConnect alarm control panels."""
"""
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)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['total_connect_client==0.7']
@@ -25,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup a TotalConnect control panel."""
"""Set up a TotalConnect control panel."""
name = config.get(CONF_NAME)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
@@ -41,13 +46,13 @@ class TotalConnect(alarm.AlarmControlPanel):
"""Initialize the TotalConnect status."""
from total_connect_client import TotalConnectClient
_LOGGER.debug('Setting up TotalConnect...')
_LOGGER.debug("Setting up TotalConnect...")
self._name = name
self._username = username
self._password = password
self._state = STATE_UNKNOWN
self._client = TotalConnectClient.TotalConnectClient(username,
password)
self._client = TotalConnectClient.TotalConnectClient(
username, password)
@property
def name(self):

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

@@ -8,11 +8,10 @@ import asyncio
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
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
@@ -24,19 +23,16 @@ DOMAIN = 'alarmdecoder'
DATA_AD = 'alarmdecoder'
CONF_DEVICE = 'device'
CONF_DEVICE_TYPE = 'type'
CONF_DEVICE_HOST = 'host'
CONF_DEVICE_PORT = 'port'
CONF_DEVICE_PATH = 'path'
CONF_DEVICE_BAUD = 'baudrate'
CONF_ZONES = 'zones'
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_PANEL_DISPLAY = 'panel_display'
CONF_ZONES = 'zones'
DEFAULT_DEVICE_TYPE = 'socket'
DEFAULT_DEVICE_HOST = 'localhost'
@@ -87,7 +83,7 @@ CONFIG_SCHEMA = vol.Schema({
@asyncio.coroutine
def async_setup(hass, config):
"""Common setup for AlarmDecoder devices."""
"""Set up for the AlarmDecoder devices."""
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice)
@@ -106,28 +102,28 @@ def async_setup(hass, config):
sync_connect = asyncio.Future(loop=hass.loop)
def handle_open(device):
"""Callback for a successful connection."""
_LOGGER.info("Established a connection with the alarmdecoder.")
"""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):
"""Callback to handle shutdown alarmdecoder."""
_LOGGER.debug("Shutting down alarmdecoder.")
"""Handle the shutdown of AlarmDecoder."""
_LOGGER.debug("Shutting down alarmdecoder")
controller.close()
@callback
def handle_message(sender, message):
"""Callback to handle message from alarmdecoder."""
"""Handle message from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message)
def zone_fault_callback(sender, zone):
"""Callback to handle zone fault from alarmdecoder."""
"""Handle zone fault from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone)
def zone_restore_callback(sender, zone):
"""Callback to handle zone restore from alarmdecoder."""
"""Handle zone restore from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_RESTORE, zone)
controller = False
@@ -157,15 +153,16 @@ def async_setup(hass, config):
if not result:
return False
hass.async_add_job(async_load_platform(hass, 'alarm_control_panel', DOMAIN,
conf, config))
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))
hass.async_add_job(async_load_platform(
hass, 'sensor', DOMAIN, conf, config))
return True

View File

@@ -141,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)
@@ -400,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)
@@ -430,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.
"""

View File

@@ -13,8 +13,8 @@ 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__)

View File

@@ -31,7 +31,7 @@ def async_trigger(hass, config, action):
if event == EVENT_SHUTDOWN:
@callback
def hass_shutdown(event):
"""Called when Home Assistant is shutting down."""
"""Execute when Home Assistant is shutting down."""
hass.async_run_job(action, {
'trigger': {
'platform': 'homeassistant',

View File

@@ -14,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({

View File

@@ -14,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__)

View File

@@ -14,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({

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

@@ -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

View File

@@ -11,7 +11,6 @@ from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import (STATE_ON, STATE_OFF, STATE_OPEN, STATE_CLOSED)
from homeassistant.components.alarmdecoder import (ZONE_SCHEMA,
CONF_ZONES,
CONF_ZONE_NAME,
@@ -27,7 +26,7 @@ _LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup AlarmDecoder binary sensor devices."""
"""Set up the AlarmDecoder binary sensor devices."""
configured_zones = discovery_info[CONF_ZONES]
devices = []
@@ -36,10 +35,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
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)
device = AlarmDecoderBinarySensor(
hass, zone_num, zone_name, zone_type)
devices.append(device)
async_add_devices(devices)
@@ -58,7 +55,7 @@ class AlarmDecoderBinarySensor(BinarySensorDevice):
self._name = zone_name
self._type = zone_type
_LOGGER.debug('AlarmDecoderBinarySensor: Setup up zone: ' + zone_name)
_LOGGER.debug("Setup up zone: %s", self._name)
@asyncio.coroutine
def async_added_to_hass(self):
@@ -69,14 +66,6 @@ class AlarmDecoderBinarySensor(BinarySensorDevice):
async_dispatcher_connect(
self.hass, SIGNAL_ZONE_RESTORE, self._restore_callback)
@property
def state(self):
"""Return the state of the binary sensor."""
if self._type == 'opening':
return STATE_OPEN if self.is_on else STATE_CLOSED
return STATE_ON if self.is_on else STATE_OFF
@property
def name(self):
"""Return the name of the entity."""

View File

@@ -15,7 +15,7 @@ DEPENDENCIES = ['android_ip_webcam']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup IP Webcam binary sensors."""
"""Set up the IP Webcam binary sensors."""
if discovery_info is None:
return
@@ -28,7 +28,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice):
"""Represents an IP Webcam binary sensor."""
"""Representation of an IP Webcam binary sensor."""
def __init__(self, name, host, ipcam, sensor):
"""Initialize the binary sensor."""
@@ -47,7 +47,7 @@ class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice):
@property
def is_on(self):
"""True if the binary sensor is on."""
"""Return true if the binary sensor is on."""
return self._state
@asyncio.coroutine

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

@@ -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

@@ -24,7 +24,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class BlinkCameraMotionSensor(BinarySensorDevice):
"""A representation of a Blink binary sensor."""
"""Representation of a Blink binary sensor."""
def __init__(self, name, data):
"""Initialize the sensor."""

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

View File

@@ -39,7 +39,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# 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)
@@ -56,7 +56,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class CommandBinarySensor(BinarySensorDevice):
"""Represent a command line binary sensor."""
"""Representation of a command line binary sensor."""
def __init__(self, hass, data, name, device_class, payload_on,
payload_off, value_template):

View File

@@ -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']:
@@ -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,7 +16,7 @@ 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, device_class):
"""Initialize the demo sensor."""

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

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

@@ -30,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
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)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
@@ -44,7 +44,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
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
@@ -53,7 +53,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
@property
def name(self):
"""The default name for the binary sensor."""
"""Return the default name for the binary sensor."""
return self.devname
@property
@@ -80,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

@@ -15,13 +15,14 @@ from homeassistant.components.envisalink import (
SIGNAL_ZONE_UPDATE)
from homeassistant.const import ATTR_LAST_TRIP_TIME
DEPENDENCIES = ['envisalink']
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['envisalink']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup Envisalink binary sensor devices."""
"""Set up the Envisalink binary sensor devices."""
configured_zones = discovery_info['zones']
devices = []

View File

@@ -48,23 +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)
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, config):
"""Constructor for binary sensor noise detection."""
"""Init for the binary sensor noise detection."""
super().__init__(config.get(CONF_INITIAL_STATE))
self._state = False
@@ -79,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
@@ -89,10 +87,10 @@ 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__(config)
@@ -125,4 +123,4 @@ class FFmpegMotion(FFmpegBinarySensor):
@property
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return "motion"
return 'motion'

View File

@@ -45,23 +45,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 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)
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__(config)
@@ -77,14 +75,12 @@ class FFmpegNoise(FFmpegBinarySensor):
if entity_ids is not None and self.entity_id not in entity_ids:
return
# init config
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
yield from self.ffmpeg.open_sensor(
input_source=self._config.get(CONF_INPUT),
output_dest=self._config.get(CONF_OUTPUT),
@@ -94,4 +90,4 @@ class FFmpegNoise(FFmpegBinarySensor):
@property
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return "sound"
return 'sound'

View File

@@ -110,7 +110,7 @@ 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)

View File

@@ -67,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)
@@ -77,16 +77,16 @@ 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 = []
@@ -104,7 +104,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
ignore = custom.get(CONF_IGNORED)
delay = custom.get(CONF_DELAY)
_LOGGER.debug('Entity: %s - %s, Options - Ignore: %s, Delay: %s',
_LOGGER.debug("Entity: %s - %s, Options - Ignore: %s, Delay: %s",
data.name, sensor_name, ignore, delay)
if not ignore:
entities.append(HikvisionBinarySensor(
@@ -126,8 +126,8 @@ class HikvisionData(object):
self._password = password
# Establish camera
self.camdata = 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.camdata.get_name
@@ -251,7 +251,7 @@ class HikvisionBinarySensor(BinarySensorDevice):
# 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

@@ -14,22 +14,22 @@ _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_devices, discovery_info=None):
"""Setup the Homematic binary sensor platform."""
"""Set up the Homematic binary sensor platform."""
if discovery_info is None:
return
@@ -56,8 +56,8 @@ class HMBinarySensor(HMDevice, BinarySensorDevice):
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

@@ -67,7 +67,7 @@ class InsteonPLMBinarySensorDevice(BinarySensorDevice):
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)
_LOGGER.info("Sensor state for %s is %s", self._address, sensorstate)
return bool(sensorstate)
@property
@@ -83,5 +83,5 @@ class InsteonPLMBinarySensorDevice(BinarySensorDevice):
@callback
def async_binarysensor_update(self, message):
"""Receive notification from transport that new data exists."""
_LOGGER.info('Received update calback from PLM for %s', self._address)
_LOGGER.info("Received update calback from PLM for %s", self._address)
self._hass.async_add_job(self.async_update_ha_state())

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

@@ -4,7 +4,6 @@ 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
@@ -15,27 +14,24 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Iterate through all MAX! Devices and add window shutters to HASS."""
"""Iterate through all MAX! Devices and add window shutters."""
cube = hass.data[MAXCUBE_HANDLE].cube
# List of devices
devices = []
for device in cube.devices:
# Create device name by concatenating room name + device name
name = "%s %s" % (cube.room_by_id(device.room_id).name, device.name)
name = "{} {}".format(
cube.room_by_id(device.room_id).name, device.name)
# Only add Window Shutters
if cube.is_windowshutter(device):
# add device to HASS
devices.append(MaxCubeShutter(hass, name, device.rf_address))
if len(devices) > 0:
if devices:
add_devices(devices)
class MaxCubeShutter(BinarySensorDevice):
"""MAX! Cube BinarySensor device."""
"""Representation of a MAX! Cube Binary Sensor device."""
def __init__(self, hass, name, rf_address):
"""Initialize MAX! Cube BinarySensorDevice."""
@@ -47,7 +43,7 @@ class MaxCubeShutter(BinarySensorDevice):
@property
def should_poll(self):
"""Polling is required."""
"""Return the polling state."""
return True
@property
@@ -68,9 +64,5 @@ class MaxCubeShutter(BinarySensorDevice):
def update(self):
"""Get latest data from MAX! Cube."""
self._cubehandle.update()
# Get the device we want to update
device = self._cubehandle.cube.device_by_rf(self._rf_address)
# Update our internal state
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

@@ -79,7 +79,7 @@ class MqttBinarySensor(BinarySensorDevice):
"""
@callback
def message_received(topic, payload, qos):
"""A new MQTT message has been received."""
"""Handle a new received MQTT message."""
if self._template is not None:
payload = self._template.async_render_with_possible_json_value(
payload)
@@ -95,7 +95,7 @@ class MqttBinarySensor(BinarySensorDevice):
@property
def should_poll(self):
"""No polling needed."""
"""Return the polling state."""
return False
@property

View File

@@ -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:

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
@@ -156,9 +152,9 @@ class NetatmoBinarySensor(BinarySensorDevice):
@property
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
if self._cameratype == "NACamera":
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

@@ -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('.')]

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,18 +79,10 @@ 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 device_class(self):
@@ -106,10 +92,9 @@ class OctoPrintBinarySensor(BinarySensorDevice):
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

@@ -35,6 +35,9 @@ 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,
@@ -102,7 +105,7 @@ class PingData(object):
if sys.platform == 'win32':
self._ping_cmd = [
'ping', '-n', str(self._count), '-w 1000', self._ip_address]
'ping', '-n', str(self._count), '-w', '1000', self._ip_address]
else:
self._ping_cmd = [
'ping', '-n', '-q', '-c', str(self._count), '-W1',
@@ -114,13 +117,23 @@ class PingData(object):
self._ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
try:
out = pinger.communicate()
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}
_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

View File

@@ -44,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)
@@ -114,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

@@ -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

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

@@ -41,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():
@@ -57,15 +57,11 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
sensors.append(
BinarySensorTemplate(
hass,
device,
friendly_name,
device_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
async_add_devices(sensors, True)
@@ -79,8 +75,8 @@ class BinarySensorTemplate(BinarySensorDevice):
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._device_class = device_class
self._template = value_template
@@ -96,7 +92,7 @@ class BinarySensorTemplate(BinarySensorDevice):
@callback
def template_bsensor_state_listener(entity, old_state, new_state):
"""Called when the target device changes state."""
"""Handle the target device state changes."""
self.hass.async_add_job(self.async_update_ha_state(True))
@callback
@@ -139,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

@@ -77,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

View File

@@ -6,22 +6,18 @@ 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,
BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA,
DEVICE_CLASSES_SCHEMA)
from homeassistant.const import (
ATTR_FRIENDLY_NAME,
ATTR_ENTITY_ID,
CONF_SENSOR_CLASS,
CONF_DEVICE_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
@@ -47,7 +43,7 @@ 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():
@@ -60,13 +56,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
sensors.append(
SensorTrend(
hass,
device,
friendly_name,
entity_id,
attribute,
device_class,
invert)
hass, device, friendly_name, entity_id, attribute,
device_class, invert)
)
if not sensors:
_LOGGER.error("No sensors added")
@@ -82,8 +73,8 @@ class SensorTrend(BinarySensorDevice):
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
@@ -95,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))

View File

@@ -3,7 +3,6 @@ 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
@@ -14,7 +13,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Volvo sensors."""
"""Set up the Volvo sensors."""
if discovery_info is None:
return
add_devices([VolvoSensor(hass, *discovery_info)])
@@ -28,7 +27,7 @@ class VolvoSensor(VolvoEntity, BinarySensorDevice):
"""Return True if the binary sensor is on."""
val = getattr(self.vehicle, self._attribute)
if self._attribute == 'bulb_failures':
return len(val) > 0
return bool(val)
elif self._attribute in ['doors', 'windows']:
return any([val[key] for key in val if 'Open' in key])
else:

View File

@@ -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."""
@@ -41,10 +41,8 @@ class WemoBinarySensor(BinarySensorDevice):
wemo.SUBSCRIPTION_REGISTRY.on(self.wemo, None, self._update_callback)
def _update_callback(self, _device, _type, _params):
"""Called by the Wemo device callback to update state."""
_LOGGER.info(
'Subscription update for %s',
_device)
"""Handle state changes."""
_LOGGER.info("Subscription update for %s", _device)
updated = self.wemo.subscription_update(_type, _params)
self._update(force_update=(not updated))
@@ -60,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):
@@ -69,7 +67,7 @@ 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):
@@ -80,5 +78,5 @@ class WemoBinarySensor(BinarySensorDevice):
try:
self._state = self.wemo.get_state(force_update)
except AttributeError as err:
_LOGGER.warning('Could not update status for %s (%s)',
self.name, 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):

View File

@@ -11,10 +11,9 @@ import datetime
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
STATE_ON, STATE_OFF, STATE_UNKNOWN, CONF_NAME, WEEKDAYS)
from homeassistant.const import CONF_NAME, WEEKDAYS
import homeassistant.util.dt as dt_util
from homeassistant.helpers.entity import Entity
from homeassistant.components.binary_sensor import BinarySensorDevice
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
@@ -66,15 +65,20 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
obj_holidays = getattr(holidays, country)(years=year)
if province:
if province not in obj_holidays.PROVINCES and \
province not in obj_holidays.STATES:
# '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
else:
year = datetime.datetime.now().year
obj_holidays = getattr(holidays, country)(prov=province,
years=year)
_LOGGER.debug("Found the following holidays for your configuration:")
for date, name in sorted(obj_holidays.items()):
@@ -92,7 +96,7 @@ def day_to_string(day):
return None
class IsWorkdaySensor(Entity):
class IsWorkdaySensor(BinarySensorDevice):
"""Implementation of a Workday sensor."""
def __init__(self, obj_holidays, workdays, excludes, name):
@@ -101,7 +105,7 @@ class IsWorkdaySensor(Entity):
self._obj_holidays = obj_holidays
self._workdays = workdays
self._excludes = excludes
self._state = STATE_UNKNOWN
self._state = None
@property
def name(self):
@@ -109,7 +113,7 @@ class IsWorkdaySensor(Entity):
return self._name
@property
def state(self):
def is_on(self):
"""Return the state of the device."""
return self._state
@@ -135,14 +139,14 @@ class IsWorkdaySensor(Entity):
def async_update(self):
"""Get date and look whether it is a holiday."""
# Default is no workday
self._state = STATE_OFF
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 = STATE_ON
self._state = True
if self.is_exclude(day_of_week, dt_util.now()):
self._state = STATE_OFF
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,7 +23,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the ZigBee binary sensor platform."""
"""Set up the ZigBee binary sensor platform."""
add_devices(
[ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))], True)

View File

@@ -20,7 +20,7 @@ DEPENDENCIES = []
def get_device(values, **kwargs):
"""Create zwave entity device."""
"""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
@@ -45,12 +45,12 @@ class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity):
self._state = self.values.primary.data
def update_properties(self):
"""Callback on data changes for node values."""
"""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 true if the binary sensor is on."""
return self._state
@property
@@ -69,7 +69,7 @@ class ZWaveTriggerSensor(ZWaveBinarySensor):
self.invalidate_after = None
def update_properties(self):
"""Called when a value for this entity's node has changed."""
"""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:
@@ -83,7 +83,7 @@ class ZWaveTriggerSensor(ZWaveBinarySensor):
@property
def is_on(self):
"""Return True if movement has happened within the rearm time."""
"""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

@@ -35,7 +35,7 @@ CONFIG_SCHEMA = vol.Schema({
# pylint: disable=unused-argument
def setup(hass, config):
"""Setup BloomSky component."""
"""Set up the BloomSky component."""
api_key = config[DOMAIN][CONF_API_KEY]
global BLOOMSKY
@@ -67,9 +67,8 @@ class BloomSky(object):
def refresh_devices(self):
"""Use the API to retrieve a list of devices."""
_LOGGER.debug("Fetching BloomSky update")
response = requests.get(self.API_URL,
headers={"Authorization": self._api_key},
timeout=10)
response = requests.get(
self.API_URL, headers={"Authorization": self._api_key}, timeout=10)
if response.status_code == 401:
raise RuntimeError("Invalid API_KEY")
elif response.status_code != 200:

View File

@@ -7,12 +7,10 @@ https://home-assistant.io/components/calendar/
import asyncio
import logging
from datetime import timedelta
import re
from homeassistant.components.google import (CONF_OFFSET,
CONF_DEVICE_ID,
CONF_NAME)
from homeassistant.components.google import (
CONF_OFFSET, CONF_DEVICE_ID, CONF_NAME)
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.helpers.config_validation import time_period_str
from homeassistant.helpers.entity import Entity, generate_entity_id
@@ -22,16 +20,18 @@ from homeassistant.util import dt
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=60)
DOMAIN = 'calendar'
ENTITY_ID_FORMAT = DOMAIN + '.{}'
SCAN_INTERVAL = timedelta(seconds=60)
@asyncio.coroutine
def async_setup(hass, config):
"""Track states and offer events for calendars."""
component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL, DOMAIN)
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DOMAIN)
yield from component.async_setup(config)
return True
@@ -55,9 +55,8 @@ class CalendarEventDevice(Entity):
self._name = data.get(CONF_NAME)
self.dev_id = data.get(CONF_DEVICE_ID)
self._offset = data.get(CONF_OFFSET, DEFAULT_CONF_OFFSET)
self.entity_id = generate_entity_id(ENTITY_ID_FORMAT,
self.dev_id,
hass=hass)
self.entity_id = generate_entity_id(
ENTITY_ID_FORMAT, self.dev_id, hass=hass)
self._cal_data = {
'all_day': False,
@@ -87,7 +86,7 @@ class CalendarEventDevice(Entity):
@property
def device_state_attributes(self):
"""State Attributes for HA."""
"""Return the device state attributes."""
start = self._cal_data.get('start', None)
end = self._cal_data.get('end', None)
start = start.strftime(DATE_STR_FORMAT) if start is not None else None

View File

@@ -10,7 +10,7 @@ from homeassistant.components.google import CONF_DEVICE_ID, CONF_NAME
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo binary sensor platform."""
"""Set up the Demo Calendar platform."""
calendar_data_future = DemoGoogleCalendarDataFuture()
calendar_data_current = DemoGoogleCalendarDataCurrent()
add_devices([
@@ -27,8 +27,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class DemoGoogleCalendarData(object):
"""Setup base class for data."""
"""Representation of a Demo Calendar element."""
# pylint: disable=no-self-use
def update(self):
"""Return true so entity knows we have new data."""
@@ -36,7 +36,7 @@ class DemoGoogleCalendarData(object):
class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
"""Setup future data event."""
"""Representation of a Demo Calendar for a future event."""
def __init__(self):
"""Set the event to a future event."""
@@ -55,7 +55,7 @@ class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData):
"""Create a current event we're in the middle of."""
"""Representation of a Demo Calendar for a current event."""
def __init__(self):
"""Set the event data."""
@@ -74,9 +74,9 @@ class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData):
class DemoGoogleCalendar(CalendarEventDevice):
"""A Demo binary sensor."""
"""Representation of a Demo Calendar element."""
def __init__(self, hass, calendar_data, data):
"""The same as a google calendar but without the api calls."""
"""Initialize Google Calendar but without the API calls."""
self.data = calendar_data
super().__init__(hass, data)

View File

@@ -9,25 +9,24 @@ import logging
from datetime import timedelta
from homeassistant.components.calendar import CalendarEventDevice
from homeassistant.components.google import (CONF_CAL_ID, CONF_ENTITIES,
CONF_TRACK, TOKEN_FILE,
GoogleCalendarService)
from homeassistant.components.google import (
CONF_CAL_ID, CONF_ENTITIES, CONF_TRACK, TOKEN_FILE,
GoogleCalendarService)
from homeassistant.util import Throttle, dt
_LOGGER = logging.getLogger(__name__)
DEFAULT_GOOGLE_SEARCH_PARAMS = {
'orderBy': 'startTime',
'maxResults': 1,
'singleEvents': True,
}
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, disc_info=None):
"""Setup the calendar platform for event devices."""
"""Set up the calendar platform for event devices."""
if disc_info is None:
return
@@ -55,7 +54,7 @@ class GoogleCalendarData(object):
"""Class to utilize calendar service object to get next event."""
def __init__(self, calendar_service, calendar_id, search=None):
"""Setup how we are going to search the google calendar."""
"""Set up how we are going to search the google calendar."""
self.calendar_service = calendar_service
self.calendar_id = calendar_id
self.search = search

View File

@@ -76,7 +76,7 @@ def async_get_image(hass, entity_id, timeout=10):
@asyncio.coroutine
def async_setup(hass, config):
"""Setup the camera component."""
"""Set up the camera component."""
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
hass.http.register_view(CameraImageView(component.entities))
@@ -121,12 +121,12 @@ class Camera(Entity):
@property
def brand(self):
"""Camera brand."""
"""Return the camera brand."""
return None
@property
def model(self):
"""Camera model."""
"""Return the camera model."""
return None
def camera_image(self):
@@ -191,7 +191,7 @@ class Camera(Entity):
@property
def state(self):
"""Camera state."""
"""Return the camera state."""
if self.is_recording:
return STATE_RECORDING
elif self.is_streaming:
@@ -201,7 +201,7 @@ class Camera(Entity):
@property
def state_attributes(self):
"""Camera state attributes."""
"""Return the camera state attributes."""
attr = {
'access_token': self.access_tokens[-1],
}
@@ -233,7 +233,7 @@ class CameraView(HomeAssistantView):
@asyncio.coroutine
def get(self, request, entity_id):
"""Start a get request."""
"""Start a GET request."""
camera = self.entities.get(entity_id)
if camera is None:
@@ -251,15 +251,15 @@ class CameraView(HomeAssistantView):
@asyncio.coroutine
def handle(self, request, camera):
"""Hanlde the camera request."""
"""Handle the camera request."""
raise NotImplementedError()
class CameraImageView(CameraView):
"""Camera view to serve an image."""
url = "/api/camera_proxy/{entity_id}"
name = "api:camera:image"
url = '/api/camera_proxy/{entity_id}'
name = 'api:camera:image'
@asyncio.coroutine
def handle(self, request, camera):
@@ -277,8 +277,8 @@ class CameraImageView(CameraView):
class CameraMjpegStream(CameraView):
"""Camera View to serve an MJPEG stream."""
url = "/api/camera_proxy_stream/{entity_id}"
name = "api:camera:stream"
url = '/api/camera_proxy_stream/{entity_id}'
name = 'api:camera:stream'
@asyncio.coroutine
def handle(self, request, camera):

View File

@@ -21,7 +21,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup a Blink Camera."""
"""Set up a Blink Camera."""
if discovery_info is None:
return
@@ -49,19 +49,19 @@ class BlinkCamera(Camera):
@property
def name(self):
"""A camera name."""
"""Return the camera name."""
return self._name
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def request_image(self):
"""An image request from Blink servers."""
"""Request a new image from Blink servers."""
_LOGGER.info("Requesting new image from blink servers")
image_url = self.check_for_motion()
header = self.data.cameras[self._name].header
self.response = requests.get(image_url, headers=header, stream=True)
def check_for_motion(self):
"""A method to check if motion has been detected since last update."""
"""Check if motion has been detected since last update."""
self.data.refresh()
notifs = self.data.cameras[self._name].notifications
if notifs > self.notifications:

View File

@@ -16,7 +16,7 @@ DEPENDENCIES = ['bloomsky']
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup access to BloomSky cameras."""
"""Set up access to BloomSky cameras."""
bloomsky = get_component('bloomsky')
for device in bloomsky.BLOOMSKY.devices.values():
add_devices([BloomSkyCamera(bloomsky.BLOOMSKY, device)])
@@ -26,14 +26,14 @@ class BloomSkyCamera(Camera):
"""Representation of the images published from the BloomSky's camera."""
def __init__(self, bs, device):
"""Setup for access to the BloomSky camera images."""
"""Initialize access to the BloomSky camera images."""
super(BloomSkyCamera, self).__init__()
self._name = device['DeviceName']
self._id = device['DeviceID']
self._bloomsky = bs
self._url = ""
self._last_url = ""
# _last_image will store images as they are downloaded so that the
# last_image will store images as they are downloaded so that the
# frequent updates in home-assistant don't keep poking the server
# to download the same image over and over.
self._last_image = ""

View File

@@ -11,7 +11,7 @@ from homeassistant.components.camera import Camera
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo camera platform."""
"""Set up the Demo camera platform."""
add_devices([
DemoCamera('Demo camera')
])
@@ -29,8 +29,8 @@ class DemoCamera(Camera):
"""Return a faked still image response."""
now = dt_util.utcnow()
image_path = os.path.join(os.path.dirname(__file__),
'demo_{}.jpg'.format(now.second % 4))
image_path = os.path.join(
os.path.dirname(__file__), 'demo_{}.jpg'.format(now.second % 4))
with open(image_path, 'rb') as file:
return file.read()

View File

@@ -16,10 +16,10 @@ from homeassistant.components.ffmpeg import (
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.aiohttp_client import (
async_aiohttp_proxy_stream)
DEPENDENCIES = ['ffmpeg']
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['ffmpeg']
DEFAULT_NAME = 'FFmpeg'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@@ -31,7 +31,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a FFmpeg Camera."""
"""Set up a FFmpeg camera."""
if not hass.data[DATA_FFMPEG].async_run_test(config.get(CONF_INPUT)):
return
async_add_devices([FFmpegCamera(hass, config)])

View File

@@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup a Foscam IP Camera."""
"""Set up a Foscam IP Camera."""
add_devices([FoscamCamera(config)])
@@ -60,7 +60,7 @@ class FoscamCamera(Camera):
)
self._name = device_info.get(CONF_NAME)
_LOGGER.info('Using the following URL for %s: %s',
_LOGGER.info("Using the following URL for %s: %s",
self._name, uri_template.format('***', '***'))
def camera_image(self):

View File

@@ -43,7 +43,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
# pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a generic IP Camera."""
"""Set up a generic IP Camera."""
async_add_devices([GenericCamera(hass, config)])
@@ -85,8 +85,8 @@ class GenericCamera(Camera):
try:
url = self._still_image_url.async_render()
except TemplateError as err:
_LOGGER.error('Error parsing template %s: %s',
self._still_image_url, err)
_LOGGER.error(
"Error parsing template %s: %s", self._still_image_url, err)
return self._last_image
if url == self._last_url and self._limit_refetch:
@@ -100,7 +100,7 @@ class GenericCamera(Camera):
response = requests.get(url, timeout=10, auth=self._auth)
return response.content
except requests.exceptions.RequestException as error:
_LOGGER.error('Error getting camera image: %s', error)
_LOGGER.error("Error getting camera image: %s", error)
return self._last_image
self._last_image = yield from self.hass.loop.run_in_executor(
@@ -114,10 +114,10 @@ class GenericCamera(Camera):
url, auth=self._auth)
self._last_image = yield from response.read()
except asyncio.TimeoutError:
_LOGGER.error('Timeout getting camera image')
_LOGGER.error("Timeout getting camera image")
return self._last_image
except aiohttp.ClientError as err:
_LOGGER.error('Error getting new camera image: %s', err)
_LOGGER.error("Error getting new camera image: %s", err)
return self._last_image
self._last_url = url

View File

@@ -26,7 +26,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera."""
"""Set up the Camera that works with local files."""
file_path = config[CONF_FILE_PATH]
# check filepath given is readable
@@ -38,7 +38,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class LocalFile(Camera):
"""Local camera."""
"""Representation of a local file camera."""
def __init__(self, name, file_path):
"""Initialize Local File Camera component."""

View File

@@ -44,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
# pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a MJPEG IP Camera."""
"""Set up a MJPEG IP Camera."""
if discovery_info:
config = PLATFORM_SCHEMA(discovery_info)
async_add_devices([MjpegCamera(hass, config)])
@@ -102,10 +102,10 @@ class MjpegCamera(Camera):
return image
except asyncio.TimeoutError:
_LOGGER.error('Timeout getting camera image')
_LOGGER.error("Timeout getting camera image")
except aiohttp.ClientError as err:
_LOGGER.error('Error getting new camera image: %s', err)
_LOGGER.error("Error getting new camera image: %s", err)
def camera_image(self):
"""Return a still image response from the camera."""

View File

@@ -32,17 +32,17 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the Camera."""
"""Set up the MQTT Camera."""
topic = config[CONF_TOPIC]
async_add_devices([MqttCamera(config[CONF_NAME], topic)])
class MqttCamera(Camera):
"""MQTT camera."""
"""representation of a MQTT camera."""
def __init__(self, name, topic):
"""Initialize Local File Camera component."""
"""Initialize the MQTT Camera."""
super().__init__()
self._name = name
@@ -61,13 +61,13 @@ class MqttCamera(Camera):
return self._name
def async_added_to_hass(self):
"""Subscribe mqtt events.
"""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."""
"""Handle new MQTT messages."""
self._last_image = payload
return mqtt.async_subscribe(

View File

@@ -1,5 +1,5 @@
"""
Camera that loads a picture from a local file.
Camera that loads a picture from Neato.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.neato/
@@ -18,12 +18,12 @@ DEPENDENCIES = ['neato']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera."""
"""Set up the Neato Camera."""
dev = []
for robot in hass.data[NEATO_ROBOTS]:
if 'maps' in robot.traits:
dev.append(NeatoCleaningMap(hass, robot))
_LOGGER.debug('Adding robots for cleaning maps %s', dev)
_LOGGER.debug("Adding robots for cleaning maps %s", dev)
add_devices(dev, True)
@@ -34,7 +34,7 @@ class NeatoCleaningMap(Camera):
"""Initialize Neato cleaning map."""
super().__init__()
self.robot = robot
self._robot_name = self.robot.name + ' Cleaning Map'
self._robot_name = '{} {}'.format(self.robot.name, 'Cleaning Map')
self._robot_serial = self.robot.serial
self.neato = hass.data[NEATO_LOGIN]
self._image_url = None
@@ -53,7 +53,7 @@ class NeatoCleaningMap(Camera):
map_data = self.hass.data[NEATO_MAP_DATA]
image_url = map_data[self._robot_serial]['maps'][0]['url']
if image_url == self._image_url:
_LOGGER.debug('The map image_url is the same as old')
_LOGGER.debug("The map image_url is the same as old")
return
image = self.neato.download_map(image_url)
self._image = image.read()

View File

@@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup access to Netatmo cameras."""
"""Set up access to Netatmo cameras."""
netatmo = get_component('netatmo')
home = config.get(CONF_HOME)
verify_ssl = config.get(CONF_VERIFY_SSL, True)
@@ -55,7 +55,7 @@ class NetatmoCamera(Camera):
"""Representation of the images published from a Netatmo camera."""
def __init__(self, data, camera_name, home, camera_type, verify_ssl):
"""Setup for access to the Netatmo camera images."""
"""Set up for access to the Netatmo camera images."""
super(NetatmoCamera, self).__init__()
self._data = data
self._camera_name = camera_name
@@ -64,10 +64,10 @@ class NetatmoCamera(Camera):
self._name = home + ' / ' + camera_name
else:
self._name = camera_name
camera_id = data.camera_data.cameraByName(camera=camera_name,
home=home)['id']
self._unique_id = "Welcome_camera {0} - {1}".format(self._name,
camera_id)
camera_id = data.camera_data.cameraByName(
camera=camera_name, home=home)['id']
self._unique_id = "Welcome_camera {0} - {1}".format(
self._name, camera_id)
self._vpnurl, self._localurl = self._data.camera_data.cameraUrls(
camera=camera_name
)
@@ -83,13 +83,13 @@ class NetatmoCamera(Camera):
response = requests.get('{0}/live/snapshot_720.jpg'.format(
self._vpnurl), timeout=10, verify=self._verify_ssl)
else:
_LOGGER.error('Welcome VPN url is None')
_LOGGER.error("Welcome VPN URL is None")
self._data.update()
(self._vpnurl, self._localurl) = \
self._data.camera_data.cameraUrls(camera=self._camera_name)
return None
except requests.exceptions.RequestException as error:
_LOGGER.error('Welcome url changed: %s', error)
_LOGGER.error("Welcome URL changed: %s", error)
self._data.update()
(self._vpnurl, self._localurl) = \
self._data.camera_data.cameraUrls(camera=self._camera_name)
@@ -103,12 +103,12 @@ class NetatmoCamera(Camera):
@property
def brand(self):
"""Camera brand."""
"""Return the camera brand."""
return "Netatmo"
@property
def model(self):
"""Camera model."""
"""Return the camera model."""
if self._cameratype == "NOC":
return "Presence"
elif self._cameratype == "NACamera":

View File

@@ -62,7 +62,7 @@ def kill_raspistill(*args):
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Raspberry Camera."""
"""Set up the Raspberry Camera."""
if shutil.which("raspistill") is None:
_LOGGER.error("'raspistill' was not found")
return False

View File

@@ -59,7 +59,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a Synology IP Camera."""
"""Set up a Synology IP Camera."""
verify_ssl = config.get(CONF_VERIFY_SSL)
timeout = config.get(CONF_TIMEOUT)
websession_init = async_get_clientsession(hass, verify_ssl)
@@ -140,16 +140,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
snapshot_path = camera['snapshot_path']
device = SynologyCamera(
hass,
websession,
config,
camera_id,
camera['name'],
snapshot_path,
streaming_path,
camera_path,
auth_path,
timeout
hass, websession, config, camera_id, camera['name'],
snapshot_path, streaming_path, camera_path, auth_path, timeout
)
devices.append(device)

View File

@@ -41,13 +41,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
try:
cameras = nvrconn.index()
except nvr.NotAuthorized:
_LOGGER.error('Authorization failure while connecting to NVR')
_LOGGER.error("Authorization failure while connecting to NVR")
return False
except nvr.NvrError:
_LOGGER.error('NVR refuses to talk to me')
_LOGGER.error("NVR refuses to talk to me")
return False
except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NVR: %s', str(ex))
_LOGGER.error("Unable to connect to NVR: %s", str(ex))
return False
identifier = nvrconn.server_version >= (3, 2, 0) and 'id' or 'uuid'
@@ -113,7 +113,7 @@ class UnifiVideoCamera(Camera):
store = uvc_store.get_info_store()
password = store.get_camera_password(self._uuid)
if password is None:
_LOGGER.debug('Logging into camera %(name)s with default password',
_LOGGER.debug("Logging into camera %(name)s with default password",
dict(name=self._name))
password = 'ubnt'
@@ -125,11 +125,10 @@ class UnifiVideoCamera(Camera):
camera = None
for addr in addrs:
try:
camera = client_cls(addr,
caminfo['username'],
password)
camera = client_cls(
addr, caminfo['username'], password)
camera.login()
_LOGGER.debug('Logged into UVC camera %(name)s via %(addr)s',
_LOGGER.debug("Logged into UVC camera %(name)s via %(addr)s",
dict(name=self._name, addr=addr))
self._connect_addr = addr
break
@@ -140,7 +139,7 @@ class UnifiVideoCamera(Camera):
except uvc_camera.CameraAuthError:
pass
if not self._connect_addr:
_LOGGER.error('Unable to login to camera')
_LOGGER.error("Unable to login to camera")
return None
self._camera = camera
@@ -157,14 +156,14 @@ class UnifiVideoCamera(Camera):
try:
return self._camera.get_snapshot()
except uvc_camera.CameraConnectError:
_LOGGER.error('Unable to contact camera')
_LOGGER.error("Unable to contact camera")
except uvc_camera.CameraAuthError:
if retry:
self._login()
return _get_image(retry=False)
else:
_LOGGER.error('Unable to log into camera, unable '
'to get snapshot')
_LOGGER.error(
"Unable to log into camera, unable to get snapshot")
raise
return _get_image()

View File

@@ -17,7 +17,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera."""
"""Set up the Verisure Camera."""
if not int(hub.config.get(CONF_SMARTCAM, 1)):
return False
directory_path = hass.config.config_dir
@@ -33,7 +33,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class VerisureSmartcam(Camera):
"""Local camera."""
"""Representation of a Verisure camera."""
def __init__(self, hass, device_id, directory_path):
"""Initialize Verisure File Camera component."""
@@ -50,9 +50,9 @@ class VerisureSmartcam(Camera):
"""Return image response."""
self.check_imagelist()
if not self._image:
_LOGGER.debug('No image to display')
_LOGGER.debug("No image to display")
return
_LOGGER.debug('Trying to open %s', self._image)
_LOGGER.debug("Trying to open %s", self._image)
with open(self._image, 'rb') as file:
return file.read()
@@ -64,35 +64,30 @@ class VerisureSmartcam(Camera):
return
images = hub.smartcam_dict[self._device_id]
new_image_id = images[0]
_LOGGER.debug('self._device_id=%s, self._images=%s, '
'self._new_image_id=%s', self._device_id,
_LOGGER.debug("self._device_id=%s, self._images=%s, "
"self._new_image_id=%s", self._device_id,
images, new_image_id)
if (new_image_id == '-1' or
self._image_id == new_image_id):
_LOGGER.debug('The image is the same, or loading image_id')
_LOGGER.debug("The image is the same, or loading image_id")
return
_LOGGER.debug('Download new image %s', new_image_id)
hub.my_pages.smartcam.download_image(self._device_id,
new_image_id,
self._directory_path)
_LOGGER.debug('Old image_id=%s', self._image_id)
_LOGGER.debug("Download new image %s", new_image_id)
hub.my_pages.smartcam.download_image(
self._device_id, new_image_id, self._directory_path)
_LOGGER.debug("Old image_id=%s", self._image_id)
self.delete_image(self)
self._image_id = new_image_id
self._image = os.path.join(self._directory_path,
'{}{}'.format(
self._image_id,
'.jpg'))
self._image = os.path.join(
self._directory_path, '{}{}'.format(self._image_id, '.jpg'))
def delete_image(self, event):
"""Delete an old image."""
remove_image = os.path.join(self._directory_path,
'{}{}'.format(
self._image_id,
'.jpg'))
remove_image = os.path.join(
self._directory_path, '{}{}'.format(self._image_id, '.jpg'))
try:
os.remove(remove_image)
_LOGGER.debug('Deleting old image %s', remove_image)
_LOGGER.debug("Deleting old image %s", remove_image)
except OSError as error:
if error.errno != errno.ENOENT:
raise

View File

@@ -51,21 +51,21 @@ def _get_image_url(hass, monitor, mode):
@asyncio.coroutine
# pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup ZoneMinder cameras."""
"""Set up the ZoneMinder cameras."""
cameras = []
monitors = zoneminder.get_state('api/monitors.json')
if not monitors:
_LOGGER.warning('Could not fetch monitors from ZoneMinder')
_LOGGER.warning("Could not fetch monitors from ZoneMinder")
return
for i in monitors['monitors']:
monitor = i['Monitor']
if monitor['Function'] == 'None':
_LOGGER.info('Skipping camera %s', monitor['Id'])
_LOGGER.info("Skipping camera %s", monitor['Id'])
continue
_LOGGER.info('Initializing camera %s', monitor['Id'])
_LOGGER.info("Initializing camera %s", monitor['Id'])
device_info = {
CONF_NAME: monitor['Name'],
@@ -75,7 +75,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
cameras.append(ZoneMinderCamera(hass, device_info, monitor))
if not cameras:
_LOGGER.warning('No active cameras found')
_LOGGER.warning("No active cameras found")
return
async_add_devices(cameras)
@@ -97,18 +97,18 @@ class ZoneMinderCamera(MjpegCamera):
def update(self):
"""Update our recording state from the ZM API."""
_LOGGER.debug('Updating camera state for monitor %i', self._monitor_id)
_LOGGER.debug("Updating camera state for monitor %i", self._monitor_id)
status_response = zoneminder.get_state(
'api/monitors/alarm/id:%i/command:status.json' % self._monitor_id
)
if not status_response:
_LOGGER.warning('Could not get status for monitor %i',
_LOGGER.warning("Could not get status for monitor %i",
self._monitor_id)
return
if status_response['success'] is False:
_LOGGER.warning('Alarm status API call failed for monitor %i',
if not status_response.get("success", False):
_LOGGER.warning("Alarm status API call failed for monitor %i",
self._monitor_id)
return

View File

@@ -23,45 +23,46 @@ from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
TEMP_CELSIUS)
DOMAIN = "climate"
DOMAIN = 'climate'
ENTITY_ID_FORMAT = DOMAIN + ".{}"
ENTITY_ID_FORMAT = DOMAIN + '.{}'
SCAN_INTERVAL = timedelta(seconds=60)
SERVICE_SET_AWAY_MODE = "set_away_mode"
SERVICE_SET_AUX_HEAT = "set_aux_heat"
SERVICE_SET_TEMPERATURE = "set_temperature"
SERVICE_SET_FAN_MODE = "set_fan_mode"
SERVICE_SET_HOLD_MODE = "set_hold_mode"
SERVICE_SET_OPERATION_MODE = "set_operation_mode"
SERVICE_SET_SWING_MODE = "set_swing_mode"
SERVICE_SET_HUMIDITY = "set_humidity"
SERVICE_SET_AWAY_MODE = 'set_away_mode'
SERVICE_SET_AUX_HEAT = 'set_aux_heat'
SERVICE_SET_TEMPERATURE = 'set_temperature'
SERVICE_SET_FAN_MODE = 'set_fan_mode'
SERVICE_SET_HOLD_MODE = 'set_hold_mode'
SERVICE_SET_OPERATION_MODE = 'set_operation_mode'
SERVICE_SET_SWING_MODE = 'set_swing_mode'
SERVICE_SET_HUMIDITY = 'set_humidity'
STATE_HEAT = "heat"
STATE_COOL = "cool"
STATE_IDLE = "idle"
STATE_AUTO = "auto"
STATE_DRY = "dry"
STATE_FAN_ONLY = "fan_only"
STATE_HEAT = 'heat'
STATE_COOL = 'cool'
STATE_IDLE = 'idle'
STATE_AUTO = 'auto'
STATE_DRY = 'dry'
STATE_FAN_ONLY = 'fan_only'
ATTR_CURRENT_TEMPERATURE = "current_temperature"
ATTR_MAX_TEMP = "max_temp"
ATTR_MIN_TEMP = "min_temp"
ATTR_TARGET_TEMP_HIGH = "target_temp_high"
ATTR_TARGET_TEMP_LOW = "target_temp_low"
ATTR_AWAY_MODE = "away_mode"
ATTR_AUX_HEAT = "aux_heat"
ATTR_FAN_MODE = "fan_mode"
ATTR_FAN_LIST = "fan_list"
ATTR_CURRENT_HUMIDITY = "current_humidity"
ATTR_HUMIDITY = "humidity"
ATTR_MAX_HUMIDITY = "max_humidity"
ATTR_MIN_HUMIDITY = "min_humidity"
ATTR_HOLD_MODE = "hold_mode"
ATTR_OPERATION_MODE = "operation_mode"
ATTR_OPERATION_LIST = "operation_list"
ATTR_SWING_MODE = "swing_mode"
ATTR_SWING_LIST = "swing_list"
ATTR_CURRENT_TEMPERATURE = 'current_temperature'
ATTR_MAX_TEMP = 'max_temp'
ATTR_MIN_TEMP = 'min_temp'
ATTR_TARGET_TEMP_HIGH = 'target_temp_high'
ATTR_TARGET_TEMP_LOW = 'target_temp_low'
ATTR_TARGET_TEMP_STEP = 'target_temp_step'
ATTR_AWAY_MODE = 'away_mode'
ATTR_AUX_HEAT = 'aux_heat'
ATTR_FAN_MODE = 'fan_mode'
ATTR_FAN_LIST = 'fan_list'
ATTR_CURRENT_HUMIDITY = 'current_humidity'
ATTR_HUMIDITY = 'humidity'
ATTR_MAX_HUMIDITY = 'max_humidity'
ATTR_MIN_HUMIDITY = 'min_humidity'
ATTR_HOLD_MODE = 'hold_mode'
ATTR_OPERATION_MODE = 'operation_mode'
ATTR_OPERATION_LIST = 'operation_list'
ATTR_SWING_MODE = 'swing_mode'
ATTR_SWING_LIST = 'swing_list'
# The degree of precision for each platform
PRECISION_WHOLE = 1
@@ -208,7 +209,7 @@ def set_swing_mode(hass, swing_mode, entity_id=None):
@asyncio.coroutine
def async_setup(hass, config):
"""Setup climate devices."""
"""Set up climate devices."""
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
yield from component.async_setup(config)
@@ -273,7 +274,7 @@ def async_setup(hass, config):
@asyncio.coroutine
def async_aux_heat_set_service(service):
"""Set auxillary heater on target climate devices."""
"""Set auxiliary heater on target climate devices."""
target_climate = component.async_extract_from_service(service)
aux_heat = service.data.get(ATTR_AUX_HEAT)
@@ -419,6 +420,10 @@ class ClimateDevice(Entity):
ATTR_TEMPERATURE:
self._convert_for_display(self.target_temperature),
}
if self.target_temperature_step is not None:
data[ATTR_TARGET_TEMP_STEP] = self.target_temperature_step
target_temp_high = self.target_temperature_high
if target_temp_high is not None:
data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display(
@@ -467,12 +472,12 @@ class ClimateDevice(Entity):
@property
def unit_of_measurement(self):
"""The unit of measurement to display."""
"""Return the unit of measurement to display."""
return self.hass.config.units.temperature_unit
@property
def temperature_unit(self):
"""The unit of measurement used by the platform."""
"""Return the unit of measurement used by the platform."""
raise NotImplementedError
@property
@@ -492,7 +497,7 @@ class ClimateDevice(Entity):
@property
def operation_list(self):
"""List of available operation modes."""
"""Return the list of available operation modes."""
return None
@property
@@ -505,6 +510,11 @@ class ClimateDevice(Entity):
"""Return the temperature we try to reach."""
return None
@property
def target_temperature_step(self):
"""Return the supported step of target temperature."""
return None
@property
def target_temperature_high(self):
"""Return the highbound target temperature we try to reach."""
@@ -537,7 +547,7 @@ class ClimateDevice(Entity):
@property
def fan_list(self):
"""List of available fan modes."""
"""Return the list of available fan modes."""
return None
@property
@@ -547,7 +557,7 @@ class ClimateDevice(Entity):
@property
def swing_list(self):
"""List of available swing modes."""
"""Return the list of available swing modes."""
return None
def set_temperature(self, **kwargs):
@@ -695,8 +705,8 @@ class ClimateDevice(Entity):
if temp is None or not isinstance(temp, Number):
return temp
if self.temperature_unit != self.unit_of_measurement:
temp = convert_temperature(temp, self.temperature_unit,
self.unit_of_measurement)
temp = convert_temperature(
temp, self.temperature_unit, self.unit_of_measurement)
# Round in the units appropriate
if self.precision == PRECISION_HALVES:
return round(temp * 2) / 2.0

View File

@@ -10,14 +10,14 @@ from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo climate devices."""
"""Set up the Demo climate devices."""
add_devices([
DemoClimate("HeatPump", 68, TEMP_FAHRENHEIT, None, None, 77,
"Auto Low", None, None, "Auto", "heat", None, None, None),
DemoClimate("Hvac", 21, TEMP_CELSIUS, True, None, 22, "On High",
67, 54, "Off", "cool", False, None, None),
DemoClimate("Ecobee", None, TEMP_CELSIUS, None, None, 23, "Auto Low",
None, None, "Auto", "auto", None, 24, 21)
DemoClimate('HeatPump', 68, TEMP_FAHRENHEIT, None, None, 77,
'Auto Low', None, None, 'Auto', 'heat', None, None, None),
DemoClimate('Hvac', 21, TEMP_CELSIUS, True, None, 22, 'On High',
67, 54, 'Off', 'cool', False, None, None),
DemoClimate('Ecobee', None, TEMP_CELSIUS, None, None, 23, 'Auto Low',
None, None, 'Auto', 'auto', None, 24, 21)
])
@@ -41,15 +41,15 @@ class DemoClimate(ClimateDevice):
self._current_operation = current_operation
self._aux = aux
self._current_swing_mode = current_swing_mode
self._fan_list = ["On Low", "On High", "Auto Low", "Auto High", "Off"]
self._operation_list = ["heat", "cool", "auto", "off"]
self._swing_list = ["Auto", "1", "2", "3", "Off"]
self._fan_list = ['On Low', 'On High', 'Auto Low', 'Auto High', 'Off']
self._operation_list = ['heat', 'cool', 'auto', 'off']
self._swing_list = ['Auto', '1', '2', '3', 'Off']
self._target_temperature_high = target_temp_high
self._target_temperature_low = target_temp_low
@property
def should_poll(self):
"""Polling not needed for a demo climate device."""
"""Return the polling state."""
return False
@property
@@ -99,7 +99,7 @@ class DemoClimate(ClimateDevice):
@property
def operation_list(self):
"""List of available operation modes."""
"""Return the list of available operation modes."""
return self._operation_list
@property
@@ -124,7 +124,7 @@ class DemoClimate(ClimateDevice):
@property
def fan_list(self):
"""List of available fan modes."""
"""Return the list of available fan modes."""
return self._fan_list
def set_temperature(self, **kwargs):

View File

@@ -45,7 +45,7 @@ RESUME_PROGRAM_SCHEMA = vol.Schema({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Ecobee Thermostat Platform."""
"""Set up the Ecobee Thermostat Platform."""
if discovery_info is None:
return
data = ecobee.NETWORK
@@ -197,19 +197,19 @@ class Thermostat(ClimateDevice):
if event['holdClimateRef'] == 'away':
if int(event['endDate'][0:4]) - \
int(event['startDate'][0:4]) <= 1:
# a temporary hold from away climate is a hold
# A temporary hold from away climate is a hold
return 'away'
else:
# a premanent hold from away climate is away_mode
# A permanent hold from away climate is away_mode
return None
elif event['holdClimateRef'] != "":
# any other hold based on climate
# Any other hold based on climate
return event['holdClimateRef']
else:
# any hold not based on a climate is a temp hold
# Any hold not based on a climate is a temp hold
return TEMPERATURE_HOLD
elif event['type'].startswith('auto'):
# all auto modes are treated as holds
# All auto modes are treated as holds
return event['type'][4:].lower()
elif event['type'] == 'vacation':
self.vacation = event['name']
@@ -278,6 +278,11 @@ class Thermostat(ClimateDevice):
"""Return true if away mode is on."""
return self.current_hold_mode == 'away'
@property
def is_aux_heat_on(self):
"""Return true if aux heater."""
return 'auxHeat' in self.thermostat['equipmentStatus']
def turn_away_mode_on(self):
"""Turn away on."""
self.set_hold_mode('away')
@@ -295,17 +300,16 @@ class Thermostat(ClimateDevice):
return
elif hold_mode == 'None' or hold_mode is None:
if hold == VACATION_HOLD:
self.data.ecobee.delete_vacation(self.thermostat_index,
self.vacation)
self.data.ecobee.delete_vacation(
self.thermostat_index, self.vacation)
else:
self.data.ecobee.resume_program(self.thermostat_index)
else:
if hold_mode == TEMPERATURE_HOLD:
self.set_temp_hold(int(self.current_temperature))
else:
self.data.ecobee.set_climate_hold(self.thermostat_index,
hold_mode,
self.hold_preference())
self.data.ecobee.set_climate_hold(
self.thermostat_index, hold_mode, self.hold_preference())
self.update_without_throttle = True
def set_auto_temp_hold(self, heat_temp, cool_temp):
@@ -351,7 +355,7 @@ class Thermostat(ClimateDevice):
self.set_temp_hold(int(temp))
else:
_LOGGER.error(
'Missing valid arguments for set_temperature in %s', kwargs)
"Missing valid arguments for set_temperature in %s", kwargs)
def set_operation_mode(self, operation_mode):
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""
@@ -360,14 +364,14 @@ class Thermostat(ClimateDevice):
def set_fan_min_on_time(self, fan_min_on_time):
"""Set the minimum fan on time."""
self.data.ecobee.set_fan_min_on_time(self.thermostat_index,
fan_min_on_time)
self.data.ecobee.set_fan_min_on_time(
self.thermostat_index, fan_min_on_time)
self.update_without_throttle = True
def resume_program(self, resume_all):
"""Resume the thermostat schedule program."""
self.data.ecobee.resume_program(self.thermostat_index,
str(resume_all).lower())
self.data.ecobee.resume_program(
self.thermostat_index, str(resume_all).lower())
self.update_without_throttle = True
def hold_preference(self):

View File

@@ -21,15 +21,15 @@ REQUIREMENTS = ['python-eq3bt==0.1.5']
_LOGGER = logging.getLogger(__name__)
STATE_BOOST = "boost"
STATE_AWAY = "away"
STATE_MANUAL = "manual"
STATE_BOOST = 'boost'
STATE_AWAY = 'away'
STATE_MANUAL = 'manual'
ATTR_STATE_WINDOW_OPEN = "window_open"
ATTR_STATE_VALVE = "valve"
ATTR_STATE_LOCKED = "is_locked"
ATTR_STATE_LOW_BAT = "low_battery"
ATTR_STATE_AWAY_END = "away_end"
ATTR_STATE_WINDOW_OPEN = 'window_open'
ATTR_STATE_VALVE = 'valve'
ATTR_STATE_LOCKED = 'is_locked'
ATTR_STATE_LOW_BAT = 'low_battery'
ATTR_STATE_AWAY_END = 'away_end'
DEVICE_SCHEMA = vol.Schema({
vol.Required(CONF_MAC): cv.string,
@@ -42,7 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the eQ-3 BLE thermostats."""
"""Set up the eQ-3 BLE thermostats."""
devices = []
for name, device_cfg in config[CONF_DEVICES].items():
@@ -112,14 +112,14 @@ class EQ3BTSmartThermostat(ClimateDevice):
@property
def current_operation(self):
"""Current mode."""
"""Return the current operation mode."""
if self._thermostat.mode < 0:
return None
return self.modes[self._thermostat.mode]
@property
def operation_list(self):
"""List of available operation modes."""
"""Return the list of available operation modes."""
return [x for x in self.modes.values()]
def set_operation_mode(self, operation_mode):

View File

@@ -14,7 +14,8 @@ from homeassistant.components import switch
from homeassistant.components.climate import (
STATE_HEAT, STATE_COOL, STATE_IDLE, ClimateDevice, PLATFORM_SCHEMA)
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE)
ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE,
CONF_NAME)
from homeassistant.helpers import condition
from homeassistant.helpers.event import (
async_track_state_change, async_track_time_interval)
@@ -27,7 +28,6 @@ DEPENDENCIES = ['switch', 'sensor']
DEFAULT_TOLERANCE = 0.3
DEFAULT_NAME = 'Generic Thermostat'
CONF_NAME = 'name'
CONF_HEATER = 'heater'
CONF_SENSOR = 'target_sensor'
CONF_MIN_TEMP = 'min_temp'
@@ -56,7 +56,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the generic thermostat."""
"""Set up the generic thermostat platform."""
name = config.get(CONF_NAME)
heater_entity_id = config.get(CONF_HEATER)
sensor_entity_id = config.get(CONF_SENSOR)
@@ -74,7 +74,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class GenericThermostat(ClimateDevice):
"""Representation of a GenericThermostat device."""
"""Representation of a Generic Thermostat device."""
def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
min_temp, max_temp, target_temp, ac_mode, min_cycle_duration,
@@ -110,7 +110,7 @@ class GenericThermostat(ClimateDevice):
@property
def should_poll(self):
"""No polling needed."""
"""Return the polling state."""
return False
@property
@@ -175,7 +175,7 @@ class GenericThermostat(ClimateDevice):
@asyncio.coroutine
def _async_sensor_changed(self, entity_id, old_state, new_state):
"""Called when temperature changes."""
"""Handle temperature changes."""
if new_state is None:
return
@@ -185,14 +185,14 @@ class GenericThermostat(ClimateDevice):
@callback
def _async_switch_changed(self, entity_id, old_state, new_state):
"""Called when heater switch changes state."""
"""Handle heater switch state changes."""
if new_state is None:
return
self.hass.async_add_job(self.async_update_ha_state())
@callback
def _async_keep_alive(self, time):
"""Called at constant intervals for keep-alive purposes."""
"""Call at constant intervals for keep-alive purposes."""
if self.current_operation in [STATE_COOL, STATE_HEAT]:
switch.async_turn_on(self.hass, self.heater_entity_id)
else:

View File

@@ -35,7 +35,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-variable
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the heatmiser thermostat."""
"""Set up the heatmiser thermostat."""
from heatmiserV3 import heatmiser, connection
ipaddress = config.get(CONF_IPADDRESS)

View File

@@ -14,17 +14,17 @@ DEPENDENCIES = ['homematic']
_LOGGER = logging.getLogger(__name__)
STATE_MANUAL = "manual"
STATE_BOOST = "boost"
STATE_COMFORT = "comfort"
STATE_LOWERING = "lowering"
STATE_MANUAL = 'manual'
STATE_BOOST = 'boost'
STATE_COMFORT = 'comfort'
STATE_LOWERING = 'lowering'
HM_STATE_MAP = {
"AUTO_MODE": STATE_AUTO,
"MANU_MODE": STATE_MANUAL,
"BOOST_MODE": STATE_BOOST,
"COMFORT_MODE": STATE_COMFORT,
"LOWERING_MODE": STATE_LOWERING
'AUTO_MODE': STATE_AUTO,
'MANU_MODE': STATE_MANUAL,
'BOOST_MODE': STATE_BOOST,
'COMFORT_MODE': STATE_COMFORT,
'LOWERING_MODE': STATE_LOWERING
}
HM_TEMP_MAP = [
@@ -41,7 +41,7 @@ HM_CONTROL_MODE = 'CONTROL_MODE'
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Homematic thermostat platform."""
"""Set up the Homematic thermostat platform."""
if discovery_info is None:
return
@@ -76,10 +76,9 @@ class HMThermostat(HMDevice, ClimateDevice):
@property
def operation_list(self):
"""List of available operation modes."""
"""Return the list of available operation modes."""
op_list = []
# generate list
for mode in self._hmdevice.ACTIONNODE:
if mode in HM_STATE_MAP:
op_list.append(HM_STATE_MAP.get(mode))
@@ -132,11 +131,9 @@ class HMThermostat(HMDevice, ClimateDevice):
def _init_data_struct(self):
"""Generate a data dict (self._data) from the Homematic metadata."""
# Add state to data dict
self._state = next(iter(self._hmdevice.WRITENODE.keys()))
self._data[self._state] = STATE_UNKNOWN
# support state
if HM_CONTROL_MODE in self._hmdevice.ATTRIBUTENODE:
self._data[HM_CONTROL_MODE] = STATE_UNKNOWN

View File

@@ -8,13 +8,12 @@ import logging
import socket
import datetime
import voluptuous as vol
import requests
import voluptuous as vol
from homeassistant.components.climate import (ClimateDevice, PLATFORM_SCHEMA,
ATTR_FAN_MODE, ATTR_FAN_LIST,
ATTR_OPERATION_MODE,
ATTR_OPERATION_LIST)
from homeassistant.components.climate import (
ClimateDevice, PLATFORM_SCHEMA, ATTR_FAN_MODE, ATTR_FAN_LIST,
ATTR_OPERATION_MODE, ATTR_OPERATION_LIST)
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT,
ATTR_TEMPERATURE)
@@ -54,7 +53,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Honeywell thermostat."""
"""Set up the Honeywell thermostat."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
region = config.get(CONF_REGION)
@@ -66,7 +65,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
def _setup_round(username, password, config, add_devices):
"""Setup rounding function."""
"""Set up the rounding function."""
from evohomeclient import EvohomeClient
away_temp = config.get(CONF_AWAY_TEMPERATURE)
@@ -87,16 +86,16 @@ def _setup_round(username, password, config, add_devices):
# config will be used later
def _setup_us(username, password, config, add_devices):
"""Setup user."""
"""Set up the user."""
import somecomfort
try:
client = somecomfort.SomeComfort(username, password)
except somecomfort.AuthError:
_LOGGER.error('Failed to login to honeywell account %s', username)
_LOGGER.error("Failed to login to honeywell account %s", username)
return False
except somecomfort.SomeComfortError as ex:
_LOGGER.error('Failed to initialize honeywell client: %s', str(ex))
_LOGGER.error("Failed to initialize honeywell client: %s", str(ex))
return False
dev_id = config.get('thermostat')
@@ -199,7 +198,7 @@ class RoundThermostat(ClimateDevice):
except StopIteration:
_LOGGER.error("Did not receive any temperature data from the "
"evohomeclient API.")
"evohomeclient API")
return
self._current_temperature = data['temp']
@@ -289,7 +288,7 @@ class HoneywellUSThermostat(ClimateDevice):
"setpoint_{}".format(mode),
temperature)
except somecomfort.SomeComfortError:
_LOGGER.error('Temperature %.1f out of range', temperature)
_LOGGER.error("Temperature %.1f out of range", temperature)
@property
def device_state_attributes(self):
@@ -369,8 +368,8 @@ class HoneywellUSThermostat(ClimateDevice):
raise exp
if not self._retry():
raise exp
_LOGGER.error("SomeComfort update failed, Retrying "
"- Error: %s", exp)
_LOGGER.error(
"SomeComfort update failed, Retrying - Error: %s", exp)
def _retry(self):
"""Recreate a new somecomfort client.
@@ -380,14 +379,14 @@ class HoneywellUSThermostat(ClimateDevice):
"""
import somecomfort
try:
self._client = somecomfort.SomeComfort(self._username,
self._password)
self._client = somecomfort.SomeComfort(
self._username, self._password)
except somecomfort.AuthError:
_LOGGER.error('Failed to login to honeywell account %s',
_LOGGER.error("Failed to login to honeywell account %s",
self._username)
return False
except somecomfort.SomeComfortError as ex:
_LOGGER.error('Failed to initialize honeywell client: %s',
_LOGGER.error("Failed to initialize honeywell client: %s",
str(ex))
return False
@@ -397,7 +396,7 @@ class HoneywellUSThermostat(ClimateDevice):
if device.name == self._device.name]
if len(devices) != 1:
_LOGGER.error('Failed to find device %s', self._device.name)
_LOGGER.error("Failed to find device %s", self._device.name)
return False
self._device = devices[0]

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