Compare commits

..

2511 Commits
0.10 ... 0.24

Author SHA1 Message Date
Fabian Affolter
dc0f16c9dd Merge pull request #2509 from home-assistant/dev
0.24
2016-07-17 00:03:26 +02:00
Paulus Schoutsen
16c71ab207 Make sqlalchemy main dependency to help migration (#2536) 2016-07-16 11:39:44 -07:00
Johann Kellerman
06d70544bc Update rpi_gpio.py (#2530)
Should be pullup, since the sensor pulls to ground (at least the one on AndrewHilliday's site)

Or do we want this configurable?
2016-07-16 11:10:41 -07:00
Pascal Vizeli
1877906fdf small bugfix (#2532) 2016-07-16 11:06:36 -07:00
Fabian Affolter
95d033f1af Round output of wind speed and humidity (#2535) 2016-07-16 11:05:29 -07:00
Paulus Schoutsen
7cff107c17 Update frontend 2016-07-16 02:15:46 -07:00
Fabian Affolter
89972ed940 Add validation and switch python-mystrom (#2529) 2016-07-15 09:02:20 -07:00
Pascal Vizeli
6694f29918 add media_player/clear_playlist and line-in/tv support to sonos (#2527)
* add media_player/clear_playlist and line-in/tv support to sonos

* add support source radio

* fix bug

* print TV/Line-In as media_title

* implement universal player

* add to demo platform

* Update demo.py

Better handling for demo object

* add unit tests

* fix unit test
2016-07-15 09:00:41 -07:00
Fabian Affolter
c1798dbe1f Catch ImportError (#2526) 2016-07-14 15:15:53 -07:00
William Scanlon
3246b58437 Support for Wink lock user codes (#2525) 2016-07-14 13:31:16 -07:00
Michaël Arnauts
63356fb5eb supported_media_commands should check for SERVICE_SELECT_SOURCE instead of SUPPORT_SELECT_SOURCE (#2482) 2016-07-14 11:14:49 -07:00
Paulus Schoutsen
ef64e11b50 known devices yaml robustness (#2523) 2016-07-13 23:56:02 -07:00
Paulus Schoutsen
e38b7d97d2 Update frontend 2016-07-13 23:05:40 -07:00
Paulus Schoutsen
8984a6b161 update frontend 2016-07-13 19:11:33 -07:00
Paulus Schoutsen
49b595e32e Update frontend 2016-07-13 19:05:25 -07:00
Johann Kellerman
a60a342864 Logbook: Query databse as_utc(). dt: Use pytz's localize (#2521) 2016-07-13 18:45:55 -07:00
Paulus Schoutsen
88b3aa54a8 Update README.rst 2016-07-13 18:43:04 -07:00
Fabian Affolter
a0c1c918b8 Switch to xmltodict and pass over missing temperature (fixes #2433) (#2463)
* Switch to xmltodict and pass over missing temperature (fixes #2433)

* Add guard clauses
2016-07-13 18:30:11 -07:00
Pascal Vizeli
675283c23e Merge pull request #2520 from pvizeli/Homematic_pro
homematic update to pyhomematic 0.1.9
2016-07-13 23:29:22 +02:00
Pascal Vizeli
c023d1d656 homematic update to pyhomematic 0.1.9 2016-07-13 23:15:21 +02:00
John Arild Berentsen
ce4891fe8e Fix node inclusion and exclusion. Also add secure inclusion. (#2519)
Fix node inclusion and exclusion.
2016-07-13 19:56:14 +02:00
John Arild Berentsen
82d98f5b89 Zwave Node attributes was missing from binary sensors. (#2516)
Fixes #2505
2016-07-13 18:01:59 +02:00
heytcass
2900855061 Update README.rst (#2517)
Editing for typos, clarifying.
2016-07-13 08:59:26 -07:00
Greg Dowling
e31d4863c7 Merge pull request #2514 from home-assistant/bump_pyloopenergy
Bump pyloopenergy version.
2016-07-13 17:34:30 +02:00
Paulus Schoutsen
af736a3e71 Update frontend (temp map solution) 2016-07-13 08:32:13 -07:00
Daniel Høyer Iversen
16feb1c55e Fix issue #2290 for rfxtrx (#2498)
* Fix issue #2290 for rfxtrx

* update tests for rfxtrx sensor

* Replace state_unkown with None in rfxtrx sensor

* Update test_rfxtrx.py
2016-07-13 07:46:11 -07:00
Fabian Affolter
497bc6ac0d Update docstrings (#2513) 2016-07-13 14:47:29 +02:00
pavoni
cae8f8a006 Bump pyloopenergy version. 2016-07-13 13:21:17 +02:00
Fabian Affolter
82e992c63c Links docs (#2510)
* Add link to docs

* Fix link to docs

* Update docstrings

* Fix link
2016-07-13 11:10:31 +02:00
Paulus Schoutsen
3dcafafc6a Merge branch 'master' into dev
Conflicts:
	homeassistant/const.py
2016-07-12 22:31:54 -07:00
Fabian Affolter
ebcda4076e Upgrade zeroconf to 0.17.6 (#2503) 2016-07-12 21:56:23 -07:00
Robbie Trencheny
011f82f9e3 Uber sensor now works with UberPool and has a bit cleaner logic. Also upgraded to latest version of the SDK and switched all single quotes to double quotes (#2507) 2016-07-12 21:52:21 -07:00
Pascal Vizeli
8ed2c8e6a4 add photo functionality to telegram (#2506)
* add photo functionality to telegram

* basic auth need password and username
2016-07-12 21:48:33 -07:00
Brent
b9cadbecaa Allow device_tracker and sensor entity for google travel times (#2479)
* Allow owntracks entity for google travel times

* Added ability to use sensor state as location

* Added zone checks for google travel timesg

* Updated to use global constents and the location helper

* Fixed type in method name and removed redundant validation

* Changed domain condition to be a bit more elegant

* Updated to allow friendly name in any instance including the config

* Fixed bad python syntax and used helper methods
2016-07-12 21:46:11 -07:00
Dan
e1db639317 add hvac mode support to radiotherm (#2442)
* add hvac mode support to radiotherm

off/cool/heat/auto modes are supported

* Moved STATE_AUTO to thermostat component, fix lint

Moved STATE_AUTO to thermostat platform. Fixed lint error.
2016-07-12 21:43:49 -07:00
rhooper
beeae17cab Merge pull request #2489 from home-assistant/recorder-tests
Add more recorder tests
2016-07-12 11:48:22 -07:00
Paulus Schoutsen
8fcfb9136c Update frontend 2016-07-12 09:16:21 -07:00
Fabian Affolter
62c11dde17 Upgrade python-telegram-bot to 4.3.3 (#2504) 2016-07-12 17:51:11 +02:00
Nolan Gilley
e58615b2a5 Join by joaoapps component & notify platform (#2315)
* initial support for Join notifier

add more functions for Join

* rename to joaoapps_join

add message default in schema

move api_key check

* move special join services to their own component

update coveragerc and requirements_all

add icon and smallicon
2016-07-12 08:10:33 -07:00
Fabian Affolter
bef2f87ddc Docstrings (#2502)
* Update docstrings

* Update docstrings

* Add link to docs
2016-07-12 16:46:29 +02:00
John Arild Berentsen
45a8b74d7f Add missing sensor command_class into sensor component (#2501)
command_class_sensor_alarm was also missing from sensor component.
2016-07-12 15:40:55 +02:00
Daniel Høyer Iversen
09a4336bc5 Fix bug in rfxtrx for int device id (#2497) 2016-07-12 01:45:22 -07:00
Paulus Schoutsen
6d60287455 Update frontend 2016-07-12 00:10:05 -07:00
Paulus Schoutsen
6cb91e66c8 Update frontend 2016-07-11 22:07:34 -07:00
Keaton Taylor
2189516966 Clamp brightness between 0 and 255 (#2494)
* Clamp brightness between 0 and 255

Change to ensure that values over 255 supplied by the config will be
clamed to a max value of 255.

* Revert "Clamp brightness between 0 and 255"

This reverts commit c87238e8b5d3a67c035b1a97d5b5b9af8f6483bc.

* Clamp brightness between 0 and 255

Change to ensure that values over 255 supplied by the config will be
clamed to a max value of 255.
2016-07-11 12:39:46 -07:00
Paulus Schoutsen
1738db9ccc Update models.py 2016-07-11 12:38:35 -07:00
Paulus Schoutsen
e0dd5a8558 Tweak Recorder 2016-07-11 08:56:07 -07:00
John Arild Berentsen
f4f2da5dc7 Missing command class for sensor (#2492) 2016-07-11 16:33:34 +02:00
Daniel Høyer Iversen
085d026ab6 Merge pull request #2487 from home-assistant/rfxtrx
Rfxtrx
2016-07-11 09:18:51 +02:00
Daniel
3b14189021 Make rfxtrx sensor not crash when unknown sensor is discovered 2016-07-11 08:59:14 +02:00
Daniel
6b9e1f3263 update rfxtrx to version 0.9 to support lighting4 2016-07-11 08:54:15 +02:00
Dan
bde2f0d5a0 Imap sensor (#2485)
* Imap unread email sensor

Checks the inbox of a imap account for unread emails. Tested against
gmail.

Example config:

```
sensor:
  - platform: imap
    name: gmail test
    user: USER
    password: PASSWORD
    server: imap.gmail.com
    port: 993

```

* added to .coveragerc

* Code cleanup and typo fix.

* Added port range validation

* Fix lint errors
2016-07-10 13:21:53 -07:00
Daniel Matuschek
50ea3c7744 Implementation of a KNX platform driver and a KNX switch (#2439)
* Implementation of a KNX platform driver and a KNX switch

* Starting working on a KNX thermostat implementation

* Removed KNX thermostat implementation from this branch again

* Make gateway parameter optional (can be auto-detected in many cases)

* Removed check for double initialisation

* KNX messages now will be handled internally and not send to the Home Assistant message bus

* Call update_ha_state only if should_poll is false

* Removed unused HASS variable

* knxip library version changed

* pylint optimization
2016-07-10 10:36:54 -07:00
Fabian Affolter
bde9e4e9c0 Upgrade googlemaps to 2.4.4 (#2481) 2016-07-10 10:32:38 -07:00
GadgetReactor
609458052c New Switch Platform: TPLink Switch (HS100 / HS110) (#2453)
* New Switch Platform: TPLink Switch (HS100 / HS110)

### Information

The TPLink switch platform allows you to control the state of your TPLink Wi-Fi Smart Plugs.

Supported devices (tested):
HS100 (UK)

It should also work with the HS110.

To use your D-Link smart plugs in your installation, add the following to your configuration.yaml file:

"""
# Example configuration.yaml entry
switch:
  platform: tplink
  host: IP_ADRRESS
  name: TPLink Switch
"""

### Configuration variables:

host (Required): The IP address of your TPlink plug, eg. http://192.168.1.105
name (Optional): The name to use when displaying this switch.

* Update tplink.py

Bug fixes

* Separate to a standalone library

* Removed unnecessary imports

* Code cleanup and update reference library link

* TPLink switch support (#2453)

* updated requirements
2016-07-10 09:48:02 -07:00
clach04
344fb9c8b4 Fix typos in demo switch doc strings (#2480) 2016-07-09 09:35:55 +02:00
koen01
03ef74b4ab Add 'Sound' to rfxtrx DATA_TYPES (#2477)
Fixes reception of SelectPlus and correctly adds the chime sensor.
2016-07-08 09:00:21 -07:00
Dale Higgs
ab63fbff3f Fix AsusWRT to prevent SSH key confusion (#2467)
Changed "pub_key" to "ssh_key" while maintaining backwards compatibility. Quotes were also updated to match across the file.
2016-07-08 08:58:31 -07:00
Pascal Vizeli
2ab2f68318 Yahoo! weather support (#2457)
* initial import yahoo weather

* fix temperature in HA style

* add suggestion from @fabaff

* change with suggestion from @balloob
2016-07-08 08:48:38 -07:00
John Arild Berentsen
5d6c13c12c Fix missing generic command class for binary sensors (#2475) 2016-07-08 13:40:04 +02:00
Brent
ff5c3c9f98 Added attributes to the statsd data (#2440)
* Added attributes to the statsd data

* Updated to allow optional attribute logging
2016-07-07 23:09:02 -07:00
Paulus Schoutsen
31b8e49ad2 Fix PyLint 1.6 issues (#2471) 2016-07-07 18:54:16 -07:00
Neil Lathwood
978ebb9c59 Updated braviatv media player to support power status (#2470)
* Updated braviatv media player to support power status

* Updated requirements_all.txt
2016-07-07 18:28:01 -07:00
Johann Kellerman
85e3dfe6a6 Exclude secrets.yaml in yaml !include_directories (#2450) 2016-07-06 22:17:02 -07:00
Marcelo Moreira de Mello - mmello
cf5aeebba6 - Added code validation on Simplisafe module on alarm_control_panel (#2455) 2016-07-06 21:55:47 -07:00
John Arild Berentsen
3e3d9c881e Return name of location to lock instead of serial number. (#2460) 2016-07-06 18:33:58 -07:00
Fabian Affolter
216a756590 Upgrade pyowm to 2.3.2 (fixes #2452) (#2464) 2016-07-06 18:31:11 -07:00
Dale Higgs
db23320659 Add names, units and icons to APCUPSd Sensor (#2443)
* Add names, units and icons to APCUPSd Sensor

* Fix farcy errors

* Attempt fix of errors

* Remove "type:" from configuration

* Remove duplicate "mdi:" prefix
2016-07-06 18:25:57 -07:00
Fabian Affolter
c634cbf866 Upgrade slacker to 0.9.21 (#2458) 2016-07-06 16:48:58 +02:00
Fabian Affolter
ceb332bc31 Upgrade python-telegram-bot to 4.3.2 (#2459) 2016-07-06 16:48:43 +02:00
Dale Higgs
86e3fdee1c Fix flood of errors if Plex server goes offline (#2447) 2016-07-05 10:50:43 -07:00
Fabian Affolter
0f4acb59fe Change schema for elevation to int (#2436) 2016-07-05 08:01:59 -07:00
Paulus Schoutsen
c5b2df01d9 Update frontend 2016-07-04 10:40:43 -07:00
Jordan Keith
83a72ab4dc Update unifi.py to support sites (#2434)
* Update unifi.py

Add support for a site that is not the default within the Unifi Controller.

i.e. A controller with multiple sites:

 - Home
 - Friends
 - Parents (default)

Supplying the identifier for 'Home' now means that the devices tracked will be associated with 'Home'.

* Update test_unifi.py

Fix test modules as well.
2016-07-04 08:20:00 -07:00
Johann Kellerman
2cdef7fb2f Persistent_notification service description (#2407)
* Persistent_notification service description

* Add service name to services.yaml
2016-07-03 18:33:23 -07:00
Paulus Schoutsen
659d67f362 properly cleanup after config test 2016-07-03 18:24:17 -07:00
Brent
ffccca1f60 Updated to new statsd library and added state change counters (#2429) 2016-07-03 15:21:18 -07:00
Brent
ef74bd9892 Updated to version 3.1.2 and fixed invalid host setup error (#2431) 2016-07-03 15:17:08 -07:00
Paulus Schoutsen
3447fdc76f Make scripts available via CLI (#2426)
* Rename sqlalchemy migrate script

* Add script support to CLI
2016-07-03 11:38:14 -07:00
rhooper
a2e45b8fdd Switch to SQLAlchemy for the Recorder component. Gives the ability t… (#2377)
* Switch to SQLAlchemy for the Recorder component.  Gives the ability to use MySQL or other.

* fixes for failed lint

* add conversion script

* code review fixes and refactor to use to_native() model methods and execute() helper

* move script to homeassistant.scripts module

* style fixes my tox lint/flake8 missed

* move exclusion up
2016-07-02 11:22:51 -07:00
Fabian Affolter
a65f196d19 Use XML source instead of website (#2400) 2016-07-02 11:22:29 -07:00
William Scanlon
a74cdc7b0d SimpliSafe Alarm (#2409) 2016-07-02 11:21:15 -07:00
rhooper
449be29022 support newer deCONZ api versions (#2410) 2016-07-02 11:18:54 -07:00
Fabian Affolter
ba8e417390 Upgrade python-telegram-bot to 4.3.1 (#2414) 2016-07-02 11:16:14 -07:00
Fabian Affolter
cad995a5f4 Upgrade slacker to 0.9.18 (#2415) 2016-07-02 11:15:39 -07:00
Fabian Affolter
06efee7ecf Upgrade fuzzywuzzy to 0.11.0 (#2416) 2016-07-02 11:12:48 -07:00
Paulus Schoutsen
bacc14d845 Merge pull request #2421 from armills/zwave-color-bulbs
Move Aeotec bulb color logic to Zwave workaround
2016-07-02 11:11:44 -07:00
Paulus Schoutsen
6f8a733434 Merge pull request #2424 from home-assistant/hotfix-23-1
Hotfix 0.23.1
2016-07-02 10:20:57 -07:00
Paulus Schoutsen
906e64fdb5 Bump version to 0.23.1 2016-07-02 10:06:24 -07:00
William Scanlon
8e406a70f6 Downgraded pubnub version (#2420) 2016-07-02 10:06:09 -07:00
AlucardZero
8d9f4a1754 check for OP_NO_COMPRESSION support before trying to use it (#2423) 2016-07-02 10:06:09 -07:00
rhooper
0a53b863cd bump pyvera version to 0.2.13 (#2406) 2016-07-02 10:06:09 -07:00
Fabian Affolter
80feb322f9 A mini update (#2418) 2016-07-02 10:05:19 -07:00
William Scanlon
2b514139eb Downgraded pubnub version (#2420) 2016-07-02 10:04:51 -07:00
AlucardZero
2b8dfb2a0e check for OP_NO_COMPRESSION support before trying to use it (#2423) 2016-07-02 10:03:49 -07:00
Adam Mills
6477122b23 Move Aeotec bulb color logic to Zwave workaround
Default behavior for warm/cold white channels is to assume the white
channel is mixed with the rgb. This is a sane default and should support
the Fibaro RGBW LED controller.
2016-07-02 12:08:01 -04:00
Fabian Affolter
1e9db41028 Remove unused links (#2417) 2016-07-02 15:06:13 +02:00
Fabian Affolter
21d3be4027 Fix update (#2402) 2016-07-02 09:09:22 +02:00
rhooper
48b3c98646 bump pyvera version to 0.2.13 (#2406) 2016-07-01 18:47:55 -07:00
Fabian Affolter
15803d1773 Move content to devel docs (fixes #2403) (#2408) 2016-07-02 00:47:54 +02:00
Fabian Affolter
3870d2e0cd Docstring updates (#2404)
* Fix docstring

* Fix typo

* Update docstrings

* Update docstrings
2016-07-01 21:39:30 +02:00
Paulus Schoutsen
fe0164b137 Version bump to 0.24.0.dev0 2016-07-01 00:58:29 -07:00
Paulus Schoutsen
6bc504bfcc Merge pull request #2381 from home-assistant/dev
0.23
2016-07-01 00:58:11 -07:00
Paulus Schoutsen
c44eefacb4 Version bump to 0.23.0 2016-07-01 00:57:55 -07:00
patkap
952b1a3e0c kodi platform: following jsonrpc-request version bump (0.3), let kodi file abstraction layer handle a collection item, url or file to play (#2398) 2016-06-30 16:35:20 -07:00
Pascal Vizeli
a57cd58675 Merge pull request #2399 from pvizeli/Homematic_fix
Homematic fix
2016-07-01 00:17:04 +02:00
Pascal Vizeli
d67f79e2eb remove unused pylint exeption 2016-07-01 00:01:16 +02:00
Pascal Vizeli
d326d187d1 fix bug in event handling and add cast for watersensor 2016-06-30 23:54:04 +02:00
Pascal Vizeli
d0b1619946 Merge remote-tracking branch 'refs/remotes/home-assistant/dev' into Homematic_fix 2016-06-30 23:44:27 +02:00
Lewis Juggins
21be4c1828 Add Sonos unjoin functionality (#2379) 2016-06-30 14:21:57 -07:00
Paulus Schoutsen
d1f4901d53 Migrate to cherrypy wsgi from eventlet (#2387) 2016-06-30 09:02:12 -07:00
patkap
7582eb9f63 jsonrpc-request version bump (0.3) (#2397) 2016-06-30 08:40:01 -07:00
Fabian Affolter
419ff18afb Docstrings (#2395)
* Replace switch with lock

* Update docstrings

* Add link to docs

* Add link to docs and update docstrings

* Update docstring

* Update docstrings and fix typos

* Add link to docs

* Add link to docs

* Add link to docs and update docstrings

* Fix link to docs and update docstrings

* Remove blank line

* Add link to docs
2016-06-30 10:33:34 +02:00
Fabian Affolter
8dd7ebb08e Add the two next trains (#2390) 2016-06-29 17:44:35 -07:00
rhooper
5cce02ab62 vera lock support (#2391)
* vera lock support

* fix formatting
2016-06-29 17:28:20 -07:00
William Scanlon
6a816116ab Wink subscription support (#2324) 2016-06-29 14:16:53 -07:00
Pascal Vizeli
bb0f484caf update pyhomematic and homematic use now events from HA for remotes 2016-06-29 22:42:35 +02:00
Brent
3c5c018e3e Fixed issue with roku timeouts throwing exceptions when roku losses n… (#2386)
* Fixed issue with roku timeouts throwing exceptions when roku losses networking

* Fixed pylint errors
2016-06-28 20:26:37 -07:00
Ardetus
78e7e17484 Support more types of 1wire sensors and bus masters (#2384)
* Support more types of 1wire sensors and bus masters

- Added support for DS18S20, DS1822, DS1825 and DS28EA00 temperature sensors
- Added support for bus masters which use fuse to mount device tree.
  Mount can be specified by 'mount_dir' configuration parameter.

* Correct the lint problem
2016-06-28 18:39:16 -07:00
AlucardZero
31d2a5d2d1 Reenable TLS1.1 and 1.2 while leaving SSLv3 disabled (#2385) 2016-06-28 16:48:25 -07:00
Pascal Vizeli
baa9bdf6fc change homematic to autodetect only 2016-06-28 22:53:53 +02:00
Fabian Affolter
00179763ef Upgrade influxdb to 3.0.0 (#2383) 2016-06-28 07:56:14 -07:00
Fabian Affolter
7a73dc7d6a Upgrade websocket-client to 0.37.0 (#2382) 2016-06-27 23:47:35 -07:00
Paulus Schoutsen
d0b9b588a9 Merge branch 'master' into dev
Conflicts:
	homeassistant/const.py
2016-06-27 23:26:46 -07:00
Fabian Affolter
592c599488 Upgrade Werkzeug to 0.11.10 (#2380) 2016-06-27 17:39:44 -07:00
Paulus Schoutsen
6714392e9c Move elevation to core config and clean up HTTP mocking in tests (#2378)
* Stick version numbers

* Move elevation to core config

* Migrate forecast test to requests-mock

* Migrate YR tests to requests-mock

* Add requests_mock to requirements_test.txt

* Move conf code from bootstrap to config

* More config fixes

* Fix some more issues

* Add test for set config and failing auto detect
2016-06-27 09:02:45 -07:00
Adam Mills
dc75b28b90 Initial Support for Zwave color bulbs (#2376)
* Initial Support for Zwave color bulbs

* Revert name override for ZwaveColorLight
2016-06-27 09:01:41 -07:00
Pascal Vizeli
d2509ce9e3 Merge remote-tracking branch 'refs/remotes/home-assistant/dev' into dev 2016-06-27 15:57:01 +02:00
Pascal Vizeli
3afc566be1 Fix timing bug while linking HM device to HA object
https://github.com/danielperna84/home-assistant/issues/14
2016-06-26 23:18:18 +02:00
Dan
fb3e388f04 Depreciate ssl2/3 (#2375)
* Depreciate ssl2/3

Following the best practices as defind here:
https://mozilla.github.io/server-side-tls/ssl-config-generator/

* Updated comment with better decription

Links to the rational rather than the config generator; explains link.

* add comment mentioning intermediate
2016-06-26 11:49:46 -07:00
Fabian Affolter
254b1c46ac Remove lxml dependency (#2374) 2016-06-26 10:13:52 -07:00
Philip Lundrigan
d13cc227cc Push State (#2365)
* Add ability to push state changes

* Add tests for push state changes

* Fix style issues

* Use better name to force an update
2016-06-26 00:33:23 -07:00
Paulus Schoutsen
446f998759 Merge pull request #2368 from pvizeli/Homematic
Homematic Support (clean)
2016-06-25 20:37:53 -07:00
Paulus Schoutsen
206e7d7a67 Extend persistent notification support (#2371) 2016-06-25 16:40:33 -07:00
Pascal Vizeli
c3b25f2cd5 fix logging-not-lazy 2016-06-25 22:20:09 +02:00
Pascal Vizeli
f3199e7dae fix wrong import 2016-06-25 22:13:29 +02:00
Pascal Vizeli
4ecd724578 fix linter errors 2016-06-25 22:10:47 +02:00
Pascal Vizeli
e4d3b25f1e Merge remote-tracking branch 'refs/remotes/home-assistant/dev' into Homematic
# Conflicts:
#	homeassistant/components/thermostat/homematic.py
2016-06-25 22:02:14 +02:00
Pascal Vizeli
7e7f7b64e5 Merge remote-tracking branch 'refs/remotes/home-assistant/dev' into dev 2016-06-25 21:58:34 +02:00
Pascal Vizeli
e0e9d3c57b change autodiscovery 2016-06-25 21:37:51 +02:00
Pascal Vizeli
a687bdb388 Revert "Third batch of (minor) fixes as suggested by @balloob"
This reverts commit 87c138c559.
2016-06-25 21:03:41 +02:00
Pascal Vizeli
199fbc7a15 Revert "fix autodiscovery"
This reverts commit 86ccf26a1a.
2016-06-25 21:03:37 +02:00
Pascal Vizeli
57754cd2ff Revert "fix discovery function"
This reverts commit be72b04855.
2016-06-25 21:03:33 +02:00
John Arild Berentsen
21381a95d4 Zwave fixes. (#2373)
* Fix move_up and move_down

I managed to switch up the zwave move_up and move_down commands.
This PR fixes it.
Thank you @nunofgs for bringing this to my attention :)

* Fix for aeotec 6 multisensor
2016-06-25 20:35:36 +02:00
Pascal Vizeli
be72b04855 fix discovery function 2016-06-25 20:30:02 +02:00
Pascal Vizeli
86ccf26a1a fix autodiscovery 2016-06-25 20:12:49 +02:00
Pascal Vizeli
87c138c559 Third batch of (minor) fixes as suggested by @balloob 2016-06-25 19:25:59 +02:00
Pascal Vizeli
b3acd7d21d add resolvenames function support from pyhomematic (homegear only) 2016-06-25 18:54:14 +02:00
Pascal Vizeli
a19f7bff28 fix false autodetect with HM GongSensor types 2016-06-25 18:36:52 +02:00
Pascal Vizeli
30b7c6b694 Second batch of (minor) fixes as suggested by @balloob 2016-06-25 18:34:35 +02:00
Daniel Perna
43faeff42a Moved trx/except, added debug messages, minor fixes 2016-06-25 18:19:05 +02:00
Daniel Perna
5ca26fc13f Moved try/except-block and moved delay to link_homematic 2016-06-25 16:25:33 +02:00
Daniel Perna
04748e3ad1 First batch of (minor) fixes as suggested by @balloob 2016-06-25 15:10:19 +02:00
Johann Kellerman
7b02dc434a Secrets support for configuration files (#2312)
* ! secret based on yaml.py

* Private Secrets Dict, removed cmdline, fixed log level

* Secrets limited to yaml only

* Add keyring & debug tests
2016-06-25 00:10:03 -07:00
Matthew Treinish
1c1d18053b Add cmus media device (#2321)
This commit adds support for the cmus console music player as a media
device.
2016-06-25 00:06:36 -07:00
arsaboo
2ac752d67a Add OpenExchangeRates sensor (#2356)
* Create openexchangerates.py

* Create OpenExchangeRates Sensor

* Add openexchangerate sensor

* Update openexchangerates.py

* Added params dict

* Update openexchangerates.py

* Update openexchangerates.py

* Update openexchangerates.py

* Update openexchangerates.py

* Added API key validation

* Update openexchangerates.py
2016-06-25 00:02:28 -07:00
John Arild Berentsen
a1ef1c996c Fix physical manual update of state of device (#2372) 2016-06-24 23:22:14 -07:00
Paulus Schoutsen
cbb897b2cf Update frontend 2016-06-24 22:34:55 -07:00
Fabian Affolter
e4b67c9574 Add persistent notification component (#1844) 2016-06-24 21:43:44 -07:00
Daniel Høyer Iversen
7a8c5a0709 Add frontend to the example config (#2367) 2016-06-24 21:40:02 -07:00
Paulus Schoutsen
aadd730ddd Merge branch 'pr/2348' into dev
Conflicts:
	.coveragerc
2016-06-24 21:30:08 -07:00
Paulus Schoutsen
68df3deee0 ABC consistent not implemented behavior (#2359) 2016-06-24 21:27:40 -07:00
Johann Kellerman
c616115419 rpi_gpi garage_door controller (#2369) 2016-06-24 21:22:10 -07:00
Daniel Perna
dfe1b8d934 Fixed minor feature-detection bug with incomplet configuration 2016-06-24 19:46:42 +02:00
John Arild Berentsen
ec8dc25c9c Zwave garagedoor (#2361)
* First go at zwave Garage door

* Refactor of zwave discovery

* Allaround fixes for rollershutter and garage door
2016-06-24 11:44:24 -04:00
Pascal Vizeli
67a04c2a0e Initial clean import 2016-06-24 10:06:58 +02:00
Dale Higgs
600a3e3965 Allow service data to be passed to shell_command (#2362) 2016-06-23 08:47:56 -07:00
Fabian Affolter
3349bdc2bd Log successful and failed login attempts (#2347) 2016-06-23 12:34:13 +02:00
Dan Cinnamon
12e26d25a5 Bump to pyenvisalink 1.0 (#2358) 2016-06-22 22:48:16 -07:00
Matthew Treinish
aa3d0e1047 Fix incorrect check on presence of password and pub_key (#2355)
This commit fixes an issue with the use of None in default values
for the config get() calls in __init__() of AsusWrtDeviceScanner.
These values are cast as strings and when a NoneType is cast it
returns the string "None" this broke the check for the existence
of these fields. This commit fixes the issue by changing the default
value to be an empty string '' which will conform with the behavior
expected by the ssh login code.

Closes #2343
2016-06-22 17:01:39 -07:00
happyleaves
d0ee8abcb8 couple fixes 2016-06-22 17:29:22 -04:00
happyleaves
94b47d8bc3 addressed review 2016-06-22 17:07:46 -04:00
Fabian Affolter
7b942243ab Increase interval (#2353) 2016-06-22 20:12:36 +02:00
Paulus Schoutsen
a70f922a71 ps - add reload core config service (#2350) 2016-06-22 09:13:18 -07:00
Jean-Philippe Bouillot
9ce9b8debb Add support for wind, battery, radio signals for Netatmo sensor (#2351)
* Add support for wind, battery, radio signals

* Fix indentation error

* second indentation fix

* Fix for pylint too many statements error

* Moving "pylint: disable=too-many-statements"
2016-06-22 09:01:53 -07:00
Dale Higgs
d7b006600e [notify.pushover] Fix 'NoneType' error on data retrieval (#2352)
* Fix 'NoneType' error on data retrieval

* Reduce code for empty dict as the default
2016-06-22 08:54:44 -07:00
Paulus Schoutsen
a564fe8286 Fix error log (#2349) 2016-06-21 22:26:40 -07:00
happyleaves
7fc9fa4b0c satisfy farcy 2016-06-21 19:31:40 -04:00
happyleavesaoc
d87e969671 add cec platform 2016-06-21 18:36:34 -04:00
Fabian Affolter
278514b994 Add support for Fixer.io (#2336)
* Add support for Fixer.io

* Add unit of measurment and set throttle to one day
2016-06-21 07:43:02 -07:00
Fabian Affolter
38b0336694 Upgrade paho-mqtt to 1.2 (#2339) 2016-06-20 21:51:50 -07:00
Fabian Affolter
caa096ebd5 Upgrade psutil to 4.3.0 (#2342)
* Upgrade psutil to 4.3.0

* Remove period
2016-06-20 21:51:07 -07:00
Fabian Affolter
ba417a730b Upgrade slacker to 0.9.17 (#2340) 2016-06-20 08:55:57 -07:00
dale3h
6fa095f4a7 Add additional Pushover parameters (#2309)
* Add additional Pushover parameters

Add support for more Pushover parameters: target (device), sound, url, url_title, priority, timestamp

* Remove data dictionary reference

https://github.com/home-assistant/home-assistant/pull/2309#discussion_r67603127
2016-06-19 23:08:30 -07:00
John Arild Berentsen
5efa076080 Make sure we exit loop when value is set (#2326) 2016-06-19 22:42:23 -07:00
Antonio Párraga Navarro
cbc0833360 Support for Sony Bravia TV (#2243)
* Added Sony Bravia support to HA

* Improvements to make it work on my poor raspberry 1

* Just a typo

* A few fixes in order to pass pylint

* - Remove noqa: was due to the 80 characters max per line restriction
- Move communication logic to a separate library at https://github.com/aparraga/braviarc.git
- Added dependency and adapt the code according to that

* A few improvements

* Just a typo in a comment

* Rebase from HM/dev

* Update requirements by executing the script/gen_requirements_all.py

* More isolation level for braviarc lib

* Remove unnecessary StringIO usage

* Revert submodule polymer commit

* Small refactorization and clean up of unused functions

* Executed script/gen_requirements_all.py

* Added a missing condition to ensure that a map is not null

* Fix missing parameter detected by pylint

* A few improvements, also added an empty line to avoid the lint error

* A typo
2016-06-19 22:35:26 -07:00
John Arild Berentsen
2e62053629 Basic implementation of Zwave Rollershutters (#2313)
* Basic implementation of Zwave Rollershutters

* Better filtering, by @wokar

* Fix typo

* Remove polling from component, and loop fix

* linter fix

* Filter to channel devices to correct component

* Remove overwriting of parent node name
2016-06-19 22:30:57 -07:00
Paulus Schoutsen
4f09279524 Merge pull request #2334 from home-assistant/hotfix-22-1
Hotfix 0.22.1
2016-06-19 21:16:22 -07:00
Paulus Schoutsen
57dfce1583 Version bump to 0.22.1 2016-06-19 20:55:21 -07:00
Paulus Schoutsen
33bafb8451 fix insteon hub discovery 2016-06-19 20:54:22 -07:00
Paulus Schoutsen
f59e242c63 fix insteon hub discovery 2016-06-19 20:53:56 -07:00
Dan Cinnamon
cb6f50b7ff Envisalink support (#2304)
* Created a new platform for envisalink-based alarm panels (Honeywell/DSC)

* Added a sensor component and cleanup

* Completed initial development.

* Fixing pylint issues.

* Fix more pylint issues

* Fixed more validation issues.

* Final pylint issues

* Final tweaks prior to PR.

* Fixed final pylint issue

* Resolved a few minor issues, and used volumptous for validation.

* Fixing final lint issues

* Fixes to validation schema and refactoring.
2016-06-19 10:45:07 -07:00
Paulus Schoutsen
44177a7fde Version bump to 0.23.0.dev0 2016-06-18 13:21:04 -07:00
Paulus Schoutsen
8c505e625b Merge pull request #2323 from home-assistant/dev
0.22
2016-06-18 13:20:51 -07:00
Paulus Schoutsen
314fa42298 Version bump to 0.22 2016-06-18 13:19:57 -07:00
Paulus Schoutsen
a80a74b586 Add camera timeouts 2016-06-18 13:06:14 -07:00
Paulus Schoutsen
2508e9f9ff Add timeout to mjpeg streams 2016-06-18 12:34:39 -07:00
Paulus Schoutsen
71157dbec9 Merge branch 'master' into dev
Conflicts:
	homeassistant/components/frontend/version.py
	homeassistant/components/frontend/www_static/core.js.gz
	homeassistant/components/frontend/www_static/frontend.html
	homeassistant/components/frontend/www_static/frontend.html.gz
	homeassistant/components/frontend/www_static/service_worker.js
	homeassistant/components/frontend/www_static/service_worker.js.gz
	homeassistant/const.py
2016-06-18 12:00:38 -07:00
devdelay
1f7792678b Add service set_hvac_mode (#2303)
* set hvac_mode

* Update __init__.py

* Update __init__.py
2016-06-18 10:20:39 -07:00
Phil Kates
40840044ca Wink Rollershutter (#2294)
* Update python-wink to 0.7.7

* Add Wink Rollershutter component
2016-06-18 09:59:13 -07:00
Nick Touran
2882f05f2c Added template rendering to shell_command component (#2268)
* Added template rendering to `shell_command` component

* Security upgrades to template rendering in shell_command.

* Added new unit tests for shell_command templates.
Better failure when template is invalid in shell_command
2016-06-18 09:57:18 -07:00
Fabian Affolter
b646accf87 Catch ValueError (#2296)
* Catch ValueError

* Less options and don't use state
2016-06-18 09:48:32 -07:00
Nick Touran
e7ea6ecf5a Better handling for when user hasn't properly configured Pandora client (#2317) 2016-06-18 08:23:35 -07:00
Paulus Schoutsen
29343ad651 Fix pep257 bt home hub 5 test 2016-06-18 08:20:14 -07:00
Fabian Affolter
28d86207e1 Add support for hydrological data from FOEN (#2318) 2016-06-18 08:18:48 -07:00
Fabian Affolter
6a01227635 Upgrade python-telegram-bot to 4.2.1 (#2319) 2016-06-18 08:16:28 -07:00
Nolan Gilley
b6fb21edaf Plex sensor (#2210)
add option to name in config

fix const import

use plexapi

add myplex support for remote access

use first server if server not specified

use list comprehension

use dictionary comprehension
2016-06-14 23:07:00 -07:00
Paulus Schoutsen
a65a122464 Fix discovery (#2305) 2016-06-14 22:51:46 -07:00
Nick Touran
5c601f1d5f Stability improvement in Pandora and proper shutdown in LIRC (#2299)
* Pandora cleanups and enhancements

Added media_content_type
reduced debug messages
made more robust station list
Eliminated auto-pause detection issue

* Added proper de-init of LIRC

* Now won't re-spawn Pandora client if turn_on command is sent twice
2016-06-14 22:42:54 -07:00
Lewis Juggins
7b8b78ec0e BT Home Hub 5 device tracker support (#2250) 2016-06-14 22:41:49 -07:00
Per Sandström
38030fcfca ASUSWRT Autodetect protocol (#2300) 2016-06-14 22:17:32 -07:00
Paulus Schoutsen
39913075f4 Fix Locative view name 2016-06-14 22:12:44 -07:00
Paulus Schoutsen
2036c44364 Hotfix 21 2 (#2302)
* Update frontend

Conflicts:
	homeassistant/components/frontend/version.py
	homeassistant/components/frontend/www_static/core.js.gz
	homeassistant/components/frontend/www_static/frontend.html
	homeassistant/components/frontend/www_static/frontend.html.gz
	homeassistant/components/frontend/www_static/home-assistant-polymer
	homeassistant/components/frontend/www_static/service_worker.js
	homeassistant/components/frontend/www_static/service_worker.js.gz

* Add a default OPTIONS handler for wsgi (#2301)

When a browser makes a CORS request, it often makes a 'preflight'
options request in order to make sure the resource is valid, and that
it has the right CORS access. This adds a default OPTIONS handler for
all views. If a view needs to customize the OPTIONS handler for some
reason, it's free to, but this way CORS will work.

* Version bump to 0.21.2
2016-06-14 19:54:09 -07:00
Josh Wright
3fcc07af04 Add a default OPTIONS handler for wsgi (#2301)
When a browser makes a CORS request, it often makes a 'preflight'
options request in order to make sure the resource is valid, and that
it has the right CORS access. This adds a default OPTIONS handler for
all views. If a view needs to customize the OPTIONS handler for some
reason, it's free to, but this way CORS will work.
2016-06-14 19:44:12 -07:00
Paulus Schoutsen
65750f667b Update frontend 2016-06-14 18:39:44 -07:00
Per Sandström
f07ba1e9a6 Merge pull request #2298 from persandstrom/verisure_lower_severity_of_message
lower severity of non critical error
2016-06-14 20:56:49 +02:00
Per Sandström
6e5e0e7acc lower severity of non critical error 2016-06-14 20:21:42 +02:00
Paulus Schoutsen
9d7c9d1262 Update frontend 2016-06-13 20:11:01 -07:00
Paulus Schoutsen
42c5475284 Fix Wink discovery 2016-06-13 20:06:32 -07:00
Edward Romano
8e839be938 Refactor Forecast.io (#2217)
* Refactor Forecast.io

* Some more refactoring and code review workoff

* Dict switch refactor

* CamelCase for data lookup

* Fixing unit_of_measure update

* Better default return for unit_of_measurement

* Test fix
2016-06-13 18:54:49 -07:00
Paulus Schoutsen
ab48010d14 Add 1024x1024 favicon 2016-06-13 00:04:54 -07:00
Matthew Treinish
1381984b77 Add ssh public key support to the asuswrt component (#2287)
The pexpect.pxssh module has support for using public key
authentication. [1] This commit adds support for leveraging that and
establishing a ssh connection with a public key instead of a password.

[1] http://pexpect.readthedocs.io/en/stable/api/pxssh.html#pexpect.pxssh.pxssh.login
2016-06-12 21:27:41 -07:00
Paulus Schoutsen
6dcf3682df Tweak event helper 2016-06-12 20:37:37 -07:00
Nick Touran
65d1f7af50 Added Pandora radio media player (#2274)
* Added Pandora media player utilizing the Pianobar client

* Added Pandora to .coveragerc ignore

* Fixes some docstring formats in Pandora

* More minor formatting tweaks for Pandora

* Eliminated non-portable assumption from Pandora component

* Updated Pandora to properly update currently-playing song.

* Docstring fixes in Pandora

* Added check to ensure Pianobar client is available in path for Pandora.

* Made Pandora client verification a function instead of method.

* Better handling of dependency verification in Pandora.
2016-06-12 18:35:12 -07:00
Jesse Zoldak
16f4695a13 Add tests for forecast.io (#2227)
* Add tests for forecast.io

* Fix linting items and don't call a platform a component
2016-06-12 17:22:58 -07:00
Landrash
c7ee74a573 Local file - Camera platform (#2282) 2016-06-12 16:26:29 -07:00
arsaboo
8e2c1ff4aa Include the Voltage sensor (#2285)
The API provides the voltage information and will be useful for people to troubleshoot their BloomSky.
2016-06-12 16:19:13 -07:00
thejacko12354
e437151881 Update samsungtv.py (#2286)
Changed line 75 'KEY_POWER' to 'KEY'
Fixes the problem that every 10 sec the tv interprets that the Up-button is pressed
2016-06-12 16:03:40 -07:00
Martin Hjelmare
81ca175906 Add mysensors IR switch device and service (#2239)
* Add mysensors IR switch device and service

* Add MySensorsIRSwitch as child class to MySensorsSwitch.
* Add platform specific service mysensors_send_ir_code. Only call
	device method in service function if device is IR device.
* Add service and required attribute to state helper to support scenes.
* Move V_IR_SEND type from sensor.mysensors to switch.mysensors
	platform.
* Populate switch.services.yaml with service descriptions.

* Fix check of entity_id in service function

Since multiple entity_ids can be passed as service data, and the
entity_id service attribute is forced to a list by the service
validation schema, the check in the service function should iterate
over any entity ids.
2016-06-12 23:04:45 +02:00
Paulus Schoutsen
ebe4c39020 Merge branch '0-21-1' into dev
Conflicts:
	homeassistant/components/frontend/www_static/core.js.gz
	homeassistant/components/frontend/www_static/frontend.html.gz
	homeassistant/components/frontend/www_static/service_worker.js.gz
	homeassistant/const.py
	requirements_all.txt
	setup.py
2016-06-12 00:25:36 -07:00
Paulus Schoutsen
952afeb717 Merge pull request #2281 from home-assistant/0-21-1
Hotfix 0.21.1
2016-06-12 00:23:03 -07:00
Paulus Schoutsen
40be883c0e version bump to 0.21.1 2016-06-12 00:06:37 -07:00
Paulus Schoutsen
5c87883c86 Update frontend 2016-06-12 00:04:37 -07:00
St. John Johnson
b2b1804f5e Fixing MJPEG streaming in Werkzeug by taking advantage of direct_passthrough (#2277) 2016-06-12 00:03:18 -07:00
Paulus Schoutsen
f5fc4cd97f Alexa: run script before generating response text (#2276) 2016-06-12 00:03:18 -07:00
Paulus Schoutsen
bc78997bbd Bugfixes random (#2270)
* Fix Z-Wave autoheal network

* Make config_per_platform handle bad config better
2016-06-12 00:03:18 -07:00
Paulus Schoutsen
35dd3b8d0d Update screenshot README 2016-06-12 00:03:17 -07:00
Nick Touran
491c06f53b Recover from rare error condition from LIRC (#2267)
* More resilient accessing of LIRC codes to handle rare error case.

* Line length fix in LIRC
2016-06-12 00:03:17 -07:00
Gergely Imreh
31c1b7f6ad sensor/gtfs: add sanity check, origin earlier than destination (#2265)
Previously experienced issues on routes where services operate in both
directions. The query picked up not just paths where service goes
from Origin ->  Destination, but trips going Destination -> Origin,
and shown bogus results.

Ensure that this doesn't happen by requiring the origin station's
stop_sequence value to be lower than the destination station.
2016-06-12 00:03:17 -07:00
Paulus Schoutsen
da5b50848a Add eventlet to base requirements (#2264)
Conflicts:
	requirements_all.txt
	setup.py
2016-06-12 00:02:58 -07:00
Paulus Schoutsen
586f69ac95 Update frontend 2016-06-11 23:57:24 -07:00
St. John Johnson
3723c3a7e8 Fixing MJPEG streaming in Werkzeug by taking advantage of direct_passthrough (#2277) 2016-06-11 20:50:10 -07:00
Paulus Schoutsen
145c98c40c Alexa: run script before generating response text (#2276) 2016-06-11 17:57:04 -07:00
Paulus Schoutsen
30f74bb3ca Migrate to generic discovery method (#2271)
* Migrate to generic discovery method

* Add tests for discovery
2016-06-11 17:43:13 -07:00
Paulus Schoutsen
c9756c40e2 Bugfixes random (#2270)
* Fix Z-Wave autoheal network

* Make config_per_platform handle bad config better
2016-06-10 22:53:31 -07:00
Paulus Schoutsen
b60806583c Update asuswrt.py 2016-06-10 21:14:11 -07:00
Michaël Arnauts
868c08e34b Add stop command to google cast component (#2269)
* Add stop command to google cast component

* Add SUPPORT_STOP capabilities to google cast component
2016-06-10 21:12:50 -07:00
Paulus Schoutsen
71eb09ee5e Fix configurator tests 2016-06-10 20:50:04 -07:00
Paulus Schoutsen
809e613148 Update frontend 2016-06-10 19:45:15 -07:00
Paulus Schoutsen
0dbc023f5b Fix lint errors 2016-06-09 23:41:26 -07:00
Joseph Piron
b6d75e6c5a Netio Switch platform support (#2181)
* WSGI based request handler

with a bit of polishing

Signed-off-by: eagleamon <joseph.piron@gmail.com>

* removed stale comment and fixed version, but failed tests do not seem to be related

* removing the wrapper hack

* added in requirements file

* Found the caved in lint error..
2016-06-09 23:40:14 -07:00
wind-rider
c78e6c088e Add a swagger.yaml file (#2182)
* Add a swagger.yaml file

@balloob
I created a swagger configuration file that will help people create clients (apps / frontends) for Home Assistant more easily. Based upon this code it is even possible to generate client code for several programming languages.

I created it by hand now, so when the API changes it will need to be updated. That's why it would be better to generate this specification automatically. This is possible for API frameworks but I don't know whether it is possible for the handwritten endpoints in Home Assistant. Maybe you could assist here?

This documentation could be used to replace a part of https://home-assistant.io/developers/rest_api/.

* Added restrict parameter

* Moved swagger file to docs folder
2016-06-09 23:35:47 -07:00
Thiago Oliveira
02f342b670 add fan_min_on_time service to ecobee (#2159) 2016-06-09 23:34:29 -07:00
Hugo Dupras
213a738240 Add Netatmo component and add support for Netatmo Welcome Camera (#2233)
* Introducing the Netatmo component

As Netatmo is providing several type of device (sensor, camera), a new Netatmo
component needs to be created in order to centralize the Netatmo login data.
Currently this change only impacts the Netatmo Weather station

* Add new Netatmo library

This new API will provide access to the Welcome Camera

* Basic support for Netatmo Welcome camera

This change introduces support for Netatmo Welcome camera. Currently, it will
add all detected camera to Home Assistant, camera filtering (similar to the one
used for weather station modules) will be added later

* Remove useless REQUIREMENTS

* Fixes for Netatmo Welcome support

* Allow to filter Welcome cameras by name and/or home

* Update requirements for Netatmo components

* Fix multi-camera support for Welcome

* Fix pep8 error/warning

* This commit also adds improved logging for bad credentials

* Add Throttle decorator for Welcome update function

As the update function updates the data for all cameras, we should prevent this
function to be called several time during an interval
2016-06-09 23:31:36 -07:00
Paulus Schoutsen
e4fe8336cc Update frontend 2016-06-09 23:27:35 -07:00
Paulus Schoutsen
068e62623d Update frontend 2016-06-09 22:12:45 -07:00
Jeffrey Lin
30f5727b40 Added support for AP mode in asuswrt (#2263)
* Added support for AP mode in asuswrt

* Corrected number of return values in asuswrt
2016-06-09 21:30:47 -07:00
Paulus Schoutsen
815a6999b1 Update screenshot README 2016-06-09 21:23:20 -07:00
Nick Touran
c229d9e90f Recover from rare error condition from LIRC (#2267)
* More resilient accessing of LIRC codes to handle rare error case.

* Line length fix in LIRC
2016-06-09 20:53:41 -07:00
Gergely Imreh
abc353c083 sensor/gtfs: add sanity check, origin earlier than destination (#2265)
Previously experienced issues on routes where services operate in both
directions. The query picked up not just paths where service goes
from Origin ->  Destination, but trips going Destination -> Origin,
and shown bogus results.

Ensure that this doesn't happen by requiring the origin station's
stop_sequence value to be lower than the destination station.
2016-06-09 20:48:12 -07:00
Paulus Schoutsen
38639d26ea Add eventlet to base requirements (#2264) 2016-06-09 18:47:35 -07:00
Hugo Dupras
1c637558bf Round download speed for nzbget sensor (#2255) 2016-06-09 08:06:01 -07:00
mikebarris
5223d20668 Removed webcolors dependency in favor of dictionary lookup. (#2215)
* Removed webcolors dependency in favor of dictionary lookup.

* Fixed code style errors.

* Moved color dictionary to module per suggestion.

* Removed try/except per suggestion.
2016-06-08 22:25:32 -07:00
Dan Sullivan
ce829d194c Added Sonos snapshot feature (#2240)
* Added Sonos snapshot feature

* Fix lint errors

* Use snake case

* Import dependency in a method
2016-06-08 21:47:49 -07:00
srirams
4a5ad24ae0 fix zwave thermostat with multiple setpoints (#2237)
* fix zwave thermostat with multiple setpoints

* fix zwave thermostat with multiple setpoints
2016-06-08 21:39:44 -07:00
Fabian Affolter
33cb1b3be6 SNMP sensor (#2244)
* Add snmp sensor

* Add ATTR_UNIT_OF_MEASUREMENT
2016-06-08 21:16:43 -07:00
Paulus Schoutsen
0525af920c Update betamax casettes 2016-06-08 21:06:14 -07:00
Fabian Affolter
831799a7af Upgrade betamax to 0.7.0 2016-06-08 21:06:14 -07:00
Fabian Affolter
8e5da5776d Add missing key 'forecast' (#2256) 2016-06-08 20:59:20 -07:00
Fabian Affolter
be9730cc6c Upgrade astral to 1.2 (#2259) 2016-06-08 20:58:16 -07:00
Daniel Høyer Iversen
e44c2a4016 Improve config validation for group (#2206)
* Improve config validation if invalid entity for groups

* Improve error message when entity id is invalid
2016-06-08 20:55:08 -07:00
Paulus Schoutsen
29ffa5c282 Version bump to 0.22.0.dev0 2016-06-07 19:28:13 -07:00
Paulus Schoutsen
d7b0929a32 Merge pull request #2183 from home-assistant/dev
0.21
2016-06-07 19:27:55 -07:00
Paulus Schoutsen
31489a56db Merge remote-tracking branch 'origin/master' into dev
Conflicts:
	homeassistant/const.py
2016-06-07 19:27:23 -07:00
Paulus Schoutsen
3e09a7360e Version bump to 0.21 2016-06-07 19:26:43 -07:00
Daniel Høyer Iversen
0cdd752d6c Fixed bug in google time travel (#2202)
Fixed bug in google time travel  when arrival time is given
2016-06-07 19:19:47 -07:00
Adam Mills
027c0b3168 Add turn_off_action to kodi media player (#2224)
A new configuration option `turn_off_action` is added to kodi. It may be
one of: none, quit, hibernate, suspend, reboot, or poweroff. The
appropriate command is sent to kodi when the turn_off action is
requested. Default value is none.

Kodi will only report turn_off supported if it is configured to
something other than none.
2016-06-07 19:18:25 -07:00
Paulus Schoutsen
271546d101 Merge branch 'pr/2251' into dev
Conflicts:
	homeassistant/components/switch/template.py
2016-06-07 19:16:14 -07:00
Johann Kellerman
d1ed17e7db Default parameter for .run() 2016-06-07 23:00:09 +02:00
Alex Harvey
fb2fb5ea73 zwave auto heal at midnight (#2213)
* zwave auto heal at midnight

* fix debug to info, running heal, any heal will send a logger event
2016-06-07 09:29:15 -07:00
John Arild Berentsen
202a8dba8e Hvac fix (#2221)
* Zwave hvac fix

* Zwave hvac fix and move max min temp to base

* Tests
2016-06-07 08:43:46 -07:00
Kyle Hendricks
042a482ef1 Add sensor for DTE Energy Bridge (#2247)
Currently only measures instantaneous energy usage in kW
2016-06-07 08:42:34 -07:00
Alexander Fortin
fff413e04e Improve vagrant provisioner resiliency (#2252)
This should make it easier to fix race conditions that might arise if
box is destroyed but setup_done placeholder file is not removed
properly
2016-06-07 08:35:40 -07:00
Dan Smith
e29459a1ae Merge pull request #2241 from kk7ds/unifi-3.2
Add support for UniFi Video >= 3.2.0
2016-06-06 20:33:45 -07:00
Dan Smith
49de55e75b Add support for UniFi Video >= 3.2.0
Unfortunately, Ubiquiti changed their (supposedly versioned) API in
3.2.0 which causes us to have to refer to cameras by id instead of
UUID. The firmware for 3.2.x also changed the on-camera login procedures
and snapshot functionality significantly.

This bumps the requirement for uvcclient to 0.9.0, which supports the
newer API and makes the tweaks necessary to interact properly.
2016-06-06 20:28:52 -07:00
Hugo D
ee4b1e2b78 The metric unit of pressure is mbar not mBar (#2248)
This is useful to vaoid having several graph for the same type of data
According to wikipedia:
Units derived from the bar include the megabar (symbol: Mbar),
kilobar (symbol: kbar), decibar (symbol: dbar), centibar (symbol: cbar),
and millibar (symbol: mbar or mb).
2016-06-06 08:00:26 -07:00
Johann Kellerman
ed44d28fc0 service helper replaced with script helper (#2242) 2016-06-06 07:36:04 -07:00
Johann Kellerman
d5f9c1bc01 Updated template switch to cache Script objects 2016-06-06 06:41:29 +02:00
Fabian Affolter
f69c900977 Add schema (#2226) 2016-06-05 16:00:51 -07:00
Fabian Affolter
9a7ea72fa0 Upgrade schiene to 0.17 (#2231) 2016-06-05 15:59:54 -07:00
Fabian Affolter
fd4a9cf7c5 Upgrade fuzzywuzzy to 0.10.0 (#2234) 2016-06-05 15:58:54 -07:00
Fabian Affolter
0fe375049a Upgrade slacker to 0.9.16 (#2235) 2016-06-05 15:58:21 -07:00
Fabian Affolter
69f2f0f34a Upgrade pysnmp to 4.3.2 (#2236)
* Upgrade pysnmp to 4.3.2

* Fix pylint issue
2016-06-05 15:57:46 -07:00
Alex Harvey
076fdc3f8b Add a robots.txt (#2207) 2016-06-05 18:48:59 -04:00
Johann Kellerman
8887c2a8af service helper replaced with script helper 2016-06-05 21:44:57 +02:00
Fabian Affolter
f4594027fd Upgrade blockchain to 1.3.3 (#2220) 2016-06-04 12:55:46 +02:00
Robbie Trencheny
59a0005e5c Add CORS to WSGI (#2209)
* Add CORS support to WSGI

* Remove X-HA-Access as a CORS header, because as @JshWright so elegantly put it: "CORS controls access to response headers, not request headers"
2016-06-03 12:53:43 -07:00
Johann Kellerman
9157f722a4 Update Qwikswitch library version (#2214) 2016-06-02 18:47:29 -07:00
Fabian Affolter
7f2a1c61da Upgrade python-telegram-bot to 4.2.0 (#2204) 2016-06-02 04:38:39 -07:00
Sam Riley
0eb9516ea7 Support for RFY protocol (#2199) 2016-06-02 03:48:42 -07:00
Greg Dowling
3bb3a70347 Merge pull request #2203 from home-assistant/bump_loopenergy
Bump pyloopenergy version.
2016-06-02 11:21:48 +01:00
pavoni
0262269b00 Bump loopenergy version. Increased interval before deciding connection is dead and reconnecting. 2016-06-02 11:08:24 +01:00
Greg Dowling
780d62ac5c Merge pull request #2201 from home-assistant/fix_pywemo_ssdp_decode_utf8
Bump pywemo version to fix ssdp discovery encoding issue.
2016-06-02 10:09:13 +01:00
pavoni
5fca9e170e Bump pywemo version to fix ssdp discovery encoding issue. 2016-06-02 09:58:54 +01:00
Jacob Tomlinson
ca7415e935 Added rfxtrx rollershutter (#2030)
* Added rfxtrx rollershutter

* Updated mock command with real one

* Corrected test string
2016-06-02 00:39:58 -07:00
Alex Harvey
26d3c3b0d6 Update PULL_REQUEST_TEMPLATE.md (#2198)
* Update PULL_REQUEST_TEMPLATE.md

* Update PULL_REQUEST_TEMPLATE.md
2016-06-01 23:57:03 -07:00
Paulus Schoutsen
81f8764bb8 Update frontend 2016-06-01 23:47:31 -07:00
Nolan Gilley
24d2eaa6ca flux platform as a switch (#2097)
* flux platform as a switch

* use track_time_change. broken :(

* use track_utc_time_change instead of track_time_change

* add some basic tests

* use brightness from RGB_to_xy

* config_schema validation

* back to platform schema. what was i doing?

* more broken tests :(

* 644

* fix some time bugs

* add working tests. config validation still not right

* bug fixes and more test cases.
2016-06-01 23:38:19 -07:00
Paulus Schoutsen
f868df1035 Fix Norway (#2197) 2016-06-01 23:02:46 -07:00
Paulus Schoutsen
d0988422d4 Merge pull request #2196 from home-assistant/revert-2192-expose-required-ssl-in-discoveries
Revert "Report whether SSL is required in discovery"
2016-06-01 22:48:17 -07:00
Robbie Trencheny
f522d95328 Revert "Report whether SSL is required in discovery" 2016-06-01 22:37:16 -07:00
Robbie Trencheny
c856c67790 Report whether SSL is required in discoverables, like /api/discovery_info and ZeroConf (#2192) 2016-06-01 19:45:19 -07:00
Paulus Schoutsen
6c5efd5b7e Merge pull request #2195 from home-assistant/hotfix-20-3
Hotfix 20 3
2016-06-01 17:39:42 -07:00
Paulus Schoutsen
c3b6086d80 Version bump to 0.20.3 2016-06-01 17:36:04 -07:00
Paulus Schoutsen
0d93369154 Optimize foreacast.io API calls 2016-06-01 17:35:50 -07:00
Paulus Schoutsen
4e064f91fd Merge pull request #2191 from home-assistant/forecast-api-calls
Optimize foreacast.io API calls
2016-06-01 17:32:55 -07:00
Fabian Affolter
f9e53ca22f Add windows 10 tile (#2166) 2016-06-01 14:04:08 -07:00
Paulus Schoutsen
f8bdc835f8 Optimize foreacast.io API calls 2016-06-01 09:20:29 -07:00
Fabian Affolter
1f602be80a Remove print (already covered by logger) (#2184) 2016-05-31 14:02:31 -07:00
Josh Wright
fe4d971427 Re-add config validation for the http component (#2186)
This commit adds back the config validation for the http component. It
was removed during the WSGI shuffle. This is just a direct copy of what
@robbiet480 added in ab294d12f7 (with some testing to verify it still
works).
2016-05-31 14:00:12 -07:00
Paul Philippov
e5efc2e430 Improve Internet Time calculation. (#2185) 2016-05-31 07:19:00 -07:00
Paulus Schoutsen
537a2a6ef6 Improve index.html template 2016-05-30 23:45:02 -07:00
Paulus Schoutsen
11cc065845 Merge remote-tracking branch 'origin/master' into dev
Conflicts:
	homeassistant/const.py
2016-05-30 10:40:50 -07:00
Paulus Schoutsen
3ac31b2c1b Fix broken tests + linting 2016-05-30 10:19:12 -07:00
Paulus Schoutsen
a91f937245 Fix linting issues 2016-05-30 10:08:49 -07:00
Fabian Affolter
fed2584d8a Add azimuth (#1951)
* Add azimuth

* Place elevation and azimuth together in update part
2016-05-29 15:03:29 -07:00
Paulus Schoutsen
eaa8e5f29d Merge branch 'pr/2139' into dev
Conflicts:
	.coveragerc
2016-05-29 15:02:24 -07:00
Bart274
65fbba0e79 List entity_ids in config and only react to them (#2144)
* List entity_ids in config and only react to them

This allows us to define a list of entity_ids in the config to make the
template sensor, binary sensor and switch only react to state changes of
these entities instead of listening to all state changes.

* Forgot to import the track_state_change function

* Changed test for added entity_ids to config

* Use default MATCH_ALL and remove event_listener
2016-05-29 14:34:21 -07:00
Alexander Fortin
19522b1f39 Feedreader: add file data storage (#2147)
Right now we ignore already parsed entries and store the information
at runtime, but it will not survive a restart. This patch adds storage
functionality storing pickled file into default config folder when
feed has `published_parsed` support.
2016-05-29 14:33:53 -07:00
Jan Harkes
afe84c2a8b Allow time condition windows to cross midnight. (#2158)
* Allow time condition windows to cross midnight.

* Address comments.

Fold _in_time_window back into the time() condition test.
Use specific time values to test the time window.
2016-05-29 14:32:32 -07:00
Warren Konkel
952436aa0b Insteon support for brightness (#2169)
* Insteon support for brightness

* Farcy fix for unused constants.

* Remove unused constant and fix whitespace.

* Prevent toggle switches from jumping between states.

* 255 not 256
2016-05-29 14:31:14 -07:00
Olimpiu Rob
8a577c8e0d Added Osram lightify platform (#2170)
* Added Osram Lightify light component

* Added color temperature and fade transition support to Osram Lightify

* Added Osram Lightify light component

* Added color temperature and fade transition support to Osram Lightify

* Updated docstring

* Added osramlightify to ignore list on coveragerc and updated docstrings

* Fixed linting issues
2016-05-29 14:29:49 -07:00
rubund
bf940bd1f3 Initial support for EnOcean (#2177)
* Initial support for EnOcean

Tested to work with:
 - Eltako FUD61 dimmer
 - Eltako FT55 battery-less switch
 - Permundo PSC234 (switch and power monitor)

* Rerun gen_requirements_all.py
2016-05-29 14:28:03 -07:00
rubund
03e8627b12 New option for the netatmo platform: station (#2178)
This is necessary if multiple weather stations are associated with
one Netatmo account.
2016-05-29 14:25:11 -07:00
Brent
e886303f08 Fixed roku exception when device is powered off or looses connection (#2173) 2016-05-29 14:24:06 -07:00
Fabian Affolter
4b0df51b40 Vendorize vincenty requirement (#2176) 2016-05-29 11:55:16 -07:00
Paulus Schoutsen
8494ac7cef Update frontend 2016-05-29 09:50:30 -07:00
Alexander Fortin
5076ebe43c Add Vagrant setup (#2171) 2016-05-28 23:58:09 -07:00
Paulus Schoutsen
05b2559df8 Update frontend 2016-05-28 23:28:57 -07:00
Paulus Schoutsen
70b74da3eb Update frontend 2016-05-28 18:38:46 -07:00
Paulus Schoutsen
9e0b107991 Update frontend 2016-05-28 11:32:35 -07:00
Paulus Schoutsen
92d05ccb5c Fix lint errors 2016-05-28 10:52:44 -07:00
Paulus Schoutsen
bfdb51a558 Bugfixes for urls with dates 2016-05-28 10:37:22 -07:00
Paulus Schoutsen
e10b00f341 Update frontend 2016-05-27 21:45:38 -07:00
Paulus Schoutsen
cd87c40bbf Update frontend 2016-05-27 01:29:48 -07:00
Paulus Schoutsen
d02bc3deaa Update frontend gzip 2016-05-26 23:08:15 -07:00
Paulus Schoutsen
1798df7686 Handle invalid dev ids for dev tracker + owntracks (#2174) 2016-05-26 21:49:44 -07:00
ntouran
d505398917 Locked in required version of python-lirc for LIRC component 2016-05-26 07:53:17 -07:00
s1gnalrunner
70d6ce5b79 Fixed issue with edimax SP-1101 switches (#2105)
* Fixed issue with edimax SP-1101 switches

* Added missing ValueError exception
2016-05-26 05:53:10 -07:00
Daniel Høyer Iversen
71452c11c1 Fix bug in google travel time. Default option dictionary must contain mode. (#2134) 2016-05-26 05:52:17 -07:00
ntouran
e30f2bf912 Cleanups to LIRC module 2016-05-25 22:26:00 -07:00
ntouran
262d95b7b1 Merge remote-tracking branch 'origin/dev' into lirc 2016-05-25 09:21:58 -07:00
William Scanlon
ca3da0e53e Round temp and percentage for octoprint sensors (#2128) 2016-05-25 09:10:59 -07:00
Fabian Affolter
49882255c4 Upgrade astral to 1.1 (#2131) 2016-05-25 09:10:08 -07:00
Scott Bartuska
3db31cb951 Update PyISY to 1.0.6 (#2133)
* Update PyISY to 1.0.6 

1.0.6 is the newest version of PyISY

* PyISY to 1.0.6
2016-05-25 09:09:40 -07:00
Paulus Schoutsen
415cfc2537 WSGI: Hide password in logs (#2164)
* WSGI: Hide password in logs

* Add auth + pw in logs tests
2016-05-24 23:19:37 -07:00
wokar
88bb136813 lg_netcast: fix exception on missing access_token (#2150)
* specified default value for acccess_token to prevent exception on init
2016-05-24 08:36:40 -07:00
Paulus Schoutsen
4cecc626f4 manifest.json: remove trailing commas 2016-05-23 22:45:35 -07:00
Paulus Schoutsen
644d5de890 Merge pull request #2154 from home-assistant/hotfix-20-2
Hotfix 20 2
2016-05-23 22:25:59 -07:00
ntouran
148b8c5055 Updated requirements for LIRC 2016-05-23 21:47:46 -07:00
ntouran
09161ae615 Moved lirc out of sensor package. 2016-05-23 21:36:48 -07:00
ntouran
c1f96aabb0 Changed LIRC component so that it just fires events on the bus. 2016-05-23 21:26:49 -07:00
Robbie Trencheny
343625d539 If we have duration_in_traffic use that as the state, otherwise use duration 2016-05-23 23:43:22 -04:00
Robbie Trencheny
2e10b4bf67 If no departure time is set, use now as the default. If departure time is set but does not have a :, assume its a preformed Unix timestamp and send along as raw input. Assume same for arrival_time. 2016-05-23 23:43:06 -04:00
Jan Harkes
dc8e55fb8b Don't even bother trying to kill stray child processes.
When we change our process group id we don't get keyboard interrupt
signals passed if our parent is a bash script.
2016-05-23 23:30:41 -04:00
Jan Harkes
d86a5a1e91 Don't even bother trying to kill stray child processes.
When we change our process group id we don't get keyboard interrupt
signals passed if our parent is a bash script.
2016-05-23 23:29:53 -04:00
Jan Harkes
1327051277 Version bump to 0.20.2 2016-05-23 23:29:53 -04:00
Josh Wright
712c51e283 Fix TLS with eventlet (#2151)
* Fix TLS with eventlet

This fixes a simple error on my part when implementing the WSGI stuff.

eventlet.wrap_ssl() returns a wrapped socket, it does not modify the
object passed to it. We need to grab the returned value and use that.

* Fix style issue
2016-05-23 17:39:55 -07:00
Robbie Trencheny
c96f73d1be If we have duration_in_traffic use that as the state, otherwise use duration 2016-05-23 14:05:12 -07:00
Robbie Trencheny
b3afb386b7 If no departure time is set, use now as the default. If departure time is set but does not have a :, assume its a preformed Unix timestamp and send along as raw input. Assume same for arrival_time. 2016-05-23 13:48:47 -07:00
Robbie Trencheny
2544635921 Update issue template to prettify the header. 2016-05-23 13:08:47 -07:00
ntouran
4e5b5f2204 LIRC: Responded to some code review requests but not the big one 2016-05-22 22:19:10 -07:00
Paulus Schoutsen
98de7c9287 Upgrade eventlet to 0.19 2016-05-22 20:14:46 -07:00
ntouran
80e60efd8f Removed LIRC dependency from requirements due to "complex" compliation
User will have to install lirc and python-lirc manually.
2016-05-22 16:28:20 -07:00
ntouran
b3e9e1dfcd added LIRC component to .coveragerc 2016-05-22 16:11:26 -07:00
ntouran
40bc49aaae Added LIRC component for responding to IR remote commands 2016-05-22 14:15:09 -07:00
Paulus Schoutsen
3c364fa7e9 Merge pull request #2132 from home-assistant/hotfix-20-1
Hotfix 0.20.1
2016-05-22 09:11:47 -07:00
Jan Harkes
05946ae5a2 Ignore assertions from python threading when looking for leaked threads. (#2130)
While looking for leaked resources (threads) after shutdown and before restart
we in some cases get an assertion in the python threading module where we find
a thread marked as running at the python level but it has no associated thread
at the C level.
2016-05-22 00:35:33 -04:00
Jan Harkes
ceb0ec5fa4 Ignore assertions from python threading when looking for leaked threads.
While looking for leaked resources (threads) after shutdown and before restart
we in some cases get an assertion in the python threading module where we find
a thread marked as running at the python level but it has no associated thread
at the C level.
2016-05-22 00:22:19 -04:00
Jan Harkes
a28196df9a Version bump to 0.20.1 2016-05-22 00:21:19 -04:00
Paulus Schoutsen
c7cc045acd Use only 1 event listener for event stream. 2016-05-21 18:24:03 -07:00
Paulus Schoutsen
225a672a92 Fix Dockerfile 2016-05-21 17:03:46 -07:00
Paulus Schoutsen
4d5eb0e3fc EventStream to sent ping on start to notify browser 2016-05-21 16:31:22 -07:00
Paulus Schoutsen
a68ab07e72 Another attempt to fix SSL in Docker 2016-05-21 16:23:03 -07:00
Paulus Schoutsen
ec4fe7e6e6 update frontend gz 2016-05-21 16:00:59 -07:00
Paulus Schoutsen
0b4b46d80b Merge pull request #2063 from home-assistant/feature/wsgi
Feature/wsgi
2016-05-21 15:14:12 -07:00
Paulus Schoutsen
3bbdd9fedd Remove unused import 2016-05-21 15:01:55 -07:00
Paulus Schoutsen
2ed135439a Remove gzip API 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
1750b22e59 Gzip all the things 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
9c5e7a9584 Add gzip for static resources 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
9b03848a2e Comment out eventstream tests 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
548d415f94 Clean up EventStream 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
18be276b08 Make event stream tests work on Travis ? 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
9aa9e57890 Cleanup 2016-05-21 15:01:35 -07:00
Paulus Schoutsen
8fe2654862 Update requirements with new static update 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
794ff20987 Get EventStream working 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
fe794d7fd8 Access camera images using access token 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
585fbb1c02 Cache files in static folder for a year 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
e4b697b1ed Generate gzip for frontend/mdi 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
de5533e3c2 Fix auth frontend 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
5aa0158761 Add url validators 2016-05-21 15:01:34 -07:00
Paulus Schoutsen
4d7555957c Fix camera 2016-05-21 15:01:34 -07:00
Josh Wright
aa34fe15b2 Friendlier exceptions for misconfigured views
If a view is missing a url or name attribute, this will result
in a more actionable exception being raised.
2016-05-21 15:01:34 -07:00
Paulus Schoutsen
1096232e17 More WIP 2016-05-21 15:01:34 -07:00
Josh Wright
54ecab7590 Improve view registration comments
Clarify that HomeAssistantWSGI.register_view() can handle either instantiated or uninstantiated view classes.
2016-05-21 15:01:33 -07:00
Paulus Schoutsen
15e329a588 Tons of fixes - WIP 2016-05-21 15:01:33 -07:00
Paulus Schoutsen
768c98d359 Fix import issues 2016-05-21 15:01:02 -07:00
Josh Wright
6490378de3 Add some missing view registrations 2016-05-21 15:01:01 -07:00
Josh Wright
d0320a9099 WIP: Add WSGI stack
This is a fair chunk of the way towards adding a WSGI compatible stack
for Home Assistant. The majot missing piece is auth/sessions. I was
undecided on implementing the current auth mechanism, or adding a new
mechanism (likely based on Werkzeug's signed cookies).

Plenty of TODOs...
2016-05-21 15:01:01 -07:00
Paulus Schoutsen
9116eb166b Version bump to 0.21.0.dev0 2016-05-21 14:19:06 -07:00
Paulus Schoutsen
37bd93a975 Version bump to 0.20 2016-05-21 14:17:02 -07:00
Paulus Schoutsen
b78765a41f Merge pull request #2113 from home-assistant/dev
0.20
2016-05-21 14:15:42 -07:00
Paulus Schoutsen
ab60b32326 Update frontend 2016-05-21 14:06:07 -07:00
Jan Harkes
3ea179cc0b Let systemd handle home-assistant process restarts. (#2127) 2016-05-21 12:58:14 -07:00
Paulus Schoutsen
5bedf5d604 Upgrade Nest to 2.9.2 (#2126) 2016-05-21 11:57:33 -07:00
Ardi Mehist
d8c1959715 Add support for Logentries (#1945)
* Add support for Logentries

Supports sending has events to Logentries web hook endpoint
see logentries.com for more

Inspired by the Splunk component

* bugfix

* fix summary

* fix test

* fix logentries url and tests

* update tests

* mock token

* Bug fixes

* typo

* typo

* fix string splitting

* remove redundant backslash
2016-05-21 11:21:23 -07:00
Robbie Trencheny
0f1c4d2f8c GTFS fixes (#2119)
* Change to official PyGTFS source

* Threading fixes for GTFS

* Actually pygtfs 0.1.3

* Update requirements_all.txt

* Update gtfs version
2016-05-21 11:04:18 -07:00
Igor Shults
3ce6c732ab #2120 Fix hvac z-wave fan list (#2121)
* #2120 Fix hvac z-wave fan list

* Properly name methods
2016-05-21 10:56:20 -07:00
Nolan Gilley
191fc8f8d4 Change color_RGB_to_xy formula & return brightness (#2095)
* Use RGB to XY calculations from Philips Hue developer site

* uppercase X,Y,Z

* rename cx,cy to x,y

* return brightness in color_RGB_to_xy

* remove try/catch

* update existing platforms using color_RGB_to_xy

* improve wemo w/ jaharkes suggestion

* allow brightness override of rgb_to_xy
2016-05-21 10:19:27 -07:00
Johann Kellerman
31c2d45a7a Updated pyqwikswitch & QS<->HA UI behaviour (#2123)
* Updated pyqwikswitch & constants

* Disable too-many-locals
2016-05-21 10:12:42 -07:00
Dan
dee6355cc5 Onkyo updates (#2084)
* use sane defaults for openzwave config

Use sane default if libopenzwave is installed. In most cases this will
mean that the zwave config path will not need to e manually specified.

* Resuming work on onkyo component

* Source control added to UI for onkyo receiver

Source will now display in the UI. Source mappings can be defined in the
config, and a rudimentary mapping is defined by default as a fallback.
When the onkyo source is updated, it will resolve to a defined name if
possible. This may break existing automations.

* fix lint errors

* Updated Onkyo receiver

Now takes an optional ip/name in additional to atempting to discover
deivces.

Source select will now take a sources mapping in the config. It will
provide default values if no source mapping is provided.

example:

- platform: onkyo
  host: 10.0.0.2
  name: receiver
  sources:
    HTPC: 'pc'
    Chromecast: 'aux1'
    Bluray: 'bd'
    Wii U: 'game'

* fix pylint error

* Use HA's error log instead of stack trace

* Flipped source mappings, code cleanup
2016-05-21 10:04:08 -07:00
Robbie Trencheny
c9b5ea97da Fix docstring issues with MoldIndicator 2016-05-21 10:03:24 -07:00
Felix
eaebe83429 Moldindicator Sensor (#1575)
* Adds MoldIndicator sensor platform

This sensor may be used to get an indication for possible mold growth in rooms.
It calculates the humidity at a pre-calibrated indoor point (wall, window).

* Automatic conversion to Fahrenheit for mold_indicator

* Minor change to critical temp label

* Fixed docstrings and styles

* Minor changes to MoldIndicator implementation

* Added first (non-working) implementation for mold_indicator test

* Small style changes

* Minor improvements to mold_indicator

* Completed unit test for mold indicator

* Fix to moldindicator initialization

* Adds missing period. Now that really matters..

* Adds test for sensor_changed function
2016-05-21 09:58:59 -07:00
Fabian Affolter
7f0b8c5e70 Docs (#2124)
* Add link to docs

* Update link
2016-05-21 16:59:52 +02:00
Jan Harkes
53d51a467d Single process restart fixes (#2118)
* Ignore permission errors on setpgid.

When launched in a docker container we got a permission denied error
from setpgid.

* Don't fail if we find our own pidfile.

When we restart using exec we are running a new instance of home-assistant with
the same process id so we shouldn't be surprised to find an existing pidfile in
that case.

* Allow restart to work when started as python -m homeassistant.

When we are started with `python -m homeassistant`, the restart command line
becomes `python /path/to/hass/homeassistant/__main__.py`. But in that case the
python path includes `/path/to/hass/homeassistant` instead of `/path/to/hass`
and we fail on the first import.

Fix this by recognizing `/__main__.py` as part of the first argument and
injecting the proper path as PYTHONPATH environment before we start the new
home-assistant instance.
2016-05-20 11:45:16 -07:00
Alexander Fortin
7eeb623b8f Add media_player.sonos_group_players service (#2087)
Sonos platform supports a `party mode` feature that groups all
available players into a single group, of which the calling player
will be the coordinator.
2016-05-20 09:54:15 -07:00
Jan Harkes
6b724f7da4 Not sure why, but this fixed a bad filedescriptor error. (#2116) 2016-05-20 07:03:08 -07:00
Alexander Fortin
a4409da700 Add add_uri_to_queue support to (sonos) media player (#1946)
Sonos (SoCo) supports add_uri_to_queue capability, making it possible
to stream media available via HTTP for example. This patch extends
media_player component and sonos platform to support this feature
2016-05-19 23:30:19 -07:00
John Arild Berentsen
1eb3181c14 Fix fitbit KeyError (#2077)
* Fix fitbit KeyError

* Set units compared to temperature_unit

* Pass true or false for is_metric
2016-05-19 23:28:53 -07:00
wokar
f7b401a20e Added the lg_netcast platform to control a LG Smart TV running NetCast 3.0 or 4.0 (#2081)
* Added the `lgtv` platform to control a LG Smart TV running NetCast 3.0
(LG Smart TV models released in 2012) and NetCast 4.0 (LG Smart TV models released in 2013).

* Fixed multi-line docstring closing quotes

* Rename lgtv to lg_netcast

* Rename lgtv to lg_netcast

* Extracted class to control the LG TV into a separate Python package 'pylgnetcast' and changed requirements accordingly.

* regenerated requirements_all.txt with script

* now uses pylgnetcast v0.2.0 which uses the requests package for the communication with the TV

* fixed lint error: Catching too general exception Exception
2016-05-19 23:27:47 -07:00
Jan Harkes
5f92ceeea9 Allow for restart without using parent/child processes. (#1793)
* Allow for restart without using parent/child processes.

Assuming that we normally correctly shut down running threads and
release resources, we just do some minimal scrubbing of open file
descriptors and child processes which would stay around across an
exec() boundary.

* Use sys.executable instead of multiprocessing.spawn.get_executable()

* Limit how many file descriptors we try to close.

Don't even try to close on OSX/Darwin until we figure out how to
recognize guarded fds because the kernel will yell at us, and kill
the process.

* Use the close on exec flag on MacOS to clean up.

* Introduce a small process runner to handle restart on windows.

* Handle missing signal.SIGHUP on Windows.
2016-05-19 23:20:59 -07:00
Per Sandström
f0f1fadee1 redirect daemon file descriptors (#2103) 2016-05-19 23:20:07 -07:00
Paulus Schoutsen
32f97dc578 Merge remote-tracking branch 'origin/master' into dev
Conflicts:
	homeassistant/const.py
2016-05-19 22:32:34 -07:00
Greg Dowling
631ba2ef0d Merge pull request #2110 from home-assistant/bump_loop_energy
Bump loop energy library version.
2016-05-19 17:19:06 +01:00
pavoni
62de16804b Bump loop energy library version. 2016-05-19 17:12:19 +01:00
Paulus Schoutsen
3d919f1235 Merge pull request #2108 from home-assistant/owntracks_fixes
Owntracks fixes
2016-05-19 08:28:36 -07:00
pavoni
8ff9506138 Ignore acc: 0 updates. 2016-05-19 16:16:43 +01:00
pavoni
dd1703469e Handle region enter/leave with spaces. 2016-05-19 16:04:55 +01:00
Daniel Høyer Iversen
5f98a70c21 Fix bug in flaky rfxtrx test (#2107) 2016-05-19 06:36:11 -07:00
Fabian Affolter
bfd64ce96e Upgrade python-telegram-bot to 4.1.1 (#2102) 2016-05-18 17:05:08 -07:00
Fabian Affolter
a032e649f5 Upgrade psutil to 4.2.0 (#2101) 2016-05-18 17:04:59 -07:00
Robbie Trencheny
c96a5d5b2b Fix profile usage with aws notify platforms (#2100) 2016-05-17 16:51:38 -07:00
Robbie Trencheny
a565cc4b73 Catch a gntp networkerror (#2099) 2016-05-17 16:51:32 -07:00
froz
8d34b76d51 Restored telnet as an option. Activate with config option 'protocol: telnet'. Default is ssh (#2096) 2016-05-17 15:55:12 -07:00
happyleavesaoc
15f89fc636 add some include_dir options (#2074)
* add some include_dir options

* validate, and extend instead of add

* add yaml include tests
2016-05-17 15:47:44 -07:00
Robbie Trencheny
a431277de1 Accept human readable color names to change light colors (#2075)
* Add support for providing color_name which accepts a CSS3 valid, human readable string such as red or blue

* Forgot the schema validation!

* ugh farcy

* use html5_parse_legacy_color for more input options

* Add webcolors==1.5 to setup.py

* Block pylint no-member errors on tuple

* add color_name_to_rgb test

* whoops

* revert changes to individual platforms

* If color_name is set, pop it off params and set rgb_color with it

* Forgot to reset wink.py

* Import the legacy function as color_name_to_rgb directly

* reset test_color.py

* Improve light services.yaml
2016-05-17 00:06:55 -07:00
Alexander Fortin
7208ff515e Better handle exceptions from Sonos players (#2085)
Sonos players can be dynamically set in various modes, for example
as TV players or Line-IN or straming from radios channels, therefore
some methods could not be available, and when invoked they cause
long exceptions to be logged. This partially solves the problem
reducing the output and logging some more informative error message
2016-05-16 22:58:57 -07:00
Paulus Schoutsen
0a79a5e964 Update frontend repo 2016-05-16 21:59:39 -07:00
Daniel Høyer Iversen
8e766daa11 Merge pull request #2086 from home-assistant/time_travel_fix
Round minutes to integer in google travel time, Fix issue #2080
2016-05-16 11:45:43 +02:00
Daniel
4ded795740 Round minutes to integer in google travel time, Fix issue #2080 2016-05-16 11:37:17 +02:00
Robbie Trencheny
84cb7a4f20 Add AWS notify platforms (Lambda, SNS, SQS) (#2073)
* AWS SNS notify platform

* Attach kwargs as MessageAttributes

* Initial pass of AWS SQS platform

* Add Lambda notify platform

* Remove unused import

* Change single quotes to double quotes because I am crazy

* Forgot to run pydocstyle

* Improve context support for Lambda

* compress the message_attributes logic
2016-05-15 13:17:35 -07:00
Rowan
cbf0caa88a Last.fm sensor (#2071)
* Last.fm component

* Pylint fixes

* Last.fm component

* Pylint fixes

* Updated with `.coveragerc` and `requirements_all.txt`

* Pylint fixes

* Updated

* Pylint fix

* Pylint fix
2016-05-15 13:11:41 -07:00
Brent
88d13f0ac9 Added support for the roku media player (#2046) 2016-05-15 13:00:31 -07:00
mnestor
3ed6be5b4e add link ability to configurator (#2035) 2016-05-15 12:56:29 -07:00
Richard Cox
0340710e5c Support for Nest Protect smoke alarms (#2076)
* Support for Nest Protect smoke alarms

* Fixing formatting issues from tox
2016-05-15 12:29:12 -07:00
froz
49acdaa8fd Device Tracker - ASUSWRT: Replaced telnet with ssh (#2079) 2016-05-15 12:20:17 -07:00
Alex Harvey
ffbc99fac2 Merge pull request #2059 from infamy/justyns-purge_old_data
Justyns purge old data
2016-05-14 23:55:28 -07:00
Johann Kellerman
6dae005b65 Resolved UI flicker, new config vars, brightness up to 255, fixed buttons, fixed race condition (#2072) 2016-05-14 14:21:05 -07:00
Robbie Trencheny
0adc853741 Add notify.twilio_sms component (#2070) 2016-05-14 14:09:28 -07:00
Robbie Trencheny
6254d4a983 Add lines for associated documentation PR 2016-05-14 14:02:14 -07:00
Robbie Trencheny
a7db208b8a Fix Google Voice documentation URL 2016-05-14 13:32:00 -07:00
Rowan
429bf2c143 Google Play Music Desktop Player component (#1788)
* Added GPM Desktop Plaeyr component

* Updated requirements_all.txt

* Pylint fix

* Updated GPMDP.py to include @balloob's comments

* Updated to work with the latest version of GPMDP

* Removed setting "self._ws.recv()" as a variable

* Made line 52 shorter

* Updated to check weather it is connected or not

* Pylint and @balloob fixes

* Updated with simplified code and pylint fix

* Made `json.loads` shorter

* Pylint fix
2016-05-14 13:28:42 -07:00
happyleavesaoc
8df91e6a17 numeric state: validate multiple entities (#2066)
* validate multiple entities

* point to current entity
2016-05-14 12:29:57 -07:00
Daniel Høyer Iversen
8656bbbc79 fix bugs in google travel time (#2069) 2016-05-14 12:14:13 -07:00
Daniel Høyer Iversen
630b7377bd Refactor get_age in util/dt (#2067) 2016-05-14 12:05:46 -07:00
Daniel Høyer Iversen
0626a80186 Merge pull request #2068 from home-assistant/yaml_env
Add test for yaml enviroment
2016-05-14 20:33:46 +02:00
Daniel
24788b106b Add test for yaml enviroment 2016-05-14 20:20:27 +02:00
Igor Shults
c5401b21c2 Fix typo in system monitor ('recieved') (#2062) 2016-05-14 09:45:32 -07:00
mnestor
954b56475e YAML: add !include_named_dir and ! include_list_dir (#2054)
* add include_dir constructor for yaml parsing

* changed to allow for flat and name based directory including

* fixed ci errors

* changed flat to list
2016-05-13 21:16:04 -07:00
Alex Harvey
53d7e0730c Fixes for farcy 2016-05-13 14:43:22 -07:00
Alex Harvey
cba85cad8d Fixes for farcy 2016-05-13 14:42:08 -07:00
Lewis Juggins
96b73684eb Update Dockerfile to use OpenSSL 1.0.2h to resolve certificate issues (#2057) 2016-05-13 07:55:52 -07:00
Robbie Trencheny
aa7fa7b550 Dont default to driving anymore, re: #2047 2016-05-12 22:49:12 -07:00
Robbie Trencheny
d229cb46b1 Google travel time improvements (#2047)
* Update google_travel_time.py

* Update google_travel_time.py

* pylint: disable=too-many-instance-attributes

* Add the mode to the title of the sensor

* Expose the travel mode on the sensor attributes

* Big improvements to the Google Travel Time sensor. Allow passing any options that Google supports in the options dict of your configuration. Deprecate travel_mode. Change name format to show the mode

* fu farcy

* Dynamically convert departure and arrival times

* Add a warning if user provides both departure and arrival times

* Add deprecation warning for travel_mode outside options and other minor fixes

* Use a copy of options dict to not overwrite the departure/arrival times constantly.

* Remove default travel_mode, but set default options.mode to driving

* Google doesnt let us query time in the past, so if the date we generate from a time string is in the past, add 1 day

* spacing fix

* Add config validation for all possible parameters

* flake8 and pylint fixes
2016-05-12 22:37:08 -07:00
happyleavesaoc
8682e2def8 supervisord sensor (#2056) 2016-05-12 22:16:58 -07:00
Johann Kellerman
65ac1ae84a Added QwikSwitch component & platforms (#1970)
* Added QwikSwitch platform

farcy - worst than my english teacher

* Clean up comments

* Import only inside functions

* Moved imports, no global var, load_platform

* add_device reworked

* Only serializable content on bus

* Fixed imports & removed some logging
2016-05-12 21:39:30 -07:00
Alex Harvey
93fd6fa11b fixes for pep and delay start 2016-05-12 10:33:22 -07:00
Alex Harvey
67b0365f62 update to latest base 2016-05-12 10:32:28 -07:00
Paulus Schoutsen
f1eda430cd Update rpi_rf.py 2016-05-12 00:13:48 -07:00
Paulus Schoutsen
69929f15fb Ignore RPI-RF in requirements_all 2016-05-11 22:56:05 -07:00
Robbie Trencheny
d553c7c8e7 Merge pull request #2027 from robbiet480/relative-time-filter
Add a Jinja filter for relative time
2016-05-11 22:50:56 -07:00
Robbie Trencheny
4d0b9f1e94 Stupid blank lines 2016-05-11 22:44:44 -07:00
Robbie Trencheny
fca4ec2b3e simplify the relative_time function 2016-05-11 22:37:37 -07:00
Robbie Trencheny
b75aa6ac08 Add get_age tests 2016-05-11 22:29:55 -07:00
Nolan Gilley
894ceacd40 Add Ecobee notify platform (#2021)
* add send_message to ecobee via service call

* farcy fixes

* fix pydocstyle

* ecobee notify component
2016-05-11 22:03:21 -07:00
Johann Kellerman
fbe940139a Discovery listener on all EntityComponents (#2042) 2016-05-11 21:58:22 -07:00
happyleavesaoc
c341ae0a39 Media Player - MPD: handle more exceptions (#2045) 2016-05-11 21:53:56 -07:00
Nolan Gilley
f9d97c4356 fix away mode. issue 2032 (#2044) 2016-05-11 21:52:56 -07:00
Nolan Gilley
b8a5d392c5 Fix speedtest by removing Throttle and adding second parameter for track_time_change (#2040) 2016-05-11 08:24:50 -07:00
Paulus Schoutsen
fd8240241f Merge pull request #2038 from home-assistant/hotfix-19-4
Hotfix 0.19.4: Fix script syntax validation of AND and OR condition
2016-05-10 21:57:22 -07:00
Paulus Schoutsen
3c9e493494 Make AND and OR conditions valid (#2037) 2016-05-10 21:49:58 -07:00
Paulus Schoutsen
786a0154b1 Version bump to 0.19.4 2016-05-10 21:48:05 -07:00
Paulus Schoutsen
dd6ab79e35 Make AND and OR conditions valid 2016-05-10 21:47:46 -07:00
Erik Eriksson
2f118c5327 log received mqtt messages (#2031) 2016-05-10 21:12:14 -07:00
Nolan Gilley
a7d1f52ac8 Use Throttle on speedtest update (#2036)
* use throttle

* fix flake8
2016-05-10 20:51:55 -07:00
Robbie Trencheny
5317f700d7 Merge pull request #2033 from home-assistant/hotfix-0193
Hotfix 0193
2016-05-10 13:56:15 -07:00
Robbie Trencheny
01eb2d5c84 Increment version 2016-05-10 13:42:23 -07:00
Paulus Schoutsen
0893ddcab7 Update README.rst 2016-05-10 13:41:23 -07:00
Landrash
e77a7f4385 Fixed minor miss-spelling (#2028)
Changed millileters to milliliters.
Changed case of mmol/l to mmol/L.
2016-05-10 13:40:39 -07:00
Robbie Trencheny
39e7942dce Fitbit flake8 and pylint fixes. Forgot to do it before pushing :( 2016-05-10 13:40:34 -07:00
Robbie Trencheny
faf5ffe610 Minor Fitbit tweaks. Correct the copy, dont require auth on the routes, get the client_id/client_secret from fitbit.conf instead of the YAML 2016-05-10 13:40:25 -07:00
Robbie Trencheny
8d2dc48261 en_UK->en_GB. Closes #2019. 2016-05-10 13:40:17 -07:00
Paulus Schoutsen
c7cfa8d245 Update README.rst 2016-05-10 13:36:03 -07:00
Robbie Trencheny
16933abce9 Remove humanize and use a relative time thing that @balloob found on Github 2016-05-10 00:04:53 -07:00
Landrash
8163b986c9 Fixed minor miss-spelling (#2028)
Changed millileters to milliliters.
Changed case of mmol/l to mmol/L.
2016-05-09 23:48:48 -07:00
Robbie Trencheny
d5a1c52359 Add a Jinja filter for relative time 2016-05-09 23:31:02 -07:00
Nolan Gilley
26ea4e41cb Bring back custom scan intervals and service for speedtest.net component (#1980)
* Bring back the functionality that was removed in PR 1717. This includes the speedtest service and the ability to define the scan times in the configuration file.  Restore default functionality of 1 scan per hour on the hour.

* remove unnecessary code.
2016-05-09 22:49:26 -07:00
Johann Kellerman
ec9544b9c3 Add a load_platform mechanism (#2012)
* discovery.load_platform method

* rm grep
2016-05-09 22:48:03 -07:00
Fabian Affolter
1d0bc1ee66 Upgrade flake8 to 2.5.4 (#2018) 2016-05-09 22:33:21 -07:00
Robbie Trencheny
9729c44d53 Merge pull request #2023 from philipbl/fix_slack
Fix problem with Slack default channel
2016-05-09 16:37:38 -07:00
Robbie Trencheny
a7292af3b1 Fitbit flake8 and pylint fixes. Forgot to do it before pushing :( 2016-05-09 15:33:04 -07:00
Robbie Trencheny
c8cbc528eb Minor Fitbit tweaks. Correct the copy, dont require auth on the routes, get the client_id/client_secret from fitbit.conf instead of the YAML 2016-05-09 15:31:47 -07:00
Philip Lundrigan
8735bfe926 Fix problem with default channel 2016-05-09 16:19:19 -06:00
Robbie Trencheny
25e8c7bc5f en_UK->en_GB. Closes #2019. 2016-05-09 15:14:33 -07:00
jazzaj
499257c8e1 Corrected link to documentation (#2022) 2016-05-09 23:30:22 +02:00
Paulus Schoutsen
6856283896 Make HVAC naming consistent (#2017) 2016-05-09 07:53:01 -07:00
Paulus Schoutsen
20dad9f194 Add HVAC to demo 2016-05-08 23:21:26 -07:00
Paulus Schoutsen
09483e3be4 More fault tolerant discovery 2016-05-08 21:23:03 -07:00
Paulus Schoutsen
8ae5708fa2 Merge pull request #2010 from home-assistant/hotfix-0192
Hotfix 0192
2016-05-08 10:19:54 -07:00
Paulus Schoutsen
1e42f85a9c Version bump to 0.19.2 2016-05-08 09:53:22 -07:00
John Arild Berentsen
92d71a6612 Fix for not recognizing Z-Wave thermostats (#2006)
* Fix for not recognizing thermostats

* Properly ignore zxt-120

* fix
2016-05-08 09:53:09 -07:00
John Arild Berentsen
ab2e85840f Fix for not recognizing Z-Wave thermostats (#2006)
* Fix for not recognizing thermostats

* Properly ignore zxt-120

* fix
2016-05-08 09:52:16 -07:00
Paulus Schoutsen
8257e3f384 Fix automation deprecation warning 2016-05-07 22:31:22 -07:00
Paulus Schoutsen
e40908d67c Improve config validation error message 2016-05-07 22:31:22 -07:00
Paulus Schoutsen
1abbb43ebd Merge pull request #2004 from home-assistant/hotfix-019-1
Hotfix 019 1
2016-05-07 22:31:00 -07:00
Paulus Schoutsen
69ecedefad Version bump to 0.19.1 2016-05-07 22:24:20 -07:00
Paulus Schoutsen
0f6c9d2f75 Fix automation deprecation warning 2016-05-07 22:24:13 -07:00
Paulus Schoutsen
c58fb00f03 Improve config validation error message 2016-05-07 22:24:04 -07:00
Paulus Schoutsen
e67729b2f4 Version bump to 0.20.0.dev0 2016-05-07 12:55:41 -07:00
Paulus Schoutsen
6b1f9a32dd Merge pull request #1995 from home-assistant/dev
0.19
2016-05-07 12:55:27 -07:00
Paulus Schoutsen
7c8c5e7763 Version bump to 0.19 2016-05-07 12:51:40 -07:00
Robbie Trencheny
8cb48615af Fitbit Sensor Take Deux (#2002)
* Fitbit Sensor

* Add configurator image
2016-05-07 12:46:45 -07:00
Robbie Trencheny
952d1c796e Add CORS (Cross Origin Resource Sharing) support to HTTP (#2000) 2016-05-07 12:21:28 -07:00
Fabian Affolter
89c22e6d8a Upgrade pytest to 2.9.1 (#2001) 2016-05-07 12:12:52 -07:00
Fabian Affolter
16adc30210 Upgrade pylint to 1.5.5 (#1999) 2016-05-07 11:49:58 -07:00
Paulus Schoutsen
2a9c822454 Update HBMQTT (#1998) 2016-05-07 10:59:23 -07:00
Daniel Høyer Iversen
6cae7c0307 Add google maps travel time sensor (#1987)
* Add travel time sensor

* Throttle update of Time travel sensor

* Rename travel time to google travel time, validate the api key
2016-05-07 10:17:28 -07:00
Paulus Schoutsen
6901e5ea5e Random fixes (#1996)
* OwnTracks handle malformed data better

Fixes #1991 .

* Remove dependency for util.dt
2016-05-07 10:16:14 -07:00
Paulus Schoutsen
8a16a7d943 Update frontend 2016-05-07 10:10:09 -07:00
Daniel Høyer Iversen
21dd8162b3 Improve error message for invalid key in config (#1975)
* Improve error message for invalid key in config

* Refactor log exception in config validation
2016-05-07 07:35:42 -07:00
Paulus Schoutsen
67f3fcc5cf Update frontend 2016-05-06 23:35:15 -07:00
Robbie Trencheny
a1480582d9 Add /api/discovery_info (#1791)
* Allow /api/ and /api/config to be accessed without auth. If config is accessed without auth, only show minimal information. Also improves comments

* Re-enable auth on /api/ since a lot of tests get broken if it does not require auth

* Move the discovery info from /api/config to /api/discovery_info

* Flake8 fixes
2016-05-06 22:11:35 -07:00
Paulus Schoutsen
713c7a5fd7 Merge branch 'master' into dev
Conflicts:
	homeassistant/const.py
2016-05-06 21:46:50 -07:00
Nolan Gilley
fb3b3db04e Check for 'unknown' sensor values in ecobee (#1983) 2016-05-06 18:50:32 -07:00
Charles Spirakis
b86a1ece01 Allow conversion from date strings to "unix" timestamp. (#1985)
"unix" timestamp is number of seconds since Jan 1, 1970 UTC.
This allows scripts that use templates to generate time
deltas in seconds if desired from state attributes such
as last_updated.

Some examples:

timestamp now is
{{ as_timestamp(now) }}

timstamp of last change is
{{ as_timestamp(states.binary_sensor.garage_door.last_changed) }}

seconds since last change is
{{ as_timestamp(now) - as_timestamp(states.binary_sensor.garage_door.last_changed) }}
2016-05-06 18:33:46 -07:00
Daniel Høyer Iversen
ca0ea6c2f3 Rfxtrx bug fix (#1992)
* Rfxtrx bug fix

* Added Sensor Status to data_types

Missing dataype for security1 sensors

* Misspelling
2016-05-06 18:24:43 -07:00
William Scanlon
1cd59cf2a9 Added battery level to wink devices (#1979) 2016-05-06 18:19:37 -07:00
Fabian Affolter
72cf7fd9c2 Add timeout to request for location elevation (#1978) 2016-05-06 18:10:13 -07:00
Ellis Percival
c72ab42c19 Enable ZigBee "push" updates for digital/analog sensors. (#1976) 2016-05-06 18:09:18 -07:00
Fabian Affolter
d73f8d5253 Upgrade to PyMata 2.12 (#1993) 2016-05-06 18:03:28 -07:00
Fabian Affolter
98bedf1bd6 Update links to docs and doc strings (#1994) 2016-05-06 18:03:18 -07:00
Kyle Hendricks
4a28be9a94 [Pioneer AVR] Display the currently select input source as the media title (#1974) 2016-05-06 17:57:57 -07:00
Hernán
393bd88091 Add Media Player Stop command + Kodi support for it (#1960)
* Started adding Stop command to Kodi media player

* minor

* minor

* minor

* abstract-method fixed
2016-05-06 17:57:00 -07:00
Fabian Affolter
e5d1ed9439 Add dweet export component (#1818) 2016-05-06 17:55:26 -07:00
Fabian Affolter
ddfda89fc9 Update link to docs 2016-05-05 09:49:52 +02:00
Fabian Affolter
2274806bee UPdate link to docs 2016-05-05 00:32:11 +02:00
Fabian Affolter
7995829790 Fix typo 2016-05-05 00:28:51 +02:00
Alex Harvey
d5031d90c4 Update README.rst (#1981)
Splitting dev and general chat links in the badges
2016-05-04 22:40:31 +02:00
Robbie Trencheny
2874ad3445 Merge pull request #1973 from kylehendricks/fix-unresolved-merge-conflict
Fix an unresolved merge conflict
2016-05-03 19:42:27 -07:00
Kyle Hendricks
8fc07ee6cd Fix an unresolved merge conflict 2016-05-03 22:34:26 -04:00
Per Sandström
4850a65ed0 add reconnect retry and longer timeouts for verisure (#1944) 2016-05-03 18:53:11 -07:00
Paulus Schoutsen
4643dcde9c Merge branch 'pr/1969' into dev
Conflicts:
	homeassistant/components/zwave.py
2016-05-03 18:48:48 -07:00
devdelay
39e03eebcf Add Z-Wave lock support 2016-05-03 18:47:52 -07:00
Brent
34193de158 Update yaml parser for handling environment variables (#1967) 2016-05-03 18:41:14 -07:00
Alexander Fortin
298b9d1f12 Limit number of processed entries by Feedreader (#1966)
* process only last 20 available entries to avoid bombing event
  bus when parsing huge feeds
* trigger first update only when HA has completed startup,
  allowing components to complete subscriptions to feedreader
  events
* quote url in logs for better readability
2016-05-03 18:40:30 -07:00
William Scanlon
6d9254ce25 Support for OctoPrint sensors (#1924) 2016-05-03 18:35:11 -07:00
John Arild Berentsen
1a59ba735f Initial HVAC component + Z-Wave platform (#1912) 2016-05-03 18:27:51 -07:00
deisi
b2abe552a0 Added a switch to control beamers from acer (#1913) 2016-05-03 18:23:38 -07:00
Paulus Schoutsen
2a972b7fe3 Fix script condition issue (Thanks @bart274) (#1972) 2016-05-03 18:19:55 -07:00
Kyle Hendricks
f2176e54ba Add Pioneer AVR media_player support (#1968) 2016-05-02 22:09:27 -07:00
Paulus Schoutsen
79653a672d Script cleanup (#1963) 2016-05-02 22:05:09 -07:00
Andrew LeCody
a6a5e4fda2 Forecast.io: Added minutely, hourly, and daily summary (#1943)
* Forecast.io: Added minutely, hourly, and daily summary

* Resolve pylint issue (Too many instance attributes)
2016-05-02 21:56:15 -07:00
Tim Harton
f6df5bc390 Mqtt client key auth (#1935)
* Made changes so that the mqtt configuration can accept client keys and certs for auth.

* Need to figure out how the broker_config works, it's failing tests

* Fixed it so all tests passed and ssl feature works for all brokers
which are't embedded

* Bring into line with pep8

* Added config validation which has allowed me to make the code simpler
2016-05-01 23:21:28 -07:00
Brent
b51561cd9b Fixed slack component bug with getting the channel when sending a message (#1954) 2016-05-01 23:10:21 -07:00
Fabian Affolter
4710b38fad Add support for sensor classes (#1950) 2016-05-01 23:05:53 -07:00
Martin Hjelmare
069a4b1706 Refactor mysensors component
* Add MySensorsDeviceEntity class to hold the common attributes,
	properties and methods for mysensors entities.
* Inherit from MySensorsDeviceEntity class in binary_sensor, light,
	sensor and switch mysensors platforms.
* Remove not needed attribute and method for const in GatewayWrapper
	class. The const attribute is already set in the wrapped object.
* Clean up state property for mysensors sensor entities.
* Inherit from MySensorsLightRGB in MySensorsLightRGBW class.
* Remove use of get_component in mysensors component and platforms.
* Clean up update method in MySensorsDeviceEntity class.
2016-04-30 15:27:59 +02:00
Fabian Affolter
cfd7ca344e Upgrade pushbullet.py to 0.10.0 (#1939) 2016-04-29 07:49:46 +02:00
Robbie Trencheny
abc00c76bc Merge pull request #1914 from robbiet480/uber-metered-fix
Uber: Dont load price sensors for metered (read: taxi/cabs) products
2016-04-28 17:57:59 -07:00
Robbie Trencheny
f8340b94bc Fix variable name 2016-04-28 17:57:03 -07:00
Erik Eriksson
cc202b886b ELIQ Online platform cleanup (#1942) 2016-04-28 17:33:33 +02:00
Paulus Schoutsen
588a0cc947 Update frontend 2016-04-28 16:32:25 +02:00
Alexander Fortin
8c943c966a Improve feedreader roboustness (#1926)
* bugfix: ignore not existing property in feedreader item
* add info and debug data
* split logic in smaller and hopefully easier to understand functions
2016-04-28 15:01:44 +02:00
Paulus Schoutsen
1d28fa712f Fix script merge conflict 2016-04-28 13:39:44 +02:00
gwendalg
31e019e88a script: Fix log output (#1918)
Signed-off-by: Gwendal Grignou <gwendal@gmail.com>
2016-04-28 13:19:38 +02:00
Fabian Affolter
157036c1d2 Upgrade pytz to 2016.4 (#1932)
* Upgrade pytz to 2016.4

* Upgrade pytz to 2016.4
2016-04-28 13:02:21 +02:00
Paulus Schoutsen
6354399d55 Initial script condition support (#1910) 2016-04-28 12:03:57 +02:00
Dennis Karpienski
953223b81b Yamaha: added mapping and exclude lists (#1880)
* added mapping and exclude lists

* reworked pr

* made code more pythonic
2016-04-28 12:03:24 +02:00
Paulus Schoutsen
0d261be6ce Update ISSUE_TEMPLATE.md 2016-04-28 11:38:38 +02:00
Fabian Affolter
d608153dbb Upgrade jsonrpc-requests to 0.2 (#1937) 2016-04-28 10:06:15 +02:00
Fabian Affolter
f5429c89b6 Upgrade TwitterAPI to 2.4.1 (#1931) 2016-04-28 08:25:55 +02:00
Fabian Affolter
7331f4910e Upgrade schiene to 0.15 (#1929) 2016-04-28 08:23:23 +02:00
Fabian Affolter
6b81773075 Upgrade messagebird to 1.2.0 (#1928) 2016-04-28 08:23:03 +02:00
Brad Johnson
725b336683 Upgrading to python-wink 0.7.5. (#1925)
This fixes a bug where light bulb statuses were failing to update on the HA polling update call.
2016-04-28 08:22:39 +02:00
Fabian Affolter
f0bcdc6bd8 Upgrade python-telegram-bot to 4.0.1 (#1927) 2016-04-28 08:09:38 +02:00
Kyle Hendricks
59e95f0d86 Fix a couple dead links in the README (#1936) 2016-04-28 07:35:36 +02:00
Josh Wright
1859c84e6d Ignore .venv (#1923)
When using virtualfish ('virtualenvwrapper' for the fish shell), you
can create a .venv file in a directory that contains the name of a
virtualenv that will be activated automatically when you cd into that
directory. This is a good and useful thing, but since folks will have
different names for their virtualenvs, we should ignore this file.

That... and I'm probably the only one using fish/virtualfish...
2016-04-27 15:27:49 -04:00
gwendalg
2b7e1a2cc9 mqtt: Fix logic when embedded and broker configs are present. (#1919)
Fix test to prevent early exit of mqtt init handler when
both embedded and broker configs are present.

Signed-off-by: Gwendal Grignou <gwendal@gmail.com>
2016-04-26 12:17:56 +02:00
Daniel Høyer Iversen
6717215438 Merge pull request #1905 from home-assistant/rfxtrx_sensor_fix
Rfxtrx: Simplified configuration
2016-04-26 11:54:11 +02:00
blackdog70
5159cc525b Arduino: Fixed pin_mode digital input (#1909) 2016-04-26 11:46:54 +02:00
happyleavesaoc
9b3403943c update snapcast with source select (#1908)
* update snapcast

* fix id
2016-04-26 11:46:08 +02:00
Dan
b4be508741 Make zwave component user sane defaults. (#1891)
Change the zwave config default path to be valid in all but rare
edge cases. This will let that config value be truely optional.

Also check that libopenzwave is installed and print a warrning if
it cannot be found pointing at the site.
2016-04-26 11:41:20 +02:00
Micha LaQua
08d60fb04b Initial support for generic 433Mhz GPIO adapters on a Raspberry Pi (#1865)
* initial support for generic 433mhz gpio adapters

* rpi-rf: refactor id_on/id_off to code_on/code_off

fits the purpose better and improves understanding

* rpi-rf: use v0.9.4

* rpi-rf: update features and dependencies to v0.9.5

includes the ability to optionally specify a protocol for each switch

* rpi-rf: remove explicit RPi.GPIO dependency

already a dependency of the rpi-rf module

* rpi-rf: make setting gpio, code_on and code_off mandatory

* rpi-rf: remove unused value_template

* rpi-rf: only enable TX once if there are switches
2016-04-26 11:35:01 +02:00
Dan Cinnamon
7154603567 Summary: Enhanced to make more robust and efficient. (#1917)
Prevented a switch from being turned on twice.

Made the module regex more robust.

Refactored the code to reduce the amount of network traffic to/from pulseaudio.

Fixed pylint issues
2016-04-26 11:29:20 +02:00
Robbie Trencheny
ee9996374c Dont load price sensors for metered (read: taxi/cabs) products 2016-04-25 11:43:18 -07:00
John Arild Berentsen
69daa383dd Exclude locally built python-openzwave from tox. (#1911)
Excludes `build` directory built by running build_python_openzwave script. When running tox test locally.
2016-04-25 12:06:28 +02:00
Daniel
2ca1f7542f Refactor rfxtrx code 2016-04-24 13:42:59 +02:00
Bart274
d4fe6f385a Update pyicloud version (#1849)
* Update requirements_all.txt

* Update icloud.py
2016-04-24 06:49:04 +02:00
deisi
3b0a35f571 Ontime and delay attribute are allways present in deutsche_bahn sensor (#1875) 2016-04-24 06:43:25 +02:00
Jeff Schroeder
448edecdd1 Merge pull request #1896 from fabaff/slacker-upgrade
Upgrade slacker to 0.9.10
2016-04-23 21:43:03 -05:00
Jeff Schroeder
d0357cd42f Merge pull request #1901 from ishults/dev
Use protocol of web page for yr.no pictures
2016-04-23 21:18:31 -05:00
Igor Shults
7afdca1121 Use protocol of web page for yr.no pictures 2016-04-23 21:09:39 -05:00
Daniel
55b51cb3fa Update rfxtrx tests to handle new config 2016-04-23 20:13:24 +02:00
Daniel
74022a3978 New configuration for rfxtrx sensor 2016-04-23 19:55:05 +02:00
Fabian Affolter
d232020de4 Upgrade slacker to 0.9.10 2016-04-23 18:20:28 +02:00
sander76
27ce394571 external dependency evohomeclient 0.2.4 gave a json decode error. (#1895)
* external dependency evohomeclient 0.2.4 gave a json decode error.
upped to 0.2.5
2016-04-23 18:03:43 +02:00
Paulus Schoutsen
413b8d34e4 Merge pull request #1892 from home-assistant/netdisco-update
Netdisco update
2016-04-23 08:41:08 +02:00
Paulus Schoutsen
8f8d936539 Netdisco bump to 0.6.6 2016-04-23 08:34:07 +02:00
Paulus Schoutsen
197d9639f9 Merge pull request #1882 from home-assistant/service-parameters
Trigger variables in automation actions
2016-04-23 07:46:26 +02:00
Paulus Schoutsen
14bd630c1d Service/Script cleanup 2016-04-23 07:11:21 +02:00
Paulus Schoutsen
533799656e Cache script object for Alexa 2016-04-23 07:10:57 +02:00
Paulus Schoutsen
1d8554359c Allow setting entity namespace (#1887) 2016-04-23 06:34:49 +02:00
Paulus Schoutsen
cc42f2d8be Show error message frontend if can't find server (#1886) 2016-04-23 06:30:34 +02:00
Per Sandström
ba696888c1 Merge pull request #1889 from persandstrom/verisure_updated_links
Verisure: new version and changed "key" in smartplug
2016-04-22 20:15:26 +02:00
Per Sandström
a4083bab1a new version and changed "key" 2016-04-22 20:02:54 +02:00
Fabian Affolter
1c6a2f87eb Add link to docs 2016-04-22 15:48:40 +02:00
Paulus Schoutsen
4a5411a957 Allow calling scripts from Alexa 2016-04-22 05:30:30 -04:00
Paulus Schoutsen
612a017bc6 Automation: Allow embedding script definition 2016-04-21 22:36:14 -04:00
Paulus Schoutsen
b8e4db9161 Script entities to allow passing in variables 2016-04-21 22:24:23 -04:00
Paulus Schoutsen
26863284b6 Script helper: support variables 2016-04-21 21:42:20 -04:00
Paulus Schoutsen
09a771a026 Move script component tests to script helper tests 2016-04-21 21:29:28 -04:00
Paulus Schoutsen
f76d545a08 Add script logic into helper. 2016-04-21 21:06:05 -04:00
Dennis Karpienski
2333c0ca3b WebOS component fixes
* fixed some exceptions

* add requirements to notify

* added optimistic state to power off

* run requirements script
2016-04-21 20:35:56 -04:00
Paulus Schoutsen
4e568f8b99 Automation: Add trigger context and expose to action 2016-04-21 13:59:42 -07:00
Paulus Schoutsen
c4913a87e4 Alexa: Expose intent variables to service calls 2016-04-21 12:27:23 -07:00
Paulus Schoutsen
4acb121689 Allow variables in service.call_from_config 2016-04-21 12:22:19 -07:00
Daniel Høyer Iversen
3318c55c65 Heat control config validation
* heat control configuration validation

* fix heat contol test
2016-04-21 07:59:35 -07:00
Daniel Høyer Iversen
d3fb69783d Tellstick config validation 2016-04-21 07:57:28 -07:00
Dan
43a94995c2 Update unifi version
New unifi version has a fix that will allow it to install correctly
2016-04-21 07:56:19 -07:00
John Arild Berentsen
dfa37511ad Improve recognition for zwave thermostats 2016-04-21 07:51:31 -07:00
Paulus Schoutsen
4745282a95 Update underline of header README 2016-04-20 19:00:12 -07:00
Paulus Schoutsen
1d3c6da6c8 Version bump to 0.18.2 for pypi 2016-04-20 18:59:47 -07:00
Paulus Schoutsen
623b023ac0 Version bump to 0.19.0.dev0 2016-04-20 18:44:27 -07:00
Paulus Schoutsen
8f18cb34d6 Release 0.18 #1854
0.18
2016-04-20 18:43:54 -07:00
Paulus Schoutsen
b6e956a3d0 Version bump to 0.18 2016-04-20 18:43:21 -07:00
Paulus Schoutsen
3e0f64e4f6 Update frontend 2016-04-20 18:13:25 -07:00
Dennis Karpienski
934cd876b4 fixed some issues with webos (#1856)
* fixed some issues

* fixed linter
2016-04-20 14:09:50 -07:00
Christoph Wagner
fbfdf5a286 Removed redundant Throttle decorator (#1862) 2016-04-20 00:20:30 -07:00
Paulus Schoutsen
7d4b11f4ec Fix wrong merge 2016-04-19 22:59:29 -07:00
Paulus Schoutsen
4abbbf0f50 Merge remote-tracking branch 'origin/master' into dev
Conflicts:
	homeassistant/bootstrap.py
	homeassistant/components/frontend/version.py
	homeassistant/const.py
2016-04-19 22:53:26 -07:00
Paulus Schoutsen
0c58a1a499 Sort .coveragerc 2016-04-19 21:45:29 -07:00
Paulus Schoutsen
bdc39ff905 Update frontend 2016-04-19 21:39:44 -07:00
Paulus Schoutsen
9d391becc1 Add mysensors tcp ethernet gateway (#1861)
* Bump version of pymysensors to 0.6, which includes the tcp gateway.
* Update requirements_all.txt.
* Replace CONF_PORT with CONF_DEVICE and ATTR_PORT with ATTR_DEVICE.
* Add tcp_port in config.
* Try to guess if tcp or serial gateway is configured, by validating
	device name as an ip address. If successful setup tcp gateway, if it
	fails, setup serial gateway.
* Update device_state_attributes to show correct device, ethernet or
	serial.
2016-04-19 21:00:56 -07:00
Paulus Schoutsen
2e79e9d5bb Correct celcius to celsius (#1860) 2016-04-19 20:30:44 -07:00
Jon Evans
9090672146 Pass format through to temper_device so that Fahrenheit works (#1858) 2016-04-19 20:00:03 -07:00
Dennis Karpienski
46274d4393 add media_player webos tv platform (#1853)
* added webos tv platform

* moved coverage entries
2016-04-19 08:53:58 -07:00
Paulus Schoutsen
177d0c20d9 Add bluepy package dependency to Dockerfile 2016-04-19 08:49:05 -07:00
Chema García
b9fd4919b3 Set name to hyperion assets (#1822)
* set name to hyperion assets

by specifying the name in the configuration:

light kodi_xxx:
  name: "Kodi XXX"
  platform: hyperion
  host: 192.168.1.222
  port: 19444

* Update hyperion.py

fix extra space
2016-04-19 08:19:27 -07:00
Manoj
c1ca13d613 Add bluetooth device tracker (#1830)
This tracker discovers new devices on boot and tracks bluetooth devices
periodically based on interval_seconds value. Devices discovered are
stored with 'BT_' as the prefix for device mac.

Requires PyBluez
2016-04-19 08:18:46 -07:00
Alexander Fortin
c0a7b0f474 Add feedreader component (#1836) 2016-04-19 08:14:36 -07:00
Markus Peter
e61ffff646 Support for EQ3 Bluetooth Smart Thermostats (#1839)
* Initial Support for EQ3 Bluetooth Smart Radiator Thermostats

* tox runs successfully

* Moved device specific stuff to bluepy_devices library

* lint fix
2016-04-19 08:12:27 -07:00
Daniel Høyer Iversen
16fe7dd937 rfxtrx config validation 2016-04-19 07:13:58 -07:00
Greg Dowling
5b0ab5c118 Merge pull request #1842 from home-assistant/add_imperial_meter
Add support for imperial gas meter and user specified gas calorific value.
2016-04-18 12:10:07 +01:00
Dan
276c2070be Do not setup or configure a hue bridge twice (#1848)
Tracks previously configured bridges by IP and prevents duplicates
from being configured
2016-04-17 22:41:31 -07:00
Paulus Schoutsen
c89e9d87e8 Catch platform setup error (#1847) 2016-04-17 22:07:53 -07:00
Brad Johnson
09693bf16c Upgrading to python-wink 0.7.4 and improving RGB color support in HA (#1832) 2016-04-17 19:07:21 -07:00
Jan Harkes
bb439129e6 Bump pywemo version to 0.4.2 2016-04-17 21:02:31 -04:00
Jan-Preben Mossin
5931bac695 Only add visible sonos devices
Some Sonos devices (e.g SUB) does not have
a upnp media renderer, but are discovered as sonos
devices. Creating a SonosDevice object from such a
device will fail.
2016-04-17 16:45:16 -07:00
John Arild Berentsen
b45c0cd735 Zwave import fixes for stability (#1845) 2016-04-17 14:46:51 -07:00
Paulus Schoutsen
ea38742067 Update bootstrap frontend script 2016-04-17 13:59:11 -07:00
Flavio Castelli
b5f1c1332a Sonos: better handling of offline players (#1829)
When a sonos player goes offline an endless stream of
exceptions is raised. That happens because homeassistant keeps trying
to refresh its status.

This can happen even when a sonos player has gone offline **before**
homeassistant is started. The sonos players take some time before
realizing one of their mates is no longer online, leading to the same
stream of exceptions inside of homeassistant.

Three types of exceptions of can be raised:

  - `requests.packages.urllib3.exceptions.MaxRetryError`
  - `requests.packages.urllib3.exceptions.NewConnectionError`
  - `TimeoutError`

It's not possible to handle all of them with a single `except` block
because they are raised in a random order and after some delays. That
means a 2nd or 3rd exception can take place while handling the 1st one.

The only solution is to check whether a a player is actually reachable
by attempting to connect to a service that must be running on it.

Also all the players in a 'unknown' state should not be polled by
homeassistant (despite of their brand).

I'm going to upstream the `_is_reachable` method I added to the
`sonos.py` file into `SoCo`. In the meantime we must ship this piece
of code with homeassistant.

Signed-off-by: Flavio Castelli <fcastelli@suse.com>
2016-04-17 13:17:13 -07:00
Dan Cinnamon
a482c4b2a1 Allow mpd to handle the play_media service. (#1831)
Even though there's not really a place in the UI for it, it will now be possible to set a playlist as part of a script, and ultimately a scene.
2016-04-17 12:34:33 -07:00
deisi
e8bf47ff59 Fix for the issue #1323 (#1835) 2016-04-17 12:32:04 -07:00
Paulus Schoutsen
ecf411c4c5 Merge pull request #1838 from MartinHjelmare/fix-influxdb
Fix field type conflict in influxdb
2016-04-17 10:43:47 -07:00
pavoni
31f061f4d3 Add support for imperial meter and user soecified calorific value. 2016-04-17 18:34:40 +01:00
icovada
b29dedaecf SCSGATE: Actually cycle through all devices to register (#1841)
* SCSGATE: Actually cycle through all devices to register

Modify _activate_next_device function to actually cycle through self-devices_to_register instead of simply checking whether there are any and onl registering one

* Deleted extra white lines
2016-04-17 10:17:42 -07:00
MartinHjelmare
ca2d969198 Fix field type conflict in influxdb
* Add STATE_UNAVAILABLE to states that are ignored when writing to the
  database. This will avoid a field type error for string if the field
  already contains a different type, eg integer.
* Add test for ignored states for influxdb.
* Clean up influxdb tests.
2016-04-16 20:25:39 +02:00
Paulus Schoutsen
37a28c799f Merge pull request #1833 from home-assistant/iso8601
Use standardised datetime format
2016-04-16 10:06:33 -07:00
Paulus Schoutsen
1cfbeabaec Update frontend 2016-04-16 10:05:29 -07:00
Paulus Schoutsen
68d92c3196 Use standardised datetime format 2016-04-16 01:46:50 -07:00
Justyn Shull
bf3b77e1f2 Change sqlite queries to work with older versions of sqlite 2016-04-15 21:18:51 -05:00
Justyn Shull
d5ca97b1f6 Add tests for purging old states and events 2016-04-15 21:02:17 -05:00
Justyn Shull
fd48fc5f83 Add CONFIG_SCHEMA to verify config. Move purge_days key name to
CONF_PURGE_DAYS so it can be changed easier later.

Use 'recorder' domain instead of 'history' domain.

Pass purge_days config directly into Recorder object instead of passing
the config object around.
2016-04-15 19:54:30 -05:00
Justyn Shull
c89cd6a68c Add 'purge_days' option to the history/recorder component
Issue https://github.com/balloob/home-assistant/issues/1337

When purge_days is set under the history component, recorder.py will
delete all events and states that are older than purge_days days ago.

Currently, this is only done once at start up.   A vacuum command is
also run to free up the disk space sqlite would still use after deleting
records.
2016-04-15 19:54:30 -05:00
Paulus Schoutsen
e7520ef401 Update frontend + mdi 2016-04-14 22:57:41 -07:00
Paulus Schoutsen
f5ee3e6e13 Merge pull request #1821 from home-assistant/service-validations
Service validations
2016-04-13 22:38:14 -07:00
Alex Harvey
0abedd8b46 fix for plex not detecting plex players after power up (#1824) 2016-04-13 22:33:30 -07:00
Paulus Schoutsen
abd376cbba Merge pull request #1816 from JshWright/feature/accurate-away-temps-nest
Improve Nest target temp display
2016-04-13 22:01:01 -07:00
Øystein Hansen
8b986b0b97 mysensors.py Prevent sensor name mixup (#1802)
Change the sensor name schema so nodes are not mixed up. The dot that was pressent before was ignored by home-assistant.
Before name:  <skeatchname> <node_id><child_id>  eg. wall 107
New name   :  <skeatchname> <node_id> <child_id>  eg. wall 10 7
This will result in a Home Assistant Entity ID of: sensor.wall_10_7
2016-04-13 21:22:40 -07:00
Dennis Karpienski
f1d8667d7e Yamaha AVR Input Select (#1796)
* added select input for yamaha

* set source_list to none on init
2016-04-13 21:13:12 -07:00
Jan Harkes
298a1c2af7 Service validation for alarm_control_panel component. 2016-04-13 13:45:11 -04:00
Fabian Affolter
9d71a8c4b9 Merge pull request #1819 from fabaff/typos
Update file header and fix typos
2016-04-13 19:35:06 +02:00
Jan Harkes
5cdaee7ebb Service validation for browser component. 2016-04-13 12:57:47 -04:00
Jan Harkes
7c9729b9c1 Service validation for conversation component. 2016-04-13 12:48:39 -04:00
Jan Harkes
003bd24976 Service validation for downloader component. 2016-04-13 12:35:08 -04:00
Jan Harkes
652fe7e0f2 Service validation for garage_door component. 2016-04-13 12:35:08 -04:00
Jan Harkes
49b002dc53 Service validation for ifttt component. 2016-04-13 12:35:07 -04:00
Jan Harkes
7e0d9bc709 Service validation for input_boolean component. 2016-04-13 12:35:07 -04:00
Jan Harkes
bfdbbbddac Service validation for input_select component. 2016-04-13 12:35:07 -04:00
Jan Harkes
620d7a92f0 Service validation for input_slider component. 2016-04-13 12:35:07 -04:00
Jan Harkes
8b40346db3 Service validation for keyboard component. 2016-04-13 12:35:07 -04:00
Jan Harkes
5c520b0d35 Service validation for lock component. 2016-04-13 12:35:07 -04:00
Jan Harkes
d6f3123937 Service validation for logbook component. 2016-04-13 12:35:07 -04:00
Jan Harkes
7ffc254a87 Service validation for notify component. 2016-04-13 12:35:07 -04:00
Jan Harkes
40e36126bc Service validation for rollershutter component. 2016-04-13 12:35:07 -04:00
Jan Harkes
ad6f5d3b1d Service validation for scene component. 2016-04-13 12:35:07 -04:00
Jan Harkes
567d1065b2 Service validation for script component. 2016-04-13 12:35:07 -04:00
Jan Harkes
d90f31bf6e Config and service validation for shell_command component. 2016-04-13 12:35:07 -04:00
Jan Harkes
1deaf2fe8f Service validation for switch component. 2016-04-13 12:35:07 -04:00
Jan Harkes
730514cea8 Service validation for the thermostat component. 2016-04-13 12:35:07 -04:00
Fabian Affolter
85901d60c4 Update file header and fix typos 2016-04-13 13:50:28 +02:00
Robbie Trencheny
05469e6d9b Update pyGTFS version 2016-04-13 00:40:12 -07:00
Paulus Schoutsen
1f96c4ad88 Update submodule 2016-04-12 23:57:07 -07:00
Robbie Trencheny
c121c9aa39 Fix links in README.rst 2016-04-12 21:37:10 -07:00
Paulus Schoutsen
3ed104529c Merge pull request #1811 from fabaff/moving
Update links
2016-04-12 21:16:01 -07:00
Jan Harkes
0e10f7ced9 Ignore tests/config/deps/ for both git and flake8.
Sometimes py.test leave some packages around in tests/config/deps.
Make sure these do not accidentally get pulled into a commit or
cause a local tox run to fail.
2016-04-12 18:46:34 -04:00
Jan Harkes
4aa43bbf7a New version of betamax breaks the yr.no sensor test.
Pin to betamax-0.5.1 for now.
2016-04-12 18:46:34 -04:00
Josh Wright
1685bbe1f7 Fix copy/paste logic error 2016-04-12 18:45:57 -04:00
Josh Wright
942d722dcf Improve target temperature selection logic
When picking which of the high/low temperatures to display as the
"target", it makes more sense to take the outside temperature into
consideration, rather than the current temperature of the thermostat.

If the temperature outside is less than the temperature of the
thermostat, then we are far more likely to end up in "heating" mode
eventually, and vice versa, regardless of where the current inside
temp falls in the range between high and low.
2016-04-12 18:25:24 -04:00
Josh Wright
c4a71fbfa7 Include away temps in target temps
The target temperature methods were not taking the 'away' status
into account. leading to misleading target temps being reported.
2016-04-12 18:15:24 -04:00
Jan Harkes
ebf45012fb Ignore tests/config/deps/ for both git and flake8.
Sometimes py.test leave some packages around in tests/config/deps.
Make sure these do not accidentally get pulled into a commit or
cause a local tox run to fail.
2016-04-12 14:58:02 -04:00
Jan Harkes
0bf49aea6f New version of betamax breaks the yr.no sensor test.
Pin to betamax-0.5.1 for now.
2016-04-12 14:43:04 -04:00
Daniel Høyer Iversen
cd80e41b32 Allow negative elevation in yr config 2016-04-12 07:54:03 -07:00
Fabian Affolter
4ecd8d5f11 Update links 2016-04-12 14:18:18 +02:00
Paulus Schoutsen
5b8a2b00df Update frontend 2016-04-12 00:24:19 -07:00
Alexander Fortin
24569e6169 Make owntracks.py pylint clean (#1808)
* refactor validation logic into validate_payload function
* add debugging messages to validation
2016-04-11 22:02:47 -07:00
Fabian Affolter
4a16d8064d Enable certificate verification and allow non-encrypted communication (#1763) 2016-04-11 21:55:17 -07:00
Jan Harkes
9d848731d9 Nest config validation (#1810)
* Config validation for Nest platforms.
2016-04-11 21:52:19 -07:00
Jan Harkes
656e187729 Some fixes for yr config validation. (#1809)
The setup_platform function is trying to get CONF_LATITUDE and CONF_LONGITUDE,
but the validation schema was not accepting these.

Also moved CONF_MONITORED_CONDITIONS and CONF_ELEVATION to homeassistant.const
because they are used in other places.
2016-04-11 21:44:39 -07:00
Jan Harkes
241735c924 Change local library path from {config_dir}/lib to {config_dir}/deps. (#1799)
Just on the off chance that someone who happens to run as root and also
doesn't correctly parse "just remove config /lib and restart".
2016-04-11 20:07:50 -07:00
Paulus Schoutsen
3de51bf75d Merge pull request #1807 from balloob/release-0.17.3
0.17.3
2016-04-11 19:56:41 -07:00
Paulus Schoutsen
4023021b21 Version bump to 0.17.3 2016-04-11 19:48:37 -07:00
Jan Harkes
2c665ca3e4 Do not propagate api password (#1797)
* Do not propagate API password in service requests.

It makes service validation fail. The choice is to either handle it as an
optional key in every service handler and make sure it doesn't end up in event
stream and notifications, or to strip it as early as possible.

* Some places still need a forwarded api password.

- Event forwarding/remote api uses the local api password to
  authenticate against the remote instance.
- The generated index.html at '/' embeds the api password.
2016-04-11 19:48:16 -07:00
Jan Harkes
4857117dda Do not propagate api password (#1797)
* Do not propagate API password in service requests.

It makes service validation fail. The choice is to either handle it as an
optional key in every service handler and make sure it doesn't end up in event
stream and notifications, or to strip it as early as possible.

* Some places still need a forwarded api password.

- Event forwarding/remote api uses the local api password to
  authenticate against the remote instance.
- The generated index.html at '/' embeds the api password.
2016-04-11 19:37:15 -07:00
Josh Wright
80d6e9f08f Use constant time comparison for http authentication (#1804)
In order to prevent a potential timing attack, it's important to make
sure the password check takes the same amount of time, regardless of
how many characters in the candidate password match the real password.

This commit does increase the verbosity of the authentication check.
Generally it is a good idea for authentication logic to be very clear,
even if that requires some extra verbosity.
2016-04-11 19:36:25 -07:00
Robbie Trencheny
0018d2b3f5 Fix flake8 error on zeroconf.py 2016-04-10 18:55:54 -07:00
Robbie Trencheny
5d8cd6d49d Merge pull request #1790 from robbiet480/upnp
UPnP port mapping component
2016-04-10 18:47:47 -07:00
Robbie Trencheny
ed6958f477 Change needs_auth ZeroConf key 2016-04-10 18:46:57 -07:00
Robbie Trencheny
27d624fc4a Merge remote-tracking branch 'upstream/dev' into upnp 2016-04-10 18:24:04 -07:00
Paulus Schoutsen
948aa6838d Remove stale print 2016-04-10 18:22:25 -07:00
Robbie Trencheny
6f149d414a Disable import-error on upnp 2016-04-10 18:19:32 -07:00
Robbie Trencheny
f1e46e63c0 Merge pull request #1733 from robbiet480/http-zeroconf
ZeroConf component
2016-04-10 18:17:06 -07:00
Robbie Trencheny
a3959d5e01 Update netdisco dependency to 0.6.4 (deja vu all over again!) 2016-04-10 18:10:31 -07:00
Robbie Trencheny
eca1631f1b Update netdisco dependency to 0.6.3 2016-04-10 18:05:30 -07:00
Robbie Trencheny
f30b406334 Merge remote-tracking branch 'upstream/dev' into http-zeroconf 2016-04-10 18:04:56 -07:00
Robbie Trencheny
1de45ebe8b Fix api_password conditional and close zeroconf when we shut down 2016-04-10 17:59:21 -07:00
Robbie Trencheny
5b51f682ca Remove unnecessary disable=no-name-in-module 2016-04-10 17:49:07 -07:00
Robbie Trencheny
41c3f695b4 UPnP port mapping component 2016-04-10 17:44:57 -07:00
Paulus Schoutsen
197388a9b2 Prevent device tracker error 2016-04-10 17:35:33 -07:00
Dennis Karpienski
a862e994c7 Thinkingcleaner support (#1784)
* added first implementation of thinking cleaner

* fix lock release

* fixed tox flaws

* updated coveragerc

* fixed lock

* changed update lock

* fixed codestyle
2016-04-10 16:59:53 -07:00
Markus Peter
fec45033bc Expanded homematic component with MAX! support via homegear (#1783)
* Expanded homematic component with MAX! support via homegear
Also multithreading fixes

* fixed tox errors

* incorporate changes suggested by balloob

* replaced HomematicConfig Container Class with namedtuple

* fixed lint errors
2016-04-10 16:26:08 -07:00
Robbie Trencheny
e1ffdcc5f1 Use hass.config.api instead of hass.http 2016-04-10 16:09:52 -07:00
Robbie Trencheny
085d90ed67 Revert all http.py changes 2016-04-10 16:08:00 -07:00
Daniel Høyer Iversen
769d958464 Config validation for rfxtrx sensor (#1780) 2016-04-10 16:05:32 -07:00
Robbie Trencheny
e70338dfe1 Block zeroconf from tests 2016-04-10 16:03:40 -07:00
Robbie Trencheny
beac69ad17 Final clean up, flake8, pylint, change a variable name, remove unnecessary imports 2016-04-10 16:02:07 -07:00
Robbie Trencheny
c33c2c01d2 Break Zeroconf into its own component 2016-04-10 15:34:04 -07:00
Paulus Schoutsen
4f834ba3f1 Make all entity_ids lowercase (#1786) 2016-04-10 15:20:20 -07:00
Paulus Schoutsen
6d65b0bbd7 Update frontend 2016-04-10 15:18:44 -07:00
Daniel Høyer Iversen
d3493c7e5a Config validation of yr sensor (#1767) 2016-04-10 10:43:05 -07:00
Josh Wright
24257fe4a3 Don't round values in Thermostat internal state (#1782)
Since all values coming out of the Thermostat component pass though the
_convert_for_display() method (which handles any necessary rounding),
there is no need to round values that only exist in the internal state
of the thermostat device. It serves no purpose and risks rounding
errors/precision loss.
2016-04-10 10:41:13 -07:00
Paulus Schoutsen
3d98b8b5b3 Update frontend 2016-04-10 01:43:40 -07:00
Paulus Schoutsen
988dd2ca83 Update frontend 2016-04-10 01:33:01 -07:00
Joel Asher Friedman
9808c0e3fd mqtt garage door component (#1742) 2016-04-09 20:31:53 -07:00
OpenDave15
91b1ebaeb7 Allow use of pynetgear 3.3 port parameter. (#1777)
* Allow use of pynetgear 3.3 port parameter.

* Fix lint problem
2016-04-09 20:29:06 -07:00
Paulus Schoutsen
1e86044590 Update netdisco to 0.6.2 2016-04-09 20:24:34 -07:00
Paulus Schoutsen
c98b56a807 Merge pull request #1778 from balloob/hotfix/0.17.2
Hotfix/0.17.2
2016-04-09 16:23:20 -07:00
Paulus Schoutsen
fa0be21342 Version bump to 0.17.2 2016-04-09 16:16:05 -07:00
Jan Harkes
7be29468d5 Make yaml config parser errors look less like bugs. (#1776)
Instead of nested tracebacks, show a simpler error message.

    Config directory: /home/user/.homeassistant
    ERROR:homeassistant.util.yaml:duplicate key: "script"
      in "/home/user/.homeassistant/configuration.yaml", line 95, column 0
      in "/home/user/.homeassistant/configuration.yaml", line 108, column 0
2016-04-09 16:15:49 -07:00
Paulus Schoutsen
9924351a42 Prevent device tracker from creating invalid YAML (#1774) 2016-04-09 16:15:49 -07:00
Jan Harkes
73859f59f0 Make yaml config parser errors look less like bugs. (#1776)
Instead of nested tracebacks, show a simpler error message.

    Config directory: /home/user/.homeassistant
    ERROR:homeassistant.util.yaml:duplicate key: "script"
      in "/home/user/.homeassistant/configuration.yaml", line 95, column 0
      in "/home/user/.homeassistant/configuration.yaml", line 108, column 0
2016-04-09 15:25:01 -07:00
Paulus Schoutsen
b87e2437aa Prevent device tracker from creating invalid YAML (#1774) 2016-04-09 13:38:51 -07:00
Paulus Schoutsen
a41514ca50 0.17.1 (#1771)
* We need to allow extra keys on top level componenet config

fixes #1756

* Add comment about location of hass (fixes #1723)

* Fix for MQTT config validation on the protocol field. (#1765)

* Update frontend with weblink fix

* Fix for light service validation. (#1770)

Incorrect validation tested if passed value was a list instead of
a member of the list.

* Accept group without entities in configuration. (#1768)

* Accept group without entities in configuration.

People seem to use these as placeholders for future expansion of their
home automation dreams, and we used to accept them.  We still have to
specify at least one of 'name', 'view' or 'icon' so that the group is
parsed as a dictionary.

* Also accept empty entities: key in a group.

* Additional fix for empty entities value in a group config.

* Version bump to 0.17.1
2016-04-09 09:55:52 -07:00
Jan Harkes
446d367aeb Accept group without entities in configuration. (#1768)
* Accept group without entities in configuration.

People seem to use these as placeholders for future expansion of their
home automation dreams, and we used to accept them.  We still have to
specify at least one of 'name', 'view' or 'icon' so that the group is
parsed as a dictionary.

* Also accept empty entities: key in a group.

* Additional fix for empty entities value in a group config.
2016-04-09 09:24:18 -07:00
Paulus Schoutsen
982f8f41ae Update frontend with weblink fix 2016-04-09 09:09:17 -07:00
Jan Harkes
7a25ae3e2c Fix for light service validation. (#1770)
Incorrect validation tested if passed value was a list instead of
a member of the list.
2016-04-09 09:07:13 -07:00
Jan Harkes
3aa4727b18 Fix for MQTT config validation on the protocol field. (#1765) 2016-04-09 09:03:41 -07:00
Paulus Schoutsen
b3bad10dab Merge pull request #1758 from turbokongen/patch-1
We need to allow extra keys on top level componenet config
2016-04-09 09:02:55 -07:00
Fabian Affolter
c210242c80 Add comment about location of hass (fixes #1723) 2016-04-09 10:55:42 +02:00
John Arild Berentsen
f36cfcdbd9 We need to allow extra keys on top level componenet config
fixes #1756
2016-04-09 10:50:46 +02:00
Paulus Schoutsen
ff47cffe8a Version bump to 0.18.0.dev0 2016-04-08 21:43:29 -07:00
Paulus Schoutsen
e97667aea0 Merge pull request #1727 from balloob/dev
0.17
2016-04-08 21:43:15 -07:00
Paulus Schoutsen
66bf8df768 Version bump to 0.17 2016-04-08 21:32:26 -07:00
Paulus Schoutsen
db3f848905 Correct frontend version 2016-04-08 21:32:18 -07:00
Paulus Schoutsen
2ec9cc15f4 Build frontend 2016-04-08 21:28:59 -07:00
Daniel Høyer Iversen
cac555fc69 Rfxtrx config validating (#1747)
* config validation

* Config validation of rfxtrx switch

* Config validation of rfxtrx light

* Config validation of rfxtrx

* Config validation of rfxtrx
2016-04-08 20:55:31 -07:00
Jan Harkes
d6abdc0d4e Add line numbers when we find duplicate keys. (#1750) 2016-04-08 20:53:27 -07:00
Jan Harkes
db2783c2d1 Upgrade astral (#1754)
* Upgrade astral to 1.0

* Pass timezone as string, not object, to astral.Location.
2016-04-08 20:51:48 -07:00
Jan Harkes
c481cbce7e Make tox run faster by using in-memory sqlite db. (#1752)
Two tests were invariably grinding my system to a halt as it was
applying migrations to an empty sqlite database. This patch reduces
the time of a pytest run from 50 to about 16 seconds on my desktop.

The difference is even more noticable on a slower laptop drive, but
is probably insignificant for all you fancy SSD users.
2016-04-08 18:28:19 -07:00
Greg Dowling
f5227e1de0 Fix vera breaking component loading order. (#1749) 2016-04-08 11:38:02 -07:00
Fabian Affolter
f6331da000 Remove print 2016-04-08 08:03:14 -07:00
Paulus Schoutsen
3dc874dcf5 Update frontend (embed Roboto) 2016-04-08 00:15:02 -07:00
Paulus Schoutsen
98543072dd Add feature request link to issue template 2016-04-07 19:42:21 -07:00
Jan Harkes
9e0e61fec9 Trying to fix failing sun component tests. (#1741)
Make sure we set a timezone to make UTC calculations predictable
and don't override the location of the test_home_assistant config.
2016-04-07 18:32:21 -07:00
Greg Dowling
a7f80608c6 Handle Share off for events in OwnTracks app (#1737) 2016-04-07 12:21:25 -07:00
Jan Harkes
29c30861bf Be flexible in what we accept for script.delay configuration. (#1738)
Accept delay configuration even when someone forgets to indent the time

specification.



Also removed 'weeks' and 'microseconds' from acceptable delay values.

There is a new homeassistant release every 2 weeks and running scripts

are not persisting across restarts. And there is still the option of

using (weeks*7) days if the long delay is really necessary.



And if someone really depends on microsecond delay precision we are

unlikely to be able to provide this accuracy, even milliseconds is

suspect for that matter but will at least allow us to specify some

subsecond delay.
2016-04-07 12:19:28 -07:00
Jan Harkes
5b17f629ad Test function for mqtt topic validators and IsFile() linting fix (#1740)
* Add test function for mqtt topic validators.
* Fix for linting error on vol.IsFile()
2016-04-07 13:52:25 -04:00
Paulus Schoutsen
7d9b13a6a2 Merge pull request #1739 from JshWright/fix/mqtt-config-validation
vol.IsFile() needs to be called
2016-04-07 10:13:53 -07:00
Josh Wright
3539193bae vol.IsFile() needs to be called
vol.IsFile results in an instance of the IsFile method being returned by
the schema validation process. It needs to be called in order to do the
right thing.
2016-04-07 12:39:27 -04:00
Paulus Schoutsen
5ff9479f0b Merge pull request #1703 from jaharkes/config-validation-mqtt
Config validation for MQTT
2016-04-07 08:43:01 -07:00
Hernán
7b80ed8135 Add Kodi play media
* Added media_player/play_media service to Kodi

* revert

* fixes

* lint fixed, base class fixed
2016-04-07 08:41:41 -07:00
Daniel Høyer Iversen
a1a2e456ad Add test for fire event in rfxtrx component 2016-04-07 08:40:15 -07:00
Greg Dowling
26c24b8ed3 Merge pull request #1736 from balloob/wemo-light-fix
Bump pywemo to 0.4.1 - fix non native light issue.
2016-04-07 14:29:14 +01:00
pavoni
54aa7b80ea Bump pywemo to 0.4.1 - fix non native light issue. 2016-04-07 10:00:25 +01:00
Jan Harkes
3bc06ac79e We need to allow extra keys on the top-level component config. 2016-04-07 00:42:56 -04:00
Jan Harkes
94835235a4 Config validation for mqtt_eventstream component. 2016-04-06 23:25:28 -04:00
Jan Harkes
a7016e4b32 Move CONF_STATE_TOPIC, CONF_COMMAND_TOPIC and CONF_RETAIN to mqtt component. 2016-04-06 22:51:39 -04:00
Jan Harkes
0ef0d4bac7 Config validation for automation MQTT trigger 2016-04-06 22:51:39 -04:00
Jan Harkes
fca08b095a Config validation for MQTT rollershutter platform. 2016-04-06 22:51:39 -04:00
Jan Harkes
deecec5e4e Config validation for MQTT switch platform. 2016-04-06 22:51:39 -04:00
Jan Harkes
eb3f812e38 Config validation for MQTT sensor platform. 2016-04-06 22:51:39 -04:00
Jan Harkes
3383854506 Move CONF_OPTIMISTIC to homeassistant.const. 2016-04-06 22:51:39 -04:00
Jan Harkes
c8df06bb9f Config validation for MQTT lock platform. 2016-04-06 22:51:38 -04:00
Jan Harkes
4e864b5caa Rename _mqtt_topic to valid_subscribe_topic. 2016-04-06 22:51:38 -04:00
Jan Harkes
29a8403741 Config validation for MQTT light platform. 2016-04-06 22:51:38 -04:00
Jan Harkes
88da42fe62 Config validation for MQTT device_tracker platform. 2016-04-06 22:51:38 -04:00
Jan Harkes
287f0f4f68 Config validation for MQTT binary_sensor platform. 2016-04-06 22:51:38 -04:00
Jan Harkes
0bd4e15fcb Config validation for MQTT alarm_control_panel platform. 2016-04-06 22:51:38 -04:00
Jan Harkes
2c119091dc Add MQTT schema validation functions for platform schemas. 2016-04-06 22:51:38 -04:00
Jan Harkes
58ea589f99 Fixes for mqtt config validation tests. 2016-04-06 22:51:38 -04:00
Jan Harkes
8cca2bb344 Config validation for MQTT 2016-04-06 22:51:38 -04:00
Josh Wright
2e9bf42688 Disable updater.updater on dev versions
The Updater component doesn't make much sense on dev versions. If you

want to run a production config with the updater enabled, you end up

with an 'Update Available' badge pointing you to the last release

version. This change disables the Updater component on dev and updates

the tests to use a faked version number.



A warning is emitted if the Updater component is disabled to ensure

there is no confusion.
2016-04-06 18:46:48 -07:00
Andrew McClure
c99617d6e5 Ensure server_host is respected in configuration.yaml 2016-04-06 18:45:40 -07:00
Will Hughes
5a32ddbe6f Update Orvibo platform to the switch component, add 'mac' option
This adds an optional 'mac' configuration option to the platform which

is passed to the underlying Orvibo library. The 'mac' option is required

when the switch is connected to a different subnet to the Home Assistant

host
2016-04-06 14:52:21 -07:00
Robbie Trencheny
27aabd961c Remove unnecessary variable 2016-04-06 13:51:43 -07:00
Robbie Trencheny
86dad0c045 Add ZeroConf support to http.py 2016-04-06 13:51:26 -07:00
Fabian Affolter
3bc37397d2 Merge pull request #1728 from fabaff/conf-sample
Fix typos and update freegeoip URL
2016-04-06 22:37:30 +02:00
Fabian Affolter
b3a6ac74fa Fix typos and update freegeoip URL 2016-04-06 22:30:05 +02:00
Josh Wright
29fb6faa40 Use whole degrees fahrenheit for thermostats
Users of fahrenheit generally expect to see whole degrees. The fahreneit

scale is suffiently precise that decimals aren't really useful in terms

of temperatures humans care about.



This change rounds fahrenheit values to whole degrees and celsius values

to one decimal place. It also renames the ThermostatDevice._convert()

method to _convert_for_display(), making its purpose more clear. It is

not useful for the min_temp() and max_temp() methods, as those relate to

the internal state of the ThermostatDevice object, and may use different

units. Adding optional source and target units to _convert() would have

added needless complexity, it's cleaner to just use convert() in those

methods.
2016-04-06 11:54:50 -07:00
Paulus Schoutsen
71196d32bc Merge branch 'master' into dev
Conflicts:
	homeassistant/const.py
	requirements_all.txt
2016-04-06 11:51:03 -07:00
Alexander Fortin
e8efcd21df Increase sonos volume increment from 1 to 5 2016-04-06 11:32:27 -07:00
Daniel Høyer Iversen
cfb318287d Refactor rfxtrx component 2016-04-06 10:34:51 -07:00
Fabian Affolter
2e44166854 Change to freegeoip.io and add a second service as fall-back 2016-04-06 10:25:40 -07:00
Paulus Schoutsen
b4ddc86304 Fix speedtest with external installed package 2016-04-06 07:38:35 -07:00
Florian Holzapfel
ecc440f459 add panasonic viera tv media player device 2016-04-05 22:51:55 -07:00
Jan Harkes
dbbbed404c Detect duplicate keys in configuration.yaml. 2016-04-05 21:21:16 -07:00
Jan Harkes
3bb571b578 Bump rxv to 0.1.11.
Fixes socket read/write timeout issues.
2016-04-05 14:17:42 -04:00
Paulus Schoutsen
8ef542927f Add automation config validation
* Add automation config validation

* Remove unnecessary dict validator

* Downgrade voluptuous to 0.8.9

* Fix linting

* Address issues
2016-04-04 12:18:58 -07:00
Jan Harkes
cbe9a7d2a3 Add case insensitive testing to boolean string validation. 2016-04-03 21:38:58 -07:00
Robbie Trencheny
eb415d7b96 Allow passing in a dictionary of provider specific data 2016-04-03 17:54:58 -07:00
Justyn Shull
c232242af0 Add support for monitoring nzbget
Calculate average download rate the same way as downloadrate



Add config option for choosing which nzbget variables to monitor, and provide a default



Pep8 fixes



Refactoring and changes based on @balloob's comments



Add nzbget.py to .coveragerc omit list.  Check if there are any http

errors (like bad auth) when creating the nzbgetapi class.   If there

are, the setup_platform() function will return false.  Exceptions are

logged as well.

When a new sensor is created, assign the initial value from the api

instead of simply using None until the first update call.
2016-04-03 15:57:50 -07:00
Robbie Trencheny
8308e2335a Merge pull request #1698 from robbiet480/fix-broken-rest-notify
This code never properly worked because the incorrect variable was used
2016-04-03 15:47:20 -07:00
Robbie Trencheny
d00e63486a This code never properly worked because the incorrect variable was used 2016-04-03 15:45:44 -07:00
Paulus Schoutsen
e140e9b8ab Add script + extra config validators
* Add config validation and extra validators

* Address PR comments
2016-04-03 10:19:09 -07:00
Paulus Schoutsen
7ed5055fa2 Fix MQTT linting 2016-04-03 02:25:02 -07:00
Jan Harkes
9ce2081110 Coerce ascii flags in MQTT publish service call.
Also fixes a bug where the test when no payload is given succeeds only

because we run the jinja templating out of memory. Sending an empty

payload instead of trying to fix it through validation for now.
2016-04-03 00:54:05 -07:00
Fabian Affolter
24b7a7b964 Add source ip to log entry 2016-04-03 00:46:05 -07:00
Paulus Schoutsen
f6d584af09 Allow platforms to specify PLATFORM_SCHEMA 2016-04-02 20:10:57 -07:00
Kai
4fba89b789 Add Z-Wave thermostat
based on @coteyr work and with a help from @turbokongen
2016-04-02 20:01:03 -07:00
Fabian Affolter
c7fd0eb9d9 Upgrade to pytz 2016.3 2016-04-02 19:30:25 -07:00
Greg Dowling
61a9562811 Reconnect loopenergy
* Bump pyloopenergy version to handle disconnects. Round floats.

* Bump pyloopenergy version - to support reconnect.
2016-04-02 08:47:21 -07:00
Jan Harkes
5c753f8ffd Service validation for MQTT component.
* Service validation for MQTT component.

* Fixes for failing mqtt tests.

- Changed behaviour when both 'payload' and 'payload_template' are provided
  instead of silently ignoring the payload_template value.
- Have validation accept any type of payload and leave encoding to paho-mqtt.
2016-04-02 08:46:09 -07:00
sander76
ebd053824d changed scene name to unique powerview id's 2016-04-02 08:41:57 -07:00
Jan Harkes
afd1e6a5cc Service validation for media_player component 2016-04-02 03:51:03 -04:00
Paulus Schoutsen
5c262753d4 Merge pull request #1677 from jaharkes/config-validation-nest
Config validation for Nest component
2016-04-01 08:07:31 -07:00
Paulus Schoutsen
a0df7d9ff3 Merge pull request #1674 from jaharkes/group-order
Maintain group ordering across validation.
2016-04-01 08:06:01 -07:00
Paulus Schoutsen
2c6b4db448 Merge pull request #1669 from fabaff/vincenty
Upgrade vincenty to 0.1.4 (fixes #1666)
2016-04-01 08:00:10 -07:00
Paulus Schoutsen
cde86831ee Merge pull request #1676 from balloob/loopenergy-shutdown
Fix thread termination on exit for Loopenergy, Vera and Wemo
2016-04-01 07:52:29 -07:00
pavoni
6ee086c0bb Fix thread termination on exit. 2016-04-01 15:36:33 +01:00
Jan Harkes
faebc9e2c4 Config validation for nest component 2016-04-01 10:31:39 -04:00
Jan Harkes
5aa04de006 Merge pull request #1675 from jaharkes/pywemo-version
Bump pywemo version
2016-04-01 10:10:20 -04:00
Jan Harkes
d0b7f6cfb0 Bump pywemo version 2016-04-01 10:02:55 -04:00
Jan Harkes
e5eb3b13c4 Maintain group ordering across validation. 2016-04-01 09:45:27 -04:00
Fabian Affolter
6731560a7d Upgrade vincenty to 0.1.4 (fixes #1666) 2016-04-01 11:08:13 +02:00
Paulus Schoutsen
deffbeb922 Update frontend 2016-04-01 00:37:30 -07:00
Paulus Schoutsen
7df8e010f3 Merge pull request #1665 from balloob/update-netdisco
Update netdisco dependency
2016-03-31 23:35:32 -07:00
Paulus Schoutsen
ee91bcc601 Update netdisco dependency 2016-03-31 23:30:08 -07:00
Paulus Schoutsen
c8e88d923a Merge pull request #1648 from balloob/yr_default_config
Add yr weather component to default config
2016-03-31 23:28:14 -07:00
Paulus Schoutsen
423d8be83f Merge pull request #1658 from balloob/add_loop_energy
Add loop Energy sensors.
2016-03-31 23:16:23 -07:00
Paulus Schoutsen
b063fa3165 Merge pull request #1646 from balloob/rfxtrx
Fixed bug in rfxtrx sensor
2016-03-31 22:12:04 -07:00
Paulus Schoutsen
d710940819 Merge pull request #1663 from balloob/fix-config-dependency
bootstrap platform components: adjust instead of replace config
2016-03-31 21:38:40 -07:00
Paulus Schoutsen
489c5b8188 bootstrap platform components: adjust instead of replace config 2016-03-31 21:11:14 -07:00
Jan Harkes
b45bbbcecf Merge pull request #1661 from jaharkes/service-call-validation
Service call validation
2016-03-31 23:36:11 -04:00
Jan Harkes
6d914126fa Validate data read from light_profiles.csv 2016-03-31 23:29:07 -04:00
Jan Harkes
4f3dc2ce8b Coerce RGB and XY color values to tuples instead of lists. 2016-03-31 22:59:18 -04:00
Jan Harkes
017f47dd2c Service validation for light.turn_on/.turn_off/.toggle 2016-03-31 22:03:38 -04:00
Robbie Trencheny
2e105e408a Merge pull request #1659 from shaftoe/sonosfix
FIX enable volume commands for non-coordinators too
2016-03-31 18:29:41 -07:00
Jan Harkes
5bd58351c7 Move service scheme validation into Service.__call__
Keeps where the schema is stored and validated close.
2016-03-31 21:13:40 -04:00
Alexander Fortin
b304b77005 FIX enable volume commands for non-coordinators too 2016-03-31 21:36:58 +02:00
Jan Harkes
64030b9d48 Add validation schema as optional argument to service registration. 2016-03-31 14:59:36 -04:00
pavoni
c41e63806c Add loop Energy sensors. 2016-03-31 17:00:43 +01:00
Paulus Schoutsen
bcb0eb53f3 Merge pull request #1650 from turbokongen/dev
Fix crash of Rfxtrx component when using config option fire_event
2016-03-30 08:42:16 -07:00
root
7b1ec418f2 Fix crash of Rfxtrx component when using config option fire_event 2016-03-30 16:20:19 +02:00
Daniel
00eda74c7e Add yr weather component to default config 2016-03-30 11:33:35 +02:00
Daniel
c4062bf6ea Fixed bug in rfxtrx sensor 2016-03-30 10:57:26 +02:00
Paulus Schoutsen
4a504a9f03 Merge pull request #1645 from srcLurker/zwave_polling
Enable zwave test_network command.
2016-03-30 01:36:13 -07:00
Charles Spirakis
b8ea743843 Enable zwave test_network command.
Allows for testing the zwave network by sending
a no-op command to all the nodes. In theory,
this will also bring back nodes which have been
put in the "presumed dead" state.
2016-03-30 01:29:11 -07:00
Paulus Schoutsen
5b00919bed Merge branch 'pr/1643' into dev
Conflicts:
	requirements_all.txt
2016-03-29 23:23:45 -07:00
Paulus Schoutsen
a4ffec341b Merge pull request #1633 from balloob/config-validation
Add initial config validation
2016-03-29 23:01:36 -07:00
Paulus Schoutsen
ac28228e6b Either validate component config or platform config 2016-03-29 22:51:33 -07:00
Paulus Schoutsen
8ceab5d4ba Add extra tests 2016-03-29 22:50:38 -07:00
Paulus Schoutsen
d0e613194e Merge pull request #1644 from robbiet480/uber-fixes
Uber sensor breaking fix
2016-03-29 22:20:21 -07:00
Robbie Trencheny
56e64d477a Little fixes 2016-03-29 21:02:17 -07:00
Paulus Schoutsen
79391d23ae Merge pull request #1642 from robbiet480/uber-requirements-fix
Change Uber requirements to point to master repo
2016-03-29 20:54:28 -07:00
Robbie Trencheny
55daf51108 Dont set default value for price_details to empty dict since we want to check price_details for is None 2016-03-29 20:42:15 -07:00
Robbie Trencheny
60b427accc Flake8 and Pylint fixes 2016-03-29 20:36:04 -07:00
Robbie Trencheny
0ac34aaa52 Fix for when you have an Uber product that doesnt give a price estimate 2016-03-29 20:14:27 -07:00
Daniel J. Kemp
86199c8277 Add onkyo receiver, and source select support
Added onkyo receiver component

Added support for input source selection to media players,
and do the onkyo receiver component.
2016-03-29 22:17:36 -04:00
Robbie Trencheny
9f5e192761 Uber Rides SDK has been updated upstream to support Python3. No need for this fork anymore! 2016-03-29 18:44:36 -07:00
Paulus Schoutsen
25269cdb6b Add tests for bootstrap config validation 2016-03-29 00:17:53 -07:00
Paulus Schoutsen
a35173a5ff Surpress silly warnings 2016-03-28 23:46:19 -07:00
Paulus Schoutsen
5baa98b79f Add initial config validation 2016-03-28 23:46:12 -07:00
Paulus Schoutsen
0549bc0290 Merge pull request #1636 from srcLurker/zwave_polling
Zwave cleanup for startup and poll_intensity.
2016-03-28 14:12:10 -07:00
Charles Spirakis
f28aa030e6 Zwave cleanup for startup and poll_intensity.
If the polling intensity is zero, specifically
disable polling for that device/sub device.

Have zwave startup wait until the zwave
nework is ready (defined by python openzwave docs):

https://python-openzwave.googlecode.com

SIGNAL_NETWORK_AWAKED : all awake nodes are queried. Some sleeping nodes may be missing.

and

You can safely ask node informations when state >= STATE_AWAKED

This appears to make the polling of nodes a bit more deterministic.
2016-03-28 10:49:58 -07:00
Paulus Schoutsen
69fd927656 Update frontend 2016-03-28 00:15:26 -07:00
Paulus Schoutsen
e989c8a24a Merge pull request #1624 from balloob/http-11
Use HTTP 1.1
2016-03-27 23:21:52 -07:00
Paulus Schoutsen
9089f19165 Merge pull request #1627 from balloob/python-check
Fix broken Python check for Python 2
2016-03-27 22:41:24 -07:00
Paulus Schoutsen
f30376443f Merge pull request #1623 from robbiet480/gtfs-sensor
GTFS sensor
2016-03-27 22:40:20 -07:00
Paulus Schoutsen
fe73cbbcb6 Revert pyicloud upgrade 2016-03-27 22:14:51 -07:00
Paulus Schoutsen
d5498dfb83 Merge pull request #1634 from balloob/hotfix/revert-pyicloud
0.16.1: Revert pyicloud upgrade
2016-03-27 22:13:43 -07:00
Paulus Schoutsen
2c0e8a75a7 Version bump to 0.16.1 2016-03-27 22:12:48 -07:00
Paulus Schoutsen
5dca81d602 Revert pyicloud upgrade 2016-03-27 22:06:27 -07:00
Paulus Schoutsen
79a2d40f4d Merge pull request #1590 from LucaSoldi/some-feature
Added Raspberry Pi Camera Component
2016-03-27 14:00:28 -07:00
Paulus Schoutsen
7cb69ae9d9 Make sure we always sent content-length header 2016-03-27 12:15:41 -07:00
Luca Soldi
5704a319ca Merge branch 'some-feature' of https://github.com/LucaSoldi/home-assistant into some-feature 2016-03-27 20:59:28 +02:00
Luca Soldi
d0503cc021 Add feature
√ add file_path config
√ changed subprocess call
2016-03-27 20:49:04 +02:00
Paulus Schoutsen
c63a3311f4 Fix broken Python check for Python 2 2016-03-27 08:44:15 -07:00
Paulus Schoutsen
fad13beea6 Merge pull request #1626 from fabaff/connection-class
Add connectivity to sensor classes
2016-03-27 08:25:18 -07:00
Fabian Affolter
2db49ebca5 Add connectivity to sensor classes 2016-03-27 11:48:48 +02:00
Paulus Schoutsen
4cbd49921f Use HTTP 1.1 2016-03-26 19:03:16 -07:00
Robbie Trencheny
2a194d8861 Use named string formatting for safety 2016-03-26 18:55:49 -07:00
Paulus Schoutsen
d8121ed8b2 Merge pull request #1621 from balloob/fix-owntracks-acc-bug
Cast acc to float before comparison.
2016-03-26 18:55:11 -07:00
Robbie Trencheny
dac3c9d1b5 Pylint and flake8 2016-03-26 18:53:21 -07:00
Robbie Trencheny
5a35e4a9ba Data source validation 2016-03-26 18:52:03 -07:00
Robbie Trencheny
1fd96296f7 Use parameterized queries when possible 2016-03-26 18:47:54 -07:00
Paulus Schoutsen
5ad95418dd Merge pull request #1622 from fabaff/sensor-class-arest
Add support for sensor classes
2016-03-26 18:40:32 -07:00
Robbie Trencheny
116b83b53f Fix PyGTFS import errors 2016-03-26 18:25:49 -07:00
Robbie Trencheny
f31ba11861 Lock SQLAlchemy 2016-03-26 18:05:34 -07:00
Robbie Trencheny
982baaba22 Annoying missing period 2016-03-26 17:59:38 -07:00
Robbie Trencheny
8a5f60ee23 .coveragerc and requirements_all.txt 2016-03-26 17:54:48 -07:00
Robbie Trencheny
8fe1a9f008 Pylint and flake8 2016-03-26 17:53:46 -07:00
Robbie Trencheny
90f1b57ed8 Initial GTFS sensor 2016-03-26 17:41:09 -07:00
Fabian Affolter
ee36c36783 Add support for sensor classes 2016-03-26 23:39:56 +01:00
pavoni
c7e49f20d3 Cast acc to float before comparison. 2016-03-26 22:38:24 +00:00
Paulus Schoutsen
37b6aa593e Merge pull request #1620 from JshWright/add-shebang
Add shebang for script/setup
2016-03-26 13:33:59 -07:00
Josh Wright
90ec2c274b Add shebang for script/setup 2016-03-26 16:21:27 -04:00
Paulus Schoutsen
80b65f1895 Merge pull request #1618 from balloob/flyte-patch-1
Remove unnecessary dependency from TCP binary sensor for #1617
2016-03-26 11:43:35 -07:00
Flyte
ada561df30 Remove unused import and unnecessary DOMAIN constant from TCP components. 2016-03-26 17:33:18 +00:00
Ellis Percival
15303fd32d Remove unnecessary dependency from TCP binary sensor for #1617 2016-03-26 16:42:53 +00:00
Fabian Affolter
d308b065a9 Merge pull request #1615 from fabaff/upgrade-pyowm
Upgrade pyowm to 2.3.1
2016-03-26 12:56:16 +01:00
Fabian Affolter
2c45d1f27d Upgrade pyowm to 2.3.1 2016-03-26 12:50:12 +01:00
Fabian Affolter
1d198579b7 Merge pull request #1614 from harrykantas/hk/systemd
systemd unit fixes
2016-03-26 12:47:35 +01:00
Harry Kantas
863c111449 systemd unit fixes 2016-03-26 09:58:16 +00:00
Paulus Schoutsen
9d0b15421c Version bump to 0.17.0.dev0 2016-03-26 01:02:30 -07:00
Paulus Schoutsen
763a9ce8c6 Merge pull request #1594 from balloob/dev
0.16
2016-03-26 01:02:12 -07:00
Paulus Schoutsen
e53adf003c Version bump to 0.16 2016-03-26 01:01:46 -07:00
Paulus Schoutsen
3df946aa9e Merge pull request #1598 from aoakeson/dev
Yamaha Receiver Support
2016-03-26 00:05:05 -07:00
Andrew
2285a6761c Initial Yamaha Receiver Implementation
Text Update

Additional additions and better support for volume, and mute.  Cleanup

Added rxv to requirements_all

Added yamaha.py to .coveragerc

Made uppercase, and removed tabs

Added requirements variable

Added doc string for lint

Removed global variable, and simplified state as per balloobs suggestion

Refactored the component with balloobs suggestions

-Added import in the method
- Only get receiver information on init
- A bit of cleanup

Remove up and down volume

Uneeded as this is handled by set volume instead

Fixed a lint build error

More lint fixes

Removed unused imports

Lint Fixes

Simplified if statement

Minor refactoring since the init calls update.

Fixed lint error

Just variable naming change

Added support for an optional name for the receiver.

Better error handling, a bit of refactoring based on balloobs suggestions

Fixed lint error.

Another lint error fix

Changed raise to return

Disable pylint error handling

Pylint broad exception

Made exception handling in the setup platform instead of the constructor.

Lint error fix

Refactored the way devices are found.  This allows for multiple receivers
2016-03-26 00:47:00 -06:00
Paulus Schoutsen
b85753d5da Merge pull request #1613 from robbiet480/media_player_services_yaml
Fill out services.yaml for media_player
2016-03-25 23:45:31 -07:00
Robbie Trencheny
ce4933d637 Fill out services.yaml for media_player 2016-03-25 23:38:10 -07:00
Paulus Schoutsen
de6fc771cb Merge pull request #1607 from fabaff/sensor-class-rest
Add support for sensor classes
2016-03-25 23:27:21 -07:00
Paulus Schoutsen
7f5109e8f3 Merge pull request #1612 from robbiet480/sonos_play_media
Sonos play_media Support
2016-03-25 23:12:29 -07:00
Robbie Trencheny
de68be06dd Misspelling fix 2016-03-25 22:57:28 -07:00
Robbie Trencheny
950cc9e618 Add play_media support to Sonos 2016-03-25 22:57:14 -07:00
Paulus Schoutsen
a3d505f45e Merge pull request #1610 from robbiet480/gntp
Add GNTP notifier
2016-03-25 22:09:13 -07:00
Paulus Schoutsen
befdecc3b0 Merge pull request #1602 from robbiet480/uber-sensor
Uber sensor
2016-03-25 21:51:03 -07:00
Paulus Schoutsen
b92a51c1c3 Merge pull request #1603 from balloob/chore/template-race-condition
Clean up template platforms
2016-03-25 21:48:36 -07:00
Robbie Trencheny
20f8935b86 Clean up a lot of pep8 and syntax errors. 2016-03-25 19:32:49 -07:00
Robbie Trencheny
652c666d14 Add GNTP notifier 2016-03-25 18:39:08 -07:00
Fabian Affolter
9157bd38e8 Update docstrings 2016-03-25 20:35:38 +01:00
Fabian Affolter
f0970f4104 Add support for sensor classes 2016-03-25 18:34:58 +01:00
Paulus Schoutsen
41f205e09d Clean up template platforms 2016-03-24 23:22:17 -07:00
Robbie Trencheny
72c40ab826 Add Uber requirements to requirements_all.txt 2016-03-24 22:30:42 -07:00
Robbie Trencheny
01b216f6cb Block uber.py tests 2016-03-24 22:30:22 -07:00
Robbie Trencheny
5b18ea4237 Fix all pylint, flake8 and pydocstyle issues 2016-03-24 22:30:10 -07:00
Paulus Schoutsen
70ce179224 Merge pull request #1551 from w1ll1am23/command_line_assumed
Added assumed state to command_line switch
2016-03-24 21:54:36 -07:00
Robbie Trencheny
0b9699fd4b Uber sensor 2016-03-24 19:48:10 -07:00
Fabian Affolter
8797ea8f37 Merge pull request #1600 from Bart274/pyiclo
upgrade pyicloud version
2016-03-24 17:31:15 +01:00
Bart274
dd691a4684 upgrade pyicloud version 2016-03-24 17:22:44 +01:00
Fabian Affolter
b6a4257753 Merge pull request #1599 from fabaff/forecast.io
Upgrade to python-forecastio 1.3.4
2016-03-24 17:10:56 +01:00
Fabian Affolter
40e17da415 Upgrade to python-forecastio 1.3.4 2016-03-24 16:42:25 +01:00
Fabian Affolter
fef682b192 Revert "Upgrade pysnmp to 4.3.2"
This reverts commit 38e6f8fdab.
2016-03-24 16:23:57 +01:00
Fabian Affolter
369d234bda Remove wallet 2016-03-24 12:38:18 +01:00
Paulus Schoutsen
5085e337e5 Update frontend 2016-03-24 00:48:21 -07:00
Fabian Affolter
10cb8c0799 Upgrade python-telegram-bot to 3.4 2016-03-24 08:07:59 +01:00
Fabian Affolter
565ae8d30f Upgrade python-mpd2 to 0.5.5 2016-03-24 08:07:06 +01:00
Fabian Affolter
2c770164f2 Upgrade blockchain to 1.3.1 2016-03-24 08:00:05 +01:00
Fabian Affolter
38e6f8fdab Upgrade pysnmp to 4.3.2 2016-03-23 23:57:32 +01:00
Fabian Affolter
a0be348f3a Upgrade psutil to 4.1.0 2016-03-23 22:44:05 +01:00
Fabian Affolter
f7943d9448 Upgrade python-nmap to 0.6.0 (attempt to fix #1592) 2016-03-23 22:25:35 +01:00
Paulus Schoutsen
890930ea32 Merge pull request #1596 from jaharkes/lms-avoid-discovery-error
Assume we only run one Logitech Media server on a host.
2016-03-23 14:14:50 -07:00
Jan Harkes
2d91dce6d0 Assume we only run one Logitech Media server on a host.
Because the LMS discovery mechanism uses the SlimProto protocol to discover the
presence of a Logitech Media server which operates on port 3483/udp and
3483/tcp. But HA uses a different 'CLI' protocol that is typically on port
9090/tcp to query player state.

However the CLI port number is configurable and if someone runs the CLI on a
different port, and has the server configured in configuration.yaml, we get an
error in the logs when we try to connect to 9090/tcp when we find the server
through discovery. Because of the way local slim player discover the server
using SlimProto we can be fairly certain only a single server will run on a
given IP address so if one is already configured with a user defined port, we
should ignore the discovered one that assumes the default port.
2016-03-23 14:47:29 -04:00
LucaSoldi
800397dbe4 Delete python2.7 2016-03-23 14:55:32 +01:00
LucaSoldi
9584f2dab4 Delete .Python 2016-03-23 14:53:52 +01:00
Paulus Schoutsen
154d184247 Merge pull request #1593 from balloob/nest-sensor-fix
Nest sensor - remove broken sensor types
2016-03-23 00:26:07 -07:00
Luca Soldi
65ef836313 Check raspistill exisance and check parameters in setup_platform 2016-03-22 22:35:09 +01:00
Paulus Schoutsen
015527aa5f Nest sensor - remove broken sensor types 2016-03-22 08:45:44 -07:00
Paulus Schoutsen
5bd004ee38 Merge pull request #1526 from tilutza/dev
Arduino switch: add support for default stat and negate port function…
2016-03-22 08:40:39 -07:00
Paulus Schoutsen
8fe0740b7f Update PULL_REQUEST_TEMPLATE.md 2016-03-22 08:39:41 -07:00
Paulus Schoutsen
c22e106d44 Update PULL_REQUEST_TEMPLATE.md 2016-03-22 08:39:24 -07:00
Paulus Schoutsen
4792b9f40c Merge pull request #1583 from Cinntax/pulseaudio-loopback-switch
Pulseaudio loopback switch
2016-03-22 08:30:17 -07:00
Luca Soldi
bf915cf3b4 Added Raspberry Pi Camera Component 2016-03-22 08:33:56 +01:00
Fabian Affolter
0490514d9e Merge pull request #1585 from jaharkes/wemo
Bump pywemo to new version.
2016-03-21 23:50:00 +01:00
Per Sandström
fcfa6f2691 Merge pull request #1586 from persandstrom/vsure_ver_bump
bump vsure version
2016-03-21 20:48:56 +01:00
Per Sandström
ca788b6e4d bump vsure verisure 2016-03-21 20:39:03 +01:00
Jan Harkes
fd7d6a9d53 Bump pywemo to new version. 2016-03-21 10:05:06 -04:00
Dan Cinnamon
6ee3ca8264 Creation of a new platform for the existing switch component. 2016-03-20 23:10:57 -05:00
dtila
a8761e1ef8 Add support for having default state on arduino switch and negate functionality
Arduino switch: add support for default stat and negate port functionality

Travis changes

Arduino switch: add support for default stat and negate port functionality
Because Travis was configured to have maxiimum 5 arguments allowed in functions, I changed the function constructor signature too ... Paul, 6 parameters for a function is really ok

Arduino Switch: add default state config and negate functionality
2016-03-20 12:52:06 +02:00
Paulus Schoutsen
557dae7ab3 Fix typo in light docs 2016-03-19 19:44:20 -07:00
Paulus Schoutsen
454688cc17 Merge pull request #1579 from seedzero/dev
ZwaveDimmer turn_on brightness changed from float to integer
2016-03-19 19:33:45 -07:00
seedzero
59dc8da365 ZwaveDimmer turn_on brightness changed from float to integer 2016-03-20 13:14:59 +11:00
Fabian Affolter
bb658412c4 Revert "Allow encrypted passwords"
This reverts commit 505b3b198e.
2016-03-19 22:19:08 +01:00
Fabian Affolter
505b3b198e Allow encrypted passwords 2016-03-19 22:15:23 +01:00
Martin Hjelmare
0bf13dbf26 Merge pull request #1573 from MartinHjelmare/service-warnings
Log error for servicecall without required data
2016-03-19 08:45:40 +01:00
MartinHjelmare
4e4b24fcff Log error for servicecall without required data
* Log error for services called without required attributes, in
	media_player, notify and thermostat platforms.
* Add fan property and methods in thermostat demo component.
* Add tests for notify file and thermostat demo component.
* Increase coverage of tests for media_player, notify and thermostat
	platforms.
* Fix some PEP issues, but not all. Tests still have old linting
	errors.
2016-03-19 08:06:57 +01:00
Paulus Schoutsen
72fdd94b29 Merge pull request #1576 from joopert/kodi_log_once
log "unable to fetch kodi data" only once
2016-03-18 15:37:52 -07:00
joopert
c6f66de16e log "unable to fetch kodi data" only once 2016-03-18 18:29:50 +01:00
Paulus Schoutsen
41021e63d0 Merge pull request #1574 from joopert/dev
wake on lan platform
2016-03-18 07:21:10 -07:00
joopert
0bbcc81285 wake on lan platform 2016-03-18 15:01:53 +01:00
Paulus Schoutsen
302f32eacd Merge pull request #1553 from florianholzapfel/notify-messagebird
provide sms notifications via messagebird
2016-03-17 22:02:08 -07:00
Paulus Schoutsen
c093a2bf54 Merge pull request #1564 from balloob/fix_template_race_condition
Fix remaining race condition in template components.
2016-03-17 21:18:38 -07:00
Paulus Schoutsen
792954adc9 Merge pull request #1566 from jaharkes/squeezebox-discovery
Add discovery for squeezebox (logitech media) servers.
2016-03-17 21:12:13 -07:00
Paulus Schoutsen
bb5c80b8f5 Merge pull request #1567 from jaharkes/wemo-color-lights
Update to new pywemo bridge API
2016-03-17 21:11:02 -07:00
Paulus Schoutsen
3f3bfbbb94 Merge pull request #1572 from balloob/update-netdisco
Update netdisco to 0.5.5
2016-03-17 21:08:48 -07:00
Paulus Schoutsen
a1f8466754 Merge pull request #1570 from w1ll1am23/wink_availability
Added available method to all wink components
2016-03-17 21:00:42 -07:00
Paulus Schoutsen
8a38ba5954 Update netdisco to 0.5.5 2016-03-17 20:57:58 -07:00
William Scanlon
208a7c9e60 Added available method to all wink components 2016-03-17 15:57:26 -04:00
Jan Harkes
27aba5c834 Update to new pywemo bridge API
Support RGBW and tunable white lights.
2016-03-17 12:27:06 -04:00
William Scanlon
a64726e321 Added assumed state to command_line switch 2016-03-17 10:41:26 -04:00
Jan Harkes
c2204433bd Add discovery for squeezebox (logitech media) servers. 2016-03-17 09:38:56 -04:00
Greg Dowling
fa15d86c2b Merge pull request #1562 from balloob/bump_pywemo_version
Bump pywemo version.
2016-03-17 12:17:42 +00:00
pavoni
4e7160139e Fix race condition in template components. 2016-03-17 12:10:19 +00:00
pavoni
47d5c4f437 Bump pywemo version. 2016-03-17 11:40:25 +00:00
pavoni
179c6efff7 Bump pywemo version. 2016-03-16 23:25:00 +00:00
Florian Holzapfel
6e32d99174 provide update message_bird.py to include the suggested changes 2016-03-16 10:34:06 +01:00
Greg Dowling
fd27e4fc7d Merge pull request #1550 from balloob/restructure_vera
Refactor vera into a platform.
2016-03-16 09:28:27 +00:00
pavoni
9fc73fa644 Refactor vera into a platform. 2016-03-16 09:03:56 +00:00
Paulus Schoutsen
ba0cbab6cb Merge pull request #1552 from balloob/hue-allow-unreachable
Hue Lights - Allow Unreachable Lights
2016-03-15 18:27:49 -07:00
Paulus Schoutsen
83778a0f55 Merge pull request #1558 from fabaff/login
Log failed login attempts
2016-03-15 18:26:26 -07:00
Fabian Affolter
b29eff5ef1 UPdate log messages 2016-03-15 23:52:55 +01:00
Fabian Affolter
c865ff852d Log failed login attempts 2016-03-15 23:40:24 +01:00
Fabian Affolter
1f7e0936fa Add missing comments 2016-03-15 19:22:21 +01:00
Florian Holzapfel
a855a9bfcd provide sms notifications via messagebird 2016-03-15 18:09:19 +01:00
Jon Maddox
9fe17423ea pass allow_unreachable for callback 2016-03-15 10:37:47 -04:00
Jon Maddox
b7b34b280f just pass them in 2016-03-15 10:27:56 -04:00
Jon Maddox
971fe8bc7b style 2016-03-15 10:27:46 -04:00
Jon Maddox
95d5c456d7 ignore unreachable state if opted in 2016-03-15 10:15:29 -04:00
Jon Maddox
dd33831cb1 pass allow_unreachable all the way down the line 2016-03-15 10:15:10 -04:00
Jon Maddox
5abff70a87 read in allow_unreachable config value 2016-03-15 10:13:57 -04:00
Paulus Schoutsen
d28116f2bf Update frontend 2016-03-14 23:55:52 -07:00
Paulus Schoutsen
cde05b91ce Better netgear logging 2016-03-14 21:12:42 -07:00
Paulus Schoutsen
663e4d57d9 Merge pull request #1546 from persandstrom/input_slider
input slider
2016-03-14 20:26:34 -07:00
Paulus Schoutsen
cf285e0a0a Merge pull request #1548 from bradsk88/wink063
Upgrading python-wink to 0.6.3
2016-03-14 20:16:55 -07:00
Paulus Schoutsen
dd607ea84a Merge pull request #1540 from balloob/slowtests_rfxtrx
Fixed close connection issue with rfxtrx device and update rfxtrx lib
2016-03-14 19:09:15 -07:00
Paulus Schoutsen
b4458b7f52 Merge pull request #1538 from balloob/script-allow-template-service
Remove support for old deprecated script call service config
2016-03-14 19:05:34 -07:00
bradsk88
8a6cc49438 Upgrading python-wink to 0.6.3
This corrects a bug where multi-sensors' internal states were rendered null when downloading state updates from the Wink API.
2016-03-14 19:16:54 -06:00
Per Sandström
2bdad928d0 input slider 2016-03-14 22:03:30 +01:00
Paulus Schoutsen
3e3d1ae9de Merge pull request #1542 from balloob/fix_race_condition
Handle Wemo startup race condition.
2016-03-14 07:47:50 -07:00
Paulus Schoutsen
fb3586c18f Merge pull request #1541 from balloob/catch_template_exceptions
Catch template automation exception common during startup.
2016-03-14 07:43:59 -07:00
pavoni
fe2adff017 Handle startup race condition. 2016-03-14 10:29:12 +00:00
pavoni
e5c8dd03e1 Catch exception common during startup. 2016-03-14 10:10:38 +00:00
Daniel
d6344d6492 Fixed close connection issue with rfxtrx device and update rfxtrx lib 2016-03-14 08:33:59 +01:00
Paulus Schoutsen
399fda079f Merge pull request #1539 from srcLurker/zwave-heal
Enable openzwave's network heal and soft reset.
2016-03-13 22:42:49 -07:00
Paulus Schoutsen
6bc3e0bb58 Merge pull request #1530 from balloob/content-length
Add content-length header to http resonses
2016-03-13 22:32:59 -07:00
Paulus Schoutsen
54b60c6564 Merge pull request #1531 from balloob/cleanup-automation
Remove support for old deprecated automation config
2016-03-13 22:32:48 -07:00
Paulus Schoutsen
61b387cd0b Script: fix template service calls and remove old config support 2016-03-13 22:29:36 -07:00
Charles Spirakis
b7044a79b2 Enable openzwave's network heal and soft reset.
Makes Zwave's network heal and the controller's soft reset
commands available as service calls. They can be used
in automation to help keep the zwave netwrok healthy.

For example:

automation:
 alias: At 2:35am, heal problematic zwave network routes
 trigger:
   platform: time
   after: '2:35:00'
 action:
   service: zwave.heal
2016-03-13 21:48:07 -07:00
Paulus Schoutsen
368668784a Merge pull request #1534 from balloob/allow_entry_passive_zones
Allow entry into passive zones.
2016-03-13 15:58:42 -07:00
Paulus Schoutsen
7099030cd7 Merge pull request #1529 from stefan-jonasson/tellstick-rewrite
Rewrite of the tellstick module. It now uses a common base for all sh…
2016-03-13 15:56:54 -07:00
Stefan Jonasson
eb9ed5ccfe Rewrite of the tellstick module. It now uses a common base for all shared functionality.
The rewrite addresses a problem with the tellstick hardware dropping
commands when too many simultaneous calls is being made from HA. Also fixes a bug when the dim level was changed externally.
This breaks previous configurations.

The new config for tellstick is

```yaml
tellstick:
  signal_repetitions: X
```
Lights and Switches are detected automatically.
Sensors work like before because they do not share any functionality with the other devices and they also needs a complete other configuration.
2016-03-13 19:28:42 +01:00
pavoni
fc455a1047 Allow entry into passive zones. 2016-03-13 18:01:29 +00:00
Paulus Schoutsen
956f6056f9 Remove support for old deprecated automation config 2016-03-13 00:00:05 -08:00
Paulus Schoutsen
f8d2da2ace Add content-length header to http resonses 2016-03-12 23:41:00 -08:00
Paulus Schoutsen
7d23a5f7e4 Merge pull request #1496 from balloob/mqtt-server
Add MQTT server component
2016-03-12 21:53:06 -08:00
Paulus Schoutsen
8386bda4e4 MQTT: Start embedded server if no config given 2016-03-12 21:42:47 -08:00
Paulus Schoutsen
13d7f742a7 Add thread names 2016-03-12 16:54:31 -08:00
Paulus Schoutsen
b67964274b Version bump to 0.16.0.dev0 2016-03-12 11:29:42 -08:00
Paulus Schoutsen
6797365d4f Merge pull request #1502 from balloob/dev
0.15
2016-03-12 11:29:30 -08:00
Paulus Schoutsen
2410942fd0 Version bump to 0.15 2016-03-12 11:23:43 -08:00
Paulus Schoutsen
2a75c6fcf6 Update frontend build scripts for pep257 2016-03-12 10:52:48 -08:00
Paulus Schoutsen
159e287959 Update frontend 2016-03-12 10:42:07 -08:00
Paulus Schoutsen
a01111ae56 Merge pull request #1457 from fabaff/sensor-classes
Add support for sensor classes
2016-03-11 22:50:32 -08:00
Paulus Schoutsen
4599fd6dae Update .coveragerc 2016-03-11 22:47:39 -08:00
Paulus Schoutsen
ddc139b853 Merge pull request #1510 from persandstrom/automation_templating
Use templates in service calls
2016-03-11 21:49:47 -08:00
Paulus Schoutsen
2b6f0586b4 Merge pull request #1524 from turbokongen/dev
Workaround for no off motion sensor: Wenzhou tkd slim sensor 3/4 in 1…
2016-03-11 21:45:40 -08:00
Paulus Schoutsen
9904667a80 Merge pull request #1520 from balloob/mqtt-fixes
Type checks for MQTT config
2016-03-11 21:45:17 -08:00
Paulus Schoutsen
097ded73b1 Merge pull request #1519 from sander76/dev
changed powerview version requirement to solve error in installing
2016-03-11 21:44:11 -08:00
Paulus Schoutsen
5b2093ebc1 Merge pull request #1523 from Bart274/patch-1
add gps_accuracy and battery information to the see function
2016-03-11 16:21:26 -08:00
Fabian Affolter
1fa2f23864 Revert "Upgrade limitlessled to 1.1.0"
This reverts commit 2e2537de2a.
2016-03-11 23:37:32 +01:00
Fabian Affolter
2e2537de2a Upgrade limitlessled to 1.1.0 2016-03-11 23:27:18 +01:00
root
1f8b66511d Workaround for no off motion sensor: Wenzhou tkd slim sensor 3/4 in 1 sensor 2016-03-11 20:51:40 +01:00
Bart274
312d0320c6 Update __init__.py 2016-03-11 14:20:08 +01:00
Bart274
284a1fd08e add gps_accuracy and battery information to the see function
the see function from device_tracker doesn't pass the gps_accuracy and the battery information to the see service, so this information gets lost.
2016-03-11 14:10:04 +01:00
sander
1fbf7afc6a changed the powerview version 2016-03-11 06:44:04 +01:00
Paulus Schoutsen
025713ee41 Type checks for MQTT config 2016-03-10 21:42:17 -08:00
Per Sandström
81e5a852f0 Use templates in service calls 2016-03-10 21:36:05 +01:00
Fabian Affolter
4637a83c29 Add sensor_class to MQTT binary sensor 2016-03-10 20:51:58 +01:00
Fabian Affolter
ce82bd7515 Fix formatting 2016-03-10 19:17:36 +01:00
Greg Dowling
534308e461 Merge pull request #1473 from balloob/add_wemo_motion
Add Wemo Motion device as a binary sensor.
2016-03-10 18:13:04 +00:00
pavoni
84bdba28b3 Add Wemo Motion 2016-03-10 17:58:24 +00:00
Fabian Affolter
8af7858415 Merge pull request #1513 from balloob/pep257
Enable Pep257 checking on CI
2016-03-10 09:29:04 +01:00
Paulus Schoutsen
56ef16e858 Add pydocstyle to requirements_test.txt 2016-03-09 23:39:38 -08:00
Paulus Schoutsen
b9856a2af5 Fix final pep257 issues 2016-03-09 23:34:38 -08:00
Paulus Schoutsen
14a9b9fe3f Add pep257 checking 2016-03-09 23:34:28 -08:00
Paulus Schoutsen
47c4f66886 Merge pull request #1485 from MartinHjelmare/refactor-scene-reproduce_state
Refactor reproduce_state for scene component
2016-03-09 15:29:10 -08:00
Fabian Affolter
0d9b8a0d06 Fix docstring 2016-03-09 23:49:54 +01:00
MartinHjelmare
c56701baaf Refactor reproduce_state for scene component
* Add tests to reach full coverage for helpers/state.py.
* Refactor reproduce_state function in helpers/state.py. Add two dicts,
	as global constants, service_attributes and service_to_state. Use
	these in combination with the dict of services per domain from
	ServiceRegistry, to find the correct service to use in a scene state
	change.
* Use break statement in for loop, to break if service was selected
	to update state, in preference to update state attributes, ie state
	update takes precedence.
* Add ATTR_CODE and ATTR_CODE_FORMAT in const. Import these in
	alarm_control_panel and lock platforms instead of making duplicate
	constants in multiple modules.
* Use ATTR_MEDIA_CONTENT_TYPE and ATTR_MEDIA_CONTENT_ID in media_player
	platform in SERVICE_PLAY_MEDIA and play_media methods, instead of
	'media_type' and 'media_id'.
* Fix PEP257 in modified files.
2016-03-09 18:52:05 +01:00
Fabian Affolter
f22a40c3e8 Fix PEP257 issues 2016-03-09 11:15:04 +01:00
Fabian Affolter
986c9c55bf Merge branch 'pep257-tests' into dev 2016-03-09 10:26:49 +01:00
Fabian Affolter
9838697d2b Fix PEP257 issues 2016-03-09 10:25:50 +01:00
Per Sandström
d1256d4889 Merge pull request #1508 from persandstrom/verisure_typo_thermometers
verisure configuration value typo fix
2016-03-08 21:42:43 +01:00
Fabian Affolter
d6eab03a61 Remove parenthesis 2016-03-08 18:05:01 +01:00
Fabian Affolter
b534244e40 Fix PEEP257 issues 2016-03-08 17:55:57 +01:00
Fabian Affolter
d784610c52 Merge branch 'pep257-sensor' into dev 2016-03-08 16:47:18 +01:00
Fabian Affolter
8bff97083c Fix PEPE257 issues 2016-03-08 16:46:34 +01:00
Paulus Schoutsen
3e4412d375 Merge pull request #1507 from sander76/dev
change module name to correct brand name "douglas" to "hunterdouglas"
2016-03-08 07:20:43 -08:00
Per Sandström
567727fb3b verisure configuration value typo fix 2016-03-08 14:10:47 +01:00
Fabian Affolter
49ebc6d0b0 Fix PEP257 issues 2016-03-08 13:35:39 +01:00
sander
fd5e2d1321 change module name to correct brand name "douglas" to "hunterdouglas" 2016-03-08 11:59:46 +01:00
Fabian Affolter
652f059d6a Fix PEP257 issues 2016-03-08 11:46:32 +01:00
Fabian Affolter
cf7c2c492a Fix PEP257 issues 2016-03-08 10:34:33 +01:00
Fabian Affolter
7f1e181c9b Merge branch 'pep257-utils' into dev 2016-03-08 08:34:50 +01:00
Fabian Affolter
08233da8a7 Merge branch 'pep257-thermostats' into dev 2016-03-08 08:11:38 +01:00
Fabian Affolter
5423252a52 Merge branch 'pep257-scene-mqtt' into dev 2016-03-08 08:11:30 +01:00
Fabian Affolter
036cfe4ef6 Merge branch 'pep257-lock' into dev 2016-03-08 08:11:21 +01:00
Fabian Affolter
db6212dae3 Merge branch 'pep257-light' into dev 2016-03-08 08:11:12 +01:00
Fabian Affolter
391c6a358a Merge branch 'pep257-garage' into dev 2016-03-08 08:10:25 +01:00
Fabian Affolter
29a651dd92 Merge branch 'pep257-device-tracker' into dev 2016-03-08 08:08:35 +01:00
Paulus Schoutsen
20dd782d9e Rename powerview to douglas_powerview 2016-03-07 22:43:38 -08:00
Paulus Schoutsen
9d76c58bd4 Merge pull request #1490 from sander76/powerview
Powerview
2016-03-07 22:42:20 -08:00
Paulus Schoutsen
c21918233b Merge pull request #1506 from fabaff/pep257-camera
PEP257 - Camera
2016-03-07 17:10:21 -08:00
Paulus Schoutsen
87008f23a1 Merge pull request #1505 from fabaff/pep257-binary-sensor
PEP257 - Binary sensor
2016-03-07 17:09:59 -08:00
Paulus Schoutsen
ba0a25aef6 Merge pull request #1503 from fabaff/pep257-automation
PEP257 - Automation
2016-03-07 17:09:11 -08:00
Paulus Schoutsen
ee728345f6 Merge pull request #1501 from fabaff/pep257-alarm
PEP257 - Alarm control panel
2016-03-07 17:08:39 -08:00
Paulus Schoutsen
2db873322d Update frontend 2016-03-07 15:17:51 -08:00
Paulus Schoutsen
8ecced5fe6 Merge branch 'master' into dev
Conflicts:
	homeassistant/components/wemo.py
	homeassistant/const.py
2016-03-07 15:15:57 -08:00
Fabian Affolter
897b5c668f Fix PEP257 issues 2016-03-08 00:06:04 +01:00
Fabian Affolter
4f536ac63d Fix PEP257 issues 2016-03-07 23:39:52 +01:00
Fabian Affolter
876978d64a Fix PEP257 issues 2016-03-07 23:20:48 +01:00
Fabian Affolter
91731c7234 Fix PEP257 issues 2016-03-07 23:01:34 +01:00
Fabian Affolter
1b8b2acb51 Fix PEP257 issues 2016-03-07 22:50:56 +01:00
Fabian Affolter
095dd70391 Fix PEP257 issues 2016-03-07 22:44:35 +01:00
Fabian Affolter
6879e39d6c Fix PEP257 issues 2016-03-07 22:13:18 +01:00
Fabian Affolter
7e8e91ef3c Fix PEP257 issues 2016-03-07 22:08:21 +01:00
Fabian Affolter
ac43d23bd7 Fix PEP257 issues 2016-03-07 21:22:21 +01:00
Fabian Affolter
cc7a4d545e Fix PEP257 issues 2016-03-07 21:18:53 +01:00
sander
40be9f4e0c Powerview hub implementation 2016-03-07 21:07:38 +01:00
Fabian Affolter
cd5b5c55e2 Fix PEP257 issues 2016-03-07 20:29:54 +01:00
Fabian Affolter
3a4250133a Fix PEP257 issues 2016-03-07 20:21:43 +01:00
Fabian Affolter
7035af6634 Fix PEP257 issues 2016-03-07 20:21:08 +01:00
Fabian Affolter
fb7bd1bfe1 Fix PEP257 issues 2016-03-07 20:20:07 +01:00
Fabian Affolter
f6bc1a4575 Revert change (FIXME) 2016-03-07 20:18:48 +01:00
Fabian Affolter
5ba9ac6465 Fix PEP257 issues 2016-03-07 20:18:48 +01:00
Paulus Schoutsen
cfd65e48cb Merge pull request #1495 from balloob/mqtt-light
MQTT Light: fix brightness issues
2016-03-07 10:20:36 -08:00
Fabian Affolter
b8a40457ee Update docstrings to match PEP257 2016-03-07 18:50:30 +01:00
Fabian Affolter
7ff9aecd4e Update docstrings to match PEP257 2016-03-07 18:50:30 +01:00
Fabian Affolter
032f06e015 Modify docstrings to match PEP257 2016-03-07 18:50:30 +01:00
Fabian Affolter
6ac9210919 Modify docstrings to match PEP257 2016-03-07 18:50:30 +01:00
Paulus Schoutsen
b47f1c3a96 MQTT Light: fix brightness issues 2016-03-07 08:54:08 -08:00
Paulus Schoutsen
5222c19b4c Fix TP-Link get auth token 2016-03-07 08:29:05 -08:00
Fabian Affolter
1e97d31711 Modify docstrings to match PEP257 2016-03-07 16:45:21 +01:00
Paulus Schoutsen
18f48191d9 Merge pull request #1482 from balloob/history-significant-states
History: update significant states
2016-03-06 21:45:48 -08:00
Paulus Schoutsen
abc7243bc8 Merge pull request #1484 from balloob/device-tracker-remove-old-conf-format
Device tracker remove old conf format
2016-03-06 21:41:59 -08:00
Paulus Schoutsen
4c64be5cfa Merge pull request #1488 from balloob/template_component_fix
Fix noisy error on template component startup.
2016-03-06 13:47:42 -08:00
Paulus Schoutsen
199375bd25 Merge pull request #1489 from balloob/zone_fix
Force zone params to be float
2016-03-06 13:47:11 -08:00
Paulus Schoutsen
69bbfe5372 Merge pull request #1491 from persandstrom/verisure_disable_password_lock
After maintenance false password errors are expected
2016-03-06 13:43:07 -08:00
Per Sandström
d2c94da938 After maintenance false password errors are expected 2016-03-06 22:09:15 +01:00
pavoni
4e3c8a8697 Fix noisy error on startup. Make callbacks code consistent. 2016-03-06 19:19:07 +00:00
pavoni
d75d08e97c Force float for zone parameters. 2016-03-06 19:07:30 +00:00
Paulus Schoutsen
cd30f2de0d Device Sun Light Trigger: Clean up 2016-03-05 20:15:33 -08:00
Paulus Schoutsen
bdad69307a Group: fix thread safety 2016-03-05 19:55:05 -08:00
Paulus Schoutsen
b16c17fae5 Merge pull request #1480 from balloob/fix-slow-tests
Fix slow tests
2016-03-05 19:05:47 -08:00
Paulus Schoutsen
91ee889527 Merge pull request #1434 from nunofgs/enhancement/add-archer-c7-support
Add ArcherC7 150427 support
2016-03-05 18:48:59 -08:00
Nuno Sousa
7b45001879 Add ArcherC7 150427 support 2016-03-05 23:15:48 +00:00
Paulus Schoutsen
fb46eff5f8 Device tracker: remove support for old config 2016-03-05 11:43:23 -08:00
Paulus Schoutsen
9701be9e9c History: ignore scripts that we cannot cancel 2016-03-05 10:28:48 -08:00
Paulus Schoutsen
605a572c86 History: Ignore insignificant domains 2016-03-05 09:49:04 -08:00
Paulus Schoutsen
1159360281 Skip rfxtrx tests because of speed reasons 2016-03-05 09:28:47 -08:00
Paulus Schoutsen
41214fd082 TCP test to work offline 2016-03-05 09:27:22 -08:00
Paulus Schoutsen
d30fb7f04a Merge pull request #1476 from stefan-jonasson/assumed-state
Add assumed state for Tellstick devices.
2016-03-05 01:41:55 -08:00
Stefan Jonasson
e57eca517b Add assumed state for Tellstick devices.
Tellstick device states are always assumed so this should be set to true.
2016-03-05 10:24:22 +01:00
Paulus Schoutsen
931dc27300 Merge pull request #1465 from bestlibre/influxdb_blacklist
Possibility to blacklist events for influxdb
2016-03-05 00:57:26 -08:00
bestlibre
d7094b996a Use global variable and merge two if in one 2016-03-04 23:32:24 +01:00
Greg Dowling
9654f6b4e4 Merge pull request #1474 from HydrelioxGitHub/Fix-Owntracks-GPS-Accuracy
Add GPS accuracy check for a location update or an event update
2016-03-04 20:07:37 +00:00
Hydreliox
c04555d7b1 Add GPS accuracy check for a location update or an event update
Add tests related to this
Great thanks to @pavoni for his support on this fix
2016-03-04 20:19:50 +01:00
Paulus Schoutsen
e755731588 Merge pull request #1471 from balloob/cast-update
Update pychromecast 0.7.2
2016-03-03 22:30:43 -08:00
Paulus Schoutsen
a687a3decb Update pychromecast 0.7.2 2016-03-03 21:59:27 -08:00
Paulus Schoutsen
88c834fdd3 Merge pull request #1466 from balloob/tests_rfxtrx_device
Tests rfxtrx device
2016-03-03 09:11:50 -08:00
Daniel Hoyer Iversen
feb1a15489 update rfxtrx lib to ver 0.5 2016-03-03 17:47:50 +01:00
bestlibre
4d5e9f2931 Possibility to blacklist events
Possibility to blacklist some events based on the entity_id
2016-03-03 17:02:41 +01:00
Paulus Schoutsen
1e3199eb8c Merge pull request #1458 from jaharkes/track-wemos-by-serial
Track wemos by serial
2016-03-02 23:10:13 -08:00
Paulus Schoutsen
17493660df Merge pull request #1463 from kk7ds/snmp-track-macless-things
Fix SNMP device_tracker results without MAC addresses
2016-03-02 14:58:31 -08:00
Dan Smith
e59d6b7da0 Fix SNMP device_tracker results without MAC addresses
@llauren reported that his router returns empty MAC addresses for things
on different subnets, which causes heartache for the HA snmp device tracker.
2016-03-02 11:43:08 -08:00
Daniel
2fd0b28c53 Added tests for RFxtrx device, updated rfxtrx to ver 0.5, fixed bug in setting brightness for rfxtrx light 2016-03-02 20:36:41 +01:00
Jan Harkes
bbd3a43585 Update netdisco to 0.5.4 2016-03-01 23:25:18 -05:00
Dan Smith
a02840379d Track WeMo devices by serial number
This makes us track WeMo devices by serial number instead of URL. Per
@jaharkes' suggestion, tracking via URL could potentially be a problem
if a device changes to another IP and then appears to be discovered again.
Since we can't track based on mac (for static-configured devices), we
can use the serial number exposed to make sure we're always looking at
a list of unique devices.
2016-03-01 10:49:38 -08:00
Paulus Schoutsen
d641cd5eef Merge pull request #1452 from balloob/rfxtrx_tests
Added tests for rfxtrx sensor
2016-03-01 08:07:21 -08:00
Daniel
6c518c74ec Added tests for rfxtrx sensor 2016-03-01 10:14:02 +01:00
Paulus Schoutsen
fcbeafc6db Update Dockerfile: link Z-Wave config 2016-02-29 23:15:14 -08:00
Paulus Schoutsen
4370f5170b Merge pull request #1374 from sander76/scene_with_platforms
scene with platforms
2016-02-29 23:00:03 -08:00
Paulus Schoutsen
49c6484f72 Merge pull request #1433 from fabaff/mqtt-lock
Add MQTT lock support
2016-02-29 22:58:55 -08:00
Paulus Schoutsen
ec642cbeff Merge pull request #1450 from kk7ds/mfi-tls-verify
Give mFi options to control TLS usage
2016-02-29 19:18:06 -08:00
Martin Hjelmare
2823d8f0d8 Merge pull request #1451 from MartinHjelmare/mysensors-assumed-state
Add assumed_state to mysensors switch and light
2016-03-01 03:37:40 +01:00
MartinHjelmare
bfa579f8b2 Add assumed_state to mysensors switch and light
* Return true for assumed_state if optimistic config setting is true.
* Fix PEP257
2016-03-01 03:09:55 +01:00
Dan Smith
be04ebf9ed Give mFi options to control TLS usage
The default configuration of the mFi controller generates self-signed
certificates which are valid for short periods of time, and which are
regnerated on start or as needed. This makes requests mad. Since most
people will be using the self-signed certificates anyway, add options
to let them choose non-TLS, or unverified connections if they want/need.

This bumps the mficlient requirement to 0.3.0 for proper handling of
verify=False.
2016-02-29 17:37:41 -08:00
Paulus Schoutsen
395a8663b5 Merge pull request #1446 from balloob/hotfix/0.14.2
Hotfix/0.14.2
2016-02-29 08:22:26 -08:00
Paulus Schoutsen
f9eb62dd9e Version bump to 0.14.2 2016-02-29 08:10:52 -08:00
Stefan Jonasson
c6a6eaee9f Fixed the z-wave sensor workarounds for empty manufacturer ids 2016-02-29 08:10:26 -08:00
Paulus Schoutsen
87e23e7d73 Merge pull request #1440 from stefan-jonasson/fix-manufacturer-id
Fixed the z-wave sensor workarounds for empty manufacturer ids
2016-02-29 08:01:41 -08:00
Stefan Jonasson
c586111c8c Fixed the z-wave sensor workarounds for empty manufacturer ids 2016-02-29 11:05:11 +01:00
Paulus Schoutsen
e92c77a113 Update frontend 2016-02-28 21:39:42 -08:00
Paulus Schoutsen
2d2b26ff1a Update Dockerfile 2016-02-28 21:08:11 -08:00
Paulus Schoutsen
eed5b1e41b Merge pull request #1437 from balloob/update-docker-zwave
Docker + Z-Wave <3
2016-02-28 20:47:49 -08:00
Paulus Schoutsen
029094e549 Docker + Z-Wave <3 2016-02-28 20:46:16 -08:00
Paulus Schoutsen
28d80e6e2d Merge pull request #1436 from partofthething/zwave-unfork
updated build script for unforking of python-openzwave
2016-02-28 20:24:56 -08:00
Paulus Schoutsen
5449d53e07 Update netdisco to 0.5.3 2016-02-28 15:32:11 -08:00
ntouran
112b85877f updated build script for unforking of python-openzwave 2016-02-28 12:40:17 -08:00
sander
0f6ec9b7ac Added your suggestions.
Looking at your code suggestion below I am not sure exactly how other people might want to put in lists. (But I am missing a more general overview of the code)

 ```
if not isinstance(scene_config,list):
  scene_config=[scene_config]
```

But it is there !
And changed "config" to "states" !
2016-02-28 21:00:51 +01:00
Paulus Schoutsen
e246c83b0e Version bump to 0.14.1 2016-02-28 09:27:52 -08:00
Paulus Schoutsen
3f4e34727d Merge pull request #1428 from balloob/hotfix/0.14.1
Hotfix/0.14.1
2016-02-28 09:26:36 -08:00
Fabian Affolter
a82931022c Add MQTT lock support 2016-02-28 18:25:28 +01:00
Paulus Schoutsen
1974e2cfbe Merge pull request #1430 from ggruner/dev
Add support for NetAtmo rain gauge
2016-02-28 09:19:41 -08:00
Dan Smith
34b463f435 Gracefully handle having no wemo config section
I broke this with my fix, where I assumed that we'd always have a wemo
config section if we're running the wemo code. However, if we're fully
auto-detected, we might not.
2016-02-28 09:18:23 -08:00
Paulus Schoutsen
e0ba33300a Merge pull request #1431 from kk7ds/fix-wemo-fix
Gracefully handle having no wemo config section
2016-02-28 08:20:04 -08:00
Dan Smith
566c143ee3 Gracefully handle having no wemo config section
I broke this with my fix, where I assumed that we'd always have a wemo
config section if we're running the wemo code. However, if we're fully
auto-detected, we might not.
2016-02-28 07:58:44 -08:00
Fabian Affolter
014b11c61d Upgrade to psutil 4.0.0 2016-02-28 16:34:06 +01:00
Fabian Affolter
b70a455a13 Upgrade py-cpuinfo to 0.2.3 2016-02-28 16:16:03 +01:00
Fabian Affolter
9da8679dbd Add link to docs 2016-02-28 15:35:20 +01:00
Gregor Gruener
c14ca9983c Add support for NetAtmo rain gauge
Example Config:
...
modules:
    Bedroom:
      - temperature
    LivingRoom:
      - temperature
    Outside:
      - temperature
    Garden:
      - rain
      - sum_rain_1
      - sum_rain_24

The three new parameters stand for:
- rain # Estimated rainfall for today in "mm"
- sum_rain_1 # Rainfall in the last hour in "mm"
- sum_rain_24 # Rainfall in "mm" from 00:00am - 23:59pm
2016-02-28 12:24:45 +01:00
Fabian Affolter
9c4fe6e7fe Modify docstrings to match PEP257 2016-02-28 12:03:47 +01:00
sander
a8edcfd315 removed logger.
I guess I should add some error checking, but I'd like you to okay this code first.
2016-02-28 10:29:21 +01:00
sander
0193454064 removed logger.
I guess I should add some error checking, but I'd like you to okay this code first.
2016-02-28 10:28:34 +01:00
sander
94633b3795 1. added platform per scene entry.
2. changed homeassistant scene setup_platform method to work with 1.
2016-02-28 10:24:02 +01:00
Paulus Schoutsen
49982ac83c Update PULL_REQUEST_TEMPLATE.md 2016-02-28 00:59:28 -08:00
Paulus Schoutsen
72940da874 Update frontend 2016-02-28 00:42:10 -08:00
Paulus Schoutsen
5acf995d71 Merge pull request #1429 from balloob/fix-script-can_cancel
Fix incorrectly setting can_cancel on scripts
2016-02-28 00:38:54 -08:00
Paulus Schoutsen
f623a332cf Fix incorrectly setting can_cancel on scripts 2016-02-27 23:11:51 -08:00
Dan Smith
3790764df9 Fix wemo known device tracking
The wemo component was tracking devices by mac to avoid adding duplicates,
but this means we'd never be able to load more than one static wemo, since
they all have mac=None.

This changes the code to track by url, which has to be unique per wemo
anyway, and which we also have for even static wemos.
2016-02-27 21:03:45 -08:00
Dan Smith
da2bcb3f27 Fix static configured wemo devices
The new wemo code was pulling 'static' from the global config instead of
the wemo component config.
2016-02-27 21:03:40 -08:00
Paulus Schoutsen
f5dd41e019 Merge pull request #1425 from kk7ds/fix-static-wemos
Fix static configured wemo devices
2016-02-27 21:02:57 -08:00
Paulus Schoutsen
97edc39d0a Merge pull request #1426 from shaftoe/python_constant
Move hardcoded required Python version into homeassistant.const
2016-02-27 21:00:28 -08:00
Dan Smith
2b4be33a3d Fix wemo known device tracking
The wemo component was tracking devices by mac to avoid adding duplicates,
but this means we'd never be able to load more than one static wemo, since
they all have mac=None.

This changes the code to track by url, which has to be unique per wemo
anyway, and which we also have for even static wemos.
2016-02-27 20:56:02 -08:00
Alexander Fortin
ac69db8133 Move hardcoded required Python version into homeassistant.const 2016-02-28 05:41:03 +01:00
Dan Smith
5a126736e4 Fix static configured wemo devices
The new wemo code was pulling 'static' from the global config instead of
the wemo component config.
2016-02-27 20:11:32 -08:00
Martin Hjelmare
8e9c557a2c Merge pull request #1423 from MartinHjelmare/fix-mysensors-sensor-types
Fix mysensors sensor types
2016-02-28 02:16:32 +01:00
MartinHjelmare
d12dfc33a5 Fix mysensors sensor types
* Remove sprinkler and water leak from sensor types. These two are
  supported by binary sensor.
2016-02-28 01:58:22 +01:00
Paulus Schoutsen
1be90081ef Version bump to 0.15.0.dev0 2016-02-27 16:22:21 -08:00
Paulus Schoutsen
50bf147d73 Merge pull request #1365 from balloob/dev
0.14
2016-02-27 16:21:54 -08:00
Paulus Schoutsen
3bdf7eabbf Version bump to 0.14.0 2016-02-27 16:13:40 -08:00
Paulus Schoutsen
4e750a4d72 Merge pull request #1417 from fabaff/freegeoip
Catch 503 responses by freegeoip.net (Fixes #1378)
2016-02-27 16:12:47 -08:00
Paulus Schoutsen
a1cd120ed4 Merge pull request #1422 from balloob/rename-command-line-platforms
Make names command line platform consistent
2016-02-27 16:03:00 -08:00
Paulus Schoutsen
be55ee059e Make names command line platform consistent 2016-02-27 15:56:35 -08:00
Fabian Affolter
eb8228237e Catch connection issue with freegeoip.net (Fixes #1378) 2016-02-27 23:58:36 +01:00
Paulus Schoutsen
afb51d14b8 Merge pull request #1302 from persandstrom/vsure_maintenace
updated verisure reconnect
2016-02-27 14:50:24 -08:00
Paulus Schoutsen
bca4dee30e Merge pull request #1393 from persandstrom/throttle_fix
Throttle should work on a single method
2016-02-27 14:49:56 -08:00
Paulus Schoutsen
9e4ddc405d Update frontend 2016-02-27 14:34:52 -08:00
Paulus Schoutsen
73ec049d1c Do not expect Hue light to have a brightness 2016-02-27 14:27:16 -08:00
Paulus Schoutsen
efeb5c5290 Merge pull request #1419 from justincmoy/sendgrid_initial
Add SendGrid notify component
2016-02-27 14:24:07 -08:00
Paulus Schoutsen
498a3f78d4 Merge pull request #1413 from fabaff/issue
Templates for PRs and issue
2016-02-27 14:19:49 -08:00
Per Sandström
562db5ea4c Throttle for two methonds in same class 2016-02-27 23:18:56 +01:00
Fabian Affolter
cd21142d5b Update with comments from PR 2016-02-27 23:17:20 +01:00
Justin Moy
9b371a8c66 Add SendGrid notify component 2016-02-27 15:00:52 -07:00
Per Sandström
d7e3c6a442 verisure refactoring and fix reconnect 2016-02-27 21:50:19 +01:00
Paulus Schoutsen
f4b5b3f88f Merge pull request #1411 from shaftoe/sonos_decorator
ADD only_if_coordinator decorator to sonos
2016-02-27 09:05:54 -08:00
Paulus Schoutsen
a0c58487ca Merge pull request #1415 from kfgoode/patch-1
Update demo.py
2016-02-27 08:50:13 -08:00
Fabian Affolter
f8f0ed860c Sync with template content 2016-02-27 12:53:06 +01:00
Fabian Affolter
f99a536b98 Add initial templates 2016-02-27 10:03:55 +01:00
Karen Goode
02faefdab3 Update demo.py 2016-02-26 18:43:50 -08:00
Karen Goode
2a01b09d31 Update demo.py 2016-02-26 18:25:39 -08:00
Karen Goode
712ba65d26 Update demo.py 2016-02-26 18:12:03 -08:00
Alexander Fortin
124a9b7a81 ADD only_if_coordinator decorator to sonos
Currently we interact with players regardless of thir coordinator
role, hence soco.exceptions.SoCoSlaveException are thrown. The use
of the decorator for each interactive method should address this
2016-02-27 00:40:34 +01:00
Karen Goode
cbd69583bd Update demo.py
Update to demo site to include input_selects, notify, inline camera and two views.
2016-02-26 15:23:44 -08:00
Paulus Schoutsen
2ec141b5d4 Merge pull request #1403 from stjohnjohnson/MQTTLightScale
Add scale support for MQTT Lights.
2016-02-26 15:19:08 -08:00
Fabian Affolter
2609852d6e Modify docstrings to match PEP257 2016-02-26 23:52:54 +01:00
St. John Johnson
e525b6e0a5 Add brightness scale support for MQTT Lights.
Converts 0..255 values that HA expects into a device 0..SCALE value
Example:
  HA considers "hall light" at 25 brightness or 10% of 255
  Device considers "hall light" at 100 brightness or 10% of 1000

This allows our existing MQTT devices to not change their data format to be used in HA
2016-02-26 10:38:07 -08:00
Daniel Høyer Iversen
278fdc0983 Merge pull request #1385 from balloob/rfxtrx
improve rfxtrx sensor
2016-02-26 10:49:10 +01:00
Greg Dowling
6dc49df2df Merge pull request #1405 from balloob/wemo_insight_updates
Fix typo in Wemo state_detail attribute.
2016-02-26 08:46:54 +00:00
pavoni
b2d32114c8 Fix typo. 2016-02-26 08:28:17 +00:00
Paulus Schoutsen
6512b7d701 Merge pull request #1380 from w1ll1am23/wink_binary_sensor
Moved Wink binary sensors to a binary sensor class
2016-02-25 18:19:38 -08:00
Paulus Schoutsen
782713ee4f Merge pull request #1398 from GreenTurtwig/steam
Update Steam sensor to show currently played game
2016-02-25 18:14:54 -08:00
Paulus Schoutsen
dd45b5e0b1 Merge pull request #1402 from kk7ds/fix-mfi-connect-exception
Fix mFi error handling in setup_platform
2016-02-25 17:06:03 -08:00
Greg Dowling
f92802fd5c Merge pull request #1401 from balloob/wemo_insight_updates
Wemo updates
2016-02-26 00:23:17 +00:00
pavoni
ddbceebd65 Cast standby_state to int before testing. 2016-02-26 00:16:33 +00:00
Dan Smith
37e5b98919 Fix mFi error handling in setup_platform
The exception we were catching incorrectly referenced the client variable
in local scope instead of the module. Also, if we fail to connect we can
get a requests exception, so catch and handle that as well.
2016-02-25 15:52:13 -08:00
pavoni
86973226b1 Remove ghost comment. 2016-02-25 23:13:20 +00:00
pavoni
bbf8897a51 Add LightSwitch to discovery, default unnown devices to switches for compatability. 2016-02-25 23:02:36 +00:00
pavoni
72144945b4 Move standby from state to attribute, add optimistic switch status. 2016-02-25 22:46:14 +00:00
William Scanlon
5a64ef2c98 Moved Wink binary sensors to a binary sensor class 2016-02-25 14:03:02 -05:00
Rowan Hine
393df2da49 Update steam_online.py 2016-02-25 17:46:51 +00:00
Rowan Hine
a54986159c Update Steam sensor to show currently played game 2016-02-25 17:05:00 +00:00
Daniel
8ffa3684e3 rfxtrx refactor 2016-02-25 17:40:24 +01:00
Paulus Schoutsen
dc02370b43 Merge pull request #1355 from deisi/deutsche_bahn
New deutsche_bahn component
2016-02-25 08:31:47 -08:00
Daniel
23db6e753f refactor rfxtrx code 2016-02-25 13:08:16 +01:00
Paulus Schoutsen
35aa9aa863 Merge pull request #1383 from kk7ds/virtual-binary-sensor
Template binary sensor
2016-02-24 22:15:01 -08:00
Paulus Schoutsen
57ac6cd76f Merge branch 'extract-entity-picture' into dev
Conflicts:
	homeassistant/components/sensor/steam_online.py
2016-02-24 22:00:58 -08:00
Dan Smith
a7519bb38b Add a template binary_sensor platform 2016-02-24 20:09:13 -08:00
Dan Smith
db4bf7319f Add float() operator to templates 2016-02-24 20:07:46 -08:00
Paulus Schoutsen
621a6e0ea0 Merge pull request #1395 from MartinHjelmare/fix-mysensors-switch-light
Fix mysensors switch & light types
2016-02-24 19:56:36 -08:00
Paulus Schoutsen
caa1b73035 Merge pull request #1394 from MartinHjelmare/use-get_component-mysensors
Use get_component instead of importing component for mysensors
2016-02-24 19:55:03 -08:00
MartinHjelmare
9c538d11c2 Fix mysensors switch & light types
* Move S_LIGHT and V_LIGHT from light back to switch platform, to avoid
  double devices showing.
* Remove MySensorsLightPlain class from light platform, since it's not
  needed anymore.
* A light switch with only a switch, ie no dimmer or
  RGB controls, will show as a regular switch device.
2016-02-25 00:48:29 +01:00
MartinHjelmare
2790ee0b02 Use get_component instead of importing component 2016-02-25 00:24:31 +01:00
Paulus Schoutsen
eb681e721c Merge pull request #1387 from stefan-jonasson/z_wave_workaround_fix
Fixed the workaround for philio slim multi sensor.
2016-02-24 14:45:27 -08:00
Stefan Jonasson
db06d5a03d Fixed the z-wave trigger sensor workaround 2016-02-24 22:44:49 +01:00
Dan Smith
eb5f208a09 Add a few more sensor classes
This adds hot, cold, and moving sensor_class values for things that we
may want to support.
2016-02-24 10:38:21 -08:00
Malte Deiseroth
b096004449 New deutsche_bahn component
Uses the (schiene)[https://pypi.python.org/pypi/schiene/0.14] API to communicate with the webserver of bahn.de
and pulls iformation about a specific connection from the (bahn.de)[http://www.bahn.de/p/view/index.shtml]
webpage. The departure time of the next train for the given connection is shown.
In case of delay, the delay is also shown. Additional `ATTRIBUTES` are used to
inform about e.g. the type of the train, price and if it is ontime.

Usage:

    sensor:
      platform: deutsche_bahn
        from: name_of_start_station
	  to: name_of_final_station

Problems:
I'm testing it for quite some time, but I have never seen the `ATTRIBUTES` in case
of a delayed train. The `ATTRIBUTES` are directly passed from the `schiene` API. So this
usecase has not been tested yet.

deutsche_bahn ist not supporting the `schiene` api unlike in the swiss_public_transport case.
It's not guaranteed that `schiene` will work forever, infact it can happen that Bahn AG will
intentionally brake the API at some point. In the past Bahn AG has not allways been very supportive
to the opensource community.
2016-02-24 17:35:00 +01:00
Paulus Schoutsen
c2729211ad Merge pull request #1390 from flyte/tcp-component-tests
Bring TCP component test coverage to 100%
2016-02-24 07:33:34 -08:00
Flyte
8840461af3 Bring TCP component test coverage to 100% 2016-02-24 13:28:39 +00:00
Fabian Affolter
5406028ace Modify docstrings to match PEP257 2016-02-24 10:47:35 +01:00
Fabian Affolter
4563c54a3e Add link to docs and modify docstrings to match PEP257 2016-02-24 10:38:06 +01:00
Stefan Jonasson
04b48e0683 Moved the workaround for philio slim multi sensor.
Changed the key matching to utilize integer values. It does not report always return the hex marker '0x' in the identifier strings. This Re closes issue #1349
2016-02-24 10:28:49 +01:00
Fabian Affolter
3f82b9d6b0 Add link to docs and modify docstrings to match PEP257 2016-02-24 10:07:54 +01:00
Paulus Schoutsen
2b839de854 Merge pull request #1372 from balloob/rfxtrx_bug_fix
Fix issue #1301
2016-02-23 23:40:17 -08:00
Paulus Schoutsen
967a751da1 Add entity_picture property 2016-02-23 22:41:24 -08:00
Paulus Schoutsen
8dc6443d14 Merge pull request #1364 from GreenTurtwig/steam
Added a Steam sensor
2016-02-23 21:31:27 -08:00
Dan Smith
537808f9be Merge pull request #1382 from kk7ds/uvc-ignore-aircams
Filter out AirCam models in UVC camera platform
2016-02-23 15:39:58 -08:00
Paulus Schoutsen
49e588deb3 Merge pull request #1381 from fabaff/template-helpers
Template helpers
2016-02-23 13:38:19 -08:00
Fabian Affolter
6b4dd64cfe Add break to fix length of lines 2016-02-23 22:06:45 +01:00
Fabian Affolter
a47d6c944e Update docstrings to match PEP257 2016-02-23 21:31:38 +01:00
Fabian Affolter
582394bc3b Modify import of template and PEP257 2016-02-23 21:19:22 +01:00
Fabian Affolter
213cc920d0 Move template to helpers 2016-02-23 21:19:10 +01:00
Dan Smith
05a1e11db2 Filter out AirCam models in UVC camera platform
The older (unsupported AirCam) models behave differently and also apparently
suffer some under the last release of the NVR that supported them. Since they
are EOL and not supported by current software, filter them out so we don't
break while trying to extract an image from them.
2016-02-23 12:01:51 -08:00
Rowan Hine
f8240a9cda Changed to use dictionary 2016-02-23 18:02:48 +00:00
Paulus Schoutsen
d6a14a1767 Merge pull request #1379 from jaharkes/wemo_switch
Fix dispatching for regular WeMo switch devices.
2016-02-23 07:22:25 -08:00
Jan Harkes
9b0b3c474e Fix dispatching of WeMo switch devices.
I only have WeMo Link and Insight devices and assumed model names of other
devices were fairly straightforward.

But it looks like the regular WeMo switch uses 'Socket' as the model name.
2016-02-23 10:05:14 -05:00
Rowan Hine
532d807771 Add Steam sensor 2016-02-23 09:35:27 +00:00
sander
019af42e94 removed unnecessary properties. 2016-02-23 09:42:34 +01:00
Fabian Affolter
60d579af84 Update/add docstrings (PEP257) 2016-02-23 06:23:04 +01:00
Paulus Schoutsen
c64da761f1 Merge pull request #1359 from balloob/template-helpers
New template helpers now, utcnow, distance, closest
2016-02-22 19:20:49 -08:00
Dan Smith
2d3d674295 Merge pull request #1376 from kk7ds/uvc-passwords-fixes-tests
UVC Fixes, features, and tests
2016-02-22 15:17:57 -08:00
Dan Smith
590512916a Add tests for camera.uvc and fix bugs found in the process
This adds tests for the uvc camera module. It's a good thing too,
because I found a few bugs which are fixed here as well:

 - Graceful handling of non-integer port
 - Failure to take the first host that works when probing host,internalHost
 - Failure to detect if neither of them actually work

This also converts the code to only call add_devices once with a listcomp.
2016-02-22 14:37:57 -08:00
Dan Smith
d398832112 Make UVC cameras honor the local camera password store, if set
The NVR tells us the admin username, but not the password for the
camera. Right now, we assume the default password, which obviously
doesn't work for people that have changed it. The uvcclient library
provides a way to set the cached admin password for a camera, which
is stored in a client-specific location. We can utilize that to
grab the password, falling back to the default if it's unset. With
this, people just need to run a command per camera to set the
admin password on their systems, if it has changed.
2016-02-22 13:17:53 -08:00
sander
88e7967a7d - removed update method
- removed failing tests from test_scene
2016-02-22 22:01:05 +01:00
sander
e37c232bf6 flake8 correction 2016-02-22 20:05:42 +01:00
sander
fb449cbc82 first commit 2016-02-22 19:53:55 +01:00
Paulus Schoutsen
88dc7a08c4 Merge pull request #1346 from stefan-jonasson/add_for_to_conditions
Added the "for" param to the conditions as well
2016-02-22 07:49:35 -08:00
Paulus Schoutsen
7cc3b8d7b1 Merge pull request #1371 from davidedmundson/dev
Fix service documentation appearing for notifications
2016-02-22 07:37:08 -08:00
Paulus Schoutsen
09ff394abc Merge pull request #1369 from t30/test-command_rollershutter
Added command_rollershutter component
2016-02-22 07:36:14 -08:00
Paulus Schoutsen
b294383f20 Merge pull request #1368 from Gerto/dev
Don't set Bitcoin wallet if not setup in configuration
2016-02-22 07:35:24 -08:00
Fabian Affolter
5bd0b5ab99 Update docstring 2016-02-22 14:43:12 +01:00
Fabian Affolter
7d9e882d52 Update docstrings to match PEP257 2016-02-22 14:42:11 +01:00
Daniel
1f842140ef Fix issue #1301 2016-02-22 13:45:01 +01:00
David Edmundson
8d5a164346 Fix service documentation appearing for notifications
We want the descriptions for notify.notify regardless of the name of the
exact notify service being called.
2016-02-22 11:14:05 +00:00
Gert
cbe27d8f1a Don't set wallet if not setup in configuration
Because of problems with the Wallet part of python blockchain library (see #1242 ) , the entire Bitcoin module isn't working currently.
This change does not fix those problems but at least makes the sensor work again for people who don't need Wallet-related functionality.

It also just seems better practice to not set a wallet and call "wallet.get_balance()" when not wallet is set in configuration.
2016-02-22 11:44:00 +01:00
t30
066b569cfe Added command_rollershutter component 2016-02-22 10:43:29 +00:00
Fabian Affolter
fd3ea95b82 Add docstrings, fix typos, and update docsstring for PEP257 2016-02-22 10:11:46 +01:00
Stefan Jonasson
e4485dcf3d Updated structure, added more tests 2016-02-22 09:40:27 +01:00
Paulus Schoutsen
7a0c99a1d5 Update frontend 2016-02-21 23:14:36 -08:00
Paulus Schoutsen
7c15f6a4b3 Merge pull request #1332 from jaharkes/wemo_leds
Wemo leds
2016-02-21 20:52:55 -08:00
Jan Harkes
afe564fb3f Move WeMo discovery into a common component 2016-02-21 22:23:00 -05:00
Paulus Schoutsen
82e11e237e Merge pull request #1268 from flyte/tcp-component-pr
Add generic TCP socket component
2016-02-21 19:21:20 -08:00
Jan Harkes
4dad40fffb Add support for WeMo LED lights. 2016-02-21 21:57:53 -05:00
Jan Harkes
368ad93eb6 Only add discovered switches instead of any WeMo device. 2016-02-21 21:57:53 -05:00
Paulus Schoutsen
92be572374 Merge pull request #1351 from tpatja/zwave_binary_sensor
ZWave binary sensor support
2016-02-21 13:57:06 -08:00
Paulus Schoutsen
c77266c544 Merge pull request #1357 from w1ll1am23/update_wink_for_binary_switch_fix
Updated wink version for binary switch fix
2016-02-21 13:50:59 -08:00
Paulus Schoutsen
aa748e3e48 Merge pull request #1358 from andythigpen/script-improvements
Script improvements
2016-02-21 13:49:49 -08:00
Paulus Schoutsen
3d8e9b4261 Lint fixes 2016-02-21 13:09:49 -08:00
Paulus Schoutsen
7c6dcdb082 Catch an extra error that could break util.convert 2016-02-21 11:23:16 -08:00
Paulus Schoutsen
c3bb6d32aa Add closest template helper 2016-02-21 11:13:40 -08:00
Paulus Schoutsen
9f5f13644a Add template multiply test 2016-02-21 11:12:37 -08:00
Paulus Schoutsen
7805d2800c Expose current time object instead of method to retrieve (thanks @fabaff) 2016-02-21 09:32:43 -08:00
Andrew Thigpen
7dd529356a Add toggle support for scripts. 2016-02-21 11:22:38 -06:00
Paulus Schoutsen
070cee48a8 Merge pull request #1353 from balloob/assume-state
Add assumed_state to Group, MQTT Switch, MQTT Light
2016-02-21 09:19:54 -08:00
Andrew Thigpen
b961b5037f Only turn on scripts that are not currently running.
Prevents an errant API call from advancing a currently executing delay
step before it should.
2016-02-21 11:11:35 -06:00
William Scanlon
3da554a198 Update wink version 2016-02-21 12:01:32 -05:00
Teemu Patja
d1a4dc77d1 Disable pylint warning 2016-02-21 10:01:03 +02:00
Paulus Schoutsen
ff9568ad26 Merge pull request #1348 from LinuxChristian/dev
Added support for d-link W215 smart plug
2016-02-20 23:49:57 -08:00
Christian Fredborg Braedstrup
2f66528595 Added support for d-link W215 smart plug 2016-02-21 08:34:07 +01:00
Paulus Schoutsen
9ad2cf7b7a Adjust template rounding tests 2016-02-20 21:59:16 -08:00
Paulus Schoutsen
6ac54b20c7 Add template distance helper 2016-02-20 21:58:53 -08:00
Paulus Schoutsen
6847dac582 Expose current time in templates
Fixes #1282
2016-02-20 20:58:01 -08:00
Paulus Schoutsen
7f81122af6 Update frontend with latest version 2016-02-20 20:46:40 -08:00
Paulus Schoutsen
1eae74be58 Add assumed_state to group 2016-02-20 19:11:02 -08:00
Paulus Schoutsen
443b39bccd MQTT Switch to expose assumed_state if optimistic 2016-02-20 17:17:30 -08:00
Paulus Schoutsen
8f70630790 MQTT Light to expose assumed_state if optimistic 2016-02-20 17:17:22 -08:00
Teemu Patja
5053c807c0 ZWave binary sensor support
Treat ZWave binary sensors as binary_sensor components instead of
regular sensors.
2016-02-20 23:57:59 +02:00
Stefan Jonasson
6e7ca9505c Removed unused import 2016-02-20 22:25:41 +01:00
Stefan Jonasson
f3c95adaca Fixed now => utcnow
Fixed added time patch to unittest
2016-02-20 22:15:49 +01:00
Paulus Schoutsen
6532eae3d5 Merge pull request #1343 from balloob/random-cleanup
Random cleanup
2016-02-20 12:16:54 -08:00
Stefan Jonasson
ff6e071dff added the for param to the conditions as well 2016-02-20 12:52:42 +01:00
Paulus Schoutsen
cd6d44ece3 Properly clean up Home Assistant instances in tests 2016-02-20 01:05:52 -08:00
Paulus Schoutsen
22b47ce9c6 Merge pull request #1314 from balloob/fix_own_tracks_mobile_beacon
Fix own tracks mobile beacon race condition
2016-02-20 00:27:07 -08:00
Paulus Schoutsen
f4e0f1d895 Update frontend 2016-02-20 00:11:07 -08:00
Paulus Schoutsen
8a1fa82205 Add sensor class to bloomsky binary_sensor 2016-02-20 00:08:02 -08:00
Paulus Schoutsen
fb9d8c79b5 Bloomsky main component to load its platforms 2016-02-19 23:22:23 -08:00
Paulus Schoutsen
f5f52010d1 Extract bloomsky binary_sensor 2016-02-19 23:21:56 -08:00
Paulus Schoutsen
1bfea626ff Handle circular setup dependency 2016-02-19 23:20:14 -08:00
Paulus Schoutsen
4c538c718b Clean up binary_sensor 2016-02-19 22:23:25 -08:00
Paulus Schoutsen
63a27f1943 Add discover helper method to discovery component 2016-02-19 22:23:01 -08:00
Paulus Schoutsen
70aa605396 Merge pull request #1340 from MartinHjelmare/mysensors-binary-sensor
Add mysensors binary sensor
2016-02-19 20:14:42 -08:00
MartinHjelmare
08aaea5444 Add mysensors binary sensor
* Add mysensors binary sensor.
* Add discovery platforms to binary_sensor base component.
* Replace device_state_attributes with state_attributes in
	binary_sensor base class.
* Fix docstrings.
* Add discovery of binary sensor to mysensors component.
* Add child.type as argument to mysensors device_class.
* Move binary sensor types from sensor to binary_sensor module.
* Fix binary_sensor attribute tests. Use state_attributes instead of
	device_state_attributes.
2016-02-20 04:28:17 +01:00
Paulus Schoutsen
2d0721abe8 Merge pull request #1338 from kk7ds/unifi-tracker
Add Ubiquiti Unifi device tracker
2016-02-19 18:41:01 -08:00
Paulus Schoutsen
4128d083e6 Merge pull request #1339 from MartinHjelmare/fix-mysensors-temp
Fix temperature unit
2016-02-19 18:18:35 -08:00
MartinHjelmare
52131a3335 Fix temperature unit
* Specify temperature unit according to gateway setting, to avoid
	converting to Fahrenheit when already Fahrenheit.
* Fix docstrings in wrapper class.
2016-02-20 02:11:15 +01:00
Dan Smith
27f456ca70 Add Ubiquiti Unifi device tracker
Ubiquiti's Unifi WAP infrastructure has a central controller (like mfi and uvc)
that can be queried for client status. This adds a device_tracker module that
can report the state of any client connected to the controller.
2016-02-19 15:24:00 -08:00
Fabian Affolter
f9385eb87a UPdate docstring 2016-02-19 23:58:45 +01:00
Paulus Schoutsen
1c8c16f85f Merge pull request #1220 from stefan-jonasson/command_line.py
New notification platform "command line"
2016-02-19 14:15:40 -08:00
Stefan Jonasson
c85875ddf4 removed command_line from coveragerc 2016-02-19 22:34:04 +01:00
Stefan Jonasson
fa6d9adcba Added some unittests for the command_line notification 2016-02-19 22:30:38 +01:00
Flyte
4e6b755b26 Add tests for TCP component. 2016-02-19 17:41:51 +00:00
Greg Dowling
d019b7f6b8 Merge pull request #1334 from balloob/add_for_to_automation
Add `for` to state automation.
2016-02-19 16:58:04 +00:00
pavoni
a75833cf2b Remove debug. 2016-02-19 16:41:05 +00:00
Paulus Schoutsen
f20ea41538 Merge pull request #1322 from w1ll1am23/nest_weather_component
Added support for nest current weather conditions
2016-02-19 08:24:07 -08:00
Paulus Schoutsen
97e1f0be98 Add neurio to .coveragerc 2016-02-19 08:13:11 -08:00
pavoni
85bf9a49ea Remove traces. 2016-02-19 15:39:44 +00:00
pavoni
9e48b88154 Add for delay to state automation. 2016-02-19 15:28:17 +00:00
William Scanlon
14afd1e409 Removed debugging logging 2016-02-19 08:26:56 -05:00
pavoni
ee62120fe5 Revise race condition test. 2016-02-19 10:19:14 +00:00
pavoni
7bd4e58b9d Add tests for race condition. 2016-02-19 09:43:59 +00:00
Paulus Schoutsen
0417803b7c Merge pull request #1331 from balloob/tox-coveralls-pt2
Travis: only run coveralls on success
2016-02-18 23:30:38 -08:00
Paulus Schoutsen
d65c1c2b0d Travis: only run coveralls on success 2016-02-18 23:23:05 -08:00
Paulus Schoutsen
1841f3994f Merge pull request #1250 from balloob/chore/remove-simple-alarm
Remove simple_alarm component
2016-02-18 22:26:58 -08:00
Paulus Schoutsen
5f3cb58d8e Remove simple_alarm component 2016-02-18 22:20:59 -08:00
Paulus Schoutsen
e8da63db28 Merge pull request #1330 from balloob/isort-test
Fix imports (using isort)
2016-02-18 21:57:48 -08:00
Paulus Schoutsen
e80309c03c Fix imports (using isort) 2016-02-18 21:27:50 -08:00
Paulus Schoutsen
233a2a2878 Merge pull request #1308 from kk7ds/binary-sensor-class
Add binary sensor class
2016-02-18 21:09:17 -08:00
Paulus Schoutsen
e677fc876b Merge pull request #1319 from shaftoe/sonosconfig
Fix media_player/sonos configuration mismatch
2016-02-18 20:33:39 -08:00
Paulus Schoutsen
560173e13b Merge pull request #1327 from justyns/zwaveremote
Return early from setup_platform when zwave NETWORK is not configured
2016-02-18 20:27:43 -08:00
Dan Smith
d57df2ddde Update the sensor classes in the demo binary_sensor
This updates the two demo sensors we have so they show contextual icons
in the UI.
2016-02-18 17:59:58 -08:00
Justyn Shull
9a740bff2a Return early from setup_platform when zwave NETWORK is not configured 2016-02-18 18:12:00 -06:00
Paulus Schoutsen
acea32949b Merge pull request #1326 from balloob/bloomsky-tweak
Fix bloomsky component importing
2016-02-18 14:46:05 -08:00
Paulus Schoutsen
30e1569b21 Fix bloomsky component importing 2016-02-18 13:10:25 -08:00
William Scanlon
d7c4b50e3e Added support for nest current weather conditions 2016-02-18 16:04:32 -05:00
Dan Smith
d93883f153 Make nx584 expose zone types (sensor classes)
With this, plus https://github.com/balloob/home-assistant-polymer/pull/32,
I can have nx584 sensors use a proper icon in the UI.
2016-02-18 12:20:35 -08:00
Dan Smith
2d932f89fc Add sensor_class to binary_sensor
This adds a 'sensor_class' property and attribute, which should be either
None or one of several defined SENSOR_CLASSES to indicate contextual
information about what the sensor is measuring.
2016-02-18 12:20:35 -08:00
Greg Dowling
182fcb5f03 Merge pull request #1320 from balloob/bump-pywemo-version
Bump pywemo version.
2016-02-18 19:40:47 +00:00
pavoni
98d18c3060 Bump pywemo version. 2016-02-18 19:32:30 +00:00
Alexander Fortin
6578928e3c Fix media_player/sonos configuration mismatch
* From configuration.yaml is easy to provide iterable elements like lists,
  this adds the possibility to provide a list of Sonos hosts using a yaml
  and still supports the comma separated string version
* Remove superfluous host reassignment
2016-02-18 18:57:50 +01:00
Flyte
c1d39a2fce Remove unnecessary top-level TCP component. Fix order of inheritance on TCP BinarySensor. 2016-02-18 17:25:02 +00:00
pavoni
9f7ce23e80 Fix suspect race condition in leave region.
Add safely check for double beacon entry. Remove battery for beacons.
Disable lint warning.
2016-02-18 12:52:40 +00:00
Paulus Schoutsen
d39e1be388 Merge pull request #1312 from balloob/tox-coveralls
Fix coveralls
2016-02-17 23:37:17 -08:00
Paulus Schoutsen
61b0d02a88 Fix coveralls 2016-02-17 23:26:55 -08:00
Paulus Schoutsen
8eb396a435 Merge pull request #1309 from kk7ds/graphite-debug
More graphite hardening work
2016-02-17 20:30:04 -08:00
Paulus Schoutsen
70f05f30d5 Merge pull request #1243 from MartinHjelmare/refactor-mysensors-light
Refactor mysensors light
2016-02-17 20:27:52 -08:00
MartinHjelmare
9ac53b502f Clean up and fix
* Add check if V_LIGHT is in values before sending message in
	_turn_on_light.
* Replace super calls with self.
* Remove not needed init method in child classes.
* Remove turn_on method in parent class and add update_ha_state
	to _turn_on_light, _turn_on_dimmer and _turn_on_rgb_or_w.
2016-02-18 02:04:06 +01:00
MartinHjelmare
6e8c79d531 Change refactor structure
* Make a flatter one level inheritance, with MySensorsLight as parent
	with four children, one per light type.
* Break out helper methods. One per plain light, dimmer and RGB/RGBW
	children and per update, turn_on and turn_off, nine in total. Put
	these in the parent.
* Call the helper methods as needed from the child methods update,
	turn_on and turn_off.
* Change name of MySensorsLightLight to MySensorsLightPlain.
* Fix module docstrings according to pep257.
* Change name of color util method from rgb_hex_to_list to
	rgb_hex_to_rgb_list.
* Add unit tests for rgb_hex_to_rgb_list.
2016-02-18 02:04:06 +01:00
MartinHjelmare
03423cc3a9 Refactor mysensors light
* Add a light entity class per V_LIGHT, V_DIMMER, V_RGB and V_RGBW.
    Make these classes inherit each other up to MySensorsLight class.
* Map the entity classes to their S_TYPE in a dict.
* Check if an entity class map or just an entity class have been passed
    to pf_callback_factory before using the entity_class variable in
    homeassistant/components/mysensors.py.
* Add rgb_hex_to_list function in homeassistant/util/color.py.
2016-02-18 02:04:06 +01:00
Dan Smith
cd6780baf4 More graphite hardening work
This adds verbose debugging which can be turned on to figure out what is
going on. It also adds a broad exception handler in the worker thread
to avoid dying. If you're running this such that stderr doesn't go to a
log, it can be easy to miss the thread's death.

I wrote all this to try to diagnose #1283, which seems to maybe have
healed itself. But since I have it, I figure we might as well keep it
in case we have trouble in the future.
2016-02-17 15:11:24 -08:00
Paulus Schoutsen
bb37708716 Merge pull request #1296 from kk7ds/honeywell-no-fan
Fix #1287 for honeywell US systems with no fan
2016-02-17 12:18:10 -08:00
Per Sandström
0bacc7be07 Merge pull request #1300 from persandstrom/vsure0.5.1
update vsure to 0.5.1
2016-02-17 19:34:03 +01:00
Per Sandström
99ac4524b9 update vsure to 0.5.1 2016-02-17 19:28:26 +01:00
Flyte
348b7abe7d Change TCP component to use Jinja2 instead of regex 2016-02-17 18:12:36 +00:00
Flyte
cf93644d54 Move generic tcp sensor entity to specific sensor component 2016-02-17 17:26:53 +00:00
Paulus Schoutsen
4d8487e7ba Merge pull request #1298 from kk7ds/fix-alarmdotcom-dep
Fix alarmdotcom requirement 0.0.7 removed
2016-02-17 08:52:10 -08:00
Dan Smith
96dde18ae3 Fix alarmdotcom requirement 0.0.7 removed
Looks like alarmdotcom just released 0.1.1 and deleted 0.0.7 which is
breaking our build.
2016-02-17 08:41:46 -08:00
Dan Smith
9aa4028718 Fix #1287 for honeywell US systems with no fan
This bumps the somecomfort requirement to 0.2.1 to pull in a change
that makes handling no-fan systems graceful. Adds a test that should
prove it gives us what we want.

If no fan, then fan is always idle and fanmode is None.
2016-02-17 08:16:02 -08:00
Paulus Schoutsen
966b83f648 Merge pull request #1293 from w1ll1am23/Wink_lock_fix
Fixed issue with Wink locks lock, and unlock methods
2016-02-17 08:00:51 -08:00
William Scanlon
b2366ce68e Added optional parameter to lock and unlock methods 2016-02-17 05:50:36 -05:00
Paulus Schoutsen
bd3f0c101d Merge pull request #1290 from balloob/cleanup-camera
Cleanup camera
2016-02-16 23:59:10 -08:00
Paulus Schoutsen
ab9ac80ee0 Update frontend with new camera UI 2016-02-16 23:52:26 -08:00
Paulus Schoutsen
aea0598805 Clean up camera component 2016-02-16 23:52:05 -08:00
Dan Smith
b7c4370e2b Merge pull request #1271 from kk7ds/nx584-sensors
Add nx584 as a sensor platform
2016-02-16 20:40:15 -08:00
Dan Smith
22865e5d96 Add nx584 as a sensor platform
This allows you to get every door, window, smoke, etc zone from your security
panel into HA. This uses the live eventing feature of pynx584, which means you
get instantaneous signaling into HA when a door opens or something happens,
which is handy for automating lights on when doors open after dark, etc.

Requires update to pynx584 0.2
2016-02-16 20:24:32 -08:00
Paulus Schoutsen
c66511e0cf Merge pull request #1275 from balloob/rfxtrxSignalRep
Rfxtrx signal rep
2016-02-16 20:23:55 -08:00
Paulus Schoutsen
79dbd14568 Merge pull request #1280 from molobrakos/tellduslive
added assumed_state property + improved error handling
2016-02-16 13:51:14 -08:00
Paulus Schoutsen
5756cff8a4 Merge pull request #1281 from molobrakos/eliqonline
improve error handling
2016-02-16 11:24:36 -08:00
Erik
44a39636b1 improve error handling 2016-02-16 18:23:08 +01:00
Erik
307b2c629b catch exception and log 2016-02-16 17:46:25 +01:00
Paulus Schoutsen
bbfa63ee79 Merge pull request #1269 from turbokongen/rfxtrx-newprotocols
Add assumed_state for rfxtrx switch and light.
2016-02-16 08:19:27 -08:00
Erik
008d65677b add assumed state property 2016-02-16 17:18:49 +01:00
Paulus Schoutsen
68973dbc4d Merge pull request #1276 from balloob/fix_efergy_key_error
Catch KeyError as well as ValueError when handling efergy errors.
2016-02-16 07:33:12 -08:00
pavoni
9a6c99264e Catch KeyError as well as ValueError when handling efergy errors. 2016-02-16 12:05:00 +00:00
Paulus Schoutsen
1d7aea7120 Merge pull request #1272 from infamy/dev
initial commit of the neurio_energy sensor
2016-02-15 22:08:35 -08:00
infamy
16865b82d3 initial commit of the neurio_energy sensor 2016-02-15 15:54:07 -08:00
Daniel Høyer Iversen
2ba3df2257 Merge pull request #1264 from balloob/rfxtrxLight
Rfxtrx light
2016-02-15 20:59:49 +01:00
Daniel
aec269050f Add signal repetition to rfxtrx 2016-02-15 19:52:39 +01:00
Daniel
b93ebe1936 Add signal repetition to rfxtrx 2016-02-15 19:45:33 +01:00
Daniel
0010cadd39 Add signal repetition to rfxtrx 2016-02-15 19:41:40 +01:00
Paulus Schoutsen
75f2b4bc0e Merge pull request #1265 from flyte/tox-execute-all-lint
Execute all lint tests even if flake8 reports errors.
2016-02-15 10:21:43 -08:00
John Arild Berentsen
a7ce9ba49e CI fix 2016-02-15 19:09:53 +01:00
John Arild Berentsen
f429a6c4ff Add assumed_state for rfxtrx switch and light. 2016-02-15 18:59:11 +01:00
Flyte
3d83eea5f7 Add tcp component. 2016-02-15 16:04:14 +00:00
Flyte
a3e8994fcc Execute all lint tests even if flake8 reports errors. 2016-02-15 10:00:46 +00:00
Daniel
eacfac6fa8 Support on-off device in rfxtrx light 2016-02-15 10:10:29 +01:00
Daniel
0d45470ea6 Support on-off device in rfxtrx light 2016-02-15 10:05:47 +01:00
Paulus Schoutsen
bca3207e0c Update frontend with assumed_state and delete state support 2016-02-15 01:02:15 -08:00
Paulus Schoutsen
de7a14074e Merge pull request #1247 from balloob/feature/entity-assumed-state
Add assumed_state property to entity
2016-02-14 23:59:35 -08:00
Paulus Schoutsen
cdc93ab670 Merge pull request #1262 from balloob/chore/tests-cleanup
More testing cleanup
2016-02-14 23:37:10 -08:00
Paulus Schoutsen
c287520432 MQTT Light test - switch order 2016-02-14 23:16:54 -08:00
Paulus Schoutsen
68803a46b6 Thread pool tweaks 2016-02-14 23:01:49 -08:00
Paulus Schoutsen
8d366a7367 Tests: Mock get_local_ip by default too 2016-02-14 22:01:30 -08:00
Paulus Schoutsen
23b116803b Merge pull request #1261 from kk7ds/graphite-gaierror
Some graphite error handling improvements
2016-02-14 17:40:40 -08:00
Dan Smith
3610f40a6a Handle EVENT_STATE_CHANGED with no new_state in graphite
I noticed some events that came in with new_state=None. Make graphite
defensive about this.
2016-02-14 15:57:03 -08:00
Dan Smith
366595fd90 Catch socket.gaierror in graphite driver
If you specify a name that can't be looked up in DNS, socket.connect()
throws socket.gaierror. We should catch and log that situation properly.
2016-02-14 15:44:11 -08:00
Paulus Schoutsen
00486dccea Merge pull request #1260 from balloob/chore/tests-cleanup
Chore/tests cleanup
2016-02-14 15:21:23 -08:00
Paulus Schoutsen
09ab3e95c0 Tests should all use test HA 2016-02-14 15:08:23 -08:00
Stefan Jonasson
fa8857dfc5 Changed process communication to use stdin for the message because of security concerns. 2016-02-14 22:22:11 +01:00
Paulus Schoutsen
bade0e0d71 Make tests pass flake8 2016-02-14 13:07:21 -08:00
Paulus Schoutsen
dd2aec0a08 Restructure tests to ensure unique ports 2016-02-14 12:54:16 -08:00
Paulus Schoutsen
64430f26f3 Merge pull request #1257 from kk7ds/handle-uvc-errors-better
Misc UVC improvements
2016-02-14 12:27:25 -08:00
Paulus Schoutsen
4eecdbdab1 Merge pull request #1259 from kk7ds/exclude-venv
Exclude venv directories from linting
2016-02-14 12:25:25 -08:00
Dan Smith
92a11819b4 Exclude venv directories from linting
Exclude venv/ (a common virtualenv name) and bin/,lib/ if the local
directory is configured as a venv.
2016-02-14 20:20:12 +00:00
Paulus Schoutsen
dabb8d5bbc Merge pull request #1246 from balloob/feature/remove-state-fire-event
Have remove state fire state_changed event
2016-02-14 10:33:59 -08:00
Sean Dague
8c67a924bc Merge pull request #895 from sdague/tox
add tox infrastructure for running tests locally and in travis
2016-02-14 13:13:13 -05:00
Sean Dague
97c0f5bb5a convert testing infrastructure to tox
This converts the testing infrastructure to tox for both locally
testing and travis. This is nearly equivalent to the previous testing
with the only exception that linting fails with the first tool to fail
and won't process all of them.

Slightly tricky thing is that tox resets *all* of the environment for
it's subprocess runs by default. A couple of the dependencies we have
will not install in non UTF8 locales: temper-python & XBee.
2016-02-14 13:04:42 -05:00
Paulus Schoutsen
aeb87b0245 Merge pull request #1248 from balloob/chore/reorg-frontend-api
Move bootstrap endpoint from api to frontend
2016-02-14 09:43:53 -08:00
Paulus Schoutsen
6be2ec7fea Merge pull request #1249 from balloob/chore/remove-usage-attr_friendly_name
Remove usage of ATTR_FRIENDLY_NAME within components/platforms
2016-02-14 09:43:39 -08:00
Dan Smith
885b61a750 Implement brand and model for UVC cameras 2016-02-14 17:27:29 +00:00
Dan Smith
0ba7fb40a4 Improve UVC performance by not logging in on each image fetch
This makes the UVC camera_image() method not log into the camera on
every single image fetch, which reduces load on hass and the camera,
and lowers the latency to get an actual image fetched.
2016-02-14 17:27:29 +00:00
Dan Smith
263839a336 Handle connection errors talking to UVC cameras during image fetch
This requires uvcclient==0.6 which breaks out exceptions for us.

Fixes #1244
2016-02-14 17:27:26 +00:00
Paulus Schoutsen
3ced457089 Merge pull request #1255 from miniconfig/splunk-fix-attributes
Converted state.attributes to dict in Splunk component
2016-02-14 07:51:48 -08:00
miniconfig
01df1f8458 Converted state.attributes to dict. Fixes Issue #1252 2016-02-14 10:47:46 -05:00
Paulus Schoutsen
b29f2f6d6f Remove usage of ATTR_FRIENDLY_NAME within components/platforms 2016-02-14 00:21:20 -08:00
Paulus Schoutsen
cafa4043b3 Move bootstrap endpoint from api to frontend 2016-02-14 00:04:08 -08:00
Paulus Schoutsen
8bea5c06de Add assumed_state property to entity 2016-02-13 23:42:11 -08:00
Paulus Schoutsen
06de73ff80 Allow removing a state via API + remote StateMachine 2016-02-13 23:00:38 -08:00
Paulus Schoutsen
ada2fb4ec0 Fire event when we remove a state 2016-02-13 22:57:40 -08:00
Paulus Schoutsen
39bbfd14d9 Merge pull request #1240 from persandstrom/dict_size_change_during_iteration
Fixed intermittent error during setup
2016-02-13 22:28:46 -08:00
Per Sandström
9e816cfd3f lock _states to prevent size change during iteration 2016-02-14 06:34:00 +01:00
Paulus Schoutsen
e170484f16 Change helpers.extract_domain_configs from generator to list bc concurrency 2016-02-13 21:20:49 -08:00
Paulus Schoutsen
9204c44eec Merge pull request #1241 from kk7ds/update-honeywell-somecomfort
Update honeywell somecomfort
2016-02-13 19:44:58 -08:00
Dan Smith
0fbd947426 Test Honeywell Round thermostat
This includes two changes to the round code:
 - Return True on setup success
 - Break out the default away temp into a constant
2016-02-14 01:05:18 +00:00
Dan Smith
5921e65d83 Allow specifying location and/or thermostat for Honeywell US
This lets you optionally only add thermostats by location or
specific device id, instead of all the thermostats in your
account. This would be helpful if you have two devices in different
houses (i.e vacation home), etc.
2016-02-13 23:13:38 +00:00
Dan Smith
c51dd64bd8 Convert Honeywell platform to use somecomfort library 2016-02-13 23:13:33 +00:00
Paulus Schoutsen
278033cbf9 Merge pull request #1235 from flyte/docker-colorlog
Add colorlog to docker images
2016-02-13 14:55:07 -08:00
Flyte
9233449551 Add colorlog to Dockerfile 2016-02-13 20:53:15 +00:00
Paulus Schoutsen
680f450278 Merge pull request #1236 from kk7ds/ci-tweak
Make it easier to run cibuild locally
2016-02-13 11:18:40 -08:00
Dan Smith
66c2fa1270 Make it easier to run cibuild locally
Just treat lack of travis environment as "run everything"
2016-02-13 18:30:34 +00:00
Paulus Schoutsen
bf0b453677 Merge branch 'hotfix/state-as-number' into dev
Conflicts:
	homeassistant/const.py
	tests/helpers/test_state.py
2016-02-13 08:32:06 -08:00
Paulus Schoutsen
29b6782b42 Merge pull request #1229 from balloob/hotfix/state-as-number
0.13.1 / Fix: state_as_number always return float
2016-02-13 08:23:14 -08:00
Paulus Schoutsen
d2df485bea Version bump to 0.13.1 2016-02-13 08:17:47 -08:00
Paulus Schoutsen
77b141a355 Update Wink to 0.6 2016-02-13 08:17:38 -08:00
Fabian Affolter
00afaac54c Update for file header, docstrings, and PEP8/PEP257 2016-02-13 14:19:11 +01:00
Fabian Affolter
34b91cf6ce Remove config details (already covered in docs) 2016-02-13 09:38:56 +01:00
Fabian Affolter
9dc055e537 Add link to docs 2016-02-13 09:35:31 +01:00
Paulus Schoutsen
6d6cf886f3 Merge pull request #1222 from turbokongen/verisure-mouse
Support for Mousedetectors connected in Verisure systems
2016-02-13 00:22:34 -08:00
Paulus Schoutsen
1571b33e4a Fix: state_as_number always return float 2016-02-13 00:08:32 -08:00
John Arild Berentsen
a29be5455c Fix unit and wrong errorhandling 2016-02-13 09:05:18 +01:00
Paulus Schoutsen
4210291e5b Version bump to 0.14.dev0 2016-02-12 21:55:40 -08:00
Paulus Schoutsen
e9fa1f1f83 Merge pull request #1182 from balloob/dev
0.13
2016-02-12 21:55:24 -08:00
Paulus Schoutsen
724d5bfe9d Version bump to 0.13 2016-02-12 21:51:34 -08:00
Paulus Schoutsen
938c9888a6 Merge pull request #918 from happyleavesaoc/snapcast
snapcast media player
2016-02-12 19:31:07 -08:00
Paulus Schoutsen
b91e4cfb4a Merge pull request #1195 from persandstrom/kodi_thumbnails
kodi thumbnails
2016-02-12 19:03:22 -08:00
Paulus Schoutsen
7dd51034cd Merge pull request #1213 from MartinHjelmare/mysensors-light
Add mysensors light platform
2016-02-12 19:01:41 -08:00
Paulus Schoutsen
2f60ff224f Merge pull request #1223 from MartinHjelmare/update-mysensors-version
Update pymysensors version to 0.5
2016-02-12 18:55:06 -08:00
Paulus Schoutsen
fc3a37cba2 Merge pull request #1224 from MartinHjelmare/fix-mysensors-version-error
Fix error in update method for V_STATUS
2016-02-12 18:54:12 -08:00
Paulus Schoutsen
223b7f85ee Merge pull request #1225 from nkgilley/ecobee-fix
fix ecobee sensor unique id.
2016-02-12 18:53:58 -08:00
happyleavesaoc
13b0beee31 snapcast 2016-02-12 18:35:32 -05:00
nkgilley@gmail.com
ba530e5a16 fix ecobee sensor unique id. 2016-02-12 17:24:00 -05:00
Per SandstrÃom
aafd36d2ce change url to host 2016-02-12 21:19:27 +00:00
MartinHjelmare
0492f0abd0 Fix error in update method for V_STATUS
* Remove check against V_STATUS to avoid error when using version 1.4
    of mysensors. V_LIGHT has the same integer value so V_STATUS is not
    needed.
2016-02-12 22:05:31 +01:00
MartinHjelmare
940799d0da Update pymysensors version to 0.5 2016-02-12 21:59:24 +01:00
John Arild Berentsen
c584b6b28d Support for Mousedetectors connected in Verisure systems 2016-02-12 21:41:01 +01:00
Stefan Jonasson
5a03ddd7e0 Removed "" and changed the call to check_call to make it race the appropriate error 2016-02-12 19:31:28 +01:00
Paulus Schoutsen
1ba60dc898 Update .coveragerc 2016-02-12 09:01:48 -08:00
Paulus Schoutsen
75d3d25969 Merge pull request #1129 from nkgilley/speedtest
Speedtest.net component
2016-02-12 08:59:19 -08:00
Paulus Schoutsen
06bd812b7b Make state unknown if None returned 2016-02-12 08:58:07 -08:00
nkgilley@gmail.com
7cb57583e2 fix line too long 2016-02-12 11:44:24 -05:00
nkgilley@gmail.com
3e3f5db2a5 use a windows & linux compatible regex 2016-02-12 11:30:55 -05:00
nkgilley@gmail.com
88fe28ea1b add update service 2016-02-12 09:55:28 -05:00
Stefan Jonasson
10a20f802b Updated coverage 2016-02-12 11:26:21 +01:00
Stefan Jonasson
9521dad263 Added a command line notification platform that could be used for all kind of custom notifications 2016-02-12 11:25:26 +01:00
Paulus Schoutsen
8857c48c17 Merge pull request #1206 from turbokongen/rfxtrx-newprotocols
Supporting electricity sensors with ELEC2/3 protocol from latest pyRFXtrx (0.4)
2016-02-11 23:30:40 -08:00
Paulus Schoutsen
3c582d1e3c Merge pull request #1143 from balloob/rfxtrx
Rfxtrx
2016-02-11 23:30:34 -08:00
Fabian Affolter
19d12716ef Update docstrings 2016-02-12 08:21:39 +01:00
Fabian Affolter
57446cfb08 Add link to docs 2016-02-12 07:55:20 +01:00
Paulus Schoutsen
ff6cb2b452 Update frontend icons + proximity icon 2016-02-11 22:21:06 -08:00
Paulus Schoutsen
a3ec7998b1 Update frontend with garage door support 2016-02-11 21:55:50 -08:00
Paulus Schoutsen
d892716bfa Merge pull request #1218 from kk7ds/influx-tests
Add tests for influxdb and fix a bug
2016-02-11 21:45:37 -08:00
Dan Smith
61e2da8827 Add tests for influxdb and fix a bug
This adds tests for the influxdb component. It also fixes a bug,
where username and password are required, but not gracefully
handled if they're missing from config.
2016-02-12 05:34:13 +00:00
Paulus Schoutsen
abc039a3d0 Check coverage for statsd and splunk 2016-02-11 20:22:01 -08:00
Paulus Schoutsen
7ba7747ce8 Merge pull request #1217 from jaharkes/nest_heating
Nest binary sensor fixes
2016-02-11 20:15:02 -08:00
Jan Harkes
b04ff7207c Make sure Nest is setup before the binary sensors. 2016-02-11 21:28:08 -05:00
Dan Smith
72235c48fb Merge pull request #1216 from kk7ds/fix-dan-broke-splunk
Re-allow splunk to report string states
2016-02-11 18:26:24 -08:00
Jan Harkes
3f7ff2b1d4 The Nest binary sensor can also track when heating system is running. 2016-02-11 21:24:51 -05:00
Dan Smith
484b7b64d7 Re-allow splunk to report string states
Splunk *can* take string states, so un-fix that wrong fix.
2016-02-12 02:20:15 +00:00
Paulus Schoutsen
7241762bcc Merge pull request #1209 from kk7ds/abstract-numeric-state
Abstract numeric state
2016-02-11 18:16:57 -08:00
Dan Smith
0a904acd4d Add some tests for splunk
This also fixes issue #1214, and I think another bug. The splunk
code will just take the value of state.state and try to serialize
it to json if it can't make it into a number. It did this before
I generalized that code. Since json.dumps() will fail on most anything
complicated, I think the right thing to do is *not* try to do that.
2016-02-12 01:45:30 +00:00
Dan Smith
76df759f4c Add simple statsd tests
These are not very amazing, but at least exercise the code a little
to make sure I didn't break anything. Hopefully they're useful in the
future too.
2016-02-12 01:45:30 +00:00
Dan Smith
4a2b956493 Convert statsd, influx, splunk, and graphite to use state_as_number()
Fixes #1205
2016-02-12 01:45:25 +00:00
Dan Smith
3aa34deaa2 Add state_as_number() helper
This adds state_as_number(), a helper method that tries to interpret
state as a number, for cases we can predict. It's a generalization of
what is copy-and-paste-ed into multiple other places.
2016-02-12 00:41:32 +00:00
nkgilley@gmail.com
b00cad7095 fix travisci errors. 2016-02-11 19:27:05 -05:00
MartinHjelmare
2cf061c768 Add mysensors light platform
* Make light controllable independently with types V_LIGHT, V_DIMMER,
    V_RGB and V_RGBW. V_RGBW is not implemented in the frontend yet.
* Add discovery for light platform.
* Add optimistic mode config setting for switch and light
    to allow feedback state from actuator.
* Move S_LIGHT, V_LIGHT, V_STATUS types from switch to light platform.
* Change node update logging to debug from info level.
* Fix some inaccurate comments.
2016-02-12 01:22:35 +01:00
nkgilley@gmail.com
e837e97c9d use track_time_change 2016-02-11 19:09:51 -05:00
Paulus Schoutsen
df8afe51f4 Merge pull request #1212 from MartinHjelmare/fix-validate-config
Fix validate config in mysensors
2016-02-11 12:39:16 -08:00
Greg Dowling
c8e6f89302 Merge pull request #1210 from balloob/fix_owntracks_passive_zone
Handle passive zones correctly.
2016-02-11 20:35:21 +00:00
pavoni
2e75a58372 Fix outtracks bug with passive zones. 2016-02-11 20:28:02 +00:00
MartinHjelmare
ae2fd149a5 Fix validate config in mysensors
* Add check of port in config.
2016-02-11 21:03:13 +01:00
Greg Dowling
ee62c2cc2b Merge pull request #1208 from kk7ds/static-wemos
Support manually-defined WeMo devices
2016-02-11 18:46:58 +00:00
Dan Smith
4cfa14c29d Support manually-defined WeMo devices
This is extremely useful if you want to support wemos that are on
another subnet or across a VPN. It also lets you sidestep the discovery
process, which is problematic for a lot of people and situations.

In order for this to work, we need to bump the pywemo requirement to
0.3.10, which includes my changes to make this possible.

WeMo devices can be manually configured by adding a static section to
the config, like this:

  switch:
    platform: wemo
    static:
       - 192.168.100.5
       - 192.168.100.6
2016-02-11 17:23:20 +00:00
Paulus Schoutsen
4ce1a67c13 Merge pull request #1077 from xrolfex/wink_garage_door_support
Wink Garage Door Support
2016-02-11 07:59:57 -08:00
Dan Smith
962463c1ab Merge pull request #1196 from kk7ds/honeywell-enumerate
Make Honeywell module enumerate all available thermostats
2016-02-11 07:53:05 -08:00
Paulus Schoutsen
74f06b6862 Merge pull request #1190 from flyte/apcupsd-component
Add APCUPSd component
2016-02-11 07:35:43 -08:00
Dan Smith
d3d7d458e1 Make Honeywell module enumerate all available thermostats
This extends the HoneywellUSThermostat functionality to find and add
all thermostats in your account. So, we add a new config element called
'region' that is the primary trigger for this, and remove the 'id'
trigger since it was never in a released version.

This does a few extra things:
 - It names the thermostat what you have it named in your account,
   which is not something we get to know *unless* we emumerate.
 - It makes all thermostats on a given account use the same session,
   and thus we have to avoid doing an explicit login every time we
   refresh our data. That was causing some rate-limiting on their
   side when I was debugging, so this is probably good. Now, we use
   their existing keepalive pinger to determine if we're still logged
   in and only re-login if we need to.
2016-02-11 15:26:41 +00:00
Eric Rolf
cca6b0c287 Test Fix. 2016-02-11 10:16:57 -05:00
Eric Rolf
23e3b8d2f2 Fixed Style Issue 2016-02-11 10:00:12 -05:00
Eric Rolf
be9a2a043e Refactored Method Names. 2016-02-11 09:57:56 -05:00
Dan Smith
cc4fa6cd38 Merge pull request #1194 from kk7ds/add-graphite-feeder
Add graphite feeder component
2016-02-11 06:36:19 -08:00
John Arild Berentsen
4d15367956 Supporting electricity sensors with ELEC2/3 protocol from latest pyRFXtrx (0.4) 2016-02-11 15:35:05 +01:00
Eric Rolf
175b49236c Fixed style attribute with redefined built in method names. 2016-02-11 09:20:47 -05:00
Eric Rolf
fd0afaa204 Fixed Test Case Logic 2016-02-11 09:12:28 -05:00
Eric Rolf
034cec7152 Fixed Demo Test Cases 2016-02-11 09:06:35 -05:00
Eric Rolf
f464d591c9 Update python wink requirement 2016-02-11 08:49:07 -05:00
Eric Rolf
06cb97adee Merge branch 'wink_garage_door_support' of https://github.com/xrolfex/home-assistant into wink_garage_door_support 2016-02-11 08:39:20 -05:00
Eric Rolf
cab46b91e3 Updated Requirements All. 2016-02-11 08:38:05 -05:00
Eric Rolf
0da09b85de refactored test case 2016-02-11 08:37:17 -05:00
Eric Rolf
95d9bc48ea Updated Demo 2016-02-11 08:37:17 -05:00
Eric Rolf
6b962a2207 Updated coveragec, cleaned up constants, added test for demo. 2016-02-11 08:37:16 -05:00
Eric Rolf
18b3d3df57 Forgot to refactor demo. 2016-02-11 08:37:16 -05:00
Eric Rolf
5f6977acda Refactor Method Name For Open and Close. 2016-02-11 08:37:16 -05:00
Eric Rolf
89f6ef9f6c Updated requirements_all.txt 2016-02-11 08:37:16 -05:00
Eric Rolf
d2ad0620ee Wink Garage Door Support 2016-02-11 08:37:16 -05:00
Eric Rolf
aa13392983 refactored test case 2016-02-11 08:30:33 -05:00
Eric Rolf
6cbf19934f Updated Demo 2016-02-11 08:23:04 -05:00
Daniel
f938134069 updated rfxtrx lib 2016-02-11 14:15:51 +01:00
Eric Rolf
7cdcb800a9 Updated coveragec, cleaned up constants, added test for demo. 2016-02-11 07:41:42 -05:00
Flyte
91fb2764cc Use a cache object to reduce the frequency of calls to APCUPSd 2016-02-11 07:33:53 +00:00
Paulus Schoutsen
82c5e2cf3c Merge pull request #1177 from Theb-1/dev-notify-rest
REST notify component
2016-02-10 23:05:34 -08:00
Flyte
bb8981b611 Add apcupsd component. 2016-02-11 06:33:23 +00:00
Paulus Schoutsen
b350f22a77 Update frontend to fix color picker 2016-02-10 22:18:08 -08:00
Paulus Schoutsen
40da28a0c7 Merge pull request #1192 from i-c/add-delay-to-launchtl-load
Add delay to launchtl load
2016-02-10 21:39:36 -08:00
Paulus Schoutsen
3bdb50510a Merge pull request #1202 from huanga/change_nest_battery-level_unit
Changing battery level unit to "V" instead of "%"
2016-02-10 21:33:10 -08:00
Dan Smith
7478c36b27 Add graphite feeder component
Like recorder, this component listens to all events and reports any
that it can to a graphite installation. This makes it easy to use
graphite for all your data collection and analysis. If you run
carbon-cache (the backend for graphite) on the local machine, no
configuration is required other than enabling the component.

For more info on graphite: http://graphite.wikidot.com/
2016-02-11 05:28:40 +00:00
Paulus Schoutsen
b1f2c90bd0 Add MQTT service description 2016-02-10 21:23:27 -08:00
Ian Copp
e53785f30c Fix __main__.py permissions change 2016-02-10 21:20:56 -08:00
Paulus Schoutsen
1a38354ed5 Merge pull request #1138 from flyte/mqtt-publish-template
Add template support to mqtt.publish service payload.
2016-02-10 21:13:02 -08:00
Andy Huang
02609d0ab5 Changing battery level unit to "V" instead of "%" as the API reports output voltage, not percentage.
This value matches with Settings > Technical Information's Battery information.
2016-02-10 21:12:43 -08:00
Paulus Schoutsen
ce4f5ff29c Merge pull request #1197 from maxdrift/expose-baud-rate-mysensors-component
Expose baud rate config for MySensors component
2016-02-10 20:51:18 -08:00
Paulus Schoutsen
5190cc74c5 Merge pull request #1200 from MartinHjelmare/mysensors-unavailable
Use entity property available in mysensors
2016-02-10 20:45:48 -08:00
Paulus Schoutsen
e83f8da342 Merge pull request #1185 from balloob/perf-states
Make State class more immutable
2016-02-10 18:53:02 -08:00
Paulus Schoutsen
ddaeeba68b Merge pull request #1186 from balloob/remove-deprecated-methods
Remove deprecated methods from core
2016-02-10 18:52:57 -08:00
MartinHjelmare
75775a561b Use entity property available 2016-02-11 03:27:02 +01:00
Fabian Affolter
058315720f Fix typo 2016-02-10 23:59:34 +01:00
Flyte
4e0c7f8a3d Create additional mqtt helper function for using template payload. 2016-02-10 22:38:33 +00:00
Riccardo Massari
c705ca4288 Expose baud rate config for mysensors component 2016-02-10 23:16:41 +01:00
Per SandstrÃom
15ad48a7a0 kodi thumbnails 2016-02-10 19:48:41 +00:00
Ian Copp
c9c15c4cf7 Fix comment phrasing
Somehow I left out the "some". Whoops.
2016-02-10 11:32:56 -08:00
Ian Copp
3046bfce7b Add small time delay to restart-osx command 2016-02-10 11:29:25 -08:00
Flyte
d52e2019c0 Update mqtt.publish() function to use template_payload. Reorganise publish service. Use mqtt.publish() in tests. 2016-02-10 11:11:02 +00:00
Paulus Schoutsen
af8f6bcaba Remove deprecated methods from core 2016-02-09 23:59:31 -08:00
Daniel
cdf0e80773 Improve the robustness of the rfxtrx module, and solve issue #1116 2016-02-10 08:44:34 +01:00
Paulus Schoutsen
b0948bef5f Make State class immutable 2016-02-09 23:27:01 -08:00
Paulus Schoutsen
70a528c04b Merge pull request #1184 from balloob/group-of-groups
Support expanding nested groups
2016-02-09 22:56:30 -08:00
Theb-1
d796625098 flake8 fix 2016-02-09 22:51:44 -08:00
Paulus Schoutsen
dc44ef7356 Support expanding nested groups 2016-02-09 22:43:07 -08:00
Theb-1
c5c4085ad4 upper/arg list/response improvements 2016-02-09 22:27:54 -08:00
Paulus Schoutsen
09b3aba51b Merge pull request #1136 from turbokongen/verisure-locks
Added support for lock connected to Verisure system.
2016-02-09 21:20:52 -08:00
Paulus Schoutsen
6f3aefde64 Merge pull request #1179 from roqeer/patch-1
Add name property to DHT sensor
2016-02-09 21:14:23 -08:00
Theb-1
b3a1491482 pylint: ignore 'too-many-arguments' 2016-02-09 21:12:33 -08:00
Theb-1
b7ff79da24 Fixes and updates
Remove setting defaults twice
Add timeout
Add optional title and target
2016-02-09 20:48:17 -08:00
roqeer
4bf4d94344 Changed to dict lookup with default value
Corrected on request
2016-02-09 22:09:44 +01:00
roqeer
3e26af5ff1 Correct bad-indentation 2016-02-09 19:09:48 +01:00
roqeer
c1270cf0bb Add name property to DHT sensor
Add name to distinguish between multiple connected DHT sensors
2016-02-09 18:58:04 +01:00
Flyte
26fc637ab5 Add payload_template to mqtt 'publish' service call. 2016-02-09 15:41:31 +00:00
Fabian Affolter
66c5d96b43 Upgrade influxdb to 2.12.0 2016-02-09 16:32:05 +01:00
turbokongen@hotmail.com
41f908ed39 Added support for lock connected to Verisure system. 2016-02-09 13:17:05 +01:00
Theb-1
0f5487b95a Add REST notify component 2016-02-08 22:24:11 -08:00
Paulus Schoutsen
23c5159f6c Update frontend to fix map CSS 2016-02-08 21:58:41 -08:00
Paulus Schoutsen
4840dd297a Add unique ID to ecobee sensor 2016-02-08 20:39:09 -08:00
Dan Smith
4605742bb7 Merge pull request #1176 from kk7ds/mfi-tests
Add mFi tests
2016-02-08 19:07:48 -08:00
Paulus Schoutsen
f222340c8e Merge pull request #1174 from balloob/wink-light
Wink light to inherit from light
2016-02-08 19:05:39 -08:00
Dan Smith
b17df44402 Add tests for mFi switches 2016-02-09 03:03:26 +00:00
Dan Smith
895ddc8433 Add tests for mFi sensors
Note that some of the indirection here is so that I can reuse
a few things for mFi switch tests to follow.
2016-02-09 02:59:34 +00:00
Per Sandström
d867d26612 Merge pull request #1168 from persandstrom/sigterm_handler
fix sigterm crash
2016-02-08 19:27:26 +01:00
Per SandstrÃom
564e328698 fix sigterm crash 2016-02-08 18:09:46 +00:00
Paulus Schoutsen
160b811ddf Wink light to inherit from light 2016-02-08 08:53:22 -08:00
Paulus Schoutsen
2e164e519a Merge pull request #1160 from stjohnjohnson/live-camera-stream
Fixes #1062 - If supported, directly stream the MJPEG from the remote camera
2016-02-07 14:43:00 -08:00
Paulus Schoutsen
779188ad27 Merge pull request #1167 from kk7ds/mfi-improvements
Mfi improvements
2016-02-07 14:40:47 -08:00
Paulus Schoutsen
3f6349d663 Merge pull request #1170 from balloob/fix_vera_dimmer_bug
Refactor VeraLight to inherit from Light, rather then VeraSwitch.
2016-02-07 14:39:16 -08:00
pavoni
ac0dc10377 Refactor VeraLight to inherit from Light, rather then VeraSwitch. 2016-02-07 21:45:15 +00:00
Dan Smith
0a7db98b0e Round mFi sensor values to reasonable levels of precision
Most of the mFi sensors are able to reasonably provide accurate
readings to a tenth of a unit or so. This patch rounds them for
better display in the UI. Normally, I would expect this to be a view
action instead of altering the actual data emitted, but since these
values are reasonable for sensor precision, we're not really losing
anything. I followed the model from the openweathermap component, which
rounds for readability in the backend.
2016-02-07 20:51:00 +00:00
Dan Smith
8f690ff077 Add support for mPort input sensors
The mPort device has input pins that can be configured as digital or
analog inputs. We should support those as sensors.
2016-02-07 20:49:02 +00:00
Dan Smith
951fa603ff Support mPort voltage output switch types
An mPort device has a voltage output port that, if configured,
we should support like a switch.
2016-02-07 20:48:57 +00:00
Dan Smith
c113997609 Tweak mFi switch behavior to avoid false states
When we update the mFi server for the state of a switch, the new
state is not always reported immediately if we update right after
the action (the server is not RESTful).

This patch adds some internal target-state handling to report the
desired state on the next poll, allowing any subsequent polls to
override that state.

Also, bump the version requirement for mficlient to 0.2.2 to absorb
a bug fix.
2016-02-07 20:48:51 +00:00
St. John Johnson
f700635445 Add support for mjpeg component to proxy it's own stream 2016-02-07 12:02:52 -08:00
Paulus Schoutsen
d49fae86e4 Update frontend with entity picture fix 2016-02-07 11:33:01 -08:00
Paulus Schoutsen
64611ab2be Merge pull request #1157 from balloob/device-state-attributes
Clean up state_attributes vs device_state_attributes
2016-02-07 10:16:34 -08:00
Paulus Schoutsen
27dc2f61fb Merge pull request #1163 from balloob/migration-5-fix
Fix recorder migration 5
2016-02-07 10:16:24 -08:00
Paulus Schoutsen
cd25c8f72d Clean up some query stuff 2016-02-07 10:07:27 -08:00
Paulus Schoutsen
9ad1d290af Fix migration 5 2016-02-07 10:07:08 -08:00
Fabian Affolter
90ef81d8d5 Merge pull request #1161 from fabaff/bitcoin
Add icon
2016-02-07 15:37:40 +01:00
Fabian Affolter
02efe903ab Add icon 2016-02-07 12:43:02 +01:00
Fabian Affolter
0bb63bf3f0 Move configuration details to docs and add link 2016-02-07 12:36:29 +01:00
Fabian Affolter
e23db5d972 Some small changes 2016-02-07 12:03:01 +01:00
Fabian Affolter
e311f89056 Move details to docs and update docstrings/comments 2016-02-07 12:00:35 +01:00
Fabian Affolter
757946293e Move configuration details to docs 2016-02-07 11:52:17 +01:00
Paulus Schoutsen
98c6e56ea4 Merge pull request #1159 from nickwaring/proximity
Proximity component
2016-02-07 00:54:47 -08:00
Nick Waring
cd0cef6403 Component to track the proximity of devices to a zone 2016-02-07 08:52:32 +00:00
Nick Waring
0d2891ebcc Test file for the proximity component 2016-02-07 08:51:21 +00:00
Paulus Schoutsen
fb6aded2e1 Update frontend with new dependencies 2016-02-07 00:15:09 -08:00
Paulus Schoutsen
8b7cfc831d Merge pull request #1133 from balloob/cast-fix
Fix Chromecast discovery
2016-02-06 23:06:23 -08:00
Paulus Schoutsen
987be65d55 Update frontend to support default_view 2016-02-06 23:01:44 -08:00
Paulus Schoutsen
f08b77dc4c Clean up state_attributes vs device_state_attributes 2016-02-06 22:34:24 -08:00
Paulus Schoutsen
681b84e1bd Update frontend with FF url-sync fix 2016-02-06 22:07:30 -08:00
Paulus Schoutsen
4103d7463b Merge pull request #1155 from balloob/fix-kb-interrupt
Fix Ctrl+C with Subprocesses
2016-02-06 20:12:27 -08:00
Paulus Schoutsen
428750eeda Merge pull request #1151 from kk7ds/add-mfi
Add support for Ubiquiti mFi sensors and switches
2016-02-06 20:11:53 -08:00
Paulus Schoutsen
0ae36e1d28 Merge pull request #1140 from kk7ds/add-nx584-alarm
Add Caddx/GE/Interlogix NetworX alarm panel support
2016-02-06 20:09:25 -08:00
Philip Lundrigan
d2e8721918 Merge pull request #1124 from philipbl/fix_influx
Fix InfluxDB field type conflict
2016-02-06 20:49:20 -07:00
Philip Lundrigan
bbdc196127 Use entity_id attribute 2016-02-06 20:33:43 -07:00
Paulus Schoutsen
a417156d84 Merge pull request #1154 from balloob/fix-time-utils
Fixed time zone conversion with no TZ specified
2016-02-06 19:10:14 -08:00
Dan Smith
3575ddb6ef Add Caddx/GE/Interlogix NetworX alarm panel support
This adds support for NetworX-based alarm panels and should work for
any such panel equipped with a NX584 serial interface module. This
includes NX-4/6/8/8E, where the NX8E has this interface built-in.

It requires the pynx584 module, and requires running the server
component somewhere that has connectivity to the panel via serial,
which may include a serial-over-lan connection.
2016-02-07 03:06:58 +00:00
Dan Smith
ffc4822f50 Add support for Ubiquiti mFi switchable devices
This adds support for mFi devices that are swichable,
such as the mFi Outlet device.
2016-02-07 03:02:49 +00:00
Dan Smith
a147304be9 Add support for Ubiquiti mFi sensors
This adds support for sensors based on Ubiquiti's mFi platform.
All ports/sensors are detected from the mFi controller and exposed.
2016-02-07 02:58:04 +00:00
Ryan Kraus
a001780afb Fix Ctrl+C with Subprocesses
Added KeyboardInterrupt handling back to block_till_stopped method.
This is because Keyboard Interrupts are sent to both the parent and
child process in no particular order so both need to handle the
interrupt.
2016-02-06 21:50:06 -05:00
Ryan Kraus
7a00bf8696 Fixed time zone conversion with no TZ specified
Using .replace to set the current time zone appears to not handle
things correctly. The proper way to do this is apparently .localize.
2016-02-06 21:31:07 -05:00
Paulus Schoutsen
7eef831ff3 Merge pull request #1141 from kk7ds/add-uvc-cameras
Add Ubiquiti Unifi Video Camera support
2016-02-06 18:21:44 -08:00
Paulus Schoutsen
9fde97efed Merge pull request #1152 from balloob/bump-pyvera-version
Bump pyvera, pywemo, add available for wemo
2016-02-06 16:43:42 -08:00
MartinHjelmare
d773ad1ecb Fix mysensors version errors
* The application of the version check in unit_of_measurement was
	messed up after the last refactor. Fix that again.
* An error could occur in device_state_attributes if there was a
	mismatch between used value_type in the device and mysensors
	version in config. Add try... except to handle that.

Bump pyvera version.

Bump pywemo version.

Add unavailable status before properly initialised for maker and insight.
2016-02-07 00:28:12 +00:00
Dan Smith
cab1100a51 Add Ubiquiti Unifi Video Camera support
This adds support for Ubiquiti's UniFi Video cameras via their
NVR device (or service). By configuring just the address of the
NVR and a valid API key, all cameras are discovered and enabled,
including direct-to-camera image snapshot-based video support.
2016-02-06 22:57:44 +00:00
Dan Smith
3616d7a7ea Fix alarm service handler state updates
This changes the service handler dispatch code to always
call update_ha_state(), and cleans up the alarm platforms that
were calling it themselves.
2016-02-06 21:11:28 +00:00
Paulus Schoutsen
d38ad57b7d Merge pull request #1142 from kk7ds/add-honeywellus-thermostat
Add Honeywell US thermostat support
2016-02-06 13:05:53 -08:00
Paulus Schoutsen
b3e966665a Merge pull request #1150 from bradsk88/master
Updating to python-wink 0.5.0
2016-02-06 13:04:42 -08:00
bradsk88
6e69737e88 Updating to python-wink 0.5.0
Major bugfix.  ``` get_bulbs ``` and similar methods were always returning empty lists.

Better unit tests have been added to https://github.com/bradsk88/python-wink to avoid this regression.
2016-02-06 14:22:46 -06:00
Dan Smith
062fe79b3f Add Honeywell US thermostat support
This adds support for the US variant of the Honeywell connected
thermostat. The interface is super simple, so this doesn't add
any external dependencies. It supports basic temperature, setpoint,
and control.

Issue #998 notes that the existing honeywell module doesn't work
for US models, which is because they are totally different. In order
to indicate to the honeywell platform module that the thermostat
is a US-type, we key off of whether or not the thermostat id is
provided. This is something that US people have (and require to
identify one of potentially multiple thermostats in their account)
and EU people will not.
2016-02-06 20:14:40 +00:00
Paulus Schoutsen
af0a44d976 Merge pull request #1144 from MartinHjelmare/fix-mysensors-errors
Fix mysensors version errors
2016-02-06 11:35:49 -08:00
Paulus Schoutsen
43613f000d Merge pull request #1147 from balloob/debug-flag
Fix Interactive Debuggers
2016-02-06 09:56:12 -08:00
Paulus Schoutsen
dde80850a6 Merge pull request #1112 from balloob/switch-template
First cut of switch.template
2016-02-06 09:12:13 -08:00
Ryan Kraus
11a2b8888b Fixes for issue #1114
1. Moved RESTART_EXIT_CODE to constants so it can safely be used by
__main__.py.
2. Allowed __main__/main to return the desired exit code.
3. Forwarded the child processes exit code to the parent process to be
duplicated.
4. Added —debug flag to pass command to force Home Assistant to run in
only one process. A warning is printed to STDERR to indicate HASS is in
debug mode. Another is printed if HASS requests a restart in debug
mode. A restart request in debug mode will quit.
5. Added an argument to __main__/main/setup_and_run_hass to indicate
that it is running in the top process. This tells it to return the exit
code rather than exiting.
2016-02-06 09:48:36 -05:00
MartinHjelmare
b700ec4faa Fix mysensors version errors
* The application of the version check in unit_of_measurement was
	messed up after the last refactor. Fix that again.
* An error could occur in device_state_attributes if there was a
	mismatch between used value_type in the device and mysensors
	version in config. Add try... except to handle that.
2016-02-06 10:57:42 +01:00
Fabian Affolter
614034d196 Update docstrings 2016-02-06 08:23:30 +01:00
Paulus Schoutsen
c9d145cb13 Merge pull request #1120 from haraldnagel/dev
Add BloomSky weather station support
2016-02-05 20:06:53 -08:00
Harald Nagel
b6a32098d1 Add BloomSky weather station support 2016-02-06 01:37:32 +00:00
Flyte
4cf85294db Add template support to mqtt.publish service payload. 2016-02-05 21:47:27 +00:00
Eric Rolf
6fc68e9c8a Forgot to refactor demo. 2016-02-05 15:16:56 -05:00
Eric Rolf
ec88733b57 Refactor Method Name For Open and Close. 2016-02-05 15:10:53 -05:00
Eric Rolf
7ef2075520 Updated requirements_all.txt 2016-02-05 14:20:06 -05:00
Eric Rolf
fbd0dbf8ee Wink Garage Door Support 2016-02-05 12:53:57 -05:00
Paulus Schoutsen
2ba237eac8 Merge pull request #1134 from fabaff/icons
Add icon
2016-02-05 07:33:31 -08:00
Fabian Affolter
6bf4532608 Add icon 2016-02-05 13:08:17 +01:00
pavoni
2622cf2e53 Use available, remove state, improve true,false tests. 2016-02-05 11:18:50 +00:00
Paulus Schoutsen
a5db23afa4 Mock util.location by default 2016-02-04 22:26:02 -08:00
Paulus Schoutsen
2c4166b5f2 Update splunk.py 2016-02-04 22:06:27 -08:00
Paulus Schoutsen
8be9aaba4f Fix Chromecast discovery 2016-02-04 21:36:37 -08:00
Paulus Schoutsen
1b16d76c40 Merge pull request #1128 from miniconfig/splunk
Added a new component to log state changes to a Splunk instance using…
2016-02-04 20:58:12 -08:00
Paulus Schoutsen
1a6539ad41 Merge pull request #1110 from lukas-hetzenecker/feature-zwave-poll-and-scene
Z-Wave: Scene activation & Polling
2016-02-04 20:51:52 -08:00
Paulus Schoutsen
96066e94ab Merge pull request #1122 from molobrakos/tellduslive
reworked telldus live support
2016-02-04 20:46:23 -08:00
nkgilley@gmail.com
78e758925b remove commented lines. 2016-02-04 18:42:38 -05:00
nkgilley@gmail.com
19fc48f4a0 use raw regex 2016-02-04 18:39:09 -05:00
nkgilley@gmail.com
d469970e5a Speedtest.net component 2016-02-04 18:21:37 -05:00
Erik
50a9b3a7c0 reworked telldus live support 2016-02-05 00:07:12 +01:00
miniconfig
ab837f9070 Added a new component to log state changes to a Splunk instance using the HTTP Event Collector 2016-02-04 16:13:55 -05:00
Paulus Schoutsen
6149e509c3 Merge pull request #1127 from molobrakos/timedate
provide default icon
2016-02-04 13:04:09 -08:00
Erik
f3b74079e0 provide default icon 2016-02-04 21:55:22 +01:00
Philip Lundrigan
c580953bd8 Fix MQTT sensor 2016-02-04 12:38:48 -07:00
Philip Lundrigan
fc3741911c Fix problem with field type conflict in influxdb 2016-02-04 12:38:48 -07:00
Lukas Hetzenecker
2589e78e84 Z-Wave: This small refactor adds the following features:
* The poll interval got fixed and the poll intensity gets configurable in the settings
* Activated scenes now fire an event
2016-02-04 19:54:43 +01:00
pavoni
ced380f0cd Remove unneeded entity_id check and blank lines. 2016-02-04 17:24:38 +00:00
Paulus Schoutsen
a33f1c61e5 Merge pull request #1108 from lukas-hetzenecker/regression-zwave-light
Z-Wave Regression: Fix state attributes of lights and switches.
2016-02-03 21:25:13 -08:00
Lukas Hetzenecker
8cf5ca0ba8 Regression: The device specific attributes of ZWave devices got lost.
Light and ZWaveDeviceEntity both have overwritten the property state_attributes
This includes the device specific attributes in the state_attributes again
2016-02-04 02:12:33 +01:00
pavoni
b20d3f8b3a Update docstrings. 2016-02-03 23:23:19 +00:00
Paulus Schoutsen
1f34b3586e Merge pull request #1117 from philipbl/influx_ssl
Add ability to specify SSL for InfluxDB connection
2016-02-03 13:33:08 -08:00
Paulus Schoutsen
37dadd1ae0 Merge pull request #974 from sdague/domains
Add recording of domain to state tables
2016-02-03 12:26:31 -08:00
Paulus Schoutsen
fac8d4b969 Merge pull request #1115 from sdague/test
add pytest-timeout to test runs
2016-02-03 12:24:35 -08:00
Sean Dague
efcba8f1ca add pytest-timeout to test runs
This adds a default 30 second timeout on every test method so that
deadlocks or broken threads are move obvious in travis. It also passes
-v by default to make things a little more verbose on where things
fail when they are failing.
2016-02-03 15:13:30 -05:00
Sean Dague
abc253c4c5 implement get_significant_states
This adds a new function to history module which returns significant
states. For most domains this is the list of state changes. For the
thermostat domain this also includes attribute changes, so that
changes in the current_temperature are exposed to the graphing layer.

Closes #881
2016-02-03 15:05:43 -05:00
Sean Dague
3d00735341 Add recording of domain to state tables
Some domains, like thermostat, need all state records, not just state
change ones, to provide accurate graphs. This introduces a new db
migration which adds a 'domain' column to all states so that is a fast
query.

Indexes were added to help with query performance.

This includes a data migration which post-date populates domain. On
large HA dbs this might take real time, as it has to touch every state
row. 100 MB db (91k states) updated in a couple of seconds on my
reasonably fast server. Be forewarned.

This is part of bug #881
2016-02-03 15:05:43 -05:00
Paulus Schoutsen
ce75c590b1 Merge pull request #1109 from lukas-hetzenecker/bugfix-zwave-fibaro-wall-plug
Z-Wave: Bugfix for Fibaro Wall Plug component
2016-02-03 08:34:06 -08:00
pavoni
6e6c3c5cd5 Tidy. 2016-02-03 14:30:58 +00:00
pavoni
5521096c02 Add actions. 2016-02-03 14:29:25 +00:00
Fabian Affolter
356013118d Update docstrings 2016-02-03 15:13:53 +01:00
pavoni
9a9dbcfaea Refactor, support template logic values, add tests. 2016-02-03 13:16:13 +00:00
Lukas Hetzenecker
1c33e01b99 styleguide fix 2016-02-03 13:03:01 +01:00
Lukas Hetzenecker
d09837fef6 Zwave: This is a bugfix for the Fibaro Wall Plug component
As discussed here ( https://www.domoticz.com/forum/viewtopic.php?f=6&t=5661 ) this components reports two different power consumption values.
Unfortunately only one of them is correct. Both of them map to the exactly same object id.
This bugfix gets rid of the incorrect one.
2016-02-03 12:44:11 +01:00
Paulus Schoutsen
f5e736d271 Merge pull request #1105 from balloob/disable-location-in-tests
Disable location queries
2016-02-02 21:38:20 -08:00
Paulus Schoutsen
61630783f1 Disable location queries 2016-02-02 21:33:59 -08:00
Paulus Schoutsen
077797ac4f Merge pull request #1086 from carlosmgr/dev
update SSH for aruba device tracker
2016-02-02 18:33:49 -08:00
Paulus Schoutsen
b14f7f7ed0 Merge pull request #1099 from balloob/sensor_template_startup_error
Sensor template startup error
2016-02-02 18:32:09 -08:00
carlosmgr
3d695405b7 pep8 2 time 2016-02-03 00:03:50 +00:00
carlosmgr
55932b048e fix pep8 2016-02-02 23:54:32 +00:00
Fabian Affolter
b19fbd8e72 Update docstrings 2016-02-03 00:35:53 +01:00
Fabian Affolter
635369ad65 Update docstrings 2016-02-03 00:23:59 +01:00
Fabian Affolter
bd8881cbe1 Add icon 2016-02-03 00:12:01 +01:00
Fabian Affolter
847e92f57a Update docstrings 2016-02-03 00:01:26 +01:00
Fabian Affolter
5cea8fda9f Update link to docs and add docstrings 2016-02-02 23:55:44 +01:00
carlosmgr
7f87df20c2 ssh aruba 2016-02-02 22:40:04 +00:00
carlosmgr
e91c8e4143 ssh aruba.py
req pexpect
2016-02-02 21:49:11 +00:00
carlosmgr
cd00ff8b56 Merge remote-tracking branch 'upstream/dev' into dev 2016-02-02 20:07:31 +00:00
Philip Lundrigan
018329b12b Add ability to specify ssl 2016-02-02 12:58:38 -07:00
pavoni
a955f3db08 WIP commit - template state working, on / off still to do. 2016-02-02 19:25:17 +00:00
pavoni
d344defc7e Switch to warning. 2016-02-02 16:26:17 +00:00
Paulus Schoutsen
2da422fd77 Merge pull request #1098 from balloob/media-player-test
Clean up and test media player
2016-02-02 08:09:40 -08:00
pavoni
93a38d39ef Add test for missimng attributes. 2016-02-02 14:15:06 +00:00
pavoni
3aad223c95 Change to warning if attributes missing. 2016-02-02 14:14:29 +00:00
Ryan Kraus
1a5d18fd66 Merge pull request #1012 from balloob/restart-service
Restart service
2016-02-02 07:15:40 -05:00
Paulus Schoutsen
e7e540d4bb Clean up and test media player 2016-02-02 00:31:36 -08:00
Paulus Schoutsen
35613d7fbf Merge pull request #1097 from molobrakos/add-test
add test for unsafe yaml
2016-02-02 00:22:19 -08:00
Erik
00d1cab091 add test for unsafe yaml 2016-02-02 08:41:18 +01:00
Paulus Schoutsen
26efaa91a3 Merge pull request #1090 from balloob/fix_sensor_template_entity_id
Fix bug in sensor.template entity_id
2016-02-01 21:21:57 -08:00
Paulus Schoutsen
3c37ecc477 Merge pull request #1091 from TangoAlpha/dev
Improvements to device detection
2016-02-01 21:21:15 -08:00
Paulus Schoutsen
274aaabd93 Merge pull request #1094 from balloob/cast-multi-room
No longer ignore ports for Chromecasts
2016-02-01 21:16:50 -08:00
Paulus Schoutsen
c8bfd27182 No longer ignore ports for Chromecasts 2016-02-01 21:07:33 -08:00
Tim
08ab7dba2c Fix whitespace 2016-02-02 00:21:15 +00:00
Tim
54cc35d729 Merge branch 'dev' of https://github.com/TangoAlpha/home-assistant into dev 2016-02-02 00:17:03 +00:00
Tim
031e7a4013 New liffylights release improves device detection
Increase device polling to 30 seconds
2016-02-02 00:15:38 +00:00
Paulus Schoutsen
41165695f0 Merge pull request #1071 from deisi/onewireupdate
Little improvement for the onewire platform
2016-02-01 15:26:22 -08:00
pavoni
9c33af60f2 Fix unreachable code! 2016-02-01 18:38:11 +00:00
pavoni
7c1241c1f8 Add another test, revise another. Improve coverage. 2016-02-01 18:30:39 +00:00
Tim
9caa4752a4 New liffylights release improves device detection
Increase device polling to 30 seconds
2016-02-01 18:29:43 +00:00
Malte Deiseroth
cb2e75befd removed trailing whitespace 2016-02-01 19:24:08 +01:00
pavoni
d54e10e54a Improve test coverage of error conditions. 2016-02-01 18:18:51 +00:00
pavoni
95748a6880 Generate entity id correctly, was using friendly_name. 2016-02-01 17:45:18 +00:00
Paulus Schoutsen
10a41a22dc Merge pull request #1084 from molobrakos/tellduslive
handle situation where no name is set yet for the sensor
2016-02-01 08:55:39 -08:00
Erik
ac0b6ca50c handle situation where no name is set yet for the sensor 2016-02-01 17:42:08 +01:00
Paulus Schoutsen
a0f6f3ac22 Merge pull request #1085 from molobrakos/yaml_safe_load
use yaml safe loader
2016-02-01 08:15:32 -08:00
Paulus Schoutsen
d9aff0c76d Merge pull request #1089 from balloob/yr
Added and fixed yr tests
2016-02-01 08:11:18 -08:00
Daniel
5005b20122 Added and fixed yr tests 2016-02-01 15:50:17 +01:00
carlosmgr
b3ef2bd2d9 Update aruba.py 2016-02-01 12:23:20 +00:00
Fabian Affolter
e29a2fa45a Fix typo 2016-02-01 11:49:44 +01:00
Fabian Affolter
395743005a Add link to docs, new docstrings, and update docstrings 2016-02-01 11:47:09 +01:00
Fabian Affolter
8de56bc8e2 Fix docstrings 2016-02-01 11:31:27 +01:00
Paulus Schoutsen
79b6269aa2 Merge pull request #1083 from balloob/fix-requirements
Fix gen_requirements_all
2016-02-01 00:00:51 -08:00
Paulus Schoutsen
525b206e1b Fix gen_requirements_all 2016-01-31 23:55:02 -08:00
Paulus Schoutsen
2f4e40db27 Merge pull request #1076 from MartinHjelmare/add-entity-online-prop
Fix 'unavailable' entity
2016-01-31 17:26:12 -08:00
MartinHjelmare
38c9f7a37a Fix 'unavailable' entity
* Report friendly_name, icon and customized attributes for 'unavailable'
  entities.
2016-02-01 02:16:56 +01:00
Paulus Schoutsen
c725f7883a Merge pull request #1063 from stefan-jonasson/samsungtv
Added a new media_player platform for controlling Samsung TVs
2016-01-31 16:57:11 -08:00
Paulus Schoutsen
10f79ab45d Merge pull request #1073 from MartinHjelmare/add-entity-online-prop
Add new 'available' property to entity.py
2016-01-31 15:59:28 -08:00
MartinHjelmare
455593017d Add new 'available' property to entity.py
* Add 'available' property. Return True by default.
* Use new property in update_ha_state(). If available is False, set
  state to 'unavailable', through constant.
* Add STATE_UNAVAILABLE constant 'unavailable' in const.py.
* Fix docstrings in entity.py and const.py, according to PEP257.
  Ignore D203 and D105.
2016-01-31 23:58:19 +01:00
Malte Deiseroth
d6b19aae48 - check for reasonable temperature values
- round temperature to one digit
2016-01-31 22:56:48 +01:00
Paulus Schoutsen
6519333e1d Merge pull request #1070 from balloob/input-select
Add input_select component
2016-01-31 13:44:32 -08:00
Paulus Schoutsen
41919e7339 Update frontend for input_select 2016-01-31 13:39:50 -08:00
Stefan Jonasson
1c10f218de Fixed duplicate import statements and made use of the config_helper 2016-01-31 22:17:00 +01:00
Paulus Schoutsen
96710ad410 Add input_select component 2016-01-31 12:52:51 -08:00
Paulus Schoutsen
c95c3d9198 Update frontend with weblink support 2016-01-31 12:00:45 -08:00
Stefan Jonasson
5719743ec7 Fixed .coveragerc and requirements_all.txt 2016-01-31 20:02:51 +01:00
Per Sandström
e2e8d4276f Merge pull request #1069 from persandstrom/vsure0.5.0
vsure 0.5.0
2016-01-31 19:33:09 +01:00
Per Sandström
3f03fefd35 vsure 0.5.0 2016-01-31 19:23:53 +01:00
Stefan Jonasson
2dab815f90 Fixes imports, styles and other misstates 2016-01-31 19:12:00 +01:00
Paulus Schoutsen
6a4b63f807 Merge pull request #1056 from flavio/scsgate
Add support for the SCSGate device
2016-01-31 09:34:07 -08:00
Flavio Castelli
8eef978241 Add support for the SCSGate device
Support the SCSGate device. This will allow home-assistant to interact
with BTicino/Legrand MyHome system.

Signed-off-by: Flavio Castelli <flavio@castelli.me>
2016-01-31 18:30:43 +01:00
Paulus Schoutsen
1789a08d21 Merge pull request #1065 from kennedyshead/weblink
Weblink component
2016-01-31 09:20:17 -08:00
magnusknutas
de4dab74b1 Adding weblink component
Adding weblink component tests
2016-01-31 18:13:04 +01:00
Paulus Schoutsen
16b1529d14 Merge pull request #1059 from balloob/entity-component-enhancements
Add tests and custom interval for entity component
2016-01-31 09:03:55 -08:00
Paulus Schoutsen
0b8e097705 Remove unused environment util 2016-01-31 08:58:30 -08:00
Paulus Schoutsen
b21be63220 Merge pull request #1066 from TangoAlpha/dev
Update for new liffylights release
2016-01-31 08:32:51 -08:00
Tim
e6a8746dba Update requirements_all 2016-01-31 15:07:06 +00:00
Tim
1974eda51d Update for new liffylights release
Fix incorrect packet timeout/ack code causing flooding when no bulbs were online, which consumed all WorkerPool threads
2016-01-31 13:31:12 +00:00
Stefan Jonasson
bd475f5db1 Added a new media_player platform for controlling Samsung TVs with a lan interface.
Configured like this
 media_player:
  platform: samsungtv
  host: <IP OF TV>
  name: <Name of the tv>
2016-01-31 10:06:39 +01:00
Paulus Schoutsen
fce8815ab4 Support custom interval for platforms 2016-01-31 01:01:23 -08:00
Paulus Schoutsen
90e17fc77f Add tests for entity component 2016-01-31 01:01:23 -08:00
Paulus Schoutsen
6418634f3a Merge pull request #1049 from balloob/new-tests
Adding more unit tests
2016-01-30 23:32:34 -08:00
Ryan Kraus
a230d00ed0 Added test for Introduction component
This test may seem useless, but it is good to ensure that default
components don’t ever crash HASS.
2016-01-30 22:50:56 -05:00
Ryan Kraus
5fdbe5fd9a More tests for Binary Command Sensor
1. Added a test for detecting STATE_OFF
2. Fixed tests for detecting STATE_ON
2016-01-30 22:41:29 -05:00
Ryan Kraus
283d621e90 Added tests for Binary Command Sensor 2016-01-30 22:32:25 -05:00
Ryan Kraus
2d0004f46a Another test for for command sensor
Added a test for command sensors with bad configurations.
2016-01-30 22:16:22 -05:00
Ryan Kraus
6a08f14120 Additional tests for Command Sensor.
1. Moved template testing out of main test.
2. Added test for bad command.
2016-01-30 22:13:42 -05:00
Ryan Kraus
97e867052d Added tests for command sensor
Added tests to create and check basic functionality of command sensor.
2016-01-30 22:01:10 -05:00
Ryan Kraus
2651021461 Added test for entity customization
Added test for entity customization from configuration. Processes a
sample configuration to hide an entity, creates the entity, updates ha
state, and then verifies customization made it through.
2016-01-30 21:27:00 -05:00
Erik
4b253d17ba use yaml safe loader 2016-01-31 00:46:08 +01:00
Paulus Schoutsen
b7722ec452 Allow usage of words domain, service, call_id in service data 2016-01-30 15:18:26 -08:00
magnusknutas
fd6086a5d6 Testing logbook service 2016-01-30 15:18:26 -08:00
Paulus Schoutsen
3e35bc06fc Merge pull request #1055 from TangoAlpha/dev
Update to new release of liffylights
2016-01-30 12:56:22 -08:00
Tim
f76dee8a05 Update to new release of liffylights 2016-01-30 20:48:57 +00:00
Ryan Kraus
56ac4281c7 Better tear down of util/package tests
Explicitly removed temp directory at the end of util/package unit tests.
2016-01-30 14:39:17 -05:00
Ryan Kraus
b8e149fe7d Cleaned up universal MP tests
Changed all assertEquals in universal media player tests to have
assumed value first.
2016-01-30 14:38:27 -05:00
Ryan Kraus
4a8f55e630 Revised package util tests
The package util tests were revised to pull the external library
pyhelloworld3 from an internal source rather than external. This speeds
up tests, makes tests more reliable, and removes dependency on internet
connection.
2016-01-30 14:08:32 -05:00
Ryan Kraus
de61bcb80e Additional testing for logger component
Added an additional test for the logger component the validates the
filtering logic of the filters that were created during setup.
2016-01-30 13:23:35 -05:00
Ryan Kraus
4cc9606bcc Added test for logger component. 2016-01-30 13:03:46 -05:00
Ryan Kraus
8ac763c6f6 Added test for universal mp service routing.
Added tests to ensure that the Universal Media Player is routing
service calls correctly.
2016-01-30 12:26:28 -05:00
Ryan Kraus
6a75b524cb Removed unused private method from universal media player
The universal media player contained a private method that was replaced
by the update method. It was meant to be removed and wasn’t. This
commit removed that method.
2016-01-30 11:57:46 -05:00
Ryan Kraus
c1d057407b Fixed typo in universal media player test. 2016-01-30 11:53:15 -05:00
Ryan Kraus
c396dbb570 Added tests to check setup and config of universal media player. 2016-01-30 07:18:37 -05:00
Ryan Kraus
0631f5c59d Added tests for package utilities 2016-01-30 06:44:22 -05:00
Paulus Schoutsen
10f9c049bb Version bump to 0.13.0.dev0 2016-01-29 22:38:01 -08:00
Paulus Schoutsen
d0bcec12b9 Merge pull request #1001 from balloob/dev
0.12
2016-01-29 22:37:38 -08:00
Paulus Schoutsen
9fc62c1851 Version bump to 0.12 2016-01-29 22:33:46 -08:00
Paulus Schoutsen
23d88cd4ad Merge pull request #1047 from haraldnagel/dev
Fix #1046 by correcting platform name
2016-01-29 22:14:21 -08:00
Harald Nagel
86f433067c Fix #1046 by correcting platform name 2016-01-30 06:05:09 +00:00
Ryan Kraus
106c53abf1 Revised HASS Core test
Changed the HASS Core test that tested KeyboardInterrupt handling to
now test SIGTERM handling. KeyboardInterrupts are no longer handled in
the HASS application process as they are handled in the HASS parent
process. SIGTERM is the proper way to now stop HASS.
2016-01-29 22:42:39 -05:00
Paulus Schoutsen
75232c43ce Merge pull request #1044 from w1ll1am23/googlevoice
Google Voice SMS notification support
2016-01-29 19:32:23 -08:00
Ryan Kraus
b56369855a Cleaned up restart handling in __main__.py
1. Fixed logged message about SIGTERM binding failure.
2. Set to only restart HASS with an exit code of 100.
3. Fixed typo in comment.
2016-01-29 22:11:11 -05:00
William Scanlon
01a743c7d4 Log if target == NULL 2016-01-29 22:09:59 -05:00
William Scanlon
28f4283b40 Validate target 2016-01-29 22:04:02 -05:00
Ryan Kraus
a41b66bb94 Cleaned up block_till_stop in core.py
1. Removed handling of KeyboardInterrupt. This will no longer happen
now that HASS is run in a subprocess. The KeyboardInterrupt will not be
sent to the parent process which will send a SIGTERM to the HASS
process.
2. Fixed logger warning about not being able to bind to SIGTERM.
3. Removed check for Windows OSs when binding to SIGTERM. This check
was originally put in place when HASS was binding to SIGQUIT. SIGTERM
exists in NT OSs, so the check is no longer required.
3. Now returning exit code of 100 when requesting a restart. This will
allow the parent process to only restart HASS if it is specifically
requested and not just on any encountered crash.
2016-01-29 22:02:39 -05:00
William Scanlon
375faa9c91 Fixed style error 2016-01-29 21:53:06 -05:00
Paulus Schoutsen
ef132e4583 Add tests for color util 2016-01-29 18:44:21 -08:00
Paulus Schoutsen
05cbe54db3 Remove owntracks from coverage 2016-01-29 18:02:42 -08:00
Paulus Schoutsen
ae7697b900 Merge pull request #1037 from balloob/owntracks_mobile_beacons
Owntracks - mobile ibeacon tracking.
2016-01-29 18:01:31 -08:00
Martin Hjelmare
a8f7bc2324 Merge pull request #1034 from MartinHjelmare/refactor-s_v_types
Mysensors: Refactor s_types and v_types mapping
2016-01-30 01:04:06 +01:00
MartinHjelmare
9db0987e53 Refactor s_types and v_types mapping
To be able to handle new platforms with multiple used v_types but
single states, a new more strict mapping was required. Each s_type is
now mapped to its corresponding v_type(s) in a dict of lists.
2016-01-30 00:55:13 +01:00
pavoni
515307b404 Remove dev/null from build script. 2016-01-29 22:11:01 +00:00
pavoni
03e7ac2a0e Fix typo. 2016-01-29 22:11:00 +00:00
pavoni
c5cdf6d7cf Copy kwargs, remove traces. 2016-01-29 22:11:00 +00:00
pavoni
a3abd8bb08 Revise tracked beacon name. 2016-01-29 22:11:00 +00:00
pavoni
5a7e380396 Revise beacon name. Add debug. 2016-01-29 22:11:00 +00:00
pavoni
09ef2e1b8c Add docstring, remove trace. 2016-01-29 22:11:00 +00:00
pavoni
80d2f35cc5 First cut mobile beacon tracking. 2016-01-29 22:11:00 +00:00
William Scanlon
ad57f27989 Added test exclude in .coveragerc 2016-01-29 16:54:56 -05:00
William Scanlon
a6720f54b3 Fixed style errors 2016-01-29 16:48:01 -05:00
William Scanlon
aaf75c7e45 Added target support for googlevoice 2016-01-29 14:14:27 -05:00
Martin Hjelmare
c5de42e7b5 Merge pull request #1033 from MartinHjelmare/refactor-unit-of-measurement
Mysensors: Refactor unit of measurement
2016-01-29 18:21:15 +01:00
Paulus Schoutsen
d6bb6a0777 Merge pull request #1020 from kennedyshead/dev
Adding service for logbook
2016-01-29 09:19:34 -08:00
Paulus Schoutsen
f87c7d6732 Merge pull request #1023 from flyte/zigbee-pr
Add ZigBee integration and components.
2016-01-29 09:18:10 -08:00
MartinHjelmare
575e97a051 Refactor unit of measurement
* Add dict with map of units to v_types.
* Avoid numerous if, elif branches and return statements.
* Add custom unit decoupled from other units.
2016-01-29 18:11:58 +01:00
Flyte
902077d78b Catch ZigBee exceptions when communicating with the devices and log appropriate messages. 2016-01-29 16:45:49 +00:00
Flyte
c17a4fca80 ZigBee: Ensure correct entity types are used for each component. 2016-01-29 12:00:53 +00:00
Flyte
241a768983 ZigBee: Remove extraneous update_ha_state() usage and use it more appropriately for initial state update. 2016-01-29 11:33:15 +00:00
Flyte
72cca0a91a ZigBee: Handle case in which Serial port is unable to open 2016-01-29 10:48:15 +00:00
Greg Dowling
dd7a7f4c75 Merge pull request #1036 from balloob/owntracks_beacon2
Improve owntracks events, add support for stationary ibeacons.
2016-01-29 09:47:20 +00:00
pavoni
468a8a1013 Improve owntracks events, add support for stationary ibeacons. 2016-01-29 09:39:00 +00:00
magnusknutas
24d84dbb42 Added entity_id and domain 2016-01-29 08:13:46 +01:00
Paulus Schoutsen
893a14e8db Merge pull request #1035 from balloob/fix-imports
Fix imports and rename insteon to insteon_hub
2016-01-28 21:53:21 -08:00
Paulus Schoutsen
cbc6323438 Fix imports 2016-01-28 21:45:26 -08:00
Paulus Schoutsen
d6db00b55a Merge pull request #1022 from haraldnagel/dev
Move Insteon API KEY into configuration.yaml
2016-01-28 21:36:35 -08:00
Harald Nagel
eebb736bf8 Add ability to control dimmable sources 2016-01-29 04:36:40 +00:00
Harald Nagel
f192a15a8f Remove unnecessary try around import 2016-01-29 02:35:04 +00:00
William Scanlon
9ec44fbe32 Updated googlevoicesms version 2016-01-28 21:19:15 -05:00
William Scanlon
ffc06e8bcb pygooglevoice-sms support 2016-01-28 21:07:59 -05:00
William Scanlon
9c7b2ce9fd pygooglevoice-sms support 2016-01-28 21:07:16 -05:00
Paulus Schoutsen
1de7dcdb5f Merge pull request #1025 from molobrakos/yr-position
allow monitoring weather at other location than home
2016-01-28 08:49:48 -08:00
Erik
9e7886b909 allow monitoring weather at other location than home (such as summer house) 2016-01-28 17:16:02 +01:00
Flyte
4045fb6862 Fix import-before-install of xbee-helper dependency. 2016-01-28 13:44:37 +00:00
Flyte
dda4f84150 Add zigbee components. 2016-01-28 13:18:29 +00:00
magnusknutas
fda88f8fda logbook.log the name of the game 2016-01-28 09:51:05 +01:00
Harald Nagel
3c05c8d1db Use validate_config, watch for import exception 2016-01-28 05:55:36 +00:00
Harald Nagel
21ec435430 Move Insteon API KEY into configuration.yaml 2016-01-28 03:01:32 +00:00
magnusknutas
24893bc28d Less complex service setup 2016-01-27 18:03:37 +01:00
magnusknutas
403b9cbe3e And with template support 2016-01-27 17:37:15 +01:00
magnusknutas
8b0d19835c Cleanup 2016-01-27 17:32:57 +01:00
magnusknutas
c31522eea9 Logbook service 2016-01-27 17:27:55 +01:00
Paulus Schoutsen
ee33aa73e1 Merge pull request #1017 from fabaff/psutil-upgrade
Upgrade psutil to 3.4.2
2016-01-27 08:08:21 -08:00
Paulus Schoutsen
47498e4aa9 Merge pull request #1016 from fabaff/cpuinfo-upgrade
Upgrade py-cpuinfo to 0.1.8
2016-01-27 08:07:55 -08:00
Fabian Affolter
ef4661f1e6 Upgrade psutil to 3.4.2 2016-01-27 12:26:38 +01:00
Fabian Affolter
b4070cfb78 Upgrade py-cpuinfo to 0.1.8 2016-01-27 11:43:49 +01:00
Fabian Affolter
c750f16275 Update docstings 2016-01-27 09:34:14 +01:00
Fabian Affolter
2248c271fa Add link to docs 2016-01-27 09:25:44 +01:00
Fabian Affolter
87b33d5098 Move configuration details to docs 2016-01-27 09:23:44 +01:00
Fabian Affolter
cf7c06d307 Update docstring and fix typos 2016-01-27 09:21:21 +01:00
Fabian Affolter
70d95cb6aa Add link to docs 2016-01-27 09:08:04 +01:00
Fabian Affolter
2c151c6db9 Update docstring 2016-01-27 09:01:08 +01:00
Fabian Affolter
3fc5a60634 Add link to docs 2016-01-27 09:00:01 +01:00
Fabian Affolter
94d2f23cfc Add link to docs and remove configuration details 2016-01-27 08:08:04 +01:00
Fabian Affolter
4bd102ddf5 Add twitter docs 2016-01-27 08:08:04 +01:00
Fabian Affolter
232aa792f1 Add link to docs and update docstrings 2016-01-27 08:08:04 +01:00
Paulus Schoutsen
ce9f76a0be Add onewire to coverage 2016-01-26 23:07:01 -08:00
Paulus Schoutsen
f3f592cdec Merge pull request #982 from stefan-jonasson/dev
Updated the entity names for all z-wave devices.
2016-01-26 22:51:34 -08:00
Stefan Jonasson
1d2cd0811b Updated Imports.
ZWave modules now import the domain from the base domain.
2016-01-27 07:37:41 +01:00
Paulus Schoutsen
886b581d2a Merge pull request #1002 from kennedyshead/dev
Running periodic tasks
2016-01-26 21:42:06 -08:00
Paulus Schoutsen
88387d3123 Merge branch 'pr/78' into dev
Conflicts:
	homeassistant/const.py
2016-01-26 21:07:53 -08:00
Ryan Kraus
3534c975f3 Added missing CONF_ICON constant 2016-01-26 22:46:01 -05:00
Ryan Kraus
519abbbfa2 Better handling of second KeyboardInterrupt
Now the second KeyboardInterrupt will be cleanly handled by the parent
process.
2016-01-26 22:41:57 -05:00
Ryan Kraus
b596fa33d6 Implemented restart service
Implemented an OS and environment safe restart service. This works by
running Home Assistant in a child process. If the child process
terminates with an exit code > 0, HASS is restarted. SIGTERM and
KeyboardInterrupts to the parent process are forwarded to the child
process. KeyboardInterrupts will only be forwarded once. The second
KeyboardInterrupt will be handled by the parent.
2016-01-26 22:39:59 -05:00
Martin Hjelmare
14cd27aaa7 Merge pull request #1011 from MartinHjelmare/fix-unit-of-measurement
Fix unit of measurement
2016-01-27 03:40:50 +01:00
MartinHjelmare
2e175b88bc Fix unit of measurement
* Add version check in unit_of_measurement, to avoid error.
* Remove not needed metric check in unit_of_measurement.
* Add more value types to unit_of_measurement.
* Fix unit prefix
* Remove unused SCAN_INTERVAL variable.
2016-01-27 03:18:59 +01:00
Paulus Schoutsen
537a7789fd Merge pull request #1005 from fabaff/astral-upgrade
Updgrade to astral 0.9
2016-01-26 17:48:14 -08:00
Paulus Schoutsen
80d1ab78dd Merge pull request #1006 from fabaff/influxdb-upgrade
Upgrade influxdb to 2.11.0
2016-01-26 17:47:59 -08:00
Paulus Schoutsen
821238f889 Merge pull request #1007 from fabaff/telegram-upgrade
Upgrade python-telegram-bot to 3.2.0
2016-01-26 17:47:42 -08:00
Paulus Schoutsen
33a9ec0106 Merge pull request #1008 from fabaff/blockchain-upgrade
Upgrade blockchain to 1.2.1
2016-01-26 17:47:14 -08:00
Paulus Schoutsen
a8f0f313c8 Merge pull request #1009 from fabaff/docstrings
Update docstrings
2016-01-26 17:46:56 -08:00
Martin Hjelmare
6796219f37 Merge pull request #1010 from MartinHjelmare/fix-device-attr
Fix device_state_attributes
2016-01-27 02:43:34 +01:00
MartinHjelmare
1dae22a465 Fix device_state_attributes
* Return a dict with keys as the names of the enum members instead of
	the member values.
* This fixes a TypeError: unorderable types: int() < str()
2016-01-27 02:33:21 +01:00
Fabian Affolter
7aba78f96e Update docstrings 2016-01-27 00:08:06 +01:00
Fabian Affolter
06cf07b097 Upgrade blockchain to 1.2.1 2016-01-26 23:53:30 +01:00
Fabian Affolter
271af2c608 Upgrade python-telegram-bot to 3.2.0 2016-01-26 23:47:06 +01:00
Fabian Affolter
8c6ce217e6 Upgrade influxdb to 2.11.0 2016-01-26 23:45:39 +01:00
Fabian Affolter
5410a0c8f6 Updgrade to astral 0.9 2016-01-26 23:34:25 +01:00
Stefan Jonasson
1a422ecd5a Moved common z-wave node functionality to a common z-wave class 2016-01-26 22:11:27 +01:00
magnusknutas
6add5e387b Remove unused import 2016-01-26 21:41:12 +01:00
magnusknutas
ca070a36e3 Dont wrap '/int' parameters with tuple 2016-01-26 21:38:07 +01:00
magnusknutas
2c3a6e7905 Remove not needed log warning 2016-01-26 21:30:00 +01:00
magnusknutas
0a4e857901 And a test just to see if nothing works if not providing any vars 2016-01-26 21:21:54 +01:00
magnusknutas
d4b444823c Tests for time and a fix for wrong access of _LOGGER 2016-01-26 21:11:30 +01:00
magnusknutas
2382dffbf4 pushed test code :) fixed now 2016-01-26 20:49:51 +01:00
magnusknutas
33b0f4d05d Fixes bug in time trigger and adds test for ex. /two 2016-01-26 20:43:29 +01:00
Stefan Jonasson
5b6371ecda Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	homeassistant/components/light/zwave.py
#	homeassistant/components/switch/zwave.py
2016-01-26 20:31:42 +01:00
magnusknutas
6f1f8ffea0 Merge remote-tracking branch 'upstream/dev' into dev 2016-01-26 20:23:48 +01:00
magnusknutas
1f6f2de9c6 Sorry, I was wrong they are needed 2016-01-26 19:37:53 +01:00
Martin Hjelmare
b13e48bd71 Merge pull request #999 from MartinHjelmare/fix-not-adding-devices
Fix adding devices on the fly
2016-01-26 19:30:31 +01:00
magnusknutas
9a79ecf2d3 Remove warnings no longer needed (I think :D) 2016-01-26 19:25:41 +01:00
magnusknutas
ebd475b380 Unused import was the problem 2016-01-26 18:50:25 +01:00
magnusknutas
cff77a175d Year periodic test (just to trigger travis but should maybe be here anyway) 2016-01-26 18:44:41 +01:00
magnusknutas
726637b867 New and improved handling of the matching! Kudos to @balloob 2016-01-26 18:37:19 +01:00
MartinHjelmare
9117fa6eb8 Fix adding devices on the fly
Devices were not added without persistence enabled and restart of HA.
Node id was added to defaultdict(list) by mistake when checking if list
of defaultdict was empty.

* Fix adding devices in mysensors_callback.
* Change devices to regular dict.
2016-01-26 18:12:13 +01:00
magnusknutas
6ae57b5aaf Some warnings if input is wrong for periodic tasks 2016-01-26 17:35:12 +01:00
magnusknutas
e8e2814313 Warnings for not divisible settings 2016-01-26 17:30:55 +01:00
magnusknutas
a918be517d test past midnight support for hours 2016-01-26 17:13:18 +01:00
magnusknutas
ec5d88b98e hourly periodic task 2016-01-26 17:06:50 +01:00
magnusknutas
13fbefcdf8 Running periodic tasks 2016-01-26 10:28:31 +01:00
Stefan Jonasson
f4c9540a1b Updated teh entity_id generation
Entity ids will now look like this:
sensor.philio_technology_corporation_psm021_slim_multisensor_doorwindow_sensor_7
sensor.philio_technology_corporation_psm021_slim_multisensor_luminance_7
sensor.philio_technology_corporation_psm021_slim_multisensor_motion_sensor_7
sensor.philio_technology_corporation_psm021_slim_multisensor_tamper_sensor_7
sensor.philio_technology_corporation_psm021_slim_multisensor_temperature_7

sensor.philio_technology_corporation_psm021_slim_multisensor_doorwindow_sensor_8
sensor.philio_technology_corporation_psm021_slim_multisensor_luminance_8
sensor.philio_technology_corporation_psm021_slim_multisensor_motion_sensor_8
sensor.philio_technology_corporation_psm021_slim_multisensor_tamper_sensor_8
sensor.philio_technology_corporation_psm021_slim_multisensor_temperature_8

And if there is several values of the same type in a node the instance id will be appended like this (three switches in the same device):
switch.fibaro_system_unknown_type0202_id1002_switch_9
switch.fibaro_system_unknown_type0202_id1002_switch_9_2
switch.fibaro_system_unknown_type0202_id1002_switch_9_3
2016-01-26 09:33:26 +01:00
Fabian Affolter
e72f61ce73 Update docstring 2016-01-26 09:11:04 +01:00
Paulus Schoutsen
4c056db3bb Fix Chrome url sync 2016-01-25 23:56:43 -08:00
Paulus Schoutsen
c10a86d1bf Merge branch 'master' into dev
Conflicts:
	homeassistant/const.py
2016-01-25 22:58:06 -08:00
Paulus Schoutsen
b97de5cef6 Merge pull request #1000 from balloob/view-url-sync
Update frontend with view url sync
2016-01-25 22:54:00 -08:00
Paulus Schoutsen
4233c0bc66 Update frontend with view url sync 2016-01-25 22:47:13 -08:00
Paulus Schoutsen
b13008201e Fix lint issue 2016-01-25 21:31:21 -08:00
Paulus Schoutsen
125ad8630d Add views to demo 2016-01-25 21:27:36 -08:00
Paulus Schoutsen
5c3ad5d4c0 Update frontend 2016-01-25 17:57:33 -08:00
Paulus Schoutsen
414aa8563d Merge pull request #930 from TangoAlpha/dev
Add LIFX bulb support
2016-01-25 17:51:47 -08:00
happyleavesaoc
d08a181c72 Merge pull request #994 from happyleavesaoc/orvibo_bump
Orvibo version bump
2016-01-25 19:34:21 -05:00
happyleavesaoc
80c6bf6744 bump orvibo version 2016-01-25 16:40:27 -05:00
Tim
b1ba792715 Brightness from HA overrides brightness from HSV conversion 2016-01-25 21:19:27 +00:00
Per Sandström
b99f6c1a46 Merge pull request #995 from persandstrom/vsure0.4.8
update python-verisure to version 0.4.8
2016-01-25 22:04:02 +01:00
Tim
1397f9e588 Fix logging typo 2016-01-25 20:58:10 +00:00
Tim
bb7f92330d Update liffylights version 2016-01-25 20:53:21 +00:00
Per Sandström
7cbd780748 update vsure version 2016-01-25 21:39:41 +01:00
Tim
784fea2d56 Update for new liffylights version 2016-01-25 19:08:48 +00:00
Tim
97f0425252 Update requirements_all 2016-01-25 15:20:23 +00:00
Tim
11120a8743 Fix liffylights import 2016-01-25 15:19:50 +00:00
Tim
8009542b3e Add extra debugging
Add duration to power on
2016-01-25 13:30:52 +00:00
Tim
32cfa6998c Update requirements_all 2016-01-25 12:13:24 +00:00
Tim
d10a5cf5e9 Update to v0.8.3 of liffylights 2016-01-25 11:54:41 +00:00
Tim
4089a7a0d3 Update requirements_all 2016-01-25 10:02:03 +00:00
Tim
5a926913d3 Update to v0.6 of liffylights 2016-01-25 10:00:15 +00:00
Paulus Schoutsen
6c91831baa Hide groups when they are views or auto defined 2016-01-24 23:45:06 -08:00
Tim
069dafa3a5 Update requirements_all 2016-01-25 07:38:37 +00:00
Paulus Schoutsen
4abc5c97cd Merge pull request #988 from auchter/thermostat-fan
Add service to control a thermostat's fan
2016-01-24 23:24:32 -08:00
Paulus Schoutsen
bb3dd47088 Merge pull request #992 from balloob/sections
Add support for sections in the frontend [Fixes #100705168]
2016-01-24 22:58:27 -08:00
Paulus Schoutsen
f6c53896e3 Allow groups to be used as views 2016-01-24 22:54:45 -08:00
Paulus Schoutsen
ad2e2d916b Merge pull request #979 from rmkraus/automation-decorator
Automation Decorator for custom components
2016-01-24 21:22:19 -08:00
Ryan Kraus
8406f81811 Removed decorator callback
The decorator callback was not actually necessary so it was removed and
replaced with a partial function instead.
2016-01-25 00:14:16 -05:00
Ryan Kraus
bcdfc555e0 Removed service decorator from event decorators 2016-01-24 23:09:09 -05:00
Ryan Kraus
3b89102338 Fixed lint issue from merge
extract_entity_ids from the service helpers was overwriting the service
decorator with one of its attributes. This was fixed.
2016-01-24 23:00:43 -05:00
Ryan Kraus
60dd2d441d Merge remote-tracking branch 'balloob/dev' into automation-decorator
# Conflicts:
#	homeassistant/helpers/service.py
#	tests/helpers/test_service.py
2016-01-24 22:51:00 -05:00
Ryan Kraus
5830da63b1 Moved service decorator to service helpers
Moved the service decorator to the service helpers module and moved the
associated tests.
2016-01-24 22:46:30 -05:00
Tim
50561ffe97 Fix long line 2016-01-25 03:39:13 +00:00
Tim
74e8446556 Bump version of liffylights 2016-01-25 03:34:24 +00:00
Tim
d94db5388c Add preliminary support for transition time 2016-01-25 03:32:55 +00:00
Ryan Kraus
f66aeb2e73 Added event helper tests
1. Added tests for all event decorators
2. Added tests for sunrise and sunset event helpers
2016-01-24 22:23:56 -05:00
Ryan Kraus
54b82ecd91 Lint fixes and additions to event decorators
1. service decorator was overwriting the function name with one of its
arguments.
2. Accidentally left an extra argument in track_sunrise.
3. Added track_utc_time_change decorator.
2016-01-24 21:06:15 -05:00
Ryan Kraus
2fa98167c2 Updated example.py component
Cleaned up example.py to better handle failed loads.
2016-01-24 20:05:40 -05:00
Ryan Kraus
57725136c0 Many updates regarding event decorators
1. Added HASS to the arguments for callbacks that are created with
event decorators.
2. Added a service decorator.
3. Updated example.py in the example config to use the event decorators.
2016-01-24 19:52:22 -05:00
Ryan Kraus
40dbeb0b60 Another revision on event decorators
This revision of event decorators removes much of the complexity. The
decorated functions are no longer wrapped with a class that tracks
last_run, etc. Bootstrap now gives hass to the event_decorators module
before initializing components so the decorators no longer require
activation.
2016-01-24 17:46:05 -05:00
Ryan Kraus
ef92940ffb A few lint fixes to event decorators. 2016-01-24 16:45:35 -05:00
Erik
e7865c1d67 Merge pull request #990 from molobrakos/squeezebox-fix
bugfix for squeezebox cover art regression
2016-01-24 21:56:21 +01:00
Ryan Kraus
02e634c6a2 Fixed bugs to allow HA to boot again
1) helpers/event should not import the sun component unless it is
requested. This prevents circular import.
2) fixed import typo in bootstrap
2) bootstrap cannot import event_decorators until it is needed because
this leads to a circular import.
2016-01-24 15:55:47 -05:00
Ryan Kraus
0f937cad74 Initial pass at event decorators
Created event decorators for custom components. Decorators were created
for the events: track_state_change, track_sunrise, track_sunset, and
track_time_change.
2016-01-24 15:28:09 -05:00
Ryan Kraus
81dd1515ae Moved sunrise/sunset tracking to helpers
The automation component contained some very handy and generic
functions for tracking sunset and sunrise. This was moved to
helpers/event.py.
2016-01-24 15:07:09 -05:00
Ryan Kraus
a65d0f0549 Reverting Automation decorator in favor of a new approach. 2016-01-24 14:44:48 -05:00
Michael Auchter
881c82c2df nest: implement fan control 2016-01-24 12:47:21 -06:00
Michael Auchter
df94c909f7 thermostat: add service to control fan mode 2016-01-24 12:47:21 -06:00
Michael Auchter
a0ed469aa2 thermostat: move fan attribute up to thermostat 2016-01-24 12:47:20 -06:00
Michael Auchter
afa4fc4ef5 thermostat: split up services 2016-01-24 12:47:20 -06:00
Paulus Schoutsen
df450c3d1f Merge pull request #987 from balloob/update-pynetgear
Update version pynetgear
2016-01-24 09:46:23 -08:00
Paulus Schoutsen
dc5d652d31 Update version pynetgear 2016-01-24 09:43:06 -08:00
Paulus Schoutsen
e4fe19fff0 Merge pull request #986 from turbokongen/dev
Small errorlog fix.
2016-01-24 08:54:54 -08:00
John Arild Berentsen
f6f3f54228 flake8 complaint fix 2016-01-24 16:43:24 +01:00
John Arild Berentsen
6df67d2852 Send correct command to pyrfxtrx
Although it seems to work with send_on, it throws an logged error. Using correct command against pyrfxtrx removes this error.
2016-01-24 16:37:38 +01:00
Tim
2411d1f2c8 Fix wrongly generated requirements 2016-01-24 10:07:56 +00:00
Tim
9f6a1c75fa Fix wrongly generated requirements 2016-01-24 10:01:23 +00:00
Stefan Jonasson
1842e5909e Updated the entity names for all z-wave devices.
Z-Wave have a unique node id, this is now added to the entity name.

This is a change will break old configs.  The Z-Wave entity_id will have to be updated in configurations.

The reason for this change is that the old behavior created duplicate entity_ids if you have several similar devices. The order devices is included is not consistent so when the service was restarted the entity ids could change and the configuration for entities will be invalid.

There was also inconsistencies between the naming for sensors and switches.
(cherry picked from commit 33a78df)
2016-01-24 10:20:51 +01:00
John Arild Berentsen
6f31aacb90 Merge pull request #1 from balloob/dev
Updating base
2016-01-24 09:58:51 +01:00
Paulus Schoutsen
e541b9ba77 Merge pull request #981 from balloob/ordered-yaml
Load YAML config into an ordered dict
2016-01-23 23:04:41 -08:00
Paulus Schoutsen
53484e46a3 Move generate_entity_id to entity helpers 2016-01-23 23:00:46 -08:00
Paulus Schoutsen
de79a46d43 Move extract_entity_id to service helpers 2016-01-23 22:57:14 -08:00
Paulus Schoutsen
bc19ef66bf Move split_entity_id to helpers 2016-01-23 22:49:49 -08:00
Paulus Schoutsen
de08f0afaa Load YAML config into an ordered dict 2016-01-23 22:41:01 -08:00
Tim
706bbeae16 Add to .coveragerc 2016-01-24 02:17:52 +00:00
Paulus Schoutsen
e5497d89f4 Merge pull request #980 from balloob/upgrade-cast
Upgrade PyChromecast version
2016-01-23 18:15:12 -08:00
Paulus Schoutsen
048ec0aa66 Merge pull request #964 from balloob/passive-zones
Allow passive zones
2016-01-23 18:15:06 -08:00
Paulus Schoutsen
03ed85b0a7 Merge pull request #971 from trollkarlen/smtp-fix
smtp: make smtp component thread safe
2016-01-23 18:08:03 -08:00
Paulus Schoutsen
9d92707fd7 Merge pull request #973 from turbokongen/dev
Added support for Dimming with lights in Rfxtrx module
2016-01-23 18:03:37 -08:00
Paulus Schoutsen
90c392e270 Upgrade PyChromecast version 2016-01-23 17:29:40 -08:00
Tim
6cb6cbfefd Update requirements 2016-01-24 01:18:18 +00:00
Tim
6d2bca0fd1 Import 3rd party library inside method 2016-01-24 01:13:51 +00:00
Tim
99286391e1 Fixes for lint 2016-01-24 01:00:02 +00:00
Tim
711f2da496 Update liffylights version 2016-01-24 00:43:50 +00:00
Ryan Kraus
fbd68b6f89 Created automation decorator prototype
Created an initial iteration of an Automation decorator.
2016-01-23 19:39:59 -05:00
Paulus Schoutsen
85ebd0ab59 Merge pull request #977 from sdague/dev
fix typo in log message
2016-01-23 14:27:37 -08:00
Tim
58034219b6 Bump version liffylights 2016-01-23 22:23:46 +00:00
Tim
17f5a466d9 Separate LIFX code and HA component 2016-01-23 22:14:57 +00:00
Sean Dague
90ca6a0998 fix typo in log message
The plex component logs an htts url, which is confusing to people, as
they think something is broken, when it is not.

Closes #959
2016-01-23 16:06:50 -05:00
Erik
ec2b433733 should be _id 2016-01-23 18:55:43 +01:00
Erik
492c4b7f00 style 2016-01-23 18:14:03 +01:00
Erik
b3beb9f3c9 style 2016-01-23 18:08:54 +01:00
Erik
837e7affa7 only query artwork by track_id if id is available (7.7 vs 7.9 version issue?) 2016-01-23 17:48:14 +01:00
turbokongen
6d527842dd Another flake8 fix too long line 2016-01-23 12:14:00 +01:00
turbokongen
e30915eb2c flake8 complaint fix 2016-01-23 12:08:21 +01:00
turbokongen
43e2b58f20 Fixing of various test errors 2016-01-23 12:00:03 +01:00
turbokongen
d3c6c892a8 Small intendation fix 2016-01-23 11:50:09 +01:00
turbokongen
a63edcf505 Added support for Dimming with lights in Rfxtrx module 2016-01-23 11:18:11 +01:00
Robert Marklund
0e7088ce3b smtp: make smtp component thread safe
Also fix so it does not require ip, port, username and password when using local smtp server.
Add debug config.

Signed-off-by: Robert Marklund <robbelibobban@gmail.com>
2016-01-23 10:43:10 +01:00
Paulus Schoutsen
0042e7725d Merge pull request #967 from HydrelioxGitHub/NetAtmo-icons
Add icons to NetAtmo sensors
2016-01-22 12:56:43 -08:00
hydreliox
613f8d0bd2 Add icons to NetAtmo sensors 2016-01-22 21:15:07 +01:00
Greg Dowling
61ca1ab2c1 Merge pull request #948 from balloob/sensor_template
First draft of sensor.template.
2016-01-22 16:49:49 +00:00
pavoni
ad62591f43 Change error state to be 'error' rather than 'unknown', trace error. 2016-01-22 16:30:02 +00:00
Paulus Schoutsen
5ba33bc40e Merge pull request #950 from michaelkuty/dev
Add statsd component.
2016-01-22 07:41:04 -08:00
Michael Kutý
143b08d661 Add statsd component. 2016-01-22 16:18:15 +01:00
pavoni
87a9fd8252 Handle race condition on startup. 2016-01-22 11:30:04 +00:00
pavoni
b1f7b5c6d7 Tidy, add test for ValueException logic. 2016-01-22 09:37:20 +00:00
Paulus Schoutsen
bb97af1504 Allow passive zones 2016-01-22 00:00:36 -08:00
Paulus Schoutsen
9a092654e9 Merge pull request #962 from FreekingDean/dev
Adding Support for Insteon Hub
2016-01-21 23:31:16 -08:00
Dean
d59b98ee2b Added Insteon Support 2016-01-22 02:28:36 -05:00
Paulus Schoutsen
6bbbbd9e17 Update mdi icons 2016-01-21 23:07:43 -08:00
Paulus Schoutsen
9fbedd8b5f Merge pull request #963 from balloob/scrip-service-helper
Script: use config service helper
2016-01-21 22:55:28 -08:00
Paulus Schoutsen
a91163877f Script: use config service helper 2016-01-21 22:47:25 -08:00
Paulus Schoutsen
0acce86596 Merge pull request #958 from balloob/itunes-updates
iTunes Updates
2016-01-21 18:44:55 -08:00
William Scanlon
c95b03f240 Fixed style 2016-01-21 18:32:10 -08:00
William Scanlon
56ce3e5f5a Wink siren support 2016-01-21 18:32:10 -08:00
pavoni
8b5751ad44 Merge branch 'dev' into sensor_template 2016-01-21 23:17:53 +00:00
pavoni
c615272c06 Tidy. 2016-01-21 23:17:19 +00:00
Jon Maddox
a3b8122707 not using these 2016-01-21 17:54:26 -05:00
Jon Maddox
682e3460e0 use custom material icons to represent speaker state 2016-01-21 17:45:30 -05:00
Jon Maddox
71dbd10b39 let port be optional 2016-01-21 17:18:52 -05:00
Paulus Schoutsen
7f143bcdf9 Merge pull request #957 from trollkarlen/yr.no-fix
yr.no: fix some bugs in the component
2016-01-21 13:33:36 -08:00
Robert Marklund
f19a46dcfe yr.no: fix some bugs in the component
Someone forgot some in:s and ()
Also added windGust sensor.

Signed-off-by: Robert Marklund <robbelibobban@gmail.com>
2016-01-21 22:04:18 +01:00
Paulus Schoutsen
625f69443a Merge pull request #953 from trollkarlen/kodi-fix
kodi: remove traceback on state check
2016-01-21 12:18:28 -08:00
Robert Marklund
0bdd293572 kodi: remove traceback on state check
If the computer is sleeping that are running xbmc then
the traceback is printed in the log all the time.
Keep the traceback in debug mode of the module if needed.

Signed-off-by: Robert Marklund <robbelibobban@gmail.com>
2016-01-21 20:59:58 +01:00
pavoni
f8072aae68 Merge branch 'dev' into sensor_template 2016-01-21 18:34:13 +00:00
pavoni
92afcae9be Add test. 2016-01-21 18:31:44 +00:00
pavoni
a6f37c032b Revise to not need dependencies (or quoting)! 2016-01-21 17:35:33 +00:00
pavoni
e66d15b71d First drafy of sensor.template. 2016-01-21 16:31:23 +00:00
Paulus Schoutsen
1098194a89 Merge pull request #937 from trollkarlen/sonos-multicast
sonos: add hosts and interface_addr to sonos config
2016-01-21 07:30:40 -08:00
Paulus Schoutsen
66d23cd15f Merge pull request #945 from zmrow/fix-exception-in-openweather
Fix #863 - Added a check for good pull from OWM and return if the object is None
2016-01-20 19:57:57 -08:00
zmrowicki@hotmail.com
c3a1193ef9 Fix #863 - Added a check for good pull from OWM and return if the object is None 2016-01-20 19:36:33 -08:00
Paulus Schoutsen
ec2d9af8dc Merge pull request #943 from trollkarlen/influxdb-fix
influxdb: fix the need of admin to run
2016-01-20 19:22:40 -08:00
Paulus Schoutsen
f0e44728d7 Merge pull request #944 from HydrelioxGitHub/twitter_notify
Add Twitter as a notification platform
2016-01-20 19:21:38 -08:00
hydreliox
f67747456f Clean some errors 2016-01-21 02:14:11 +01:00
hydreliox
f6017a17b2 Add Twitter as a notification platform 2016-01-21 02:02:32 +01:00
Robert Marklund
89aa3cbc62 influxdb: fix the need of admin to run
Use select statment to show if db exits instead of
'SHOW DATABASES' which cant be run by a non admin user.
See https://github.com/influxdata/influxdb/issues/4785 for more info.

Also influxdb dont like empty writes('') so ignore state changes of that kind,
this happens on startup of home assistant.

Signed-off-by: Robert Marklund <robbelibobban@gmail.com>
2016-01-21 00:19:16 +01:00
Robert Marklund
543190dfb0 sonos: add hosts and interface_addr to sonos config
Config can now specify one or more hosts to connect and
also a interface_addr to multicast on if multiple interfaces exists.

Signed-off-by: Robert Marklund <robbelibobban@gmail.com>
2016-01-20 22:55:08 +01:00
Paulus Schoutsen
fdc8c45a69 Merge pull request #940 from balloob/remove_sensor_state
Remove sensor state
2016-01-20 12:52:23 -08:00
pavoni
d2d421ca8f Remove ghost debug code. 2016-01-20 20:02:03 +00:00
pavoni
7ad5b3a17b Fix bug related to maker_param types 2016-01-20 19:13:29 +00:00
Paulus Schoutsen
c8dd9696b4 Merge pull request #939 from molobrakos/squeezebox-fix
artwork fixes
2016-01-20 09:16:32 -08:00
Erik
58ef69b95d less hacky way of getting unique cover art 2016-01-20 16:31:51 +01:00
pavoni
0de9229d75 More tidying. 2016-01-20 11:25:20 +00:00
pavoni
f4c3ac2a62 Tidy 2016-01-20 11:19:00 +00:00
pavoni
6c5ceaf686 Remove sensor state from switch and wemo 2016-01-20 11:06:08 +00:00
Erik
54f65ae87d 1) artwork_url might be a relative url (such as /imageproxy). in that case, join it with the base url. note: urllib.parse.urljoin will handle case when the artwork url is absolute. 2) artwork would not be replaced in the user interface because the url did not change between tracks (http://.../cover.jpg). solved by appending internal hash of the media title to the url to force reload 2016-01-20 10:57:39 +01:00
Paulus Schoutsen
4f2dc3cc2a Merge pull request #934 from balloob/mqtt-protocol
Allow forcing MQTT protocol v3.1
2016-01-19 20:20:04 -08:00
Paulus Schoutsen
a4ee2bd8ef Merge pull request #935 from balloob/0.11.1
0.11.1
2016-01-19 12:20:26 -08:00
MartinHjelmare
d4629a7efe Fix missing binary sensor types
* Add missing binary sensor types to sensor/mysensors.
* Remove unneeded pylint disable.
2016-01-19 12:13:34 -08:00
Paulus Schoutsen
441ae73344 Merge pull request #936 from MartinHjelmare/fix-mysensors-sensors
Fix missing binary sensor types
2016-01-19 12:11:33 -08:00
MartinHjelmare
9249dc6dd3 Fix missing binary sensor types
* Add missing binary sensor types to sensor/mysensors.
* Remove unneeded pylint disable.
2016-01-19 19:26:40 +01:00
Paulus Schoutsen
4c4539caff Version bump to 0.11.1 2016-01-19 09:12:03 -08:00
Paulus Schoutsen
4c0ff0e0d0 Allow forcing MQTT protocol v3.1 2016-01-19 09:07:54 -08:00
Paulus Schoutsen
1ceee2d6c5 Fix MQTT reconnecting 2016-01-19 09:07:35 -08:00
Paulus Schoutsen
cbb74d50ce Enforce entity attribute types 2016-01-19 09:07:27 -08:00
Erik
c2d72bbf09 fix issue where sensors and switches were duplicated because of component getting initialized twice. closes #913 2016-01-19 09:06:57 -08:00
Paulus Schoutsen
f97ba263c4 Allow forcing MQTT protocol v3.1 2016-01-19 09:00:40 -08:00
Paulus Schoutsen
85df9e98bd Merge pull request #922 from balloob/mqtt-fixes
Fix MQTT reconnecting
2016-01-19 08:45:49 -08:00
Paulus Schoutsen
2faafb9c0f Merge pull request #931 from molobrakos/fix-tellduslive-duplicates
proper initialization
2016-01-18 18:01:12 -08:00
Erik
d43101f22a fix issue where sensors and switches were duplicated because of component getting initialized twice. closes #913 2016-01-18 19:41:41 +01:00
Tim
3d23cd10fc Attempt to fix ungrouped-imports pylint error 2016-01-18 18:30:09 +00:00
Tim
66cd8d264e Remove use of warn() 2016-01-18 18:27:46 +00:00
Tim
291910d74e Add LIFX bulb support 2016-01-18 18:10:32 +00:00
Paulus Schoutsen
7ac648d0ab Merge pull request #889 from Bart274/dev
Create command_sensor.py
2016-01-18 07:47:00 -08:00
Bart274
3b42390062 Update command_sensor.py 2016-01-18 13:48:09 +01:00
Bart274
a80917f530 Update command_sensor.py 2016-01-18 09:24:38 +01:00
Paulus Schoutsen
8fbb585874 Fix MQTT reconnecting 2016-01-17 21:39:25 -08:00
Ryan Kraus
027d97321f Merge pull request #911 from rmkraus/service-toggle
Added toggle service
2016-01-17 21:11:35 -05:00
Paulus Schoutsen
62a1c9687e Merge pull request #920 from balloob/enforce-entity-types
Enforce entity attribute types
2016-01-17 18:01:20 -08:00
Paulus Schoutsen
a9c6f8c1d9 Enforce entity attribute types 2016-01-17 17:50:20 -08:00
Paulus Schoutsen
06b4fcc2cf Fix lint errors 2016-01-17 16:36:25 -08:00
Paulus Schoutsen
6dc2501116 ps - fix RPi GPIO imports 2016-01-17 16:29:41 -08:00
Paulus Schoutsen
54060f27ef Merge pull request #893 from joshughes/nest_sensor
Add the nest sensor for tracking data from nest
2016-01-17 15:16:25 -08:00
Ryan Kraus
85aa4fdd2e Revised entity toggle to use is_on
The toggle function in the Entity ABC was using state == STATE_ON to
determine whether the entity was on. This was revised to use the is_on
property instead.
2016-01-17 16:59:22 -05:00
Ryan Kraus
0624445627 Added tests for toggle service.
1) Added tests to toggle service.
2) Removed color_util import in light tests. It was not being used.
2016-01-17 16:42:18 -05:00
Joseph Hughes
4ca4941c82 fix pylint errors in sensor/nest 2016-01-16 12:56:38 -07:00
Joseph Hughes
4dbd84ead0 make sure everything inherits from NesSensor 2016-01-16 12:53:42 -07:00
Joseph Hughes
0495776a22 merge upstream dev 2016-01-16 12:52:22 -07:00
Joseph Hughes
dd35551047 fix order of inhertiance 2016-01-16 12:47:08 -07:00
Paulus Schoutsen
9f61369156 Version bump to 0.12.0.dev0 2016-01-16 11:23:55 -08:00
Paulus Schoutsen
bd536be66d Merge pull request #883 from balloob/dev
0.11.0
2016-01-16 11:23:40 -08:00
Paulus Schoutsen
c5b69a0ee4 Update version to 0.11 2016-01-16 11:20:02 -08:00
Paulus Schoutsen
206b3a88a2 Merge pull request #910 from rmkraus/nginx-config
Added nginx sample configuration
2016-01-16 09:44:42 -08:00
Paulus Schoutsen
880bd011a9 Merge pull request #908 from persandstrom/verisure_code_digits
Verisure - code digits settings
2016-01-16 09:04:53 -08:00
Paulus Schoutsen
7de91a270a Merge pull request #905 from Xorso/alarmdotcom_bugfix
Alarmdotcom bugfix
2016-01-16 08:48:07 -08:00
Paulus Schoutsen
09973abe8a Merge pull request #897 from balloob/input-boolean
New component: input_boolean
2016-01-16 08:47:29 -08:00
Ryan Kraus
342a819fd4 Added toggle service
Added a toggle service to the homeassistant, light, switch, and
media_player domains.
2016-01-16 10:45:05 -05:00
Ryan Kraus
4bf185c868 Added nginx sample configuration
Added a sample nginx configuration with instructions detailing how to
setup a very secure HTTPS server for HA that servers over standard
ports without requiring HA to run as root.
2016-01-16 10:17:26 -05:00
Per Sandström
78742c016b code digits settings 2016-01-16 15:12:54 +01:00
Greg Dowling
1ed314f6f6 Merge pull request #906 from balloob/bump_vera_version
Bump pywemo version.
2016-01-16 11:40:10 +00:00
pavoni
be23c6c86d Bump pywemo version. 2016-01-16 11:35:17 +00:00
Daren Lord
a194c4f1bd Merge branch 'dev' of https://github.com/balloob/home-assistant into alarmdotcom_bugfix 2016-01-15 22:16:01 -07:00
Daren Lord
edb24add6b Fixed but when alarm is trying to change state the state gets updated and changes the page. 2016-01-15 22:15:31 -07:00
Paulus Schoutsen
bc88985889 Merge pull request #901 from philipbl/ssl
Increase security of using SSL
2016-01-15 17:32:51 -08:00
Greg Dowling
3d27dd3ec4 Merge pull request #902 from balloob/fix_vera_sensor_subscriptions
Another Vera fix
2016-01-15 21:46:27 +00:00
pavoni
c2f5eb3073 Missed change. 2016-01-15 21:42:51 +00:00
pavoni
541b268721 Update to use refactored pyvera, fixes subscription issues - esp sensors. 2016-01-15 21:30:58 +00:00
Philip Lundrigan
e77daed086 Merge pull request #900 from philipbl/fix_locative
Fix bug in Locative logic
2016-01-15 13:43:52 -07:00
Philip Lundrigan
fdbb409331 Increase security of using SSL 2016-01-15 13:39:54 -07:00
Philip Lundrigan
f96c5aa62f Fix bug in locative logic 2016-01-15 13:19:53 -07:00
Paulus Schoutsen
c07a096e57 Merge pull request #899 from sfam/dev
Update RPi.GPIO version and code refactoring
2016-01-15 11:56:27 -08:00
sfam
48b6c5b5cb fix import BinarySensorDevice 2016-01-15 18:14:46 +00:00
sfam
d8d59d9a66 remove rpi_gpio sensor 2016-01-15 18:05:48 +00:00
sfam
702dddbb2f update requirements_all 2016-01-15 17:28:32 +00:00
sfam
127488004c update coveragerc and requirements_all 2016-01-15 17:16:02 +00:00
sfam
7c925ac295 update comments 2016-01-15 16:53:46 +00:00
sfam
8617b92d1b Update RPi.GPIO version and code refactoring 2016-01-15 16:53:45 +00:00
Paulus Schoutsen
bb80e3a9fc Merge pull request #898 from balloob/vera_fixes
Vera fixes
2016-01-15 07:43:03 -08:00
Joseph Hughes
80023f62d9 Merge remote-tracking branch 'upstream/dev' into nest_sensor
# Conflicts:
#	.coveragerc
#	requirements_all.txt
2016-01-15 08:18:16 -07:00
Joseph Hughes
9617288bd5 multiple inheritance for nest binary sensor 2016-01-15 08:16:33 -07:00
pavoni
4fd79afa42 Bump pyvera version. 2016-01-15 11:45:17 +00:00
pavoni
719f9a63d9 Fix style issue 2016-01-15 10:52:58 +00:00
pavoni
4bc33d0352 Bump pyvera version. 2016-01-15 10:34:14 +00:00
pavoni
c4e1035638 Add humidity sensor, add units for humidity and light sensors. 2016-01-15 09:21:48 +00:00
Bart274
d40e889d3b Update command_sensor.py
Importing CommandSensorData from the command_sensor in sensors in order not to duplicate code
2016-01-15 09:01:58 +01:00
Bart274
41acc8fa43 Update .coveragerc
This shouldn't be excluded according to @balloob because it's a pure python component
2016-01-15 08:59:11 +01:00
Fabian Affolter
90c2aed7b4 Update docstrings 2016-01-15 08:55:59 +01:00
Fabian Affolter
5108602de3 Update link to docs and docstrings 2016-01-15 08:55:59 +01:00
Paulus Schoutsen
5ee17ffc58 Update frontend 2016-01-14 23:47:55 -08:00
Paulus Schoutsen
6b899ddc1d 100% test coverage for input_boolean 2016-01-14 23:25:25 -08:00
Paulus Schoutsen
0a711922ef Remove unnecessary instance variable 2016-01-14 23:19:08 -08:00
Paulus Schoutsen
475b631d9c Initial version input_boolean 2016-01-14 23:18:52 -08:00
Paulus Schoutsen
40c75f0a51 Merge pull request #887 from sdague/dev
Add support for Proliphix thermostat
2016-01-14 22:03:09 -08:00
Paulus Schoutsen
1dd99a6d5d Update frontend 2016-01-14 22:02:02 -08:00
Paulus Schoutsen
bed9b038c8 Merge pull request #856 from w1ll1am23/Wink_power_strip_support
Wink power strip support
2016-01-14 19:23:41 -08:00
Joseph Hughes
9210c57c2d Fix lint errors and PR comments 2016-01-14 14:32:43 -07:00
Joseph Hughes
313cbda0aa fix multiple PR issues 2016-01-14 14:17:28 -07:00
Paulus Schoutsen
86b0e49995 Merge pull request #894 from Xorso/alarmdotcom
Adding in alarm control panel for Alarm.com accounts.
2016-01-14 13:01:58 -08:00
Joseph Hughes
a39148dd38 fix pylint errors for Nest Sensor 2016-01-14 11:37:17 -07:00
Joseph Hughes
b8c8c71b78 run requirements_all again for nest sensor 2016-01-14 11:28:28 -07:00
Joseph Hughes
65a3bf2325 fix merge error 2016-01-14 11:01:53 -07:00
Joseph Hughes
ac34db3c8a Merge remote-tracking branch 'upstream/dev' into nest_sensor
# Conflicts:
#	.coveragerc
#	requirements_all.txt
2016-01-14 11:00:34 -07:00
Joseph Hughes
f2e86ecd8e Merge remote-tracking branch 'upstream/master' into nest_sensor
# Conflicts:
#	homeassistant/const.py
2016-01-14 10:52:19 -07:00
Joseph Hughes
7b993da0de address PR comments for Nest Sensor 2016-01-14 10:48:24 -07:00
William Scanlon
de5bee6359 Updated python-wink version 2016-01-14 08:56:59 -05:00
Daren Lord
34f124190c Fixing pylint errors 2016-01-14 06:29:12 -07:00
Sean Dague
d867366be1 add proliphix thermostat support
The proliphix nt10e is an early network thermostat that supports an
HTTP interface. This adds basic support for it to home-assistant (get
/ set heating setback).
2016-01-14 06:32:08 -05:00
Bart274
d0d375d433 Update command_sensor.py 2016-01-14 10:27:11 +01:00
Bart274
d17aa103b4 Update command_sensor.py 2016-01-14 10:13:57 +01:00
Fabian Affolter
f0af23a4f5 Add link to docs and update pressure unit 2016-01-14 09:16:20 +01:00
Paulus Schoutsen
bdd6bb7918 Update frontend 2016-01-13 23:51:29 -08:00
Paulus Schoutsen
3ec49a0ef0 Merge pull request #892 from sdague/f_rounding
round min / max values for temperature
2016-01-13 22:50:15 -08:00
Daren Lord
7a2d049ce3 Removing LIFX from requirements_all.txt 2016-01-13 23:33:19 -07:00
Paulus Schoutsen
7fba4b354e Merge pull request #878 from HydrelioxGitHub/netatmo
Netatmo
2016-01-13 22:24:17 -08:00
Daren Lord
87cecd7e95 Adding to requirements_all 2016-01-13 23:22:42 -07:00
Daren Lord
303cb8e350 Adding alarmdotcom to coveragerc 2016-01-13 23:18:52 -07:00
Daren Lord
236ae94474 Merging dev branch 2016-01-13 23:14:58 -07:00
Daren Lord
308969e6dd Adding in alarm.com control panel. 2016-01-13 23:09:39 -07:00
hydreliox
4dd558a420 Update Requirements 2016-01-14 07:09:25 +01:00
Joseph Hughes
0e6a60b086 Add the nest sensor for tracking data from nest 2016-01-13 21:05:47 -07:00
Sean Dague
4fc0163139 round min / max values for temperature
In order for the polymer thermostat component to have sensible step
values the min / max values have to be round numbers. The current code
only does that for systems running in degrees C. For those of us in
silly land that still function in degrees F, this causes some
oddities in the UI.

Always round mix / max values to make it good no matter what
fundamental units we are in.
2016-01-13 21:22:56 -05:00
hydreliox
314d34a644 Update library lnetatmo requirements
Thanks to @rmkraus
2016-01-14 03:00:51 +01:00
Paulus Schoutsen
2745b0f99e Merge pull request #874 from xifle/zwave
Zwave inclusion / exclusion events
2016-01-13 12:47:39 -08:00
Bart274
c2e8646aed Update .coveragerc 2016-01-13 12:20:37 +01:00
Bart274
e5919c1bfe Update command_sensor.py 2016-01-13 12:19:20 +01:00
Bart274
c8961fcf99 Create command_sensor.py
This adds a binary command_sensor
2016-01-13 11:52:42 +01:00
hydreliox
58cee75c0e coverage and requirements updated 2016-01-13 09:06:16 +01:00
hydreliox
4f13236008 Merge remote-tracking branch 'refs/remotes/balloob/dev' into netatmo 2016-01-13 09:03:44 +01:00
Paulus Schoutsen
2a377a6125 Refactor syslog component for Windows users 2016-01-12 23:59:15 -08:00
hydreliox
058dba50cc Correct name using format instead of concatenation 2016-01-13 08:46:45 +01:00
Paulus Schoutsen
e6846e7eb9 Convert asuswrt user/pass to strings 2016-01-12 22:28:53 -08:00
Ryan Kraus
a0ddda4bc6 Updated frontend to newest commit 2016-01-12 22:15:23 -08:00
Ryan Kraus
57c0f96118 Renamed update_state to update in universal media player
Renamed update_state method in universal media player to update so that
it would be called by HA when the state was being published. Moved the
update_ha_state to a function inside of __init__. Updated the tests
accordingly.
2016-01-12 22:15:23 -08:00
Ryan Kraus
a84429538b Fixed attribute configuration handling in universal media player
Forced all parsed attribute configurations to be of length 2. Removed
entity_id=None option from entity lookups. Explicitly passed entity
lookup information to _entity_lkp.
2016-01-12 22:15:23 -08:00
Ryan Kraus
07953fb7e3 Removed dependencies property from universal media player
The dependencies property was only being called once by the __init__
method so it was removed and the code was moved to the __init__ method.
The tests were updated to reflect this.
2016-01-12 22:15:23 -08:00
Ryan Kraus
12da6f531e Removed property from universal media player
The active_child_state property was unnecessary as it was not being
referenced outside the class. This commit removes it and updates the
tests accordingly.
2016-01-12 22:15:22 -08:00
Ryan Kraus
769f5aafb7 Added should_poll = False to universal media player 2016-01-12 22:15:22 -08:00
Ryan Kraus
a1abab8ced Set universal media player to force refresh when updating HA 2016-01-12 22:15:22 -08:00
Ryan Kraus
270a998e3c Merged service calling method in universal media player 2016-01-12 22:15:22 -08:00
Ryan Kraus
d829497c3d Changed universal media player to keep service attrs in dict
Revised universal media player to keep service data in a dictionary
rather than passing it around as magic parameters.
2016-01-12 22:15:22 -08:00
Ryan Kraus
a8d5b0e5ec Made universal media player cache active player
Revised universal media player to cache the active player when updating
the state when any of the children change. Revised tests to accommodate
this change.
2016-01-12 22:15:22 -08:00
Ryan Kraus
85d732a45a Streamlined child state lookups in universal media player
1) Removed children property because it was only being used by one
method.
2) Removed option to return state as object from _entity_lkp as it was
no longer needed.
3) Used hass.states.get to get entity state objects.
4) Revised test to remove children property.
2016-01-12 22:15:22 -08:00
Ryan Kraus
8f3e8d29f0 Renamed SUPPORT_VOLUME_STEP flag in media_player
1) Renamed SUPPORT_VOLUME_BUTTONS to SUPPORT_VOLUME_STEP
2) Removed unused imports from tests.
2016-01-12 22:15:22 -08:00
Ryan Kraus
ee4543d739 Using call_from_config in Universal Media Player
Changed universal media player to use the call_from_config helper to
call services specified in the configuration file. This was done to
copy what is done in the Alexa and Automation components.
2016-01-12 22:15:22 -08:00
Ryan Kraus
59456f20fb Added tests to universal media player and fixed bug
1) Fixed universal media player to maintain specified child order when
checking for active child.
2) Added many tests to universal media player.
2016-01-12 22:15:22 -08:00
Ryan Kraus
4a1f609893 Lint fixes and faster updating to universal media player.
1) Many lint fixes.
2) Bound the Universal Media Player to its dependencies so that its
state will be updated when one of its dependencies is changed.
2016-01-12 22:15:22 -08:00
Ryan Kraus
36214c73ee Better handling of entity lookups in Universal media player.
Allowed the lookup function in the Universal Media Player to return
either a state object or the actual state of an entity during lookup.
2016-01-12 22:15:21 -08:00
Ryan Kraus
20a1025a8c Added active_child attribute to universal media players.
The entity of the first active child is now reported in the attributes
for a universal media player.
2016-01-12 22:15:21 -08:00
Ryan Kraus
ec85884d92 Added initial implementation of universal media player. 2016-01-12 22:15:21 -08:00
Paulus Schoutsen
22c01b956f Merge pull request #888 from balloob/lint-fixes
Lint fixes
2016-01-12 22:00:48 -08:00
Paulus Schoutsen
9cdf84dacf Update flake8 and pylint versions 2016-01-12 21:57:43 -08:00
Paulus Schoutsen
60f40800c4 Use mock HA for locative tests 2016-01-12 21:56:09 -08:00
Paulus Schoutsen
3b7b12bbd5 Make Flake8 happy 2016-01-12 21:53:27 -08:00
Paulus Schoutsen
9a1aad8e92 Merge pull request #882 from moonshot/mqtt-eventstream
Create mqtt eventstream component
2016-01-12 21:29:17 -08:00
Moonshot
6f398f59df Fix filtering of EVENT_CALL_SERVICE and EVENT_SERVICE_EXECUTED events 2016-01-12 22:57:03 -05:00
Moonshot
8ace656657 Create mqtt eventstream component 2016-01-12 22:56:26 -05:00
hydreliox
a4481efe07 Code cleanup 2016-01-13 04:26:40 +01:00
hydreliox
dc31ddbef2 Extract 'modules' as a constant 2016-01-13 04:19:27 +01:00
hydreliox
0c2fe4c5f3 Remove temp unit logic
HA should convert unit automatically
2016-01-13 04:16:25 +01:00
hydreliox
03febb81d3 Extract 'secret_key' as a constant 2016-01-13 03:45:43 +01:00
hydreliox
6f1a25d8d6 Add a configuration validation
All parameters are required
2016-01-13 03:43:10 +01:00
hydreliox
f182f7dccd Remove uncessary requirement check
HA already check the requirement before setup the platform
2016-01-13 03:29:17 +01:00
Fabian Affolter
31fcd230b1 Update docstrings 2016-01-12 11:30:12 +01:00
Paulus Schoutsen
1ad5cae98e Merge pull request #884 from partofthething/zwave-alarm
Added z-wave alarm sensors to list of devices that can be auto-detected and used
2016-01-11 23:52:06 -08:00
ntouran
5af4864326 ZWave alarm sensor cleanup (pylint fixes) 2016-01-11 23:27:53 -08:00
Paulus Schoutsen
ea8d278f8f Rename freesms to free_mobile 2016-01-11 21:05:32 -08:00
Paulus Schoutsen
88de9908ce Merge branch 'pr/879' into dev
Conflicts:
	requirements_all.txt
2016-01-11 21:03:52 -08:00
hydreliox
1bbecce5eb Add requirements and coverage exception 2016-01-11 21:03:22 -08:00
ntouran
2495226c87 Merge remote-tracking branch 'origin/dev' into zwave-alarm 2016-01-11 20:48:54 -08:00
ntouran
c1aa1fb0e0 First attempt at adding Z-wave COMMAND_CLASS_ALARM 2016-01-11 20:46:45 -08:00
Paulus Schoutsen
a5b198e2b8 Merge pull request #771 from MartinHjelmare/mysensors-component-switch
Mysensors component switch
2016-01-11 19:04:35 -08:00
xifle
cd669239ae Changed zwave node add/remove events to services 2016-01-11 22:39:28 +01:00
hydreliox
bc73a6829d Code formatting
Correct pylint errors
2016-01-11 09:30:32 +01:00
hydreliox
542b640ef0 FreeMobile Notify
First Commit for FreeSMS platform
2016-01-11 09:25:26 +01:00
hydreliox
7823fb9788 Merge remote-tracking branch 'refs/remotes/balloob/dev' into dev 2016-01-11 08:40:07 +01:00
hydreliox
bcb42674fc Corrections due to pylint tests 2016-01-11 06:57:31 +01:00
hydreliox
1f1a46a8bd Remove unused library
Remove the library used for dev
2016-01-11 05:35:26 +01:00
hydreliox
7b999e6cd1 Convert Temperature output
Convert temperature from celcius to fahrenheit if the HA config need it
2016-01-11 05:29:32 +01:00
hydreliox
c97a25cc86 Add configuration verification and sensors type
Generate an error in the configuration name of a module or a queried
sensor type is not correct.
Add support for co2 pressure and noise sensors
2016-01-11 05:21:38 +01:00
Greg Dowling
cdf24ec205 Merge pull request #872 from balloob/vera-debugging
Vera updates
2016-01-10 17:34:49 +00:00
Paulus Schoutsen
579f4d4cca Merge pull request #875 from xifle/dev
Owntracks transition events minor improvement
2016-01-10 09:16:27 -08:00
xifle
fce04e7ad0 Added inclusion / exclusion events
Events may be used to start inclusion / exclusion of zwave devices.
This is especially useful in the case of a Z-Wave stick without
"hardware" inclusion button.
2016-01-10 15:28:34 +01:00
xifle
6c94650603 Accept lower & upper case for owntracks 'home' region 2016-01-10 15:00:14 +01:00
pavoni
fca8ad5b0b Tidy. 2016-01-10 12:48:36 +00:00
pavoni
4b4fb038e3 Update for new library, slightly revise switch logic. 2016-01-10 12:30:47 +00:00
MartinHjelmare
0b3a66dd1a Merge branch 'dev' into mysensors-component-switch 2016-01-10 04:27:39 +01:00
MartinHjelmare
2d8cf7de44 Fix wrapper and S_BINARY and bump req. version
* Wrap existing SerialGateway instance instead of subclassing
	SerialGatewat class.
* Add S_BINARY in switch platform only in version 1.5 of mysenors api.
* Use version 0.4 of pymysensors.
* Show gateway port as state attribute.
2016-01-10 04:10:38 +01:00
Paulus Schoutsen
ad931eac60 Merge pull request #870 from balloob/update-pychromecast
Update PyChromecast dependency
2016-01-09 16:27:09 -08:00
Paulus Schoutsen
438e78610d Update PyChromecast dependency 2016-01-09 16:21:08 -08:00
Paulus Schoutsen
058f6f9303 Merge pull request #862 from balloob/alexa-service
Add calling service functionality to Alexa
2016-01-09 16:13:46 -08:00
Paulus Schoutsen
73cdf00512 More service helper tests 2016-01-09 16:01:27 -08:00
Paulus Schoutsen
12b5caed70 ps - strip entity IDs in service call 2016-01-09 15:51:51 -08:00
Paulus Schoutsen
18d2668e3b Merge pull request #869 from philipbl/mqtt-fix
Default to MQTT protocol v3.1.1
2016-01-09 15:27:33 -08:00
pavoni
af21f72d17 Update pyvera version. 2016-01-09 22:58:28 +00:00
pavoni
b64680e4a8 Revise to depend on vera subscription data updates, rather than talking to device. 2016-01-09 21:13:34 +00:00
Philip Lundrigan
9faedf0e67 Default to MQTT protocol v3.1.1 (fix #854) 2016-01-09 13:43:44 -07:00
Paulus Schoutsen
204c151113 Merge pull request #865 from fabaff/owm-update
Update pyowm to 2.3.0
2016-01-09 11:59:15 -08:00
Paulus Schoutsen
9b8256ec07 Merge pull request #867 from persandstrom/verisure_fix_lost_connection
Verisure fix lost connection
2016-01-09 11:47:39 -08:00
pavoni
d61eb93c03 Remove throttle doesn't play well with subscriptions. 2016-01-09 16:16:41 +00:00
Fabian Affolter
a2c6cde83d Update pyowm to 2.3.0 2016-01-09 13:20:51 +01:00
Paulus Schoutsen
825c91f0c3 Add calling service functionality to Alexa 2016-01-08 18:54:28 -08:00
Paulus Schoutsen
d406d7fa94 Merge pull request #860 from philipbl/fix-test
Fix Yr test
2016-01-08 12:53:09 -08:00
Philip Lundrigan
3db6faab4d Fix yr test 2016-01-08 13:30:16 -07:00
Per Sandström
15a046f20c update module version 2016-01-08 19:52:03 +01:00
Per Sandström
d3cd304f68 correced status text 2016-01-08 19:50:49 +01:00
Paulus Schoutsen
84fb96a42f Merge pull request #858 from balloob/remove-wemo-polling
Remove wemo polling
2016-01-08 08:19:33 -08:00
pavoni
5a1fed3980 Bump pywemo version. 2016-01-08 16:00:56 +00:00
pavoni
bb8af3a2d5 Bump pywemo version, turn off polling, tidy trace. 2016-01-08 16:00:26 +00:00
William Scanlon
2803631906 Updated python-wink to 0.4.0 2016-01-08 08:25:26 -05:00
hydreliox
4c47ed31ff Correction to import lnetatmo right 2016-01-08 06:19:03 +01:00
hydreliox
1ed574b2a0 Point lnetatmo library directly from github 2016-01-08 05:34:51 +01:00
Fabian Affolter
d69c1b848a Fix docstrings 2016-01-07 11:57:45 +01:00
Fabian Affolter
35c29dac3f Use mbar instead of hPa 2016-01-07 11:50:02 +01:00
Fabian Affolter
aac44f3a2b Use the same unit for pressure as for the forecast sensor 2016-01-07 11:48:42 +01:00
William Scanlon
17dd8ddc9a Added wink power strip support 2016-01-06 12:22:50 -05:00
hydreliox
a8b36d9baa Multiple Module Configuration
Handle multiple module (see configuration.yaml)
2016-01-06 04:36:04 +01:00
hydreliox
520a8d0d0d Add NetAtmo Platform
Alpha version of the platform.
API library is not yet on PyPI
2016-01-06 03:39:16 +01:00
Paulus Schoutsen
033bd30391 Merge pull request #844 from balloob/delay-group-switch-sensors
Fix calling turn_on for groups with mixed content
2016-01-05 08:55:58 -08:00
Paulus Schoutsen
99e14380fe Merge pull request #847 from molobrakos/patch-1
No need to call update() here
2016-01-05 08:55:48 -08:00
Erik
5576649d60 Update eliqonline.py 2016-01-04 21:36:39 +01:00
Erik
82cd2f4ed6 Update eliqonline.py 2016-01-04 21:31:42 +01:00
Erik
66f12afbb1 don't fail if error
don't fail if request for updated data raises exception in underlying library
2016-01-04 21:12:10 +01:00
Greg Dowling
431656bbcf Merge pull request #848 from balloob/fix-vera-bugs
Bump pyvera version to fix vera dimmer off bug, and avoid shutdown race condition
2016-01-04 19:34:17 +00:00
Erik
a174a06e5c No need to call update() here
This also fixes a problem where the sensor is left uninitialized when the energy meter temporarily has lost connection with the hub. This caused the ELIQ Online server to return HTTP error 400: "user have no current power data", which in turn caused the used eliq library to fail during JSON parsing (issue reported).
2016-01-04 19:25:52 +01:00
Fabian Affolter
0d0fdb0adf Remove configuration details 2016-01-04 16:26:11 +01:00
pavoni
5f8dd65acf Bump pyvera version 2016-01-04 11:24:24 +00:00
Paulus Schoutsen
601211f1d9 Sun docs cleanup 2016-01-04 00:15:44 -08:00
Paulus Schoutsen
8983a97c70 Fix calling turn_on for groups with mixed content 2016-01-03 21:25:15 -08:00
Paulus Schoutsen
2e899bd61c Merge pull request #843 from rhooper/multiple-hues
Support multiple hue hubs using a filename parameter.
2016-01-03 18:39:21 -08:00
Roy Hooper
d0a8a57ae4 Ensure filename arg is passed around everywhere it's needed. 2016-01-03 15:30:06 -05:00
Paulus Schoutsen
08aabd18ad New version frontend 2016-01-03 11:44:26 -08:00
Paulus Schoutsen
2478623ebc Merge pull request #840 from balloob/reproduce-group
Reproduce state upgrades
2016-01-03 11:36:45 -08:00
Paulus Schoutsen
736183e6f5 Fix bug in reproduce_state with complex state attributes 2016-01-03 11:27:30 -08:00
Paulus Schoutsen
31f2707b2f Merge pull request #841 from xifle/dev
Owntracks transition events
2016-01-03 11:19:02 -08:00
xifle
d244d3b599 Fixed flake8 style errors 2016-01-03 17:42:49 +01:00
xifle
82904c59ce Fixed code style 2016-01-03 17:12:11 +01:00
Paulus Schoutsen
f8b2570cb3 Group entities when reproducing a state 2016-01-03 02:32:09 -08:00
Paulus Schoutsen
6268840b55 Merge pull request #839 from philipbl/sun_fix
Fix for sun if condition
2016-01-03 00:27:33 -08:00
Philip Lundrigan
c9ff0ab7eb Fix for sun if condition 2016-01-03 01:03:53 -07:00
Paulus Schoutsen
cf1f9a29bf Merge pull request #833 from eiaro/dev
Added more sensors to Telldus Live
2016-01-02 17:05:54 -08:00
Paulus Schoutsen
48b1f8e137 Merge pull request #829 from joshughes/influx_hack
Interpolate what we are sending to influx so its not always a string
2016-01-02 16:59:31 -08:00
Ronny Eia
4b96a7c820 Untabified lines 2016-01-03 01:00:10 +01:00
Paulus Schoutsen
452ebdac8e Merge pull request #838 from balloob/travis-tweaks
Make CI erros more prominent
2016-01-02 15:46:03 -08:00
Paulus Schoutsen
7dc1499386 Make CI erros more prominent 2016-01-02 14:43:03 -08:00
Paulus Schoutsen
3ccc7787af Merge pull request #834 from R1chardTM/reference-fix
Fix reference known_devices.yaml in service description
2016-01-02 14:05:31 -08:00
Paulus Schoutsen
02879e79e6 Merge pull request #828 from sander76/honeywell_away_mode
Honeywell away mode
2016-01-02 14:05:20 -08:00
Richard
305c87a9c9 Fix reference known_devices.yaml 2016-01-02 16:01:58 -06:00
Ronny Eia
3abc78eef2 Added power sensor 2016-01-02 22:30:02 +01:00
Paulus Schoutsen
4a421e25b0 Simplify Rest sensors 2016-01-02 13:29:33 -08:00
Ronny Eia
86047eceb1 Added wind sensor 2016-01-02 22:28:15 +01:00
Ronny Eia
7edbb6aadc Added rain sensor 2016-01-02 22:21:04 +01:00
Roy Hooper
0361f37178 Support multiple hue hubs using a filename parameter. 2016-01-02 16:13:58 -05:00
sander
55c5d254d5 some more pylinting.. 2016-01-02 21:09:03 +01:00
sander
36f5caa214 more pylinting.. 2016-01-02 20:59:45 +01:00
sander
8c7898ed05 pylinting.. 2016-01-02 20:53:25 +01:00
sander
39de92960d line too long change 2016-01-02 20:27:40 +01:00
Paulus Schoutsen
6d35bdafee Merge pull request #832 from R1chardTM/device-tracker
Add service description device tracker
2016-01-02 10:34:05 -08:00
Paulus Schoutsen
217ffc215b Update PyNetgear version 2016-01-02 10:27:11 -08:00
xifle
cbd3860585 Merge branch 'dev' of https://github.com/balloob/home-assistant into dev 2016-01-02 18:56:14 +01:00
xifle
5804dde0e9 Enables the use of owntracks transition events
By using the configuration option "use_events:yes" in the device_tracker section,
only 'enter'/'leave' events are considered to calculate the state of a tracker device.
The home zone is defined as the owntracks region 'home'. Other regions may also be defined, the name of
the region is then used as state for the device. All owntracks regions, the 'Share' setting must be enabled in the app.
2016-01-02 18:26:59 +01:00
Joseph Hughes
e9b2cf1600 Ensure we send data to influx as float and not as a string value. 2016-01-02 10:24:23 -07:00
Richard
cdf2179b3e Describe device tracker see service 2016-01-02 10:54:26 -06:00
sander
8f2ca856c7 added return False 2016-01-02 11:56:07 +01:00
Greg Dowling
622a6deb04 Merge pull request #820 from balloob/vera-subscriptons
Add ability to respond to events from Vera hub
2016-01-02 10:15:14 +00:00
Paulus Schoutsen
a698bc477d Merge pull request #819 from rhooper/phue-deconz
Add support for deCONZ (Raspbee-GW hue-like API)
2016-01-01 22:21:48 -08:00
Roy Hooper
a36ae4b24a Reduce chatiness 2016-01-02 01:01:11 -05:00
sander
c703c89dbd implement away mode 2016-01-01 15:29:58 +01:00
sander
b3227e491b Merge remote-tracking branch 'refs/remotes/balloob/dev' into dev 2016-01-01 14:44:25 +01:00
happyleavesaoc
9e83a80215 Merge pull request #788 from happyleavesaoc/command_switch_state
add statecmd to command_switch
2015-12-31 18:43:02 -05:00
happyleaves
9c85702c87 combine ifs 2015-12-31 18:39:40 -05:00
Paulus Schoutsen
9b7b39055d Merge pull request #826 from andythigpen/feature/is-state-attr
Add is_state_attr method.
2015-12-31 14:17:59 -08:00
Andrew Thigpen
11f32d0500 Add is_state_attr method.
Returns True if the entity exists and has an attribute with the given
name and value.
2015-12-31 14:58:18 -06:00
Philip Lundrigan
326e26fbeb Merge pull request #825 from philipbl/locative
Update Locative component
2015-12-31 13:10:11 -07:00
Philip Lundrigan
394c87c40b Remove unnecessary condition in write_text 2015-12-31 13:05:24 -07:00
Philip Lundrigan
ce152e9c94 Simplify logic 2015-12-31 12:39:36 -07:00
pavoni
9e0946b207 Turn off polling for sensor too! 2015-12-31 19:15:21 +00:00
Paulus Schoutsen
da77edf8fc Merge pull request #818 from balloob/update-wemo-library
Improve wemo subscription error handling.
2015-12-31 11:06:43 -08:00
Paulus Schoutsen
6cb991d583 Merge pull request #814 from Mosibi/fix_mpd_title_keyerror
Fix KeyError on 'title' when title is empty
2015-12-31 11:04:30 -08:00
pavoni
f8e5df237b Remove '#'' from requirements 2015-12-31 18:58:12 +00:00
Philip Lundrigan
5d953061e8 Remove unnecessary error checking 2015-12-31 11:56:27 -07:00
Philip Lundrigan
1bcca8cba1 Fix problem with test 2015-12-31 11:56:27 -07:00
Philip Lundrigan
bdb6182921 Changes to locative based on tests 2015-12-31 11:56:27 -07:00
Philip Lundrigan
55d1ad94ef Add tests for Locative 2015-12-31 11:56:27 -07:00
pavoni
6773c35760 Bump pywemo version 2015-12-31 18:47:12 +00:00
pavoni
5f89b34831 Bump pyvera version 2015-12-31 16:09:05 +00:00
pavoni
90ae5c6646 Add missed import, fix style error. 2015-12-31 12:25:24 +00:00
pavoni
a8bb75d070 Update sensor with subscription code, change to use pyvera library 2015-12-31 12:16:03 +00:00
pavoni
d82859b6ea Turn off poll 2015-12-31 10:57:54 +00:00
Philip Lundrigan
7d41ce4e46 Switch from json messages to plain text messages 2015-12-30 22:43:32 -07:00
Philip Lundrigan
c23375a18b Add case for test message 2015-12-30 22:42:11 -07:00
MartinHjelmare
4c4e5d5f47 Fix to remove old unused variables. 2015-12-31 06:19:47 +01:00
MartinHjelmare
6ff24ed047 Merge branch 'dev' into mysensors-component-switch
Conflicts:
	homeassistant/components/sensor/__init__.py
	homeassistant/components/switch/__init__.py
2015-12-31 06:05:06 +01:00
MartinHjelmare
69ed6fe6e7 Add gateway wrapper, fix discovery and callbacks
* Add gateway wrapper by subclassing serial gateway.
* Fix platform setup with discovery service.
* Fix platform callback functions with callback factory.
2015-12-31 05:48:23 +01:00
Roy Hooper
4e2d75a8f4 fix style 2015-12-30 16:59:22 -05:00
pavoni
ae0dbbcfa5 Added support for event subscriptions 2015-12-30 19:44:02 +00:00
Philip Lundrigan
25e1432403 Fix style issues 2015-12-30 12:30:49 -07:00
Philip Lundrigan
adfcfad488 Update locative functionality 2015-12-30 12:26:03 -07:00
Roy Hooper
b0734e613f Add support for deCONZ (Raspbee-GW hue-like API) - Doesn't support the none transition type, so don't send it 2015-12-30 13:54:18 -05:00
Richard Arends
913c5ab47c identing error... sorry 2015-12-30 13:26:42 +01:00
Richard Arends
429904c437 Returning None when name and title are both not available
Removed trailing whitespaces
2015-12-30 13:00:34 +01:00
pavoni
41a36df801 Update pywemo version 2015-12-30 11:54:21 +00:00
Richard Arends
56a2ffca1d Changed if else statements. The following situations are handled now:
- name and title can be None
  - name can be None
  - title can be None
  - name and title can contain data
2015-12-29 22:10:09 +01:00
Richard Arends
6e2fb17f19 Fix KeyError on 'title' when title is empty 2015-12-29 17:52:05 +01:00
Paulus Schoutsen
586be7fad1 Prevent division by 0 xy->rgb color conversion 2015-12-29 00:09:38 -08:00
Paulus Schoutsen
d9b30d1421 Pep257 fixes for core. 2015-12-27 21:14:35 -08:00
happyleaves
e9059a3ed9 added test; addressed comments 2015-12-27 22:51:37 -05:00
Paulus Schoutsen
473d6b1d05 Fix console coloring for scripts 2015-12-27 19:19:29 -08:00
Paulus Schoutsen
7f17a50b4a Swap lint/requirements validation between Python versions 2015-12-27 18:04:38 -08:00
Paulus Schoutsen
c7183a14a5 Tweak lint script colors for travis 2015-12-27 18:03:23 -08:00
Paulus Schoutsen
c1eaf60461 VCR YR sensor test 2015-12-27 17:37:32 -08:00
Paulus Schoutsen
ca6b957839 Make test deps explicit 2015-12-27 16:57:16 -08:00
Paulus Schoutsen
680385df93 Hide some build log spam 2015-12-27 16:35:14 -08:00
Paulus Schoutsen
62f21c3ac6 colorize lint errors 2015-12-27 16:31:53 -08:00
Paulus Schoutsen
acfbbb3898 Update copyright 2015-12-27 16:31:52 -08:00
Paulus Schoutsen
4403fe941d Test config clean up 2015-12-27 16:31:52 -08:00
Paulus Schoutsen
244fde880e Convert MQTT event to lowercase 2015-12-27 16:31:52 -08:00
Greg Dowling
df99e4ef22 Merge pull request #794 from pavoni/wemo-subscription
Adds Wemo event support - so wemo devices update HA more quickly
2015-12-28 00:11:34 +00:00
pavoni
976d9f2d08 Fix style issue 2015-12-28 00:04:30 +00:00
pavoni
f5dd146676 Fix bug in shutdown 2015-12-27 23:56:18 +00:00
Paulus Schoutsen
7b00b19223 Merge pull request #807 from andythigpen/scene-fix
Fix issue with scene component when using YAML aliases.
2015-12-27 15:39:19 -08:00
pavoni
b114ba56ea Fix style issue 2015-12-27 23:31:48 +00:00
pavoni
0d32bd7a19 Simplify callback logging, add stop log 2015-12-27 23:26:35 +00:00
pavoni
4feef3dd0d Simplify update state call, shutdown properly. 2015-12-27 23:09:39 +00:00
Paulus Schoutsen
9c3b1b7a96 Fix sun import issue 2015-12-27 15:00:49 -08:00
Paulus Schoutsen
a09d731058 Merge pull request #803 from molobrakos/tellduslive2
added rudimentary support for telldus live
2015-12-27 15:00:01 -08:00
Erik
27e35d5f34 don't poll (turns out a request for state immediately a state turn on/off request will not return the newly updated state. import constants from tellive, not tellcore 2015-12-27 21:49:45 +01:00
Erik
c8fa6cc127 bug fix 2015-12-27 21:47:49 +01:00
Per Sandström
468087e6bc Merge pull request #806 from persandstrom/verisure-pypi
verisure module from pypi
2015-12-27 21:10:18 +01:00
Andrew Thigpen
d4b6a7343f Fix issue with scene component when using YAML aliases.
YAML aliases/anchors can make repetitive configuration sections easier
to deal with.  However when dealing with dictionaries, care needs to be
taken to not modify the original anchor since PyYAML utilizes a
reference when encountering an alias instead of a copy of the
dictionary.
2015-12-27 13:24:34 -06:00
Paulus Schoutsen
87c88078c8 Update sun to use elevation util 2015-12-27 11:22:10 -08:00
Paulus Schoutsen
8c1ebde1de Update requirements_all.txt 2015-12-27 11:10:14 -08:00
Paulus Schoutsen
ab5a3f9de3 Clean up YR sensor 2015-12-27 11:07:25 -08:00
Per Sandström
eb3da8cb03 verisure component from pypi 2015-12-27 20:07:09 +01:00
Paulus Schoutsen
9e1ecd7124 Fix flaky history test 2015-12-27 10:38:27 -08:00
Erik
efbaf47dc7 reference constants from tellive package 2015-12-27 18:49:11 +01:00
Erik
f10ecb2a8d remove obsolete comment 2015-12-27 18:42:10 +01:00
Erik
6e81391711 no percentage sign 2015-12-27 18:37:34 +01:00
Paulus Schoutsen
0d64f4a2d5 Merge pull request #804 from molobrakos/systemmon-icons
Systemmon icons
2015-12-27 08:54:14 -08:00
Erik
d63e5a60ae added rudimentary support for telldus live 2015-12-27 12:32:08 +01:00
Paulus Schoutsen
384f1344fd Merge branch 'pr/792' into dev 2015-12-26 17:48:29 -08:00
Paulus Schoutsen
add24915a3 ps - clean up sun automation tests 2015-12-26 17:48:20 -08:00
Paulus Schoutsen
089bbfc5cc Travis: Less verbose requirements_all.txt check 2015-12-26 17:19:53 -08:00
Paulus Schoutsen
1944b6a335 Merge pull request #796 from persandstrom/verisure-update
Verisure update
2015-12-26 08:17:08 -08:00
Paulus Schoutsen
b8cfe63fc6 Merge pull request #797 from molobrakos/eliq-icon
replace default icon
2015-12-26 08:15:01 -08:00
Paulus Schoutsen
9e091a2c92 Merge pull request #798 from R1chardTM/hue-random
Add random color effect for Philips Hue
2015-12-26 08:10:09 -08:00
Paulus Schoutsen
41bcdc3356 Merge pull request #793 from philipbl/rest_bug_fix
Fix bug in rest sensor
2015-12-25 15:00:52 -08:00
Philip Lundrigan
40486676df Simplify error handling 2015-12-25 14:34:30 -07:00
Erik
6f2078cda3 bugfix 2015-12-25 22:02:10 +01:00
Erik
b8d2f2ba37 moved into sensor types 2015-12-25 21:44:32 +01:00
Erik
03491fcc09 icons 2015-12-25 21:19:51 +01:00
Per Sandström
571073fe1f added docstring 2015-12-25 21:04:16 +01:00
Per Sandström
a577d5c5fa revert accidental change 2015-12-25 20:57:30 +01:00
Per Sandström
160814f425 log texts 2015-12-25 20:42:03 +01:00
Per Sandström
b83b36274a changed to python-verisure 0.4.1 2015-12-25 20:16:51 +01:00
Erik
f3db4306c2 added icon 2015-12-25 18:50:35 +01:00
richard
5c7fb5d7ae Fix styling issues 2015-12-24 21:35:36 -06:00
richard
0dfc1c4e7a Add functionality set random color Philips Hue 2015-12-24 21:10:27 -06:00
pavoni
3f151428b7 Update pywemo version, use wildcard filter 2015-12-24 09:35:02 +00:00
Philip Lundrigan
2606e4d641 Simplify if statement 2015-12-24 00:38:49 -07:00
MartinHjelmare
be25ea4f09 Fix avoid event bus for updates 2015-12-24 02:14:58 +01:00
MartinHjelmare
77959341a3 Merge branch 'dev' into mysensors-component-switch
Conflicts:
	homeassistant/components/sensor/mysensors.py
	requirements_all.txt
2015-12-23 23:45:32 +01:00
MartinHjelmare
9f54bcc21b Fix comments for pull request
* Fix cleaner user config.
* Remove bad disabling of linting.
* Extract default mysensors version into constant.
* Clean up selection of mysensors.CONST from version.
* Update mysensors update decorator to add devices and update values
	in one go.
* Fix persistence update.
* Clean up setup of ports.
* Setup of mysensors platforms from main mysensors component.
* Clean up v_types selection in mysensors sensor platform.
* Fix s_types and v_types selection version dependency in platforms.
2015-12-23 23:20:39 +01:00
pavoni
6d236b8169 Force state update 2015-12-23 18:03:40 +00:00
pavoni
09b894a4aa Fix style issues 2015-12-23 15:57:51 +00:00
pavoni
1e2b5e6991 Add support for subscriptions 2015-12-23 15:46:18 +00:00
Philip Lundrigan
496ec4bcca Fix bug in rest sensor 2015-12-23 03:37:03 -07:00
Paulus Schoutsen
3e51d0b539 Merge pull request #791 from andythigpen/logger-fix
Set the root logger to lowest level in logger component.
2015-12-22 23:13:45 -08:00
Andrew Thigpen
c31a291a9c Set the root logger to lowest level in logger component.
In combination with resetting the log level on the handlers, this
allows messages lower than the default INFO to be logged when using
the logger component.
2015-12-23 00:57:41 -06:00
Paulus Schoutsen
96938bb33c Merge pull request #786 from philipbl/locative
Rename geofancy to locative (fix #761)
2015-12-22 19:02:08 -08:00
Paulus Schoutsen
e7b1682a4e Merge branch 'pr/780' into dev 2015-12-22 18:57:42 -08:00
Paulus Schoutsen
d191635fd8 Merge branch 'yr_no' into dev 2015-12-22 18:53:27 -08:00
Paulus Schoutsen
bdd945c1c4 Set default log level to INFO 2015-12-22 18:39:46 -08:00
Paulus Schoutsen
6ccf63dae2 Merge pull request #790 from andythigpen/logger-fix
Reset log handlers to lowest level.
2015-12-22 18:38:58 -08:00
Paulus Schoutsen
987282da78 Logbook entry events are now lower case 2015-12-22 18:35:05 -08:00
Fabian Affolter
56186232f3 Enable logging-too-many-args 2015-12-22 22:33:20 +01:00
Fabian Affolter
fb2da6be9a Remove space 2015-12-22 22:02:55 +01:00
Fabian Affolter
8796187389 Equalize log messages 2015-12-22 22:02:55 +01:00
Andrew Thigpen
edff53609f Reset log handlers to lowest level.
This is necessary to enable logging lower than INFO for the error log file.
2015-12-22 13:50:59 -06:00
Paulus Schoutsen
dbc91c1d48 Merge pull request #789 from balloob/release-101
Release 0.10.1
2015-12-22 09:05:55 -08:00
Paulus Schoutsen
0607c8f4b4 Version bump to 0.10.1 2015-12-22 08:59:32 -08:00
Paulus Schoutsen
7ccb6b960c Merge branch 'release-101' into dev 2015-12-22 02:20:25 -08:00
Paulus Schoutsen
561a78bef3 Fix EntityComponent deadlock 2015-12-22 02:19:55 -08:00
Paulus Schoutsen
9876a2a081 Fix Alexa bug if no value for slots 2015-12-22 02:08:46 -08:00
happyleaves
fba5becd90 warn->warning 2015-12-21 20:18:00 -05:00
happyleaves
d5179b4bdc add statecmd to command_switch 2015-12-21 19:49:39 -05:00
Philip Lundrigan
ff8f22854c Add test 2015-12-21 16:28:26 -07:00
Philip Lundrigan
110d721c76 Add tests 2015-12-21 16:09:51 -07:00
Philip Lundrigan
8c010c8df4 Add ability to use sun as condition in automation 2015-12-21 16:09:27 -07:00
Philip Lundrigan
0ac1759395 Rename geofancy to locative (fix #761) 2015-12-21 11:05:20 -07:00
Paulus Schoutsen
07fb4ff243 Revert last fix. Will fix better. 2015-12-21 09:44:17 -08:00
Paulus Schoutsen
2650d235ea Fix: EntityComponent deadlock when adding new devices during update state 2015-12-21 08:56:27 -08:00
Daniel
9e89197284 small fix in yr sensor name 2015-12-21 10:42:42 +01:00
Daniel
8159d36114 small fix in yr sensor name 2015-12-21 10:36:25 +01:00
Daniel
cf4f4ce8c7 changed to use requestes in stead of urllib for yr sensor 2015-12-21 10:33:19 +01:00
Daniel
9a1883bb49 changed to use requestes in stead of urllib for yr sensor 2015-12-21 10:29:12 +01:00
Daniel
8e16a443e5 Added yr sensor to requirements_all 2015-12-21 10:24:22 +01:00
Paulus Schoutsen
35411cd57e Version bump to 0.11.dev0 2015-12-20 15:32:51 -08:00
MartinHjelmare
845926236e Add config sample and fix requirements_all 2015-12-18 03:58:21 +01:00
MartinHjelmare
eae07c070a Merge branch 'dev' into mysensors-component-switch 2015-12-18 03:39:41 +01:00
MartinHjelmare
659226886f Update .coveragerc and requirements 2015-12-18 03:37:49 +01:00
MartinHjelmare
1e52d5c7f2 Add S_TYPES to platform type and fix persistence
* Add S_TYPES to platform type.
* Fix persistence update on startup.
* Clean up code.
2015-12-09 04:43:18 +01:00
MartinHjelmare
9463c84603 Clean up 2015-12-08 02:47:15 +01:00
MartinHjelmare
7cc707f1ce Fix docstrings to conform to pep 2015-12-08 01:03:07 +01:00
MartinHjelmare
59524c7933 Add multiple gateways
* Add support for multiple serial gateways.
* Fix serialization of python objects by adding dict representation of
    classes.
* Add support for showing more than one child value type per entity.
    The entity state is always only one value type. This is defined by
    the platform value types. Value types that are not defined as the
    platform value type are shown as state_attributes.
* Add more unit of measurement types.
* Clean up code.
2015-12-06 00:29:03 +01:00
MartinHjelmare
1d141566bd Merge 'dev' into mysensors-component-switch 2015-12-05 23:55:36 +01:00
Daniel Hoyer Iversen
ac41f3028c Refactor yr sensor 2015-12-04 15:10:26 +01:00
Daniel Hoyer Iversen
750ca79ac0 Refactor yr sensor 2015-12-04 15:05:23 +01:00
Daniel Hoyer Iversen
71bf707bcf fix tests in yr sensor 2015-12-02 13:32:52 +01:00
Daniel Hoyer Iversen
31f1e1d7a4 added comment for yr sensor 2015-12-02 13:04:23 +01:00
Daniel Høyer Iversen
361ab0f92b Update yr.py 2015-12-01 20:19:59 +01:00
Daniel Høyer Iversen
e68a8f9c0f Update yr.py 2015-12-01 20:16:04 +01:00
Daniel Høyer Iversen
15770ff90f Update yr.py 2015-12-01 20:12:07 +01:00
Daniel Hoyer Iversen
618ebfe43c try to fix requirements for yr sensor 2015-12-01 13:40:26 +01:00
Daniel Hoyer Iversen
ff15fea9f8 Added units to sensor yr 2015-12-01 13:31:55 +01:00
Daniel Hoyer Iversen
2872c89f0c Fix in yr sensor 2015-12-01 13:24:32 +01:00
Daniel Hoyer Iversen
2dc9bc98f7 Tests for yr sensor 2015-12-01 13:24:03 +01:00
Daniel Hoyer Iversen
72d7e6e9dd Added requirements to yr sensor 2015-12-01 12:57:08 +01:00
Daniel Hoyer Iversen
f912daf4b2 Updated yr sensor 2015-12-01 12:46:08 +01:00
Daniel Hoyer Iversen
d9fc2a8bf6 initial version of yr.no weather component 2015-11-30 17:00:28 +01:00
MartinHjelmare
45fe37a301 Add mysensors component and switch platform
* Add a general mysensors component. This sets up the serial comm
        with the gateway through pymysensors. The component also
        contains a decorator function for the callback function of
        mysensors platforms. Mysensors platforms should create a
        function that listens for the node update event fired by the
        mysensors component. This function should call another
        function, that uses the decorator, and returns a dict. The dict
        should contain a list of which mysensors V_TYPE values the
        platform handles, the platfrom class and the add_devices
        function (from setup_platform).
    * Change existing mysensors sensor platform to depend on the new
        mysensors component.
    * Add a mysensors switch platform. The switch platform takes
        advantage of new functionality from the the fork of pymysensors
        https://github.com/MartinHjelmare/pymysensors, that enables the
        gateway to send commands to change node child values.
    * Change const and is_metric to global constants, in the mysensors
        component and import const depending on the mysensors version
        used.
    * Change variables devices and gateway to global variables.
    * Add some debug logging at INFO log level.
2015-11-06 01:58:41 +01:00
Malte Deiseroth
ef76047ba2 new try to add everythin from the stylecheckers 2015-09-22 13:27:08 +02:00
Malte Deiseroth
d475e5362b respect flake8 errors 2015-09-22 12:53:44 +02:00
Malte Deiseroth
3027b4a5a8 respect pylint suggestions 2015-09-22 12:32:45 +02:00
Malte Deiseroth
3829abbd2d updated with remote 2015-09-22 12:18:00 +02:00
Malte Deiseroth
e6e3b37a62 merged with current dev 2015-09-22 12:11:57 +02:00
Malte Deiseroth
ce501ae627 Improved onewire configuration 2015-09-16 14:17:41 +02:00
deisi
b6f954e082 Changed handling of config file
I tried to implement your suggesteions for the default handlig of the device names. I think this way, everything you wanted is in.
2015-09-16 10:18:11 +02:00
deisi
b368388714 Update .gitignore 2015-09-16 08:49:12 +02:00
Malte Deiseroth
8842e4e94f gitignore ready for emacs 2015-09-16 08:34:08 +02:00
Malte Deiseroth
0ed608abff little bug 2015-04-07 21:10:16 +02:00
Malte Deiseroth
afcf3eaac3 - add ds18S20 1-Wire sensor support
- gitignore emacs backup files
2015-03-29 14:48:17 +02:00
706 changed files with 61083 additions and 20036 deletions

View File

@@ -3,50 +3,117 @@ source = homeassistant
omit =
homeassistant/__main__.py
homeassistant/scripts/*.py
# omit pieces of code that rely on external devices being present
homeassistant/components/apcupsd.py
homeassistant/components/*/apcupsd.py
homeassistant/components/arduino.py
homeassistant/components/*/arduino.py
homeassistant/components/bloomsky.py
homeassistant/components/*/bloomsky.py
homeassistant/components/dweet.py
homeassistant/components/*/dweet.py
homeassistant/components/ecobee.py
homeassistant/components/*/ecobee.py
homeassistant/components/envisalink.py
homeassistant/components/*/envisalink.py
homeassistant/components/insteon_hub.py
homeassistant/components/*/insteon_hub.py
homeassistant/components/isy994.py
homeassistant/components/*/isy994.py
homeassistant/components/modbus.py
homeassistant/components/*/modbus.py
homeassistant/components/*/tellstick.py
homeassistant/components/*/vera.py
homeassistant/components/mysensors.py
homeassistant/components/*/mysensors.py
homeassistant/components/ecobee.py
homeassistant/components/*/ecobee.py
homeassistant/components/nest.py
homeassistant/components/*/nest.py
homeassistant/components/octoprint.py
homeassistant/components/*/octoprint.py
homeassistant/components/qwikswitch.py
homeassistant/components/*/qwikswitch.py
homeassistant/components/rpi_gpio.py
homeassistant/components/*/rpi_gpio.py
homeassistant/components/scsgate.py
homeassistant/components/*/scsgate.py
homeassistant/components/tellduslive.py
homeassistant/components/*/tellduslive.py
homeassistant/components/tellstick.py
homeassistant/components/*/tellstick.py
homeassistant/components/*/thinkingcleaner.py
homeassistant/components/vera.py
homeassistant/components/*/vera.py
homeassistant/components/verisure.py
homeassistant/components/*/verisure.py
homeassistant/components/*/webostv.py
homeassistant/components/wemo.py
homeassistant/components/*/wemo.py
homeassistant/components/wink.py
homeassistant/components/*/wink.py
homeassistant/components/zigbee.py
homeassistant/components/*/zigbee.py
homeassistant/components/zwave.py
homeassistant/components/*/zwave.py
homeassistant/components/rfxtrx.py
homeassistant/components/*/rfxtrx.py
homeassistant/components/enocean.py
homeassistant/components/*/enocean.py
homeassistant/components/netatmo.py
homeassistant/components/*/netatmo.py
homeassistant/components/homematic.py
homeassistant/components/*/homematic.py
homeassistant/components/knx.py
homeassistant/components/switch/knx.py
homeassistant/components/binary_sensor/knx.py
homeassistant/components/alarm_control_panel/alarmdotcom.py
homeassistant/components/alarm_control_panel/nx584.py
homeassistant/components/alarm_control_panel/simplisafe.py
homeassistant/components/binary_sensor/arest.py
homeassistant/components/binary_sensor/rest.py
homeassistant/components/browser.py
homeassistant/components/camera/*
homeassistant/components/camera/bloomsky.py
homeassistant/components/camera/foscam.py
homeassistant/components/camera/generic.py
homeassistant/components/camera/mjpeg.py
homeassistant/components/camera/rpi_camera.py
homeassistant/components/device_tracker/actiontec.py
homeassistant/components/device_tracker/aruba.py
homeassistant/components/device_tracker/asuswrt.py
homeassistant/components/device_tracker/bluetooth_tracker.py
homeassistant/components/device_tracker/bt_home_hub_5.py
homeassistant/components/device_tracker/ddwrt.py
homeassistant/components/device_tracker/fritz.py
homeassistant/components/device_tracker/geofancy.py
homeassistant/components/device_tracker/icloud.py
homeassistant/components/device_tracker/luci.py
homeassistant/components/device_tracker/netgear.py
homeassistant/components/device_tracker/nmap_tracker.py
homeassistant/components/device_tracker/owntracks.py
homeassistant/components/device_tracker/snmp.py
homeassistant/components/device_tracker/thomson.py
homeassistant/components/device_tracker/tomato.py
@@ -54,46 +121,94 @@ omit =
homeassistant/components/device_tracker/ubus.py
homeassistant/components/discovery.py
homeassistant/components/downloader.py
homeassistant/components/feedreader.py
homeassistant/components/garage_door/wink.py
homeassistant/components/garage_door/rpi_gpio.py
homeassistant/components/hdmi_cec.py
homeassistant/components/ifttt.py
homeassistant/components/influxdb.py
homeassistant/components/joaoapps_join.py
homeassistant/components/keyboard.py
homeassistant/components/light/blinksticklight.py
homeassistant/components/light/hue.py
homeassistant/components/light/hyperion.py
homeassistant/components/light/lifx.py
homeassistant/components/light/limitlessled.py
homeassistant/components/light/osramlightify.py
homeassistant/components/lirc.py
homeassistant/components/media_player/braviatv.py
homeassistant/components/media_player/cast.py
homeassistant/components/media_player/cmus.py
homeassistant/components/media_player/denon.py
homeassistant/components/media_player/firetv.py
homeassistant/components/media_player/gpmdp.py
homeassistant/components/media_player/itunes.py
homeassistant/components/media_player/kodi.py
homeassistant/components/media_player/lg_netcast.py
homeassistant/components/media_player/mpd.py
homeassistant/components/media_player/onkyo.py
homeassistant/components/media_player/panasonic_viera.py
homeassistant/components/media_player/pandora.py
homeassistant/components/media_player/pioneer.py
homeassistant/components/media_player/plex.py
homeassistant/components/media_player/roku.py
homeassistant/components/media_player/samsungtv.py
homeassistant/components/media_player/snapcast.py
homeassistant/components/media_player/sonos.py
homeassistant/components/media_player/squeezebox.py
homeassistant/components/media_player/yamaha.py
homeassistant/components/notify/aws_lambda.py
homeassistant/components/notify/aws_sns.py
homeassistant/components/notify/aws_sqs.py
homeassistant/components/notify/free_mobile.py
homeassistant/components/notify/gntp.py
homeassistant/components/notify/googlevoice.py
homeassistant/components/notify/instapush.py
homeassistant/components/notify/joaoapps_join.py
homeassistant/components/notify/message_bird.py
homeassistant/components/notify/nma.py
homeassistant/components/notify/pushbullet.py
homeassistant/components/notify/pushetta.py
homeassistant/components/notify/pushover.py
homeassistant/components/notify/rest.py
homeassistant/components/notify/sendgrid.py
homeassistant/components/notify/slack.py
homeassistant/components/notify/smtp.py
homeassistant/components/notify/syslog.py
homeassistant/components/notify/telegram.py
homeassistant/components/notify/twilio_sms.py
homeassistant/components/notify/twitter.py
homeassistant/components/notify/xmpp.py
homeassistant/components/scene/hunterdouglas_powerview.py
homeassistant/components/sensor/arest.py
homeassistant/components/sensor/bitcoin.py
homeassistant/components/sensor/cpuspeed.py
homeassistant/components/sensor/deutsche_bahn.py
homeassistant/components/sensor/dht.py
homeassistant/components/sensor/dweet.py
homeassistant/components/sensor/dte_energy_bridge.py
homeassistant/components/sensor/efergy.py
homeassistant/components/sensor/eliqonline.py
homeassistant/components/sensor/fitbit.py
homeassistant/components/sensor/fixer.py
homeassistant/components/sensor/forecast.py
homeassistant/components/sensor/glances.py
homeassistant/components/sensor/mysensors.py
homeassistant/components/sensor/google_travel_time.py
homeassistant/components/sensor/gtfs.py
homeassistant/components/sensor/imap.py
homeassistant/components/sensor/lastfm.py
homeassistant/components/sensor/loopenergy.py
homeassistant/components/sensor/neurio_energy.py
homeassistant/components/sensor/nzbget.py
homeassistant/components/sensor/onewire.py
homeassistant/components/sensor/openweathermap.py
homeassistant/components/sensor/openexchangerates.py
homeassistant/components/sensor/plex.py
homeassistant/components/sensor/rest.py
homeassistant/components/sensor/rpi_gpio.py
homeassistant/components/sensor/sabnzbd.py
homeassistant/components/sensor/snmp.py
homeassistant/components/sensor/speedtest.py
homeassistant/components/sensor/steam_online.py
homeassistant/components/sensor/supervisord.py
homeassistant/components/sensor/swiss_hydrological_data.py
homeassistant/components/sensor/swiss_public_transport.py
homeassistant/components/sensor/systemmonitor.py
homeassistant/components/sensor/temper.py
@@ -101,21 +216,30 @@ omit =
homeassistant/components/sensor/torque.py
homeassistant/components/sensor/transmission.py
homeassistant/components/sensor/twitch.py
homeassistant/components/sensor/uber.py
homeassistant/components/sensor/worldclock.py
homeassistant/components/sensor/yweather.py
homeassistant/components/switch/acer_projector.py
homeassistant/components/switch/arest.py
homeassistant/components/switch/dlink.py
homeassistant/components/switch/edimax.py
homeassistant/components/switch/hikvisioncam.py
homeassistant/components/switch/mystrom.py
homeassistant/components/switch/netio.py
homeassistant/components/switch/orvibo.py
homeassistant/components/switch/pulseaudio_loopback.py
homeassistant/components/switch/rest.py
homeassistant/components/switch/rpi_gpio.py
homeassistant/components/switch/rpi_rf.py
homeassistant/components/switch/tplink.py
homeassistant/components/switch/transmission.py
homeassistant/components/switch/wemo.py
homeassistant/components/switch/wake_on_lan.py
homeassistant/components/thermostat/eq3btsmart.py
homeassistant/components/thermostat/heatmiser.py
homeassistant/components/thermostat/homematic.py
homeassistant/components/thermostat/honeywell.py
homeassistant/components/thermostat/nest.py
homeassistant/components/thermostat/proliphix.py
homeassistant/components/thermostat/radiotherm.py
homeassistant/components/upnp.py
homeassistant/components/zeroconf.py
[report]

35
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,35 @@
Make sure you are running the latest version of Home Assistant before reporting an issue.
You should only file an issue if you found a bug. Feature and enhancement requests should go in [the Feature Requests section](https://community.home-assistant.io/c/feature-requests) of our community forum:
**Home Assistant release (`hass --version`):**
**Python release (`python3 --version`):**
**Component/platform:**
**Description of problem:**
**Expected:**
**Problem-relevant `configuration.yaml` entries and steps to reproduce:**
```yaml
```
1.
2.
3.
**Traceback (if applicable):**
```bash
```
**Additional info:**

30
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,30 @@
**Description:**
**Related issue (if applicable):** fixes #
**Pull request in [home-assistant.io](https://github.com/home-assistant/home-assistant.io) with documentation (if applicable):** home-assistant/home-assistant.io#
**Example entry for `configuration.yaml` (if applicable):**
```yaml
```
**Checklist:**
If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [home-assistant.io](https://github.com/home-assistant/home-assistant.io)
If code communicates with devices, web services, or a:
- [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**
- [ ] New dependencies have been added to the `REQUIREMENTS` variable ([example][ex-requir]).
- [ ] New dependencies are only imported inside functions that use them ([example][ex-import]).
- [ ] New dependencies have been added to `requirements_all.txt` by running `script/gen_requirements_all.py`.
- [ ] New files were added to `.coveragerc`.
If the code does not interact with devices:
- [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**
- [ ] Tests have been added to verify that the new code works.
[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L16
[ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L51

21
.gitignore vendored
View File

@@ -1,6 +1,5 @@
config/*
!config/home-assistant.conf.default
homeassistant/components/frontend/www_static/polymer/bower_components/*
# There is not a better solution afaik..
!config/custom_components
@@ -9,6 +8,7 @@ config/custom_components/*
!config/custom_components/hello_world.py
!config/custom_components/mqtt_example.py
tests/config/deps
tests/config/home-assistant.log
# Hide sublime text stuff
@@ -41,6 +41,7 @@ Icon
dist
build
eggs
.eggs
parts
bin
var
@@ -68,6 +69,24 @@ nosetests.xml
.python-version
# emacs auto backups
*~
*#
*.orig
# venv stuff
pyvenv.cfg
pip-selfcheck.json
venv
.venv
# vimmy stuff
*.swp
*.swo
ctags.tmp
# vagrant stuff
virtualization/vagrant/setup_done
virtualization/vagrant/.vagrant
virtualization/vagrant/config

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "homeassistant/components/frontend/www_static/home-assistant-polymer"]
path = homeassistant/components/frontend/www_static/home-assistant-polymer
url = https://github.com/balloob/home-assistant-polymer.git
url = https://github.com/home-assistant/home-assistant-polymer.git

View File

@@ -1,17 +1,19 @@
sudo: false
language: python
matrix:
fast_finish: true
include:
- python: "3.4"
env: TOXENV=py34
- python: "3.4"
env: TOXENV=requirements
- python: "3.5"
env: TOXENV=lint
- python: "3.5"
env: TOXENV=py35
cache:
directories:
- $HOME/.cache/pip
# - "$HOME/virtualenv/python$TRAVIS_PYTHON_VERSION"
python:
- 3.4
- 3.5
install:
# Validate requirements_all.txt on Python 3.5
- if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then python3 setup.py develop; script/gen_requirements_all.py validate; fi
- script/bootstrap_server
script:
- script/cibuild
matrix:
fast_finish: true
install: pip install -U tox coveralls
language: python
script: tox
after_success: coveralls

View File

@@ -4,68 +4,10 @@ Everybody is invited and welcome to contribute to Home Assistant. There is a lot
The process is straight-forward.
- Fork the Home Assistant [git repository](https://github.com/balloob/home-assistant).
- Fork the Home Assistant [git repository](https://github.com/home-assistant/home-assistant).
- Write the code for your device, notification service, sensor, or IoT thing.
- Check it with ``pylint`` and ``flake8``.
- Create a Pull Request against the [**dev**](https://github.com/balloob/home-assistant/tree/dev) branch of Home Assistant.
- Ensure tests work.
- Create a Pull Request against the [**dev**](https://github.com/home-assistant/home-assistant/tree/dev) branch of Home Assistant.
Still interested? Then you should read the next sections and get more details.
Still interested? Then you should take a peak at the [developer documentation](https://home-assistant.io/developers/) to get more details.
## Adding support for a new device
For help on building your component, please see the [developer documentation](https://home-assistant.io/developers/) on [home-assistant.io](https://home-assistant.io/).
After you finish adding support for your device:
- Add any new dependencies to `requirements_all.txt` if needed. Use `script/gen_requirements_all.py`.
- Update the `.coveragerc` file to exclude your platform if there are no tests available.
- Provide some documentation for [home-assistant.io](https://home-assistant.io/). It's OK to just add a docstring with configuration details (sample entry for `configuration.yaml` file and alike) to the file header as a start. Visit the [website documentation](https://home-assistant.io/developers/website/) for further information on contributing to [home-assistant.io](https://github.com/balloob/home-assistant.io).
- Make sure all your code passes ``pylint`` and ``flake8`` (PEP8 and some more) validation. To check your repository, run `./script/lint`.
- Create a Pull Request against the [**dev**](https://github.com/balloob/home-assistant/tree/dev) branch of Home Assistant.
- Check for comments and suggestions on your Pull Request and keep an eye on the [Travis output](https://travis-ci.org/balloob/home-assistant/).
If you add a platform for an existing component, there is usually no need for updating the frontend. Only if you've added a new component that should show up in the frontend, there are more steps needed:
- Update the file [`home-assistant-icons.html`](https://github.com/balloob/home-assistant/blob/master/homeassistant/components/frontend/www_static/polymer/resources/home-assistant-icons.html) with an icon for your domain ([pick one from this list](https://www.polymer-project.org/1.0/components/core-elements/demo.html#core-icon)).
- Update the demo component with two states that it provides.
- Add your component to `home-assistant.conf.example`.
Since you've updated `home-assistant-icons.html`, you've made changes to the frontend:
- Run `build_frontend`. This will build a new version of the frontend. Make sure you add the changed files `frontend.py` and `frontend.html` to the commit.
### Setting states
It is the responsibility of the component to maintain the states of the devices in your domain. Each device should be a single state and, if possible, a group should be provided that tracks the combined state of the devices.
A state can have several attributes that will help the frontend in displaying your state:
- `friendly_name`: this name will be used as the name of the device
- `entity_picture`: this picture will be shown instead of the domain icon
- `unit_of_measurement`: this will be appended to the state in the interface
- `hidden`: This is a suggestion to the frontend on if the state should be hidden
These attributes are defined in [homeassistant.components](https://github.com/balloob/home-assistant/blob/master/homeassistant/components/__init__.py#L25).
### Proper Visibility Handling
Generally, when creating a new entity for Home Assistant you will want it to be a class that inherits the [homeassistant.helpers.entity.Entity](https://github.com/balloob/home-assistant/blob/master/homeassistant/helpers/entity.py) class. If this is done, visibility will be handled for you.
You can set a suggestion for your entity's visibility by setting the hidden property by doing something similar to the following.
```python
self.hidden = True
```
This will SUGGEST that the active frontend hides the entity. This requires that the active frontend support hidden cards (the default frontend does) and that the value of hidden be included in your attributes dictionary (see above). The Entity abstract class will take care of this for you.
Remember: The suggestion set by your component's code will always be overwritten by user settings in the configuration.yaml file. This is why you may set hidden to be False, but the property may remain True (or vice-versa).
### Working on the frontend
The frontend is composed of [Polymer](https://www.polymer-project.org) web-components and compiled into the file `frontend.html`. During development you do not want to work with the compiled version but with the seperate files. To have Home Assistant serve the seperate files, set `development=1` for the *http-component* in your config.
When you are done with development and ready to commit your changes, run `build_frontend`, set `development=0` in your config and validate that everything still works.
### Notes on PyLint and PEP8 validation
In case a PyLint warning cannot be avoided, add a comment to disable the PyLint check for that line. This can be done using the format `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable PyLint warning is if you do not use the passed in datetime if you're listening for time change.

View File

@@ -6,20 +6,21 @@ VOLUME /config
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# For the nmap tracker
RUN pip3 install --no-cache-dir colorlog cython
# For the nmap tracker, bluetooth tracker, Z-Wave
RUN apt-get update && \
apt-get install -y --no-install-recommends nmap net-tools && \
apt-get install -y --no-install-recommends nmap net-tools cython3 libudev-dev sudo libglib2.0-dev && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY script/build_python_openzwave script/build_python_openzwave
RUN apt-get update && \
apt-get install -y cython3 libudev-dev && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
pip3 install "cython<0.23" && \
script/build_python_openzwave
RUN script/build_python_openzwave && \
mkdir -p /usr/local/share/python-openzwave && \
ln -sf /usr/src/app/build/python-openzwave/openzwave/config /usr/local/share/python-openzwave/config
COPY requirements_all.txt requirements_all.txt
RUN pip3 install --no-cache-dir -r requirements_all.txt
# certifi breaks Debian based installs
RUN pip3 install --no-cache-dir -r requirements_all.txt && pip3 uninstall -y certifi
# Copy source
COPY . .

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013 Paulus Schoutsen
Copyright (c) 2016 Paulus Schoutsen
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@@ -1,5 +1,5 @@
Home Assistant |Build Status| |Coverage Status| |Join the chat at https://gitter.im/balloob/home-assistant|
===========================================================================================================
Home Assistant |Build Status| |Coverage Status| |Join the chat at https://gitter.im/home-assistant/home-assistant| |Join the dev chat at https://gitter.im/home-assistant/home-assistant/devs|
==============================================================================================================================================================================================
Home Assistant is a home automation platform running on Python 3. The
goal of Home Assistant is to be able to track and control all devices at
@@ -18,7 +18,7 @@ tutorials and documentation.
|screenshot-states|
Examples of devices it can interface it:
Examples of devices Home Assistant can interface with:
- Monitoring connected devices to a wireless router:
`OpenWrt <https://openwrt.org/>`__,
@@ -61,11 +61,11 @@ Examples of devices it can interface it:
- `See full list of supported
devices <https://home-assistant.io/components/>`__
Built home automation on top of your devices:
Build home automation on top of your devices:
- Keep a precise history of every change to the state of your house
- Turn on the lights when people get home after sun set
- Turn on lights slowly during sun set to compensate for less light
- Turn on the lights when people get home after sunset
- Turn on lights slowly during sunset to compensate for less light
- Turn off all lights and devices when everybody leaves the house
- Offers a `REST API <https://home-assistant.io/developers/api/>`__
and can interface with MQTT for easy integration with other projects
@@ -75,24 +75,26 @@ Built home automation on top of your devices:
(NMA) <http://www.notifymyandroid.com/>`__,
`PushBullet <https://www.pushbullet.com/>`__,
`PushOver <https://pushover.net/>`__, `Slack <https://slack.com/>`__,
`Telegram <https://telegram.org/>`__, and `Jabber
`Telegram <https://telegram.org/>`__, `Join <http://joaoapps.com/join/>`__, and `Jabber
(XMPP) <http://xmpp.org>`__
The system is built modular so support for other devices or actions can
The system is built using a modular approach so support for other devices or actions can
be implemented easily. See also the `section on
architecture <https://home-assistant.io/developers/architecture.html>`__
architecture <https://home-assistant.io/developers/architecture/>`__
and the `section on creating your own
components <https://home-assistant.io/developers/creating_components.html>`__.
components <https://home-assistant.io/developers/creating_components/>`__.
If you run into issues while using Home Assistant or during development
of a component, check the `Home Assistant help
section <https://home-assistant.io/help/>`__ how to reach us.
.. |Build Status| image:: https://travis-ci.org/balloob/home-assistant.svg?branch=master
:target: https://travis-ci.org/balloob/home-assistant
.. |Coverage Status| image:: https://img.shields.io/coveralls/balloob/home-assistant.svg
:target: https://coveralls.io/r/balloob/home-assistant?branch=master
.. |Join the chat at https://gitter.im/balloob/home-assistant| image:: https://badges.gitter.im/Join%20Chat.svg
:target: https://gitter.im/balloob/home-assistant?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
.. |screenshot-states| image:: https://raw.github.com/balloob/home-assistant/master/docs/screenshots.png
.. |Build Status| image:: https://travis-ci.org/home-assistant/home-assistant.svg?branch=master
:target: https://travis-ci.org/home-assistant/home-assistant
.. |Coverage Status| image:: https://img.shields.io/coveralls/home-assistant/home-assistant.svg
:target: https://coveralls.io/r/home-assistant/home-assistant?branch=master
.. |Join the chat at https://gitter.im/home-assistant/home-assistant| image:: https://img.shields.io/badge/gitter-general-blue.svg
:target: https://gitter.im/home-assistant/home-assistant?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
.. |Join the dev chat at https://gitter.im/home-assistant/home-assistant/devs| image:: https://img.shields.io/badge/gitter-development-yellowgreen.svg
:target: https://gitter.im/home-assistant/home-assistant/devs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
.. |screenshot-states| image:: https://raw.github.com/home-assistant/home-assistant/master/docs/screenshots.png
:target: https://home-assistant.io/demo/

View File

@@ -1,13 +1,16 @@
homeassistant:
# Omitted values in this section will be auto detected using freegeoip.net
# Omitted values in this section will be auto detected using freegeoip.io
# Location required to calculate the time the sun rises and sets.
# Cooridinates are also used for location for weather related components.
# Google Maps can be used to determine more precise GPS cooridinates.
# Coordinates are also used for location for weather related components.
# Google Maps can be used to determine more precise GPS coordinates.
latitude: 32.87336
longitude: 117.22743
# C for Celcius, F for Fahrenheit
# Impacts weather/sunrise data
elevation: 665
# C for Celsius, F for Fahrenheit
temperature_unit: C
# Pick yours from here:
@@ -22,6 +25,9 @@ http:
# Set to 1 to enable development mode
# development: 1
# Enable the frontend
frontend:
light:
# platform: hue
@@ -30,17 +36,12 @@ wink:
access_token: 'YOUR_TOKEN'
device_tracker:
# The following types are available: ddwrt, netgear, tomato, luci,
# and nmap_tracker
# The following tracker are available:
# https://home-assistant.io/components/#presence-detection
platform: netgear
host: 192.168.1.1
username: admin
password: PASSWORD
# http_id is needed for Tomato routers only
# http_id: ABCDEFGHH
# For nmap_tracker, only the IP addresses to scan are needed:
# hosts: 192.168.1.1/24 # netmask prefix notation or
# hosts: 192.168.1.1-255 # address range
chromecast:
@@ -71,24 +72,25 @@ device_sun_light_trigger:
# A comma separated list of states that have to be tracked as a single group
# Grouped states should share the same type of states (ON/OFF or HOME/NOT_HOME)
# You can also have groups within groups.
# https://home-assistant.io/components/group/
group:
Home:
- group.living_room
- group.kitchen
living_room:
- light.Bowl
- light.Ceiling
- light.TV_back_light
kitchen:
- light.fan_bulb_1
- light.fan_bulb_2
children:
- device_tracker.child_1
- device_tracker.child_2
default_view:
view: yes
entities:
- group.awesome_people
- group.climate
process:
# items are which processes to look for: <entity_id>: <search string within ps>
xbmc: XBMC.App
kitchen:
name: Kitchen
entities:
- switch.kitchen_pin_3
upstairs:
name: Kids
icon: mdi:account-multiple
view: yes
entities:
- input_boolean.notify_home
- camera.demo_camera
example:
@@ -102,6 +104,7 @@ browser:
keyboard:
# https://home-assistant.io/getting-started/automation/
automation:
- alias: 'Rule 1 Light on in the evening'
trigger:
@@ -123,7 +126,6 @@ automation:
entity_id: group.living_room
- alias: 'Rule 2 - Away Mode'
trigger:
- platform: state
entity_id: group.all_devices
@@ -136,6 +138,14 @@ automation:
# Sensors need to be added into the configuration.yaml as sensor:, sensor 2:, sensor 3:, etc.
# Each sensor label should be unique or your sensors might not load correctly.
# Another way to do is to collect all entries under one "sensor:"
# sensor:
# - platform: mqtt
# name: "MQTT Sensor 1"
# - platform: mqtt
# name: "MQTT Sensor 2"
#
# Details: https://home-assistant.io/getting-started/devices/
sensor:
platform: systemmonitor
@@ -146,14 +156,6 @@ sensor:
arg: '/home'
- type: 'disk_use'
arg: '/home'
- type: 'disk_free'
arg: '/'
- type: 'memory_use_percent'
- type: 'memory_use'
- type: 'memory_free'
- type: 'processor_use'
- type: 'process'
arg: 'octave-cli'
sensor 2:
platform: forecast
@@ -163,14 +165,6 @@ sensor 2:
- precip_type
- precip_intensity
- temperature
- dew_point
- wind_speed
- wind_bearing
- cloud_cover
- humidity
- pressure
- visibility
- ozone
script:
# Turns on the bedroom lights and then the living room lights 1 minute later

View File

@@ -1,6 +1,5 @@
"""
custom_components.example
~~~~~~~~~~~~~~~~~~~~~~~~~
Example of a custom component.
Example component to target an entity_id to:
- turn it on at 7AM in the morning
@@ -29,22 +28,29 @@ import time
import logging
from homeassistant.const import STATE_HOME, STATE_NOT_HOME, STATE_ON, STATE_OFF
import homeassistant.loader as loader
from homeassistant.helpers import validate_config
from homeassistant.helpers.event_decorators import \
track_state_change, track_time_change
from homeassistant.helpers.service import service
import homeassistant.components as core
from homeassistant.components import device_tracker
from homeassistant.components import light
# The domain of your component. Should be equal to the name of your component
# The domain of your component. Should be equal to the name of your component.
DOMAIN = "example"
# List of component names (string) your component depends upon
# List of component names (string) your component depends upon.
# We depend on group because group will be loaded after all the components that
# initialize devices have been setup.
DEPENDENCIES = ['group']
DEPENDENCIES = ['group', 'device_tracker', 'light']
# Configuration key for the entity id we are targetting
# Configuration key for the entity id we are targeting.
CONF_TARGET = 'target'
# Name of the service that we expose
# Variable for storing configuration parameters.
TARGET_ID = None
# Name of the service that we expose.
SERVICE_FLASH = 'flash'
# Shortcut for the logger
@@ -52,85 +58,92 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config):
""" Setup example component. """
"""Setup example component."""
global TARGET_ID
# Validate that all required config options are given
# Validate that all required config options are given.
if not validate_config(config, {DOMAIN: [CONF_TARGET]}, _LOGGER):
return False
target_id = config[DOMAIN][CONF_TARGET]
TARGET_ID = config[DOMAIN][CONF_TARGET]
# Validate that the target entity id exists
if hass.states.get(target_id) is None:
_LOGGER.error("Target entity id %s does not exist", target_id)
# Validate that the target entity id exists.
if hass.states.get(TARGET_ID) is None:
_LOGGER.error("Target entity id %s does not exist",
TARGET_ID)
# Tell the bootstrapper that we failed to initialize
# Tell the bootstrapper that we failed to initialize and clear the
# stored target id so our functions don't run.
TARGET_ID = None
return False
# We will use the component helper methods to check the states.
device_tracker = loader.get_component('device_tracker')
light = loader.get_component('light')
def track_devices(entity_id, old_state, new_state):
""" Called when the group.all devices change state. """
# If anyone comes home and the core is not on, turn it on.
if new_state.state == STATE_HOME and not core.is_on(hass, target_id):
core.turn_on(hass, target_id)
# If all people leave the house and the core is on, turn it off
elif new_state.state == STATE_NOT_HOME and core.is_on(hass, target_id):
core.turn_off(hass, target_id)
# Register our track_devices method to receive state changes of the
# all tracked devices group.
hass.states.track_change(
device_tracker.ENTITY_ID_ALL_DEVICES, track_devices)
def wake_up(now):
""" Turn it on in the morning if there are people home and
it is not already on. """
if device_tracker.is_on(hass) and not core.is_on(hass, target_id):
_LOGGER.info('People home at 7AM, turning it on')
core.turn_on(hass, target_id)
# Register our wake_up service to be called at 7AM in the morning
hass.track_time_change(wake_up, hour=7, minute=0, second=0)
def all_lights_off(entity_id, old_state, new_state):
""" If all lights turn off, turn off. """
if core.is_on(hass, target_id):
_LOGGER.info('All lights have been turned off, turning it off')
core.turn_off(hass, target_id)
# Register our all_lights_off method to be called when all lights turn off
hass.states.track_change(
light.ENTITY_ID_ALL_LIGHTS, all_lights_off, STATE_ON, STATE_OFF)
def flash_service(call):
""" Service that will turn the target off for 10 seconds
if on and vice versa. """
if core.is_on(hass, target_id):
core.turn_off(hass, target_id)
time.sleep(10)
core.turn_on(hass, target_id)
else:
core.turn_on(hass, target_id)
time.sleep(10)
core.turn_off(hass, target_id)
# Register our service with HASS.
hass.services.register(DOMAIN, SERVICE_FLASH, flash_service)
# Tells the bootstrapper that the component was successfully initialized
# Tell the bootstrapper that we initialized successfully.
return True
@track_state_change(device_tracker.ENTITY_ID_ALL_DEVICES)
def track_devices(hass, entity_id, old_state, new_state):
"""Called when the group.all devices change state."""
# If the target id is not set, return
if not TARGET_ID:
return
# If anyone comes home and the entity is not on, turn it on.
if new_state.state == STATE_HOME and not core.is_on(hass, TARGET_ID):
core.turn_on(hass, TARGET_ID)
# If all people leave the house and the entity is on, turn it off.
elif new_state.state == STATE_NOT_HOME and core.is_on(hass, TARGET_ID):
core.turn_off(hass, TARGET_ID)
@track_time_change(hour=7, minute=0, second=0)
def wake_up(hass, now):
"""Turn light on in the morning.
Turn the light on at 7 AM if there are people home and it is not already
on.
"""
if not TARGET_ID:
return
if device_tracker.is_on(hass) and not core.is_on(hass, TARGET_ID):
_LOGGER.info('People home at 7AM, turning it on')
core.turn_on(hass, TARGET_ID)
@track_state_change(light.ENTITY_ID_ALL_LIGHTS, STATE_ON, STATE_OFF)
def all_lights_off(hass, entity_id, old_state, new_state):
"""If all lights turn off, turn off."""
if not TARGET_ID:
return
if core.is_on(hass, TARGET_ID):
_LOGGER.info('All lights have been turned off, turning it off')
core.turn_off(hass, TARGET_ID)
@service(DOMAIN, SERVICE_FLASH)
def flash_service(hass, call):
"""Service that will toggle the target.
Set the light to off for 10 seconds if on and vice versa.
"""
if not TARGET_ID:
return
if core.is_on(hass, TARGET_ID):
core.turn_off(hass, TARGET_ID)
time.sleep(10)
core.turn_on(hass, TARGET_ID)
else:
core.turn_on(hass, TARGET_ID)
time.sleep(10)
core.turn_off(hass, TARGET_ID)

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 232 KiB

567
docs/swagger.yaml Normal file
View File

@@ -0,0 +1,567 @@
swagger: '2.0'
info:
title: Home Assistant
description: Home Assistant REST API
version: "1.0.0"
# the domain of the service
host: localhost:8123
# array of all schemes that your API supports
schemes:
- http
- https
securityDefinitions:
api_key:
type: apiKey
description: API password
name: api_password
in: query
# api_key:
# type: apiKey
# description: API password
# name: x-ha-access
# in: header
# will be prefixed to all paths
basePath: /api
consumes:
- application/json
produces:
- application/json
paths:
/:
get:
summary: API alive message
description: Returns message if API is up and running.
tags:
- Core
responses:
200:
description: API is up and running
schema:
$ref: '#/definitions/Message'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/config:
get:
summary: API alive message
description: Returns the current configuration as JSON.
tags:
- Core
responses:
200:
description: Current configuration
schema:
$ref: '#/definitions/ApiConfig'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/discovery_info:
get:
summary: Basic information about Home Assistant instance
tags:
- Core
responses:
200:
description: Basic information
schema:
$ref: '#/definitions/DiscoveryInfo'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/bootstrap:
get:
summary: Returns all data needed to bootstrap Home Assistant.
tags:
- Core
responses:
200:
description: Bootstrap information
schema:
$ref: '#/definitions/BootstrapInfo'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/events:
get:
summary: Array of event objects.
description: Returns an array of event objects. Each event object contain event name and listener count.
tags:
- Events
responses:
200:
description: Events
schema:
type: array
items:
$ref: '#/definitions/Event'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/services:
get:
summary: Array of service objects.
description: Returns an array of service objects. Each object contains the domain and which services it contains.
tags:
- Services
responses:
200:
description: Services
schema:
type: array
items:
$ref: '#/definitions/Service'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/history:
get:
summary: Array of state changes in the past.
description: Returns an array of state changes in the past. Each object contains further detail for the entities.
tags:
- State
responses:
200:
description: State changes
schema:
type: array
items:
$ref: '#/definitions/History'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/states:
get:
summary: Array of state objects.
description: |
Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes.
tags:
- State
responses:
200:
description: States
schema:
type: array
items:
$ref: '#/definitions/State'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/states/{entity_id}:
get:
summary: Specific state object.
description: |
Returns a state object for specified entity_id.
tags:
- State
parameters:
- name: entity_id
in: path
description: entity_id of the entity to query
required: true
type: string
responses:
200:
description: State
schema:
$ref: '#/definitions/State'
404:
description: Not found
schema:
$ref: '#/definitions/Message'
default:
description: Error
schema:
$ref: '#/definitions/Message'
post:
description: |
Updates or creates the current state of an entity.
tags:
- State
consumes:
- application/json
parameters:
- name: entity_id
in: path
description: entity_id to set the state of
required: true
type: string
- $ref: '#/parameters/State'
responses:
200:
description: State of existing entity was set
schema:
$ref: '#/definitions/State'
201:
description: State of new entity was set
schema:
$ref: '#/definitions/State'
headers:
location:
type: string
description: location of the new entity
default:
description: Error
schema:
$ref: '#/definitions/Message'
/error_log:
get:
summary: Error log
description: |
Retrieve all errors logged during the current session of Home Assistant as a plaintext response.
tags:
- Core
produces:
- text/plain
responses:
200:
description: Plain text error log
default:
description: Error
schema:
$ref: '#/definitions/Message'
/camera_proxy/camera.{entity_id}:
get:
summary: Camera image.
description: |
Returns the data (image) from the specified camera entity_id.
tags:
- Camera
produces:
- image/jpeg
parameters:
- name: entity_id
in: path
description: entity_id of the camera to query
required: true
type: string
responses:
200:
description: Camera image
schema:
type: file
default:
description: Error
schema:
$ref: '#/definitions/Message'
/events/{event_type}:
post:
description: |
Fires an event with event_type
tags:
- Events
consumes:
- application/json
parameters:
- name: event_type
in: path
description: event_type to fire event with
required: true
type: string
- $ref: '#/parameters/EventData'
responses:
200:
description: Response message
schema:
$ref: '#/definitions/Message'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/services/{domain}/{service}:
post:
description: |
Calls a service within a specific domain. Will return when the service has been executed or 10 seconds has past, whichever comes first.
tags:
- Services
consumes:
- application/json
parameters:
- name: domain
in: path
description: domain of the service
required: true
type: string
- name: service
in: path
description: service to call
required: true
type: string
- $ref: '#/parameters/ServiceData'
responses:
200:
description: List of states that have changed while the service was being executed. The result will include any changed states that changed while the service was being executed, even if their change was the result of something else happening in the system.
schema:
type: array
items:
$ref: '#/definitions/State'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/template:
post:
description: |
Render a Home Assistant template.
tags:
- Template
consumes:
- application/json
produces:
- text/plain
parameters:
- $ref: '#/parameters/Template'
responses:
200:
description: Returns the rendered template in plain text.
schema:
type: string
default:
description: Error
schema:
$ref: '#/definitions/Message'
/event_forwarding:
post:
description: |
Setup event forwarding to another Home Assistant instance.
tags:
- Core
consumes:
- application/json
parameters:
- $ref: '#/parameters/EventForwarding'
responses:
200:
description: It will return a message if event forwarding was setup successful.
schema:
$ref: '#/definitions/Message'
default:
description: Error
schema:
$ref: '#/definitions/Message'
delete:
description: |
Cancel event forwarding to another Home Assistant instance.
tags:
- Core
consumes:
- application/json
parameters:
- $ref: '#/parameters/EventForwarding'
responses:
200:
description: It will return a message if event forwarding was cancelled successful.
schema:
$ref: '#/definitions/Message'
default:
description: Error
schema:
$ref: '#/definitions/Message'
/stream:
get:
summary: Server-sent events
description: The server-sent events feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer.
tags:
- Core
- Events
produces:
- text/event-stream
parameters:
- name: restrict
in: query
description: comma-separated list of event_types to filter
required: false
type: string
responses:
default:
description: Stream of events
schema:
type: object
x-events:
state_changed:
type: object
properties:
entity_id:
type: string
old_state:
$ref: '#/definitions/State'
new_state:
$ref: '#/definitions/State'
definitions:
ApiConfig:
type: object
properties:
components:
type: array
description: List of component types
items:
type: string
description: Component type
latitude:
type: number
format: float
description: Latitude of Home Assistant server
longitude:
type: number
format: float
description: Longitude of Home Assistant server
location_name:
type: string
temperature_unit:
type: string
time_zone:
type: string
version:
type: string
DiscoveryInfo:
type: object
properties:
base_url:
type: string
location_name:
type: string
requires_api_password:
type: boolean
version:
type: string
BootstrapInfo:
type: object
properties:
config:
$ref: '#/definitions/ApiConfig'
events:
type: array
items:
$ref: '#/definitions/Event'
services:
type: array
items:
$ref: '#/definitions/Service'
states:
type: array
items:
$ref: '#/definitions/State'
Event:
type: object
properties:
event:
type: string
listener_count:
type: integer
Service:
type: object
properties:
domain:
type: string
services:
type: object
additionalProperties:
$ref: '#/definitions/DomainService'
DomainService:
type: object
properties:
description:
type: string
fields:
type: object
description: Object with service fields that can be called
State:
type: object
properties:
attributes:
$ref: '#/definitions/StateAttributes'
state:
type: string
entity_id:
type: string
last_changed:
type: string
format: date-time
StateAttributes:
type: object
additionalProperties:
type: string
History:
allOf:
- $ref: '#/definitions/State'
- type: object
properties:
last_updated:
type: string
format: date-time
Message:
type: object
properties:
message:
type: string
parameters:
State:
name: body
in: body
description: State parameter
required: false
schema:
type: object
required:
- state
properties:
attributes:
$ref: '#/definitions/StateAttributes'
state:
type: string
EventData:
name: body
in: body
description: event_data
required: false
schema:
type: object
ServiceData:
name: body
in: body
description: service_data
required: false
schema:
type: object
Template:
name: body
in: body
description: Template to render
required: true
schema:
type: object
required:
- template
properties:
template:
description: Jinja2 template string
type: string
EventForwarding:
name: body
in: body
description: Event Forwarding parameter
required: true
schema:
type: object
required:
- host
- api_password
properties:
host:
type: string
api_password:
type: string
port:
type: integer

View File

@@ -0,0 +1 @@
"""Init file for Home Assistant."""

View File

@@ -1,28 +1,36 @@
""" Starts home assistant. """
"""Starts home assistant."""
from __future__ import print_function
import sys
import os
import argparse
import os
import platform
import subprocess
import sys
import threading
from homeassistant import bootstrap
import homeassistant.config as config_util
from homeassistant.const import __version__, EVENT_HOMEASSISTANT_START
from homeassistant.const import (
__version__,
EVENT_HOMEASSISTANT_START,
REQUIRED_PYTHON_VER,
RESTART_EXIT_CODE,
)
def validate_python():
""" Validate we're running the right Python version. """
"""Validate we're running the right Python version."""
major, minor = sys.version_info[:2]
req_major, req_minor = REQUIRED_PYTHON_VER
if major < 3 or (major == 3 and minor < 4):
print("Home Assistant requires atleast Python 3.4")
if major < req_major or (major == req_major and minor < req_minor):
print("Home Assistant requires at least Python {}.{}".format(
req_major, req_minor))
sys.exit(1)
def ensure_config_path(config_dir):
""" Validates configuration directory. """
lib_dir = os.path.join(config_dir, 'lib')
"""Validate the configuration directory."""
import homeassistant.config as config_util
lib_dir = os.path.join(config_dir, 'deps')
# Test if configuration directory exists
if not os.path.isdir(config_dir):
@@ -49,7 +57,8 @@ def ensure_config_path(config_dir):
def ensure_config_file(config_dir):
""" Ensure configuration file exists. """
"""Ensure configuration file exists."""
import homeassistant.config as config_util
config_path = config_util.ensure_config_exists(config_dir)
if config_path is None:
@@ -60,7 +69,8 @@ def ensure_config_file(config_dir):
def get_arguments():
""" Get parsed passed in arguments. """
"""Get parsed passed in arguments."""
import homeassistant.config as config_util
parser = argparse.ArgumentParser(
description="Home Assistant: Observe, Control, Automate.")
parser.add_argument('--version', action='version', version=__version__)
@@ -73,6 +83,10 @@ def get_arguments():
'--demo-mode',
action='store_true',
help='Start Home Assistant in demo mode')
parser.add_argument(
'--debug',
action='store_true',
help='Start Home Assistant in debug mode')
parser.add_argument(
'--open-ui',
action='store_true',
@@ -96,55 +110,64 @@ def get_arguments():
default=None,
help='Enables daily log rotation and keeps up to the specified days')
parser.add_argument(
'--install-osx',
'--runner',
action='store_true',
help='Installs as a service on OS X and loads on boot.')
help='On restart exit with code {}'.format(RESTART_EXIT_CODE))
parser.add_argument(
'--uninstall-osx',
action='store_true',
help='Uninstalls from OS X.')
parser.add_argument(
'--restart-osx',
action='store_true',
help='Restarts on OS X.')
if os.name != "nt":
'--script',
nargs=argparse.REMAINDER,
help='Run one of the embedded scripts')
if os.name == "posix":
parser.add_argument(
'--daemon',
action='store_true',
help='Run Home Assistant as daemon')
arguments = parser.parse_args()
if os.name == "nt":
if os.name != "posix" or arguments.debug or arguments.runner:
arguments.daemon = False
return arguments
def daemonize():
""" Move current process to daemon process """
# create first fork
"""Move current process to daemon process."""
# Create first fork
pid = os.fork()
if pid > 0:
sys.exit(0)
# decouple fork
# Decouple fork
os.setsid()
os.umask(0)
# create second fork
# Create second fork
pid = os.fork()
if pid > 0:
sys.exit(0)
# redirect standard file descriptors to devnull
infd = open(os.devnull, 'r')
outfd = open(os.devnull, 'a+')
sys.stdout.flush()
sys.stderr.flush()
os.dup2(infd.fileno(), sys.stdin.fileno())
os.dup2(outfd.fileno(), sys.stdout.fileno())
os.dup2(outfd.fileno(), sys.stderr.fileno())
def check_pid(pid_file):
""" Check that HA is not already running """
# check pid file
"""Check that HA is not already running."""
# Check pid file
try:
pid = int(open(pid_file, 'r').readline())
except IOError:
# PID File does not exist
return
# If we just restarted, we just found our own pidfile.
if pid == os.getpid():
return
try:
os.kill(pid, 0)
except OSError:
@@ -155,7 +178,7 @@ def check_pid(pid_file):
def write_pid(pid_file):
""" Create PID File """
"""Create a PID File."""
pid = os.getpid()
try:
open(pid_file, 'w').write(str(pid))
@@ -164,74 +187,46 @@ def write_pid(pid_file):
sys.exit(1)
def install_osx():
""" Setup to run via launchd on OS X """
with os.popen('which hass') as inp:
hass_path = inp.read().strip()
def closefds_osx(min_fd, max_fd):
"""Make sure file descriptors get closed when we restart.
with os.popen('whoami') as inp:
user = inp.read().strip()
We cannot call close on guarded fds, and we cannot easily test which fds
are guarded. But we can set the close-on-exec flag on everything we want to
get rid of.
"""
from fcntl import fcntl, F_GETFD, F_SETFD, FD_CLOEXEC
cwd = os.path.dirname(__file__)
template_path = os.path.join(cwd, 'startup', 'launchd.plist')
with open(template_path, 'r', encoding='utf-8') as inp:
plist = inp.read()
plist = plist.replace("$HASS_PATH$", hass_path)
plist = plist.replace("$USER$", user)
path = os.path.expanduser("~/Library/LaunchAgents/org.homeassistant.plist")
try:
with open(path, 'w', encoding='utf-8') as outp:
outp.write(plist)
except IOError as err:
print('Unable to write to ' + path, err)
return
os.popen('launchctl load -w -F ' + path)
print("Home Assistant has been installed. \
Open it here: http://localhost:8123")
for _fd in range(min_fd, max_fd):
try:
val = fcntl(_fd, F_GETFD)
if not val & FD_CLOEXEC:
fcntl(_fd, F_SETFD, val | FD_CLOEXEC)
except IOError:
pass
def uninstall_osx():
""" Unload from launchd on OS X """
path = os.path.expanduser("~/Library/LaunchAgents/org.homeassistant.plist")
os.popen('launchctl unload ' + path)
print("Home Assistant has been uninstalled.")
def cmdline():
"""Collect path and arguments to re-execute the current hass instance."""
if sys.argv[0].endswith('/__main__.py'):
modulepath = os.path.dirname(sys.argv[0])
os.environ['PYTHONPATH'] = os.path.dirname(modulepath)
return [sys.executable] + [arg for arg in sys.argv if arg != '--daemon']
def main():
""" Starts Home Assistant. """
validate_python()
def setup_and_run_hass(config_dir, args):
"""Setup HASS and run."""
from homeassistant import bootstrap
args = get_arguments()
config_dir = os.path.join(os.getcwd(), args.config)
ensure_config_path(config_dir)
# os x launchd functions
if args.install_osx:
install_osx()
return
if args.uninstall_osx:
uninstall_osx()
return
if args.restart_osx:
uninstall_osx()
install_osx()
return
# daemon functions
if args.pid_file:
check_pid(args.pid_file)
if args.daemon:
daemonize()
if args.pid_file:
write_pid(args.pid_file)
# Run a simple daemon runner process on Windows to handle restarts
if os.name == 'nt' and '--runner' not in sys.argv:
args = cmdline() + ['--runner']
while True:
try:
subprocess.check_call(args)
sys.exit(0)
except subprocess.CalledProcessError as exc:
if exc.returncode != RESTART_EXIT_CODE:
sys.exit(exc.returncode)
if args.demo_mode:
config = {
@@ -239,19 +234,21 @@ def main():
'demo': {}
}
hass = bootstrap.from_config_dict(
config, config_dir=config_dir, daemon=args.daemon,
verbose=args.verbose, skip_pip=args.skip_pip,
log_rotate_days=args.log_rotate_days)
config, config_dir=config_dir, verbose=args.verbose,
skip_pip=args.skip_pip, log_rotate_days=args.log_rotate_days)
else:
config_file = ensure_config_file(config_dir)
print('Config directory:', config_dir)
hass = bootstrap.from_config_file(
config_file, daemon=args.daemon, verbose=args.verbose,
skip_pip=args.skip_pip, log_rotate_days=args.log_rotate_days)
config_file, verbose=args.verbose, skip_pip=args.skip_pip,
log_rotate_days=args.log_rotate_days)
if hass is None:
return
if args.open_ui:
def open_browser(event):
""" Open the webinterface in a browser. """
"""Open the webinterface in a browser."""
if hass.config.api is not None:
import webbrowser
webbrowser.open(hass.config.api.base_url)
@@ -259,7 +256,80 @@ def main():
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, open_browser)
hass.start()
hass.block_till_stopped()
exit_code = int(hass.block_till_stopped())
return exit_code
def try_to_restart():
"""Attempt to clean up state and start a new homeassistant instance."""
# Things should be mostly shut down already at this point, now just try
# to clean up things that may have been left behind.
sys.stderr.write('Home Assistant attempting to restart.\n')
# Count remaining threads, ideally there should only be one non-daemonized
# thread left (which is us). Nothing we really do with it, but it might be
# useful when debugging shutdown/restart issues.
try:
nthreads = sum(thread.isAlive() and not thread.isDaemon()
for thread in threading.enumerate())
if nthreads > 1:
sys.stderr.write(
"Found {} non-daemonic threads.\n".format(nthreads))
# Somehow we sometimes seem to trigger an assertion in the python threading
# module. It seems we find threads that have no associated OS level thread
# which are not marked as stopped at the python level.
except AssertionError:
sys.stderr.write("Failed to count non-daemonic threads.\n")
# Try to not leave behind open filedescriptors with the emphasis on try.
try:
max_fd = os.sysconf("SC_OPEN_MAX")
except ValueError:
max_fd = 256
if platform.system() == 'Darwin':
closefds_osx(3, max_fd)
else:
os.closerange(3, max_fd)
# Now launch into a new instance of Home-Assistant. If this fails we
# fall through and exit with error 100 (RESTART_EXIT_CODE) in which case
# systemd will restart us when RestartForceExitStatus=100 is set in the
# systemd.service file.
sys.stderr.write("Restarting Home-Assistant\n")
args = cmdline()
os.execv(args[0], args)
def main():
"""Start Home Assistant."""
validate_python()
args = get_arguments()
if args.script is not None:
from homeassistant import scripts
return scripts.run(args.script)
config_dir = os.path.join(os.getcwd(), args.config)
ensure_config_path(config_dir)
# Daemon functions
if args.pid_file:
check_pid(args.pid_file)
if args.daemon:
daemonize()
if args.pid_file:
write_pid(args.pid_file)
exit_code = setup_and_run_hass(config_dir, args)
if exit_code == RESTART_EXIT_CODE and not args.runner:
try_to_restart()
return exit_code
if __name__ == "__main__":
main()
sys.exit(main())

View File

@@ -1,46 +1,37 @@
"""
homeassistant.bootstrap
~~~~~~~~~~~~~~~~~~~~~~~
Provides methods to bootstrap a home assistant instance.
"""Provides methods to bootstrap a home assistant instance."""
Each method will return a tuple (bus, statemachine).
After bootstrapping you can add your own components or
start by calling homeassistant.start_home_assistant(bus)
"""
from collections import defaultdict
import logging
import logging.handlers
import os
import shutil
import sys
from collections import defaultdict
from threading import RLock
import voluptuous as vol
import homeassistant.core as core
import homeassistant.util.dt as date_util
import homeassistant.util.package as pkg_util
import homeassistant.util.location as loc_util
import homeassistant.config as config_util
import homeassistant.loader as loader
import homeassistant.components as core_components
import homeassistant.components.group as group
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
__version__, EVENT_COMPONENT_LOADED, CONF_LATITUDE, CONF_LONGITUDE,
CONF_TEMPERATURE_UNIT, CONF_NAME, CONF_TIME_ZONE, CONF_CUSTOMIZE,
TEMP_CELCIUS, TEMP_FAHRENHEIT)
from homeassistant.components import group, persistent_notification
import homeassistant.config as conf_util
import homeassistant.core as core
import homeassistant.helpers.config_validation as cv
import homeassistant.loader as loader
import homeassistant.util.package as pkg_util
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
event_decorators, service, config_per_platform, extract_domain_configs)
_LOGGER = logging.getLogger(__name__)
_SETUP_LOCK = RLock()
_CURRENT_SETUP = []
ATTR_COMPONENT = 'component'
PLATFORM_FORMAT = '{}.{}'
ERROR_LOG_FILENAME = 'home-assistant.log'
def setup_component(hass, domain, config=None):
""" Setup a component and all its dependencies. """
"""Setup a component and all its dependencies."""
if domain in hass.config.components:
return True
@@ -63,12 +54,12 @@ def setup_component(hass, domain, config=None):
def _handle_requirements(hass, component, name):
""" Installs requirements for component. """
"""Install the requirements for a component."""
if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'):
return True
for req in component.REQUIREMENTS:
if not pkg_util.install_package(req, target=hass.config.path('lib')):
if not pkg_util.install_package(req, target=hass.config.path('deps')):
_LOGGER.error('Not initializing %s because could not install '
'dependency %s', name, req)
return False
@@ -77,51 +68,114 @@ def _handle_requirements(hass, component, name):
def _setup_component(hass, domain, config):
""" Setup a component for Home Assistant. """
"""Setup a component for Home Assistant."""
# pylint: disable=too-many-return-statements,too-many-branches
if domain in hass.config.components:
return True
component = loader.get_component(domain)
missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
if dep not in hass.config.components]
with _SETUP_LOCK:
# It might have been loaded while waiting for lock
if domain in hass.config.components:
return True
if missing_deps:
_LOGGER.error(
'Not initializing %s because not all dependencies loaded: %s',
domain, ", ".join(missing_deps))
return False
if not _handle_requirements(hass, component, domain):
return False
try:
if not component.setup(hass, config):
_LOGGER.error('component %s failed to initialize', domain)
if domain in _CURRENT_SETUP:
_LOGGER.error('Attempt made to setup %s during setup of %s',
domain, domain)
return False
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error during setup of component %s', domain)
return False
hass.config.components.append(component.DOMAIN)
component = loader.get_component(domain)
missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
if dep not in hass.config.components]
# Assumption: if a component does not depend on groups
# it communicates with devices
if group.DOMAIN not in getattr(component, 'DEPENDENCIES', []):
hass.pool.add_worker()
if missing_deps:
_LOGGER.error(
'Not initializing %s because not all dependencies loaded: %s',
domain, ", ".join(missing_deps))
return False
hass.bus.fire(
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN})
if hasattr(component, 'CONFIG_SCHEMA'):
try:
config = component.CONFIG_SCHEMA(config)
except vol.MultipleInvalid as ex:
cv.log_exception(_LOGGER, ex, domain, config)
return False
return True
elif hasattr(component, 'PLATFORM_SCHEMA'):
platforms = []
for p_name, p_config in config_per_platform(config, domain):
# Validate component specific platform schema
try:
p_validated = component.PLATFORM_SCHEMA(p_config)
except vol.MultipleInvalid as ex:
cv.log_exception(_LOGGER, ex, domain, p_config)
return False
# Not all platform components follow same pattern for platforms
# So if p_name is None we are not going to validate platform
# (the automation component is one of them)
if p_name is None:
platforms.append(p_validated)
continue
platform = prepare_setup_platform(hass, config, domain,
p_name)
if platform is None:
return False
# Validate platform specific schema
if hasattr(platform, 'PLATFORM_SCHEMA'):
try:
p_validated = platform.PLATFORM_SCHEMA(p_validated)
except vol.MultipleInvalid as ex:
cv.log_exception(_LOGGER, ex, '{}.{}'
.format(domain, p_name), p_validated)
return False
platforms.append(p_validated)
# Create a copy of the configuration with all config for current
# component removed and add validated config back in.
filter_keys = extract_domain_configs(config, domain)
config = {key: value for key, value in config.items()
if key not in filter_keys}
config[domain] = platforms
if not _handle_requirements(hass, component, domain):
return False
_CURRENT_SETUP.append(domain)
try:
if not component.setup(hass, config):
_LOGGER.error('component %s failed to initialize', domain)
return False
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error during setup of component %s', domain)
return False
finally:
_CURRENT_SETUP.remove(domain)
hass.config.components.append(component.DOMAIN)
# Assumption: if a component does not depend on groups
# it communicates with devices
if group.DOMAIN not in getattr(component, 'DEPENDENCIES', []):
hass.pool.add_worker()
hass.bus.fire(
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN})
return True
def prepare_setup_platform(hass, config, domain, platform_name):
""" Loads a platform and makes sure dependencies are setup. """
"""Load a platform and makes sure dependencies are setup."""
_ensure_loader_prepared(hass)
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
platform = loader.get_component(platform_path)
platform = loader.get_platform(domain, platform_name)
# Not found
if platform is None:
@@ -147,17 +201,11 @@ def prepare_setup_platform(hass, config, domain, platform_name):
return platform
def mount_local_lib_path(config_dir):
""" Add local library to Python Path """
sys.path.insert(0, os.path.join(config_dir, 'lib'))
# pylint: disable=too-many-branches, too-many-statements, too-many-arguments
def from_config_dict(config, hass=None, config_dir=None, enable_log=True,
verbose=False, daemon=False, skip_pip=False,
verbose=False, skip_pip=False,
log_rotate_days=None):
"""
Tries to configure Home Assistant from a config dict.
"""Try to configure Home Assistant from a config dict.
Dynamically loads required components and its dependencies.
"""
@@ -166,13 +214,20 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True,
if config_dir is not None:
config_dir = os.path.abspath(config_dir)
hass.config.config_dir = config_dir
mount_local_lib_path(config_dir)
_mount_local_lib_path(config_dir)
process_ha_config_upgrade(hass)
process_ha_core_config(hass, config.get(core.DOMAIN, {}))
core_config = config.get(core.DOMAIN, {})
try:
conf_util.process_ha_core_config(hass, core_config)
except vol.Invalid as ex:
cv.log_exception(_LOGGER, ex, 'homeassistant', core_config)
return None
conf_util.process_ha_config_upgrade(hass)
if enable_log:
enable_logging(hass, verbose, daemon, log_rotate_days)
enable_logging(hass, verbose, log_rotate_days)
hass.config.skip_pip = skip_pip
if skip_pip:
@@ -194,11 +249,16 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True,
if not core_components.setup(hass, config):
_LOGGER.error('Home Assistant core failed to initialize. '
'Further initialization aborted.')
return hass
persistent_notification.setup(hass, config)
_LOGGER.info('Home Assistant core initialized')
# Give event decorators access to HASS
event_decorators.HASS = hass
service.HASS = hass
# Setup the components
for domain in loader.load_order_components(components):
_setup_component(hass, domain, config)
@@ -206,11 +266,11 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True,
return hass
def from_config_file(config_path, hass=None, verbose=False, daemon=False,
skip_pip=True, log_rotate_days=None):
"""
Reads the configuration file and tries to start all the required
functionality. Will add functionality to 'hass' parameter if given,
def from_config_file(config_path, hass=None, verbose=False, skip_pip=True,
log_rotate_days=None):
"""Read the configuration file and try to start all the functionality.
Will add functionality to 'hass' parameter if given,
instantiates a new Home Assistant object if 'hass' is not given.
"""
if hass is None:
@@ -219,39 +279,40 @@ def from_config_file(config_path, hass=None, verbose=False, daemon=False,
# Set config dir to directory holding config file
config_dir = os.path.abspath(os.path.dirname(config_path))
hass.config.config_dir = config_dir
mount_local_lib_path(config_dir)
_mount_local_lib_path(config_dir)
enable_logging(hass, verbose, daemon, log_rotate_days)
enable_logging(hass, verbose, log_rotate_days)
config_dict = config_util.load_config_file(config_path)
try:
config_dict = conf_util.load_yaml_config_file(config_path)
except HomeAssistantError:
return None
return from_config_dict(config_dict, hass, enable_log=False,
skip_pip=skip_pip)
def enable_logging(hass, verbose=False, daemon=False, log_rotate_days=None):
""" Setup the logging for home assistant. """
if not daemon:
logging.basicConfig(level=logging.INFO)
fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) "
"[%(name)s] %(message)s%(reset)s")
try:
from colorlog import ColoredFormatter
logging.getLogger().handlers[0].setFormatter(ColoredFormatter(
fmt,
datefmt='%y-%m-%d %H:%M:%S',
reset=True,
log_colors={
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}
))
except ImportError:
_LOGGER.warning(
"Colorlog package not found, console coloring disabled")
def enable_logging(hass, verbose=False, log_rotate_days=None):
"""Setup the logging."""
logging.basicConfig(level=logging.INFO)
fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) "
"[%(name)s] %(message)s%(reset)s")
try:
from colorlog import ColoredFormatter
logging.getLogger().handlers[0].setFormatter(ColoredFormatter(
fmt,
datefmt='%y-%m-%d %H:%M:%S',
reset=True,
log_colors={
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}
))
except ImportError:
pass
# Log errors to a file if we have write access to file or config dir
err_log_path = hass.config.path(ERROR_LOG_FILENAME)
@@ -275,114 +336,19 @@ def enable_logging(hass, verbose=False, daemon=False, log_rotate_days=None):
datefmt='%y-%m-%d %H:%M:%S'))
logger = logging.getLogger('')
logger.addHandler(err_handler)
logger.setLevel(logging.NOTSET) # this sets the minimum log level
logger.setLevel(logging.INFO)
else:
_LOGGER.error(
'Unable to setup error log %s (access denied)', err_log_path)
def process_ha_config_upgrade(hass):
""" Upgrade config if necessary. """
version_path = hass.config.path('.HA_VERSION')
try:
with open(version_path, 'rt') as inp:
conf_version = inp.readline().strip()
except FileNotFoundError:
# Last version to not have this file
conf_version = '0.7.7'
if conf_version == __version__:
return
_LOGGER.info('Upgrading config directory from %s to %s', conf_version,
__version__)
lib_path = hass.config.path('lib')
if os.path.isdir(lib_path):
shutil.rmtree(lib_path)
with open(version_path, 'wt') as outp:
outp.write(__version__)
def process_ha_core_config(hass, config):
""" Processes the [homeassistant] section from the config. """
hac = hass.config
def set_time_zone(time_zone_str):
""" Helper method to set time zone in HA. """
if time_zone_str is None:
return
time_zone = date_util.get_time_zone(time_zone_str)
if time_zone:
hac.time_zone = time_zone
date_util.set_default_time_zone(time_zone)
else:
_LOGGER.error('Received invalid time zone %s', time_zone_str)
for key, attr, typ in ((CONF_LATITUDE, 'latitude', float),
(CONF_LONGITUDE, 'longitude', float),
(CONF_NAME, 'location_name', str)):
if key in config:
try:
setattr(hac, attr, typ(config[key]))
except ValueError:
_LOGGER.error('Received invalid %s value for %s: %s',
typ.__name__, key, attr)
set_time_zone(config.get(CONF_TIME_ZONE))
customize = config.get(CONF_CUSTOMIZE)
if isinstance(customize, dict):
for entity_id, attrs in config.get(CONF_CUSTOMIZE, {}).items():
if not isinstance(attrs, dict):
continue
Entity.overwrite_attribute(entity_id, attrs.keys(), attrs.values())
if CONF_TEMPERATURE_UNIT in config:
unit = config[CONF_TEMPERATURE_UNIT]
if unit == 'C':
hac.temperature_unit = TEMP_CELCIUS
elif unit == 'F':
hac.temperature_unit = TEMP_FAHRENHEIT
# If we miss some of the needed values, auto detect them
if None not in (
hac.latitude, hac.longitude, hac.temperature_unit, hac.time_zone):
return
_LOGGER.info('Auto detecting location and temperature unit')
info = loc_util.detect_location_info()
if info is None:
_LOGGER.error('Could not detect location information')
return
if hac.latitude is None and hac.longitude is None:
hac.latitude = info.latitude
hac.longitude = info.longitude
if hac.temperature_unit is None:
if info.use_fahrenheit:
hac.temperature_unit = TEMP_FAHRENHEIT
else:
hac.temperature_unit = TEMP_CELCIUS
if hac.location_name is None:
hac.location_name = info.city
if hac.time_zone is None:
set_time_zone(info.time_zone)
def _ensure_loader_prepared(hass):
""" Ensure Home Assistant loader is prepared. """
"""Ensure Home Assistant loader is prepared."""
if not loader.PREPARED:
loader.prepare(hass)
def _mount_local_lib_path(config_dir):
"""Add local library to Python Path."""
sys.path.insert(0, os.path.join(config_dir, 'deps'))

View File

@@ -1,33 +1,32 @@
"""
homeassistant.components
~~~~~~~~~~~~~~~~~~~~~~~~
This package contains components that can be plugged into Home Assistant.
Component design guidelines:
Each component defines a constant DOMAIN that is equal to its filename.
Each component that tracks states should create state entity names in the
format "<DOMAIN>.<OBJECT_ID>".
Each component should publish services only under its own domain.
- Each component defines a constant DOMAIN that is equal to its filename.
- Each component that tracks states should create state entity names in the
format "<DOMAIN>.<OBJECT_ID>".
- Each component should publish services only under its own domain.
"""
import itertools as it
import logging
import homeassistant.core as ha
import homeassistant.util as util
from homeassistant.helpers import extract_entity_ids
from homeassistant.helpers.entity import split_entity_id
from homeassistant.helpers.service import extract_entity_ids
from homeassistant.loader import get_component
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF)
ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE)
_LOGGER = logging.getLogger(__name__)
SERVICE_RELOAD_CORE_CONFIG = 'reload_core_config'
def is_on(hass, entity_id=None):
""" Loads up the module to call the is_on method.
If there is no entity id given we will check all. """
"""Load up the module to call the is_on method.
If there is no entity id given we will check all.
"""
if entity_id:
group = get_component('group')
@@ -36,7 +35,7 @@ def is_on(hass, entity_id=None):
entity_ids = hass.states.entity_ids()
for entity_id in entity_ids:
domain = util.split_entity_id(entity_id)[0]
domain = split_entity_id(entity_id)[0]
module = get_component(domain)
@@ -53,7 +52,7 @@ def is_on(hass, entity_id=None):
def turn_on(hass, entity_id=None, **service_data):
""" Turns specified entity on if possible. """
"""Turn specified entity on if possible."""
if entity_id is not None:
service_data[ATTR_ENTITY_ID] = entity_id
@@ -61,18 +60,30 @@ def turn_on(hass, entity_id=None, **service_data):
def turn_off(hass, entity_id=None, **service_data):
""" Turns specified entity off. """
"""Turn specified entity off."""
if entity_id is not None:
service_data[ATTR_ENTITY_ID] = entity_id
hass.services.call(ha.DOMAIN, SERVICE_TURN_OFF, service_data)
def setup(hass, config):
""" Setup general services related to homeassistant. """
def toggle(hass, entity_id=None, **service_data):
"""Toggle specified entity."""
if entity_id is not None:
service_data[ATTR_ENTITY_ID] = entity_id
hass.services.call(ha.DOMAIN, SERVICE_TOGGLE, service_data)
def reload_core_config(hass):
"""Reload the core config."""
hass.services.call(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
def setup(hass, config):
"""Setup general services related to Home Assistant."""
def handle_turn_service(service):
""" Method to handle calls to homeassistant.turn_on/off. """
"""Method to handle calls to homeassistant.turn_on/off."""
entity_ids = extract_entity_ids(hass, service)
# Generic turn on/off method requires entity id
@@ -84,18 +95,44 @@ def setup(hass, config):
# Group entity_ids by domain. groupby requires sorted data.
by_domain = it.groupby(sorted(entity_ids),
lambda item: util.split_entity_id(item)[0])
lambda item: split_entity_id(item)[0])
for domain, ent_ids in by_domain:
# We want to block for all calls and only return when all calls
# have been processed. If a service does not exist it causes a 10
# second delay while we're blocking waiting for a response.
# But services can be registered on other HA instances that are
# listening to the bus too. So as a in between solution, we'll
# block only if the service is defined in the current HA instance.
blocking = hass.services.has_service(domain, service.service)
# Create a new dict for this call
data = dict(service.data)
# ent_ids is a generator, convert it to a list.
data[ATTR_ENTITY_ID] = list(ent_ids)
hass.services.call(domain, service.service, data, True)
hass.services.call(domain, service.service, data, blocking)
hass.services.register(ha.DOMAIN, SERVICE_TURN_OFF, handle_turn_service)
hass.services.register(ha.DOMAIN, SERVICE_TURN_ON, handle_turn_service)
hass.services.register(ha.DOMAIN, SERVICE_TOGGLE, handle_turn_service)
def handle_reload_config(call):
"""Service handler for reloading core config."""
from homeassistant.exceptions import HomeAssistantError
from homeassistant import config as conf_util
try:
path = conf_util.find_config_file(hass.config.config_dir)
conf = conf_util.load_yaml_config_file(path)
except HomeAssistantError as err:
_LOGGER.error(err)
return
conf_util.process_ha_core_config(hass, conf.get(ha.DOMAIN) or {})
hass.services.register(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG,
handle_reload_config)
return True

View File

@@ -1,16 +1,20 @@
"""
homeassistant.components.alarm_control_panel
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to interface with a alarm control panel.
Component to interface with an alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel/
"""
import logging
import os
from homeassistant.components import verisure
import voluptuous as vol
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER,
ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER,
SERVICE_ALARM_DISARM, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_ARM_AWAY)
from homeassistant.config import load_yaml_config_file
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
@@ -19,11 +23,6 @@ SCAN_INTERVAL = 30
ENTITY_ID_FORMAT = DOMAIN + '.{}'
# Maps discovered services to their platforms
DISCOVERY_PLATFORMS = {
verisure.DISCOVER_SENSORS: 'verisure'
}
SERVICE_TO_METHOD = {
SERVICE_ALARM_DISARM: 'alarm_disarm',
SERVICE_ALARM_ARM_HOME: 'alarm_arm_home',
@@ -31,49 +30,49 @@ SERVICE_TO_METHOD = {
SERVICE_ALARM_TRIGGER: 'alarm_trigger'
}
ATTR_CODE = 'code'
ATTR_CODE_FORMAT = 'code_format'
ATTR_TO_PROPERTY = [
ATTR_CODE,
ATTR_CODE_FORMAT
]
ALARM_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(ATTR_CODE): cv.string,
})
def setup(hass, config):
""" Track states and offer events for sensors. """
"""Track states and offer events for sensors."""
component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL,
DISCOVERY_PLATFORMS)
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
component.setup(config)
def alarm_service_handler(service):
""" Maps services to methods on Alarm. """
"""Map services to methods on Alarm."""
target_alarms = component.extract_from_service(service)
if ATTR_CODE not in service.data:
code = None
else:
code = service.data[ATTR_CODE]
code = service.data.get(ATTR_CODE)
method = SERVICE_TO_METHOD[service.service]
for alarm in target_alarms:
getattr(alarm, method)(code)
if alarm.should_poll:
alarm.update_ha_state(True)
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
for service in SERVICE_TO_METHOD:
hass.services.register(DOMAIN, service, alarm_service_handler,
descriptions.get(service))
descriptions.get(service),
schema=ALARM_SERVICE_SCHEMA)
return True
def alarm_disarm(hass, code=None, entity_id=None):
""" Send the alarm the command for disarm. """
"""Send the alarm the command for disarm."""
data = {}
if code:
data[ATTR_CODE] = code
@@ -84,7 +83,7 @@ def alarm_disarm(hass, code=None, entity_id=None):
def alarm_arm_home(hass, code=None, entity_id=None):
""" Send the alarm the command for arm home. """
"""Send the alarm the command for arm home."""
data = {}
if code:
data[ATTR_CODE] = code
@@ -95,7 +94,7 @@ def alarm_arm_home(hass, code=None, entity_id=None):
def alarm_arm_away(hass, code=None, entity_id=None):
""" Send the alarm the command for arm away. """
"""Send the alarm the command for arm away."""
data = {}
if code:
data[ATTR_CODE] = code
@@ -106,7 +105,7 @@ def alarm_arm_away(hass, code=None, entity_id=None):
def alarm_trigger(hass, code=None, entity_id=None):
""" Send the alarm the command for trigger. """
"""Send the alarm the command for trigger."""
data = {}
if code:
data[ATTR_CODE] = code
@@ -118,33 +117,33 @@ def alarm_trigger(hass, code=None, entity_id=None):
# pylint: disable=no-self-use
class AlarmControlPanel(Entity):
""" ABC for alarm control devices. """
"""An abstract class for alarm control devices."""
@property
def code_format(self):
""" regex for code format or None if no code is required. """
"""Regex for code format or None if no code is required."""
return None
def alarm_disarm(self, code=None):
""" Send disarm command. """
"""Send disarm command."""
raise NotImplementedError()
def alarm_arm_home(self, code=None):
""" Send arm home command. """
"""Send arm home command."""
raise NotImplementedError()
def alarm_arm_away(self, code=None):
""" Send arm away command. """
"""Send arm away command."""
raise NotImplementedError()
def alarm_trigger(self, code=None):
""" Send alarm trigger command. """
"""Send alarm trigger command."""
raise NotImplementedError()
@property
def state_attributes(self):
""" Return the state attributes. """
"""Return the state attributes."""
state_attr = {
ATTR_CODE_FORMAT: self.code_format,
}
}
return state_attr

View File

@@ -0,0 +1,113 @@
"""
Interfaces with Alarm.com alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.alarmdotcom/
"""
import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN)
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['https://github.com/Xorso/pyalarmdotcom'
'/archive/0.1.1.zip'
'#pyalarmdotcom==0.1.1']
DEFAULT_NAME = 'Alarm.com'
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup an Alarm.com control panel."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
if username is None or password is None:
_LOGGER.error('Must specify username and password!')
return False
add_devices([AlarmDotCom(hass,
config.get('name', DEFAULT_NAME),
config.get('code'),
username,
password)])
# pylint: disable=too-many-arguments, too-many-instance-attributes
# pylint: disable=abstract-method
class AlarmDotCom(alarm.AlarmControlPanel):
"""Represent an Alarm.com status."""
def __init__(self, hass, name, code, username, password):
"""Initialize the Alarm.com status."""
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
self._alarm = Alarmdotcom(username, password, timeout=10)
self._hass = hass
self._name = name
self._code = str(code) if code else None
self._username = username
self._password = password
@property
def should_poll(self):
"""No polling needed."""
return True
@property
def name(self):
"""Return the name of the alarm."""
return self._name
@property
def code_format(self):
"""One or more characters if code is defined."""
return None if self._code is None else '.+'
@property
def state(self):
"""Return the state of the device."""
if self._alarm.state == 'Disarmed':
return STATE_ALARM_DISARMED
elif self._alarm.state == 'Armed Stay':
return STATE_ALARM_ARMED_HOME
elif self._alarm.state == 'Armed Away':
return STATE_ALARM_ARMED_AWAY
else:
return STATE_UNKNOWN
def alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'arming home'):
return
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
# Open another session to alarm.com to fire off the command
_alarm = Alarmdotcom(self._username, self._password, timeout=10)
_alarm.disarm()
def alarm_arm_home(self, code=None):
"""Send arm home command."""
if not self._validate_code(code, 'arming home'):
return
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
# Open another session to alarm.com to fire off the command
_alarm = Alarmdotcom(self._username, self._password, timeout=10)
_alarm.arm_stay()
def alarm_arm_away(self, code=None):
"""Send arm away command."""
if not self._validate_code(code, 'arming home'):
return
from pyalarmdotcom.pyalarmdotcom import Alarmdotcom
# Open another session to alarm.com to fire off the command
_alarm = Alarmdotcom(self._username, self._password, timeout=10)
_alarm.arm_away()
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)
return check

View File

@@ -1,13 +1,14 @@
"""
homeassistant.components.alarm_control_panel.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo platform that has two fake alarm control panels.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
import homeassistant.components.alarm_control_panel.manual as manual
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Demo alarm control panels. """
"""Setup the Demo alarm control panel platform."""
add_devices([
manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10),
])

View File

@@ -0,0 +1,105 @@
"""
Support for Envisalink-based alarm control panels (Honeywell/DSC).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.envisalink/
"""
import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.envisalink import (EVL_CONTROLLER,
EnvisalinkDevice,
PARTITION_SCHEMA,
CONF_CODE,
CONF_PARTITIONNAME,
SIGNAL_PARTITION_UPDATE,
SIGNAL_KEYPAD_UPDATE)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN, STATE_ALARM_TRIGGERED)
DEPENDENCIES = ['envisalink']
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Perform the setup for Envisalink alarm panels."""
_configured_partitions = discovery_info['partitions']
_code = discovery_info[CONF_CODE]
for part_num in _configured_partitions:
_device_config_data = PARTITION_SCHEMA(
_configured_partitions[part_num])
_device = EnvisalinkAlarm(
part_num,
_device_config_data[CONF_PARTITIONNAME],
_code,
EVL_CONTROLLER.alarm_state['partition'][part_num],
EVL_CONTROLLER)
add_devices_callback([_device])
return True
class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
"""Represents the Envisalink-based alarm panel."""
# pylint: disable=too-many-arguments
def __init__(self, partition_number, alarm_name, code, info, controller):
"""Initialize the alarm panel."""
from pydispatch import dispatcher
self._partition_number = partition_number
self._code = code
_LOGGER.debug('Setting up alarm: ' + alarm_name)
EnvisalinkDevice.__init__(self, alarm_name, info, controller)
dispatcher.connect(self._update_callback,
signal=SIGNAL_PARTITION_UPDATE,
sender=dispatcher.Any)
dispatcher.connect(self._update_callback,
signal=SIGNAL_KEYPAD_UPDATE,
sender=dispatcher.Any)
def _update_callback(self, partition):
"""Update HA state, if needed."""
if partition is None or int(partition) == self._partition_number:
self.update_ha_state()
@property
def code_format(self):
"""The characters if code is defined."""
return self._code
@property
def state(self):
"""Return the state of the device."""
if self._info['status']['alarm']:
return STATE_ALARM_TRIGGERED
elif self._info['status']['armed_away']:
return STATE_ALARM_ARMED_AWAY
elif self._info['status']['armed_stay']:
return STATE_ALARM_ARMED_HOME
elif self._info['status']['alpha']:
return STATE_ALARM_DISARMED
else:
return STATE_UNKNOWN
def alarm_disarm(self, code=None):
"""Send disarm command."""
if self._code:
EVL_CONTROLLER.disarm_partition(str(code),
self._partition_number)
def alarm_arm_home(self, code=None):
"""Send arm home command."""
if self._code:
EVL_CONTROLLER.arm_stay_partition(str(code),
self._partition_number)
def alarm_arm_away(self, code=None):
"""Send arm away command."""
if self._code:
EVL_CONTROLLER.arm_away_partition(str(code),
self._partition_number)
def alarm_trigger(self, code=None):
"""Alarm trigger command. Not possible for us."""
raise NotImplementedError()

View File

@@ -1,20 +1,18 @@
"""
homeassistant.components.alarm_control_panel.manual
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for manual alarms.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.manual/
"""
import logging
import datetime
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.helpers.event import track_point_in_time
import homeassistant.util.dt as dt_util
import logging
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.util.dt as dt_util
from homeassistant.const import (
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED)
from homeassistant.helpers.event import track_point_in_time
_LOGGER = logging.getLogger(__name__)
@@ -24,8 +22,7 @@ DEFAULT_TRIGGER_TIME = 120
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the manual alarm platform. """
"""Setup the manual alarm platform."""
add_devices([ManualAlarm(
hass,
config.get('name', DEFAULT_ALARM_NAME),
@@ -47,6 +44,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
"""
def __init__(self, hass, name, code, pending_time, trigger_time):
"""Initalize the manual alarm panel."""
self._state = STATE_ALARM_DISARMED
self._hass = hass
self._name = name
@@ -57,18 +55,19 @@ class ManualAlarm(alarm.AlarmControlPanel):
@property
def should_poll(self):
""" No polling needed. """
"""No polling needed."""
return False
@property
def name(self):
""" Returns the name of the device. """
"""Return the name of the device."""
return self._name
@property
def state(self):
""" Returns the state of the device. """
if self._state in (STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY) and \
"""Return the state of the device."""
if self._state in (STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY) and \
self._pending_time and self._state_ts + self._pending_time > \
dt_util.utcnow():
return STATE_ALARM_PENDING
@@ -84,11 +83,11 @@ class ManualAlarm(alarm.AlarmControlPanel):
@property
def code_format(self):
""" One or more characters. """
"""One or more characters."""
return None if self._code is None else '.+'
def alarm_disarm(self, code=None):
""" Send disarm command. """
"""Send disarm command."""
if not self._validate_code(code, STATE_ALARM_DISARMED):
return
@@ -97,7 +96,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self.update_ha_state()
def alarm_arm_home(self, code=None):
""" Send arm home command. """
"""Send arm home command."""
if not self._validate_code(code, STATE_ALARM_ARMED_HOME):
return
@@ -111,7 +110,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._state_ts + self._pending_time)
def alarm_arm_away(self, code=None):
""" Send arm away command. """
"""Send arm away command."""
if not self._validate_code(code, STATE_ALARM_ARMED_AWAY):
return
@@ -125,7 +124,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._state_ts + self._pending_time)
def alarm_trigger(self, code=None):
""" Send alarm trigger command. No code needed. """
"""Send alarm trigger command. No code needed."""
self._state = STATE_ALARM_TRIGGERED
self._state_ts = dt_util.utcnow()
self.update_ha_state()
@@ -140,7 +139,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._state_ts + self._pending_time + self._trigger_time)
def _validate_code(self, code, state):
""" Validate given code. """
"""Validate given code."""
check = self._code is None or code == self._code
if not check:
_LOGGER.warning('Invalid code given for %s', state)

View File

@@ -1,60 +1,70 @@
"""
homeassistant.components.alarm_control_panel.mqtt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This platform enables the possibility to control a MQTT alarm.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.mqtt/
"""
import logging
import homeassistant.components.mqtt as mqtt
import homeassistant.components.alarm_control_panel as alarm
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.components.mqtt as mqtt
from homeassistant.const import (
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN)
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN,
CONF_NAME)
from homeassistant.components.mqtt import (
CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "MQTT Alarm"
DEFAULT_QOS = 0
DEFAULT_PAYLOAD_DISARM = "DISARM"
DEFAULT_PAYLOAD_ARM_HOME = "ARM_HOME"
DEFAULT_PAYLOAD_ARM_AWAY = "ARM_AWAY"
DEPENDENCIES = ['mqtt']
CONF_PAYLOAD_DISARM = 'payload_disarm'
CONF_PAYLOAD_ARM_HOME = 'payload_arm_home'
CONF_PAYLOAD_ARM_AWAY = 'payload_arm_away'
CONF_CODE = 'code'
DEFAULT_NAME = "MQTT Alarm"
DEFAULT_DISARM = "DISARM"
DEFAULT_ARM_HOME = "ARM_HOME"
DEFAULT_ARM_AWAY = "ARM_AWAY"
PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Required(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string,
vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string,
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
vol.Optional(CONF_CODE): cv.string,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the MQTT platform. """
if config.get('state_topic') is None:
_LOGGER.error("Missing required variable: state_topic")
return False
if config.get('command_topic') is None:
_LOGGER.error("Missing required variable: command_topic")
return False
"""Setup the MQTT platform."""
add_devices([MqttAlarm(
hass,
config.get('name', DEFAULT_NAME),
config.get('state_topic'),
config.get('command_topic'),
config.get('qos', DEFAULT_QOS),
config.get('payload_disarm', DEFAULT_PAYLOAD_DISARM),
config.get('payload_arm_home', DEFAULT_PAYLOAD_ARM_HOME),
config.get('payload_arm_away', DEFAULT_PAYLOAD_ARM_AWAY),
config.get('code'))])
config[CONF_NAME],
config[CONF_STATE_TOPIC],
config[CONF_COMMAND_TOPIC],
config[CONF_QOS],
config[CONF_PAYLOAD_DISARM],
config[CONF_PAYLOAD_ARM_HOME],
config[CONF_PAYLOAD_ARM_AWAY],
config.get(CONF_CODE))])
# pylint: disable=too-many-arguments, too-many-instance-attributes
# pylint: disable=abstract-method
class MqttAlarm(alarm.AlarmControlPanel):
""" represents a MQTT alarm status within home assistant. """
"""Represent a MQTT alarm status."""
def __init__(self, hass, name, state_topic, command_topic, qos,
payload_disarm, payload_arm_home, payload_arm_away, code):
"""Initalize the MQTT alarm panel."""
self._state = STATE_UNKNOWN
self._hass = hass
self._name = name
@@ -64,10 +74,10 @@ class MqttAlarm(alarm.AlarmControlPanel):
self._payload_disarm = payload_disarm
self._payload_arm_home = payload_arm_home
self._payload_arm_away = payload_arm_away
self._code = str(code) if code else None
self._code = code
def message_received(topic, payload, qos):
""" A new MQTT message has been received. """
"""A 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):
@@ -80,47 +90,47 @@ class MqttAlarm(alarm.AlarmControlPanel):
@property
def should_poll(self):
""" No polling needed """
"""No polling needed."""
return False
@property
def name(self):
""" Returns the name of the device. """
"""Return the name of the device."""
return self._name
@property
def state(self):
""" Returns the state of the device. """
"""Return the state of the device."""
return self._state
@property
def code_format(self):
""" One or more characters if code is defined """
"""One or more characters if code is defined."""
return None if self._code is None else '.+'
def alarm_disarm(self, code=None):
""" Send disarm command. """
"""Send disarm command."""
if not self._validate_code(code, 'disarming'):
return
mqtt.publish(self.hass, self._command_topic,
self._payload_disarm, self._qos)
def alarm_arm_home(self, code=None):
""" Send arm home command. """
"""Send arm home command."""
if not self._validate_code(code, 'arming home'):
return
mqtt.publish(self.hass, self._command_topic,
self._payload_arm_home, self._qos)
def alarm_arm_away(self, code=None):
""" Send arm away command. """
"""Send arm away command."""
if not self._validate_code(code, 'arming away'):
return
mqtt.publish(self.hass, self._command_topic,
self._payload_arm_away, self._qos)
def _validate_code(self, code, state):
""" Validate given code. """
"""Validate given code."""
check = self._code is None or code == self._code
if not check:
_LOGGER.warning('Wrong code entered for %s', state)

View File

@@ -0,0 +1,105 @@
"""
Support for NX584 alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.nx584/
"""
import logging
import requests
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN)
REQUIREMENTS = ['pynx584==0.2']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup nx584 platform."""
host = config.get('host', 'localhost:5007')
try:
add_devices([NX584Alarm(hass, host, config.get('name', 'NX584'))])
except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NX584: %s', str(ex))
return False
class NX584Alarm(alarm.AlarmControlPanel):
"""Represents the NX584-based alarm panel."""
def __init__(self, hass, host, name):
"""Initalize the nx584 alarm panel."""
from nx584 import client
self._hass = hass
self._host = host
self._name = name
self._alarm = client.Client('http://%s' % host)
# Do an initial list operation so that we will try to actually
# talk to the API and trigger a requests exception for setup_platform()
# to catch
self._alarm.list_zones()
@property
def should_poll(self):
"""Polling needed."""
return True
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def code_format(self):
"""The characters if code is defined."""
return '[0-9]{4}([0-9]{2})?'
@property
def state(self):
"""Return the state of the device."""
try:
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',
dict(host=self._host, reason=ex))
return STATE_UNKNOWN
except IndexError:
_LOGGER.error('nx584 reports no partitions')
return STATE_UNKNOWN
bypassed = False
for zone in zones:
if zone['bypassed']:
_LOGGER.debug('Zone %(zone)s is bypassed, '
'assuming HOME',
dict(zone=zone['number']))
bypassed = True
break
if not part['armed']:
return STATE_ALARM_DISARMED
elif bypassed:
return STATE_ALARM_ARMED_HOME
else:
return STATE_ALARM_ARMED_AWAY
def alarm_disarm(self, code=None):
"""Send disarm command."""
self._alarm.disarm(code)
def alarm_arm_home(self, code=None):
"""Send arm home command."""
self._alarm.arm('home')
def alarm_arm_away(self, code=None):
"""Send arm away command."""
self._alarm.arm('auto')
def alarm_trigger(self, code=None):
"""Alarm trigger command."""
raise NotImplementedError()

View File

@@ -0,0 +1,124 @@
"""
Interfaces with SimpliSafe alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.simplisafe/
"""
import logging
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, STATE_UNKNOWN,
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY)
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['https://github.com/w1ll1am23/simplisafe-python/archive/'
'586fede0e85fd69e56e516aaa8e97eb644ca8866.zip#'
'simplisafe-python==0.0.1']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the SimpliSafe platform."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
if username is None or password is None:
_LOGGER.error('Must specify username and password!')
return False
add_devices([SimpliSafeAlarm(
config.get('name', "SimpliSafe"),
username,
password,
config.get('code'))])
# pylint: disable=abstract-method
class SimpliSafeAlarm(alarm.AlarmControlPanel):
"""Representation a SimpliSafe alarm."""
def __init__(self, name, username, password, code):
"""Initialize the SimpliSafe alarm."""
from simplisafe import SimpliSafe
self.simplisafe = SimpliSafe(username, password)
self._name = name
self._code = str(code) if code else None
self._id = self.simplisafe.get_id()
status = self.simplisafe.get_state()
if status == 'Off':
self._state = STATE_ALARM_DISARMED
elif status == 'Home':
self._state = STATE_ALARM_ARMED_HOME
elif status == 'Away':
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = STATE_UNKNOWN
@property
def should_poll(self):
"""Poll the SimpliSafe API."""
return True
@property
def name(self):
"""Return the name of the device."""
if self._name is not None:
return self._name
else:
return 'Alarm {}'.format(self._id)
@property
def code_format(self):
"""One or more characters if code is defined."""
return None if self._code is None else '.+'
@property
def state(self):
"""Return the state of the device."""
return self._state
def update(self):
"""Update alarm status."""
self.simplisafe.get_location()
status = self.simplisafe.get_state()
if status == 'Off':
self._state = STATE_ALARM_DISARMED
elif status == 'Home':
self._state = STATE_ALARM_ARMED_HOME
elif status == 'Away':
self._state = STATE_ALARM_ARMED_AWAY
else:
self._state = STATE_UNKNOWN
def alarm_disarm(self, code=None):
"""Send disarm command."""
if not self._validate_code(code, 'disarming'):
return
self.simplisafe.set_state('off')
_LOGGER.info('SimpliSafe alarm disarming')
self.update()
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')
self.update()
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')
self.update()
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)
return check

View File

@@ -1,97 +1,95 @@
"""
homeassistant.components.alarm_control_panel.verisure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interfaces with Verisure alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/verisure/
https://home-assistant.io/components/alarm_control_panel.verisure/
"""
import logging
import homeassistant.components.verisure as verisure
import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.verisure import HUB as hub
from homeassistant.const import (
STATE_UNKNOWN,
STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY)
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_UNKNOWN)
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Verisure platform. """
if not verisure.MY_PAGES:
_LOGGER.error('A connection has not been made to Verisure mypages.')
return False
"""Setup the Verisure platform."""
alarms = []
alarms.extend([
VerisureAlarm(value)
for value in verisure.get_alarm_status().values()
if verisure.SHOW_ALARM
])
if int(hub.config.get('alarm', '1')):
hub.update_alarms()
alarms.extend([
VerisureAlarm(value.id)
for value in hub.alarm_status.values()
])
add_devices(alarms)
# pylint: disable=abstract-method
class VerisureAlarm(alarm.AlarmControlPanel):
""" Represents a Verisure alarm status. """
"""Represent a Verisure alarm status."""
def __init__(self, alarm_status):
self._id = alarm_status.id
self._device = verisure.MY_PAGES.DEVICE_ALARM
def __init__(self, device_id):
"""Initalize the Verisure alarm panel."""
self._id = device_id
self._state = STATE_UNKNOWN
self._digits = int(hub.config.get('code_digits', '4'))
@property
def name(self):
""" Returns the name of the device. """
"""Return the name of the device."""
return 'Alarm {}'.format(self._id)
@property
def state(self):
""" Returns the state of the device. """
"""Return the state of the device."""
return self._state
@property
def available(self):
"""Return True if entity is available."""
return hub.available
@property
def code_format(self):
""" Four digit code required. """
return '^\\d{4}$'
"""The code format as regex."""
return '^\\d{%s}$' % self._digits
def update(self):
""" Update alarm status """
verisure.update()
"""Update alarm status."""
hub.update_alarms()
if verisure.STATUS[self._device][self._id].status == 'unarmed':
if hub.alarm_status[self._id].status == 'unarmed':
self._state = STATE_ALARM_DISARMED
elif verisure.STATUS[self._device][self._id].status == 'armedhome':
elif hub.alarm_status[self._id].status == 'armedhome':
self._state = STATE_ALARM_ARMED_HOME
elif verisure.STATUS[self._device][self._id].status == 'armedaway':
elif hub.alarm_status[self._id].status == 'armed':
self._state = STATE_ALARM_ARMED_AWAY
elif verisure.STATUS[self._device][self._id].status != 'pending':
elif hub.alarm_status[self._id].status != 'pending':
_LOGGER.error(
'Unknown alarm state %s',
verisure.STATUS[self._device][self._id].status)
hub.alarm_status[self._id].status)
def alarm_disarm(self, code=None):
""" Send disarm command. """
verisure.MY_PAGES.set_alarm_status(
code,
verisure.MY_PAGES.ALARM_DISARMED)
_LOGGER.warning('disarming')
"""Send disarm command."""
hub.my_pages.alarm.set(code, 'DISARMED')
_LOGGER.info('verisure alarm disarming')
hub.my_pages.alarm.wait_while_pending()
self.update()
def alarm_arm_home(self, code=None):
""" Send arm home command. """
verisure.MY_PAGES.set_alarm_status(
code,
verisure.MY_PAGES.ALARM_ARMED_HOME)
_LOGGER.warning('arming home')
"""Send arm home command."""
hub.my_pages.alarm.set(code, 'ARMED_HOME')
_LOGGER.info('verisure alarm arming home')
hub.my_pages.alarm.wait_while_pending()
self.update()
def alarm_arm_away(self, code=None):
""" Send arm away command. """
verisure.MY_PAGES.set_alarm_status(
code,
verisure.MY_PAGES.ALARM_ARMED_AWAY)
_LOGGER.warning('arming away')
"""Send arm away command."""
hub.my_pages.alarm.set(code, 'ARMED_AWAY')
_LOGGER.info('verisure alarm arming away')
hub.my_pages.alarm.wait_while_pending()
self.update()

View File

@@ -1,7 +1,5 @@
"""
components.alexa
~~~~~~~~~~~~~~~~
Component to offer a service end point for an Alexa skill.
Support for Alexa skill service end point.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/alexa/
@@ -9,105 +7,128 @@ https://home-assistant.io/components/alexa/
import enum
import logging
from homeassistant.const import HTTP_OK, HTTP_UNPROCESSABLE_ENTITY
from homeassistant.util import template
from homeassistant.const import HTTP_BAD_REQUEST
from homeassistant.helpers import template, script
from homeassistant.components.http import HomeAssistantView
DOMAIN = 'alexa'
DEPENDENCIES = ['http']
_LOGGER = logging.getLogger(__name__)
_CONFIG = {}
API_ENDPOINT = '/api/alexa'
CONF_INTENTS = 'intents'
CONF_CARD = 'card'
CONF_SPEECH = 'speech'
CONF_ACTION = 'action'
def setup(hass, config):
""" Activate Alexa component. """
_CONFIG.update(config[DOMAIN].get(CONF_INTENTS, {}))
hass.http.register_path('POST', API_ENDPOINT, _handle_alexa, True)
"""Activate Alexa component."""
hass.wsgi.register_view(AlexaView(hass,
config[DOMAIN].get(CONF_INTENTS, {})))
return True
def _handle_alexa(handler, path_match, data):
""" Handle Alexa. """
_LOGGER.debug('Received Alexa request: %s', data)
class AlexaView(HomeAssistantView):
"""Handle Alexa requests."""
req = data.get('request')
url = API_ENDPOINT
name = 'api:alexa'
if req is None:
_LOGGER.error('Received invalid data from Alexa: %s', data)
handler.write_json_message(
"Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY)
return
def __init__(self, hass, intents):
"""Initialize Alexa view."""
super().__init__(hass)
req_type = req['type']
for name, intent in intents.items():
if CONF_ACTION in intent:
intent[CONF_ACTION] = script.Script(
hass, intent[CONF_ACTION], "Alexa intent {}".format(name))
if req_type == 'SessionEndedRequest':
handler.send_response(HTTP_OK)
handler.end_headers()
return
self.intents = intents
intent = req.get('intent')
response = AlexaResponse(handler.server.hass, intent)
def post(self, request):
"""Handle Alexa."""
data = request.json
if req_type == 'LaunchRequest':
response.add_speech(
SpeechType.plaintext,
"Hello, and welcome to the future. How may I help?")
handler.write_json(response.as_dict())
return
_LOGGER.debug('Received Alexa request: %s', data)
if req_type != 'IntentRequest':
_LOGGER.warning('Received unsupported request: %s', req_type)
return
req = data.get('request')
intent_name = intent['name']
config = _CONFIG.get(intent_name)
if req is None:
_LOGGER.error('Received invalid data from Alexa: %s', data)
return self.json_message('Expected request value not received',
HTTP_BAD_REQUEST)
if config is None:
_LOGGER.warning('Received unknown intent %s', intent_name)
response.add_speech(
SpeechType.plaintext,
"This intent is not yet configured within Home Assistant.")
handler.write_json(response.as_dict())
return
req_type = req['type']
speech = config.get(CONF_SPEECH)
card = config.get(CONF_CARD)
if req_type == 'SessionEndedRequest':
return None
# pylint: disable=unsubscriptable-object
if speech is not None:
response.add_speech(SpeechType[speech['type']], speech['text'])
intent = req.get('intent')
response = AlexaResponse(self.hass, intent)
if card is not None:
response.add_card(CardType[card['type']], card['title'],
card['content'])
if req_type == 'LaunchRequest':
response.add_speech(
SpeechType.plaintext,
"Hello, and welcome to the future. How may I help?")
return self.json(response)
handler.write_json(response.as_dict())
if req_type != 'IntentRequest':
_LOGGER.warning('Received unsupported request: %s', req_type)
return self.json_message(
'Received unsupported request: {}'.format(req_type),
HTTP_BAD_REQUEST)
intent_name = intent['name']
config = self.intents.get(intent_name)
if config is None:
_LOGGER.warning('Received unknown intent %s', intent_name)
response.add_speech(
SpeechType.plaintext,
"This intent is not yet configured within Home Assistant.")
return self.json(response)
speech = config.get(CONF_SPEECH)
card = config.get(CONF_CARD)
action = config.get(CONF_ACTION)
if action is not None:
action.run(response.variables)
# pylint: disable=unsubscriptable-object
if speech is not None:
response.add_speech(SpeechType[speech['type']], speech['text'])
if card is not None:
response.add_card(CardType[card['type']], card['title'],
card['content'])
return self.json(response)
class SpeechType(enum.Enum):
""" Alexa speech types. """
"""The Alexa speech types."""
plaintext = "PlainText"
ssml = "SSML"
class CardType(enum.Enum):
""" Alexa card types. """
"""The Alexa card types."""
simple = "Simple"
link_account = "LinkAccount"
class AlexaResponse(object):
""" Helps generating the response for Alexa. """
"""Help generating the response for Alexa."""
def __init__(self, hass, intent=None):
"""Initialize the response."""
self.hass = hass
self.speech = None
self.card = None
@@ -116,12 +137,12 @@ class AlexaResponse(object):
self.should_end_session = True
if intent is not None and 'slots' in intent:
self.variables = {key: value['value'] for key, value
in intent['slots'].items()}
in intent['slots'].items() if 'value' in value}
else:
self.variables = {}
def add_card(self, card_type, title, content):
""" Add a card to the response. """
"""Add a card to the response."""
assert self.card is None
card = {
@@ -137,7 +158,7 @@ class AlexaResponse(object):
self.card = card
def add_speech(self, speech_type, text):
""" Add speech to the response. """
"""Add speech to the response."""
assert self.speech is None
key = 'ssml' if speech_type == SpeechType.ssml else 'text'
@@ -148,7 +169,7 @@ class AlexaResponse(object):
}
def add_reprompt(self, speech_type, text):
""" Add repromopt if user does not answer. """
"""Add reprompt if user does not answer."""
assert self.reprompt is None
key = 'ssml' if speech_type == SpeechType.ssml else 'text'
@@ -159,7 +180,7 @@ class AlexaResponse(object):
}
def as_dict(self):
""" Returns response in an Alexa valid dict. """
"""Return response in an Alexa valid dict."""
response = {
'shouldEndSession': self.should_end_session
}
@@ -182,5 +203,5 @@ class AlexaResponse(object):
}
def _render(self, template_string):
""" Render a response, adding data from intent if available. """
"""Render a response, adding data from intent if available."""
return template.render(self.hass, template_string, self.variables)

View File

@@ -0,0 +1,82 @@
"""
Support for status output of APCUPSd via its Network Information Server (NIS).
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/apcupsd/
"""
import logging
from datetime import timedelta
from homeassistant.util import Throttle
DOMAIN = "apcupsd"
REQUIREMENTS = ("apcaccess==0.0.4",)
CONF_HOST = "host"
CONF_PORT = "port"
CONF_TYPE = "type"
DEFAULT_HOST = "localhost"
DEFAULT_PORT = 3551
KEY_STATUS = "STATUS"
VALUE_ONLINE = "ONLINE"
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
DATA = None
_LOGGER = logging.getLogger(__name__)
def setup(hass, config):
"""Use config values to set up a function enabling status retrieval."""
global DATA
host = config[DOMAIN].get(CONF_HOST, DEFAULT_HOST)
port = config[DOMAIN].get(CONF_PORT, DEFAULT_PORT)
DATA = APCUPSdData(host, port)
# It doesn't really matter why we're not able to get the status, just that
# we can't.
# pylint: disable=broad-except
try:
DATA.update(no_throttle=True)
except Exception:
_LOGGER.exception("Failure while testing APCUPSd status retrieval.")
return False
return True
class APCUPSdData(object):
"""Stores the data retrieved from APCUPSd.
For each entity to use, acts as the single point responsible for fetching
updates from the server.
"""
def __init__(self, host, port):
"""Initialize the data oject."""
from apcaccess import status
self._host = host
self._port = port
self._status = None
self._get = status.get
self._parse = status.parse
@property
def status(self):
"""Get latest update if throttle allows. Return status."""
self.update()
return self._status
def _get_status(self):
"""Get the status from APCUPSd and parse it into a dict."""
return self._parse(self._get(host=self._host, port=self._port))
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self, **kwargs):
"""Fetch the latest status from APCUPSd."""
self._status = self._get_status()

View File

@@ -1,31 +1,28 @@
"""
homeassistant.components.api
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides a Rest API for Home Assistant.
Rest API for Home Assistant.
For more details about the RESTful API, please refer to the documentation at
https://home-assistant.io/developers/api/
"""
import re
import logging
import threading
import json
import logging
import queue
import homeassistant.core as ha
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.state import TrackStates
import homeassistant.remote as rem
from homeassistant.util import template
from homeassistant.bootstrap import ERROR_LOG_FILENAME
from homeassistant.const import (
URL_API, URL_API_STATES, URL_API_EVENTS, URL_API_SERVICES, URL_API_STREAM,
URL_API_EVENT_FORWARD, URL_API_STATES_ENTITY, URL_API_COMPONENTS,
URL_API_CONFIG, URL_API_BOOTSTRAP, URL_API_ERROR_LOG, URL_API_LOG_OUT,
URL_API_TEMPLATE, EVENT_TIME_CHANGED, EVENT_HOMEASSISTANT_STOP, MATCH_ALL,
HTTP_OK, HTTP_CREATED, HTTP_BAD_REQUEST, HTTP_NOT_FOUND,
HTTP_UNPROCESSABLE_ENTITY, HTTP_HEADER_CONTENT_TYPE,
CONTENT_TYPE_TEXT_PLAIN)
EVENT_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED,
HTTP_BAD_REQUEST, HTTP_CREATED, HTTP_NOT_FOUND,
HTTP_UNPROCESSABLE_ENTITY, MATCH_ALL, URL_API, URL_API_COMPONENTS,
URL_API_CONFIG, URL_API_DISCOVERY_INFO, URL_API_ERROR_LOG,
URL_API_EVENT_FORWARD, URL_API_EVENTS, URL_API_SERVICES,
URL_API_STATES, URL_API_STATES_ENTITY, URL_API_STREAM, URL_API_TEMPLATE,
__version__)
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.state import TrackStates
from homeassistant.helpers import template
from homeassistant.components.http import HomeAssistantView
DOMAIN = 'api'
DEPENDENCIES = ['http']
@@ -37,366 +34,361 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config):
""" Register the API with the HTTP interface. """
# /api - for validation purposes
hass.http.register_path('GET', URL_API, _handle_get_api)
# /api/stream
hass.http.register_path('GET', URL_API_STREAM, _handle_get_api_stream)
# /api/config
hass.http.register_path('GET', URL_API_CONFIG, _handle_get_api_config)
# /api/bootstrap
hass.http.register_path(
'GET', URL_API_BOOTSTRAP, _handle_get_api_bootstrap)
# /states
hass.http.register_path('GET', URL_API_STATES, _handle_get_api_states)
hass.http.register_path(
'GET', re.compile(r'/api/states/(?P<entity_id>[a-zA-Z\._0-9]+)'),
_handle_get_api_states_entity)
hass.http.register_path(
'POST', re.compile(r'/api/states/(?P<entity_id>[a-zA-Z\._0-9]+)'),
_handle_post_state_entity)
hass.http.register_path(
'PUT', re.compile(r'/api/states/(?P<entity_id>[a-zA-Z\._0-9]+)'),
_handle_post_state_entity)
# /events
hass.http.register_path('GET', URL_API_EVENTS, _handle_get_api_events)
hass.http.register_path(
'POST', re.compile(r'/api/events/(?P<event_type>[a-zA-Z\._0-9]+)'),
_handle_api_post_events_event)
# /services
hass.http.register_path('GET', URL_API_SERVICES, _handle_get_api_services)
hass.http.register_path(
'POST',
re.compile((r'/api/services/'
r'(?P<domain>[a-zA-Z\._0-9]+)/'
r'(?P<service>[a-zA-Z\._0-9]+)')),
_handle_post_api_services_domain_service)
# /event_forwarding
hass.http.register_path(
'POST', URL_API_EVENT_FORWARD, _handle_post_api_event_forward)
hass.http.register_path(
'DELETE', URL_API_EVENT_FORWARD, _handle_delete_api_event_forward)
# /components
hass.http.register_path(
'GET', URL_API_COMPONENTS, _handle_get_api_components)
hass.http.register_path('GET', URL_API_ERROR_LOG,
_handle_get_api_error_log)
hass.http.register_path('POST', URL_API_LOG_OUT, _handle_post_api_log_out)
hass.http.register_path('POST', URL_API_TEMPLATE,
_handle_post_api_template)
"""Register the API with the HTTP interface."""
hass.wsgi.register_view(APIStatusView)
hass.wsgi.register_view(APIEventStream)
hass.wsgi.register_view(APIConfigView)
hass.wsgi.register_view(APIDiscoveryView)
hass.wsgi.register_view(APIStatesView)
hass.wsgi.register_view(APIEntityStateView)
hass.wsgi.register_view(APIEventListenersView)
hass.wsgi.register_view(APIEventView)
hass.wsgi.register_view(APIServicesView)
hass.wsgi.register_view(APIDomainServicesView)
hass.wsgi.register_view(APIEventForwardingView)
hass.wsgi.register_view(APIComponentsView)
hass.wsgi.register_view(APIErrorLogView)
hass.wsgi.register_view(APITemplateView)
return True
def _handle_get_api(handler, path_match, data):
""" Renders the debug interface. """
handler.write_json_message("API running.")
class APIStatusView(HomeAssistantView):
"""View to handle Status requests."""
url = URL_API
name = "api:status"
def _handle_get_api_stream(handler, path_match, data):
""" Provide a streaming interface for the event bus. """
gracefully_closed = False
hass = handler.server.hass
wfile = handler.wfile
write_lock = threading.Lock()
block = threading.Event()
session_id = None
def get(self, request):
"""Retrieve if API is running."""
return self.json_message('API running.')
restrict = data.get('restrict')
if restrict:
restrict = restrict.split(',')
def write_message(payload):
""" Writes a message to the output. """
with write_lock:
msg = "data: {}\n\n".format(payload)
class APIEventStream(HomeAssistantView):
"""View to handle EventStream requests."""
try:
wfile.write(msg.encode("UTF-8"))
wfile.flush()
except (IOError, ValueError):
# IOError: socket errors
# ValueError: raised when 'I/O operation on closed file'
block.set()
url = URL_API_STREAM
name = "api:stream"
def forward_events(event):
""" Forwards events to the open request. """
nonlocal gracefully_closed
def get(self, request):
"""Provide a streaming interface for the event bus."""
stop_obj = object()
to_write = queue.Queue()
if block.is_set() or event.event_type == EVENT_TIME_CHANGED:
return
elif event.event_type == EVENT_HOMEASSISTANT_STOP:
gracefully_closed = True
block.set()
return
restrict = request.args.get('restrict')
if restrict:
restrict = restrict.split(',') + [EVENT_HOMEASSISTANT_STOP]
handler.server.sessions.extend_validation(session_id)
write_message(json.dumps(event, cls=rem.JSONEncoder))
def forward_events(event):
"""Forward events to the open request."""
if event.event_type == EVENT_TIME_CHANGED:
return
handler.send_response(HTTP_OK)
handler.send_header('Content-type', 'text/event-stream')
session_id = handler.set_session_cookie_header()
handler.end_headers()
if restrict and event.event_type not in restrict:
return
if restrict:
for event in restrict:
hass.bus.listen(event, forward_events)
else:
hass.bus.listen(MATCH_ALL, forward_events)
_LOGGER.debug('STREAM %s FORWARDING %s', id(stop_obj), event)
while True:
write_message(STREAM_PING_PAYLOAD)
if event.event_type == EVENT_HOMEASSISTANT_STOP:
data = stop_obj
else:
data = json.dumps(event, cls=rem.JSONEncoder)
block.wait(STREAM_PING_INTERVAL)
to_write.put(data)
if block.is_set():
break
def stream():
"""Stream events to response."""
self.hass.bus.listen(MATCH_ALL, forward_events)
if not gracefully_closed:
_LOGGER.info("Found broken event stream to %s, cleaning up",
handler.client_address[0])
_LOGGER.debug('STREAM %s ATTACHED', id(stop_obj))
if restrict:
for event in restrict:
hass.bus.remove_listener(event, forward_events)
else:
hass.bus.remove_listener(MATCH_ALL, forward_events)
# Fire off one message right away to have browsers fire open event
to_write.put(STREAM_PING_PAYLOAD)
while True:
try:
payload = to_write.get(timeout=STREAM_PING_INTERVAL)
def _handle_get_api_config(handler, path_match, data):
""" Returns the Home Assistant config. """
handler.write_json(handler.server.hass.config.as_dict())
if payload is stop_obj:
break
msg = "data: {}\n\n".format(payload)
_LOGGER.debug('STREAM %s WRITING %s', id(stop_obj),
msg.strip())
yield msg.encode("UTF-8")
except queue.Empty:
to_write.put(STREAM_PING_PAYLOAD)
except GeneratorExit:
break
def _handle_get_api_bootstrap(handler, path_match, data):
""" Returns all data needed to bootstrap Home Assistant. """
hass = handler.server.hass
_LOGGER.debug('STREAM %s RESPONSE CLOSED', id(stop_obj))
self.hass.bus.remove_listener(MATCH_ALL, forward_events)
handler.write_json({
'config': hass.config.as_dict(),
'states': hass.states.all(),
'events': _events_json(hass),
'services': _services_json(hass),
})
return self.Response(stream(), mimetype='text/event-stream')
def _handle_get_api_states(handler, path_match, data):
""" Returns a dict containing all entity ids and their state. """
handler.write_json(handler.server.hass.states.all())
class APIConfigView(HomeAssistantView):
"""View to handle Config requests."""
url = URL_API_CONFIG
name = "api:config"
def _handle_get_api_states_entity(handler, path_match, data):
""" Returns the state of a specific entity. """
entity_id = path_match.group('entity_id')
def get(self, request):
"""Get current configuration."""
return self.json(self.hass.config.as_dict())
state = handler.server.hass.states.get(entity_id)
if state:
handler.write_json(state)
else:
handler.write_json_message("State does not exist.", HTTP_NOT_FOUND)
class APIDiscoveryView(HomeAssistantView):
"""View to provide discovery info."""
requires_auth = False
url = URL_API_DISCOVERY_INFO
name = "api:discovery"
def _handle_post_state_entity(handler, path_match, data):
""" Handles updating the state of an entity.
def get(self, request):
"""Get discovery info."""
needs_auth = self.hass.config.api.api_password is not None
return self.json({
'base_url': self.hass.config.api.base_url,
'location_name': self.hass.config.location_name,
'requires_api_password': needs_auth,
'version': __version__
})
This handles the following paths:
/api/states/<entity_id>
"""
entity_id = path_match.group('entity_id')
try:
new_state = data['state']
except KeyError:
handler.write_json_message("state not specified", HTTP_BAD_REQUEST)
return
class APIStatesView(HomeAssistantView):
"""View to handle States requests."""
attributes = data['attributes'] if 'attributes' in data else None
url = URL_API_STATES
name = "api:states"
is_new_state = handler.server.hass.states.get(entity_id) is None
def get(self, request):
"""Get current states."""
return self.json(self.hass.states.all())
# Write state
handler.server.hass.states.set(entity_id, new_state, attributes)
state = handler.server.hass.states.get(entity_id)
class APIEntityStateView(HomeAssistantView):
"""View to handle EntityState requests."""
status_code = HTTP_CREATED if is_new_state else HTTP_OK
url = "/api/states/<entity(exist=False):entity_id>"
name = "api:entity-state"
handler.write_json(
state.as_dict(),
status_code=status_code,
location=URL_API_STATES_ENTITY.format(entity_id))
def get(self, request, entity_id):
"""Retrieve state of entity."""
state = self.hass.states.get(entity_id)
if state:
return self.json(state)
else:
return self.json_message('Entity not found', HTTP_NOT_FOUND)
def post(self, request, entity_id):
"""Update state of entity."""
try:
new_state = request.json['state']
except KeyError:
return self.json_message('No state specified', HTTP_BAD_REQUEST)
def _handle_get_api_events(handler, path_match, data):
""" Handles getting overview of event listeners. """
handler.write_json(_events_json(handler.server.hass))
attributes = request.json.get('attributes')
force_update = request.json.get('force_update', False)
is_new_state = self.hass.states.get(entity_id) is None
def _handle_api_post_events_event(handler, path_match, event_data):
""" Handles firing of an event.
# Write state
self.hass.states.set(entity_id, new_state, attributes, force_update)
This handles the following paths:
/api/events/<event_type>
# Read the state back for our response
resp = self.json(self.hass.states.get(entity_id))
Events from /api are threated as remote events.
"""
event_type = path_match.group('event_type')
if is_new_state:
resp.status_code = HTTP_CREATED
if event_data is not None and not isinstance(event_data, dict):
handler.write_json_message(
"event_data should be an object", HTTP_UNPROCESSABLE_ENTITY)
resp.headers.add('Location', URL_API_STATES_ENTITY.format(entity_id))
event_origin = ha.EventOrigin.remote
return resp
# Special case handling for event STATE_CHANGED
# We will try to convert state dicts back to State objects
if event_type == ha.EVENT_STATE_CHANGED and event_data:
for key in ('old_state', 'new_state'):
state = ha.State.from_dict(event_data.get(key))
def delete(self, request, entity_id):
"""Remove entity."""
if self.hass.states.remove(entity_id):
return self.json_message('Entity removed')
else:
return self.json_message('Entity not found', HTTP_NOT_FOUND)
if state:
event_data[key] = state
handler.server.hass.bus.fire(event_type, event_data, event_origin)
class APIEventListenersView(HomeAssistantView):
"""View to handle EventListeners requests."""
handler.write_json_message("Event {} fired.".format(event_type))
url = URL_API_EVENTS
name = "api:event-listeners"
def get(self, request):
"""Get event listeners."""
return self.json(events_json(self.hass))
def _handle_get_api_services(handler, path_match, data):
""" Handles getting overview of services. """
handler.write_json(_services_json(handler.server.hass))
class APIEventView(HomeAssistantView):
"""View to handle Event requests."""
# pylint: disable=invalid-name
def _handle_post_api_services_domain_service(handler, path_match, data):
""" Handles calling a service.
url = '/api/events/<event_type>'
name = "api:event"
This handles the following paths:
/api/services/<domain>/<service>
"""
domain = path_match.group('domain')
service = path_match.group('service')
def post(self, request, event_type):
"""Fire events."""
event_data = request.json
with TrackStates(handler.server.hass) as changed_states:
handler.server.hass.services.call(domain, service, data, True)
if event_data is not None and not isinstance(event_data, dict):
return self.json_message('Event data should be a JSON object',
HTTP_BAD_REQUEST)
handler.write_json(changed_states)
# Special case handling for event STATE_CHANGED
# We will try to convert state dicts back to State objects
if event_type == ha.EVENT_STATE_CHANGED and event_data:
for key in ('old_state', 'new_state'):
state = ha.State.from_dict(event_data.get(key))
if state:
event_data[key] = state
# pylint: disable=invalid-name
def _handle_post_api_event_forward(handler, path_match, data):
""" Handles adding an event forwarding target. """
self.hass.bus.fire(event_type, event_data, ha.EventOrigin.remote)
try:
host = data['host']
api_password = data['api_password']
except KeyError:
handler.write_json_message(
"No host or api_password received.", HTTP_BAD_REQUEST)
return
return self.json_message("Event {} fired.".format(event_type))
try:
port = int(data['port']) if 'port' in data else None
except ValueError:
handler.write_json_message(
"Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY)
return
api = rem.API(host, api_password, port)
class APIServicesView(HomeAssistantView):
"""View to handle Services requests."""
if not api.validate_api():
handler.write_json_message(
"Unable to validate API", HTTP_UNPROCESSABLE_ENTITY)
return
url = URL_API_SERVICES
name = "api:services"
if handler.server.event_forwarder is None:
handler.server.event_forwarder = \
rem.EventForwarder(handler.server.hass)
def get(self, request):
"""Get registered services."""
return self.json(services_json(self.hass))
handler.server.event_forwarder.connect(api)
handler.write_json_message("Event forwarding setup.")
class APIDomainServicesView(HomeAssistantView):
"""View to handle DomainServices requests."""
url = "/api/services/<domain>/<service>"
name = "api:domain-services"
def _handle_delete_api_event_forward(handler, path_match, data):
""" Handles deleting an event forwarding target. """
def post(self, request, domain, service):
"""Call a service.
try:
host = data['host']
except KeyError:
handler.write_json_message("No host received.", HTTP_BAD_REQUEST)
return
Returns a list of changed states.
"""
with TrackStates(self.hass) as changed_states:
self.hass.services.call(domain, service, request.json, True)
try:
port = int(data['port']) if 'port' in data else None
except ValueError:
handler.write_json_message(
"Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY)
return
return self.json(changed_states)
if handler.server.event_forwarder is not None:
api = rem.API(host, None, port)
handler.server.event_forwarder.disconnect(api)
class APIEventForwardingView(HomeAssistantView):
"""View to handle EventForwarding requests."""
handler.write_json_message("Event forwarding cancelled.")
url = URL_API_EVENT_FORWARD
name = "api:event-forward"
event_forwarder = None
def post(self, request):
"""Setup an event forwarder."""
data = request.json
if data is None:
return self.json_message("No data received.", HTTP_BAD_REQUEST)
try:
host = data['host']
api_password = data['api_password']
except KeyError:
return self.json_message("No host or api_password received.",
HTTP_BAD_REQUEST)
def _handle_get_api_components(handler, path_match, data):
""" Returns all the loaded components. """
try:
port = int(data['port']) if 'port' in data else None
except ValueError:
return self.json_message("Invalid value received for port.",
HTTP_UNPROCESSABLE_ENTITY)
handler.write_json(handler.server.hass.config.components)
api = rem.API(host, api_password, port)
if not api.validate_api():
return self.json_message("Unable to validate API.",
HTTP_UNPROCESSABLE_ENTITY)
def _handle_get_api_error_log(handler, path_match, data):
""" Returns the logged errors for this session. """
handler.write_file(handler.server.hass.config.path(ERROR_LOG_FILENAME),
False)
if self.event_forwarder is None:
self.event_forwarder = rem.EventForwarder(self.hass)
self.event_forwarder.connect(api)
def _handle_post_api_log_out(handler, path_match, data):
""" Log user out. """
handler.send_response(HTTP_OK)
handler.destroy_session()
handler.end_headers()
return self.json_message("Event forwarding setup.")
def delete(self, request):
"""Remove event forwarer."""
data = request.json
if data is None:
return self.json_message("No data received.", HTTP_BAD_REQUEST)
def _handle_post_api_template(handler, path_match, data):
""" Log user out. """
template_string = data.get('template', '')
try:
host = data['host']
except KeyError:
return self.json_message("No host received.", HTTP_BAD_REQUEST)
try:
rendered = template.render(handler.server.hass, template_string)
try:
port = int(data['port']) if 'port' in data else None
except ValueError:
return self.json_message("Invalid value received for port.",
HTTP_UNPROCESSABLE_ENTITY)
handler.send_response(HTTP_OK)
handler.send_header(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN)
handler.end_headers()
handler.wfile.write(rendered.encode('utf-8'))
except TemplateError as e:
handler.write_json_message(str(e), HTTP_UNPROCESSABLE_ENTITY)
return
if self.event_forwarder is not None:
api = rem.API(host, None, port)
self.event_forwarder.disconnect(api)
def _services_json(hass):
""" Generate services data to JSONify. """
return self.json_message("Event forwarding cancelled.")
class APIComponentsView(HomeAssistantView):
"""View to handle Components requests."""
url = URL_API_COMPONENTS
name = "api:components"
def get(self, request):
"""Get current loaded components."""
return self.json(self.hass.config.components)
class APIErrorLogView(HomeAssistantView):
"""View to handle ErrorLog requests."""
url = URL_API_ERROR_LOG
name = "api:error-log"
def get(self, request):
"""Serve error log."""
return self.file(request, self.hass.config.path(ERROR_LOG_FILENAME))
class APITemplateView(HomeAssistantView):
"""View to handle requests."""
url = URL_API_TEMPLATE
name = "api:template"
def post(self, request):
"""Render a template."""
try:
return template.render(self.hass, request.json['template'],
request.json.get('variables'))
except TemplateError as ex:
return self.json_message('Error rendering template: {}'.format(ex),
HTTP_BAD_REQUEST)
def services_json(hass):
"""Generate services data to JSONify."""
return [{"domain": key, "services": value}
for key, value in hass.services.services.items()]
def _events_json(hass):
""" Generate event data to JSONify. """
def events_json(hass):
"""Generate event data to JSONify."""
return [{"event": key, "listener_count": value}
for key, value in hass.bus.listeners.items()]

View File

@@ -1,44 +1,29 @@
"""
components.arduino
~~~~~~~~~~~~~~~~~~
Arduino component that connects to a directly attached Arduino board which
runs with the Firmata firmware.
Support for Arduino boards running with the Firmata firmware.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/arduino/
"""
import logging
try:
from PyMata.pymata import PyMata
except ImportError:
PyMata = None
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers import validate_config
from homeassistant.const import (EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP)
DOMAIN = "arduino"
REQUIREMENTS = ['PyMata==2.07a']
REQUIREMENTS = ['PyMata==2.12']
BOARD = None
_LOGGER = logging.getLogger(__name__)
def setup(hass, config):
""" Setup the Arduino component. """
global PyMata # pylint: disable=invalid-name
if PyMata is None:
from PyMata.pymata import PyMata as PyMata_
PyMata = PyMata_
import serial
"""Setup the Arduino component."""
if not validate_config(config,
{DOMAIN: ['port']},
_LOGGER):
return False
import serial
global BOARD
try:
BOARD = ArduinoBoard(config[DOMAIN]['port'])
@@ -51,11 +36,11 @@ def setup(hass, config):
return False
def stop_arduino(event):
""" Stop the Arduino service. """
"""Stop the Arduino service."""
BOARD.disconnect()
def start_arduino(event):
""" Start the Arduino service. """
"""Start the Arduino service."""
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_arduino)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_arduino)
@@ -64,14 +49,16 @@ def setup(hass, config):
class ArduinoBoard(object):
""" Represents an Arduino board. """
"""Representation of an Arduino board."""
def __init__(self, port):
"""Initialize the board."""
from PyMata.pymata import PyMata
self._port = port
self._board = PyMata(self._port, verbose=False)
def set_mode(self, pin, direction, mode):
""" Sets the mode and the direction of a given pin. """
"""Set the mode and the direction of a given pin."""
if mode == 'analog' and direction == 'in':
self._board.set_pin_mode(pin,
self._board.INPUT,
@@ -82,7 +69,7 @@ class ArduinoBoard(object):
self._board.ANALOG)
elif mode == 'digital' and direction == 'in':
self._board.set_pin_mode(pin,
self._board.OUTPUT,
self._board.INPUT,
self._board.DIGITAL)
elif mode == 'digital' and direction == 'out':
self._board.set_pin_mode(pin,
@@ -94,31 +81,31 @@ class ArduinoBoard(object):
self._board.PWM)
def get_analog_inputs(self):
""" Get the values from the pins. """
"""Get the values from the pins."""
self._board.capability_query()
return self._board.get_analog_response_table()
def set_digital_out_high(self, pin):
""" Sets a given digital pin to high. """
"""Set a given digital pin to high."""
self._board.digital_write(pin, 1)
def set_digital_out_low(self, pin):
""" Sets a given digital pin to low. """
"""Set a given digital pin to low."""
self._board.digital_write(pin, 0)
def get_digital_in(self, pin):
""" Gets the value from a given digital pin. """
"""Get the value from a given digital pin."""
self._board.digital_read(pin)
def get_analog_in(self, pin):
""" Gets the value from a given analog pin. """
"""Get the value from a given analog pin."""
self._board.analog_read(pin)
def get_firmata(self):
""" Return the version of the Firmata firmware. """
"""Return the version of the Firmata firmware."""
return self._board.get_firmata_version()
def disconnect(self):
""" Disconnects the board and closes the serial connection. """
"""Disconnect the board and close the serial connection."""
self._board.reset()
self._board.close()

View File

@@ -1,26 +1,26 @@
"""
homeassistant.components.automation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to setup simple automation rules via the config file.
Allow to setup simple automation rules via the config file.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/automation/
"""
import logging
import voluptuous as vol
from homeassistant.bootstrap import prepare_setup_platform
from homeassistant.util import split_entity_id
from homeassistant.const import ATTR_ENTITY_ID, CONF_PLATFORM
from homeassistant.components import logbook
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import extract_domain_configs, script, condition
from homeassistant.loader import get_platform
import homeassistant.helpers.config_validation as cv
DOMAIN = 'automation'
DEPENDENCIES = ['group']
CONF_ALIAS = 'alias'
CONF_SERVICE = 'service'
CONF_SERVICE_ENTITY_ID = 'entity_id'
CONF_SERVICE_DATA = 'data'
CONF_CONDITION = 'condition'
CONF_ACTION = 'action'
@@ -33,47 +33,86 @@ CONDITION_TYPE_OR = 'or'
DEFAULT_CONDITION_TYPE = CONDITION_TYPE_AND
METHOD_TRIGGER = 'trigger'
METHOD_IF_ACTION = 'if_action'
_LOGGER = logging.getLogger(__name__)
def _platform_validator(method, schema):
"""Generate platform validator for different steps."""
def validator(config):
"""Validate it is a valid platform."""
platform = get_platform(DOMAIN, config[CONF_PLATFORM])
if not hasattr(platform, method):
raise vol.Invalid('invalid method platform')
if not hasattr(platform, schema):
return config
return getattr(platform, schema)(config)
return validator
_TRIGGER_SCHEMA = vol.All(
cv.ensure_list,
[
vol.All(
vol.Schema({
vol.Required(CONF_PLATFORM): cv.platform_validator(DOMAIN)
}, extra=vol.ALLOW_EXTRA),
_platform_validator(METHOD_TRIGGER, 'TRIGGER_SCHEMA')
),
]
)
_CONDITION_SCHEMA = vol.Any(
CONDITION_USE_TRIGGER_VALUES,
vol.All(
cv.ensure_list,
[
vol.All(
vol.Schema({
CONF_PLATFORM: str,
CONF_CONDITION: str,
}, extra=vol.ALLOW_EXTRA),
cv.has_at_least_one_key(CONF_PLATFORM, CONF_CONDITION),
),
]
)
)
PLATFORM_SCHEMA = vol.Schema({
CONF_ALIAS: cv.string,
vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA,
vol.Required(CONF_CONDITION_TYPE, default=DEFAULT_CONDITION_TYPE):
vol.All(vol.Lower, vol.Any(CONDITION_TYPE_AND, CONDITION_TYPE_OR)),
CONF_CONDITION: _CONDITION_SCHEMA,
vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA,
})
def setup(hass, config):
""" Sets up automation. """
config_key = DOMAIN
found = 1
"""Setup the automation."""
success = False
for config_key in extract_domain_configs(config, DOMAIN):
conf = config[config_key]
while config_key in config:
# check for one block syntax
if isinstance(config[config_key], dict):
config_block = _migrate_old_config(config[config_key])
name = config_block.get(CONF_ALIAS, config_key)
_setup_automation(hass, config_block, name, config)
for list_no, config_block in enumerate(conf):
name = config_block.get(CONF_ALIAS, "{}, {}".format(config_key,
list_no))
success = (_setup_automation(hass, config_block, name, config) or
success)
# check for multiple block syntax
elif isinstance(config[config_key], list):
for list_no, config_block in enumerate(config[config_key]):
name = config_block.get(CONF_ALIAS,
"{}, {}".format(config_key, list_no))
_setup_automation(hass, config_block, name, config)
# any scalar value is incorrect
else:
_LOGGER.error('Error in config in section %s.', config_key)
found += 1
config_key = "{} {}".format(DOMAIN, found)
return True
return success
def _setup_automation(hass, config_block, name, config):
""" Setup one instance of automation """
"""Setup one instance of automation."""
action = _get_action(hass, config_block.get(CONF_ACTION, {}), name)
if action is None:
return False
if CONF_CONDITION in config_block or CONF_CONDITION_TYPE in config_block:
if CONF_CONDITION in config_block:
action = _process_if(hass, config, config_block, action)
if action is None:
@@ -85,122 +124,79 @@ def _setup_automation(hass, config_block, name, config):
def _get_action(hass, config, name):
""" Return an action based on a config. """
"""Return an action based on a configuration."""
script_obj = script.Script(hass, config, name)
if CONF_SERVICE not in config:
_LOGGER.error('Error setting up %s, no action specified.', name)
return None
def action():
""" Action to be executed. """
def action(variables=None):
"""Action to be executed."""
_LOGGER.info('Executing %s', name)
logbook.log_entry(hass, name, 'has been triggered', DOMAIN)
domain, service = split_entity_id(config[CONF_SERVICE])
service_data = config.get(CONF_SERVICE_DATA, {})
if not isinstance(service_data, dict):
_LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
service_data = {}
if CONF_SERVICE_ENTITY_ID in config:
try:
service_data[ATTR_ENTITY_ID] = \
config[CONF_SERVICE_ENTITY_ID].split(",")
except AttributeError:
service_data[ATTR_ENTITY_ID] = \
config[CONF_SERVICE_ENTITY_ID]
hass.services.call(domain, service, service_data)
script_obj.run(variables)
return action
def _migrate_old_config(config):
""" Migrate old config to new. """
if CONF_PLATFORM not in config:
return config
_LOGGER.warning(
'You are using an old configuration format. Please upgrade: '
'https://home-assistant.io/components/automation/')
new_conf = {
CONF_TRIGGER: dict(config),
CONF_CONDITION: config.get('if', []),
CONF_ACTION: dict(config),
}
for cat, key, new_key in (('trigger', 'mqtt_topic', 'topic'),
('trigger', 'mqtt_payload', 'payload'),
('trigger', 'state_entity_id', 'entity_id'),
('trigger', 'state_before', 'before'),
('trigger', 'state_after', 'after'),
('trigger', 'state_to', 'to'),
('trigger', 'state_from', 'from'),
('trigger', 'state_hours', 'hours'),
('trigger', 'state_minutes', 'minutes'),
('trigger', 'state_seconds', 'seconds'),
('action', 'execute_service', 'service'),
('action', 'service_entity_id', 'entity_id'),
('action', 'service_data', 'data')):
if key in new_conf[cat]:
new_conf[cat][new_key] = new_conf[cat].pop(key)
return new_conf
def _process_if(hass, config, p_config, action):
""" Processes if checks. """
"""Process if checks."""
cond_type = p_config.get(CONF_CONDITION_TYPE,
DEFAULT_CONDITION_TYPE).lower()
# Deprecated since 0.19 - 5/5/2016
if cond_type != DEFAULT_CONDITION_TYPE:
_LOGGER.warning('Using condition_type: "or" is deprecated. Please use '
'"condition: or" instead.')
if_configs = p_config.get(CONF_CONDITION)
use_trigger = if_configs == CONDITION_USE_TRIGGER_VALUES
if use_trigger:
if_configs = p_config[CONF_TRIGGER]
if isinstance(if_configs, dict):
if_configs = [if_configs]
checks = []
for if_config in if_configs:
platform = _resolve_platform('if_action', hass, config,
if_config.get(CONF_PLATFORM))
if platform is None:
continue
# Deprecated except for used by use_trigger_values
# since 0.19 - 5/5/2016
if CONF_PLATFORM in if_config:
if not use_trigger:
_LOGGER.warning("Please switch your condition configuration "
"to use 'condition' instead of 'platform'.")
if_config = dict(if_config)
if_config[CONF_CONDITION] = if_config.pop(CONF_PLATFORM)
check = platform.if_action(hass, if_config)
# To support use_trigger_values with state trigger accepting
# multiple entity_ids to monitor.
if_entity_id = if_config.get(ATTR_ENTITY_ID)
if isinstance(if_entity_id, list) and len(if_entity_id) == 1:
if_config[ATTR_ENTITY_ID] = if_entity_id[0]
# Invalid conditions are allowed if we base it on trigger
if check is None and not use_trigger:
return None
checks.append(check)
try:
checks.append(condition.from_config(if_config))
except HomeAssistantError as ex:
# Invalid conditions are allowed if we base it on trigger
if use_trigger:
_LOGGER.warning('Ignoring invalid condition: %s', ex)
else:
_LOGGER.warning('Invalid condition: %s', ex)
return None
if cond_type == CONDITION_TYPE_AND:
def if_action():
""" AND all conditions. """
if all(check() for check in checks):
action()
def if_action(variables=None):
"""AND all conditions."""
if all(check(hass, variables) for check in checks):
action(variables)
else:
def if_action():
""" OR all conditions. """
if any(check() for check in checks):
action()
def if_action(variables=None):
"""OR all conditions."""
if any(check(hass, variables) for check in checks):
action(variables)
return if_action
def _process_trigger(hass, config, trigger_configs, name, action):
""" Setup triggers. """
if isinstance(trigger_configs, dict):
trigger_configs = [trigger_configs]
"""Setup the triggers."""
for conf in trigger_configs:
platform = _resolve_platform('trigger', hass, config,
platform = _resolve_platform(METHOD_TRIGGER, hass, config,
conf.get(CONF_PLATFORM))
if platform is None:
continue
@@ -212,7 +208,7 @@ def _process_trigger(hass, config, trigger_configs, name, action):
def _resolve_platform(method, hass, config, platform):
""" Find automation platform. """
"""Find the automation platform."""
if platform is None:
return None
platform = prepare_setup_platform(hass, config, DOMAIN, platform)

View File

@@ -1,34 +1,43 @@
"""
homeassistant.components.automation.event
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers event listening automation rules.
Offer event listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#event-trigger
"""
import logging
import voluptuous as vol
from homeassistant.const import CONF_PLATFORM
from homeassistant.helpers import config_validation as cv
CONF_EVENT_TYPE = "event_type"
CONF_EVENT_DATA = "event_data"
_LOGGER = logging.getLogger(__name__)
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'event',
vol.Required(CONF_EVENT_TYPE): cv.string,
vol.Optional(CONF_EVENT_DATA): dict,
})
def trigger(hass, config, action):
""" Listen for events based on config. """
"""Listen for events based on configuration."""
event_type = config.get(CONF_EVENT_TYPE)
if event_type is None:
_LOGGER.error("Missing configuration key %s", CONF_EVENT_TYPE)
return False
event_data = config.get(CONF_EVENT_DATA)
def handle_event(event):
""" Listens for events and calls the action when data matches. """
"""Listen for events and calls the action when data matches."""
if not event_data or all(val == event.data.get(key) for key, val
in event_data.items()):
action()
action({
'trigger': {
'platform': 'event',
'event': event,
},
})
hass.bus.listen(event_type, handle_event)
return True

View File

@@ -1,35 +1,43 @@
"""
homeassistant.components.automation.mqtt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers MQTT listening automation rules.
Offer MQTT listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#mqtt-trigger
"""
import logging
import voluptuous as vol
import homeassistant.components.mqtt as mqtt
from homeassistant.const import CONF_PLATFORM
import homeassistant.helpers.config_validation as cv
DEPENDENCIES = ['mqtt']
CONF_TOPIC = 'topic'
CONF_PAYLOAD = 'payload'
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): mqtt.DOMAIN,
vol.Required(CONF_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_PAYLOAD): cv.string,
})
def trigger(hass, config, action):
""" Listen for state changes based on `config`. """
topic = config.get(CONF_TOPIC)
"""Listen for state changes based on configuration."""
topic = config[CONF_TOPIC]
payload = config.get(CONF_PAYLOAD)
if topic is None:
logging.getLogger(__name__).error(
"Missing configuration key %s", CONF_TOPIC)
return False
def mqtt_automation_listener(msg_topic, msg_payload, qos):
""" Listens for MQTT messages. """
"""Listen for MQTT messages."""
if payload is None or payload == msg_payload:
action()
action({
'trigger': {
'platform': 'mqtt',
'topic': msg_topic,
'payload': msg_payload,
'qos': qos,
}
})
mqtt.subscribe(hass, topic, mqtt_automation_listener)

View File

@@ -1,111 +1,69 @@
"""
homeassistant.components.automation.numeric_state
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers numeric state listening automation rules.
Offer numeric state listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#numeric-state-trigger
"""
import logging
from homeassistant.const import CONF_VALUE_TEMPLATE
import voluptuous as vol
from homeassistant.const import (
CONF_VALUE_TEMPLATE, CONF_PLATFORM, CONF_ENTITY_ID,
CONF_BELOW, CONF_ABOVE)
from homeassistant.helpers.event import track_state_change
from homeassistant.util import template
from homeassistant.helpers import condition, config_validation as cv
CONF_ENTITY_ID = "entity_id"
CONF_BELOW = "below"
CONF_ABOVE = "above"
TRIGGER_SCHEMA = vol.All(vol.Schema({
vol.Required(CONF_PLATFORM): 'numeric_state',
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
CONF_BELOW: vol.Coerce(float),
CONF_ABOVE: vol.Coerce(float),
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
}), cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE))
_LOGGER = logging.getLogger(__name__)
def trigger(hass, config, action):
""" Listen for state changes based on `config`. """
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
if entity_id is None:
_LOGGER.error("Missing configuration key %s", CONF_ENTITY_ID)
return False
below = config.get(CONF_BELOW)
above = config.get(CONF_ABOVE)
value_template = config.get(CONF_VALUE_TEMPLATE)
if below is None and above is None:
_LOGGER.error("Missing configuration key."
" One of %s or %s is required",
CONF_BELOW, CONF_ABOVE)
return False
if value_template is not None:
renderer = lambda value: template.render(hass,
value_template,
{'state': value})
else:
renderer = lambda value: value.state
# pylint: disable=unused-argument
def state_automation_listener(entity, from_s, to_s):
""" Listens for state changes and calls action. """
"""Listen for state changes and calls action."""
if to_s is None:
return
# Fire action if we go from outside range into range
if _in_range(above, below, renderer(to_s)) and \
(from_s is None or not _in_range(above, below, renderer(from_s))):
action()
variables = {
'trigger': {
'platform': 'numeric_state',
'entity_id': entity,
'below': below,
'above': above,
}
}
# If new one doesn't match, nothing to do
if not condition.numeric_state(
hass, to_s, below, above, value_template, variables):
return
# Only match if old didn't exist or existed but didn't match
# Written as: skip if old one did exist and matched
if from_s is not None and condition.numeric_state(
hass, from_s, below, above, value_template, variables):
return
variables['trigger']['from_state'] = from_s
variables['trigger']['to_state'] = to_s
action(variables)
track_state_change(
hass, entity_id, state_automation_listener)
return True
def if_action(hass, config):
""" Wraps action method with state based condition. """
entity_id = config.get(CONF_ENTITY_ID)
if entity_id is None:
_LOGGER.error("Missing configuration key %s", CONF_ENTITY_ID)
return None
below = config.get(CONF_BELOW)
above = config.get(CONF_ABOVE)
value_template = config.get(CONF_VALUE_TEMPLATE)
if below is None and above is None:
_LOGGER.error("Missing configuration key."
" One of %s or %s is required",
CONF_BELOW, CONF_ABOVE)
return None
if value_template is not None:
renderer = lambda value: template.render(hass,
value_template,
{'state': value})
else:
renderer = lambda value: value.state
def if_numeric_state():
""" Test numeric state condition. """
state = hass.states.get(entity_id)
return state is not None and _in_range(above, below, renderer(state))
return if_numeric_state
def _in_range(range_start, range_end, value):
""" Checks if value is inside the range """
try:
value = float(value)
except ValueError:
_LOGGER.warning("Value returned from template is not a number: %s",
value)
return False
if range_start is not None and range_end is not None:
return float(range_start) <= value < float(range_end)
elif range_end is not None:
return value < float(range_end)
else:
return float(range_start) <= value

View File

@@ -1,65 +1,85 @@
"""
homeassistant.components.automation.state
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers state listening automation rules.
Offer state listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#state-trigger
"""
import logging
from homeassistant.helpers.event import track_state_change
from homeassistant.const import MATCH_ALL
import voluptuous as vol
import homeassistant.util.dt as dt_util
from homeassistant.const import (
EVENT_STATE_CHANGED, EVENT_TIME_CHANGED, MATCH_ALL, CONF_PLATFORM)
from homeassistant.helpers.event import track_state_change, track_point_in_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"
TRIGGER_SCHEMA = vol.All(
vol.Schema({
vol.Required(CONF_PLATFORM): 'state',
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
# These are str on purpose. Want to catch YAML conversions
CONF_FROM: str,
CONF_TO: str,
CONF_STATE: str,
CONF_FOR: vol.All(cv.time_period, cv.positive_timedelta),
}),
vol.Any(cv.key_dependency(CONF_FOR, CONF_TO),
cv.key_dependency(CONF_FOR, CONF_STATE))
)
def trigger(hass, config, action):
""" Listen for state changes based on `config`. """
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
if entity_id is None:
logging.getLogger(__name__).error(
"Missing trigger configuration key %s", CONF_ENTITY_ID)
return False
from_state = config.get(CONF_FROM, MATCH_ALL)
to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL
if isinstance(from_state, bool) or isinstance(to_state, bool):
logging.getLogger(__name__).error(
'Config error. Surround to/from values with quotes.')
return False
time_delta = config.get(CONF_FOR)
def state_automation_listener(entity, from_s, to_s):
""" Listens for state changes and calls action. """
action()
"""Listen for state changes and calls action."""
def call_action():
"""Call action with right context."""
action({
'trigger': {
'platform': 'state',
'entity_id': entity,
'from_state': from_s,
'to_state': to_s,
'for': time_delta,
}
})
if time_delta is None:
call_action()
return
def state_for_listener(now):
"""Fire on state changes after a delay and calls action."""
hass.bus.remove_listener(
EVENT_STATE_CHANGED, attached_state_for_cancel)
call_action()
def state_for_cancel_listener(entity, inner_from_s, inner_to_s):
"""Fire on changes and cancel for listener if changed."""
if inner_to_s.state == to_s.state:
return
hass.bus.remove_listener(EVENT_TIME_CHANGED,
attached_state_for_listener)
hass.bus.remove_listener(EVENT_STATE_CHANGED,
attached_state_for_cancel)
attached_state_for_listener = track_point_in_time(
hass, state_for_listener, dt_util.utcnow() + time_delta)
attached_state_for_cancel = track_state_change(
hass, entity, state_for_cancel_listener)
track_state_change(
hass, entity_id, state_automation_listener, from_state, to_state)
return True
def if_action(hass, config):
""" Wraps action method with state based condition. """
entity_id = config.get(CONF_ENTITY_ID)
state = config.get(CONF_STATE)
if entity_id is None or state is None:
logging.getLogger(__name__).error(
"Missing if-condition configuration key %s or %s", CONF_ENTITY_ID,
CONF_STATE)
return None
state = str(state)
def if_state():
""" Test if condition. """
return hass.states.is_state(entity_id, state)
return if_state

View File

@@ -1,105 +1,49 @@
"""
homeassistant.components.automation.sun
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers sun based automation rules.
Offer sun based automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#sun-trigger
"""
import logging
from datetime import timedelta
import logging
from homeassistant.components import sun
from homeassistant.helpers.event import track_point_in_utc_time
import homeassistant.util.dt as dt_util
import voluptuous as vol
from homeassistant.const import (
CONF_EVENT, CONF_OFFSET, CONF_PLATFORM, SUN_EVENT_SUNRISE)
from homeassistant.helpers.event import track_sunrise, track_sunset
import homeassistant.helpers.config_validation as cv
DEPENDENCIES = ['sun']
CONF_OFFSET = 'offset'
CONF_EVENT = 'event'
EVENT_SUNSET = 'sunset'
EVENT_SUNRISE = 'sunrise'
_LOGGER = logging.getLogger(__name__)
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'sun',
vol.Required(CONF_EVENT): cv.sun_event,
vol.Required(CONF_OFFSET, default=timedelta(0)): cv.time_period,
})
def trigger(hass, config, action):
""" Listen for events based on config. """
"""Listen for events based on configuration."""
event = config.get(CONF_EVENT)
offset = config.get(CONF_OFFSET)
if event is None:
_LOGGER.error("Missing configuration key %s", CONF_EVENT)
return False
event = event.lower()
if event not in (EVENT_SUNRISE, EVENT_SUNSET):
_LOGGER.error("Invalid value for %s: %s", CONF_EVENT, event)
return False
if CONF_OFFSET in config:
raw_offset = config.get(CONF_OFFSET)
negative_offset = False
if raw_offset.startswith('-'):
negative_offset = True
raw_offset = raw_offset[1:]
try:
(hour, minute, second) = [int(x) for x in raw_offset.split(':')]
except ValueError:
_LOGGER.error('Could not parse offset %s', raw_offset)
return False
offset = timedelta(hours=hour, minutes=minute, seconds=second)
if negative_offset:
offset *= -1
else:
offset = timedelta(0)
def call_action():
"""Call action with right context."""
action({
'trigger': {
'platform': 'sun',
'event': event,
'offset': offset,
},
})
# Do something to call action
if event == EVENT_SUNRISE:
trigger_sunrise(hass, action, offset)
if event == SUN_EVENT_SUNRISE:
track_sunrise(hass, call_action, offset)
else:
trigger_sunset(hass, action, offset)
track_sunset(hass, call_action, offset)
return True
def trigger_sunrise(hass, action, offset):
""" Trigger action at next sun rise. """
def next_rise():
""" Returns next sunrise. """
next_time = sun.next_rising_utc(hass) + offset
while next_time < dt_util.utcnow():
next_time = next_time + timedelta(days=1)
return next_time
def sunrise_automation_listener(now):
""" Called when it's time for action. """
track_point_in_utc_time(hass, sunrise_automation_listener, next_rise())
action()
track_point_in_utc_time(hass, sunrise_automation_listener, next_rise())
def trigger_sunset(hass, action, offset):
""" Trigger action at next sun set. """
def next_set():
""" Returns next sunrise. """
next_time = sun.next_setting_utc(hass) + offset
while next_time < dt_util.utcnow():
next_time = next_time + timedelta(days=1)
return next_time
def sunset_automation_listener(now):
""" Called when it's time for action. """
track_point_in_utc_time(hass, sunset_automation_listener, next_set())
action()
track_point_in_utc_time(hass, sunset_automation_listener, next_set())

View File

@@ -1,65 +1,53 @@
"""
homeassistant.components.automation.template
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers template automation rules.
Offer template automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#template-trigger
"""
import logging
from homeassistant.const import CONF_VALUE_TEMPLATE, EVENT_STATE_CHANGED
from homeassistant.exceptions import TemplateError
from homeassistant.util import template
import voluptuous as vol
from homeassistant.const import (
CONF_VALUE_TEMPLATE, CONF_PLATFORM, MATCH_ALL)
from homeassistant.helpers import condition
from homeassistant.helpers.event import track_state_change
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'template',
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
})
def trigger(hass, config, action):
""" Listen for state changes based on `config`. """
"""Listen for state changes based on configuration."""
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is None:
_LOGGER.error("Missing configuration key %s", CONF_VALUE_TEMPLATE)
return False
# Local variable to keep track of if the action has already been triggered
already_triggered = False
def event_listener(event):
""" Listens for state changes and calls action. """
def state_changed_listener(entity_id, from_s, to_s):
"""Listen for state changes and calls action."""
nonlocal already_triggered
template_result = _check_template(hass, value_template)
template_result = condition.template(hass, value_template)
# Check to see if template returns true
if template_result and not already_triggered:
already_triggered = True
action()
action({
'trigger': {
'platform': 'template',
'entity_id': entity_id,
'from_state': from_s,
'to_state': to_s,
},
})
elif not template_result:
already_triggered = False
hass.bus.listen(EVENT_STATE_CHANGED, event_listener)
track_state_change(hass, MATCH_ALL, state_changed_listener)
return True
def if_action(hass, config):
""" Wraps action method with state based condition. """
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is None:
_LOGGER.error("Missing configuration key %s", CONF_VALUE_TEMPLATE)
return False
return lambda: _check_template(hass, value_template)
def _check_template(hass, value_template):
""" Checks if result of template is true """
try:
value = template.render(hass, value_template, {})
except TemplateError:
_LOGGER.exception('Error parsing template')
return False
return value.lower() == 'true'

View File

@@ -1,107 +1,53 @@
"""
homeassistant.components.automation.time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers time listening automation rules.
Offer time listening automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#time-trigger
"""
import logging
from homeassistant.util import convert
import homeassistant.util.dt as dt_util
import voluptuous as vol
from homeassistant.const import CONF_AFTER, CONF_PLATFORM
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import track_time_change
CONF_HOURS = "hours"
CONF_MINUTES = "minutes"
CONF_SECONDS = "seconds"
CONF_BEFORE = "before"
CONF_AFTER = "after"
CONF_WEEKDAY = "weekday"
WEEKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
_LOGGER = logging.getLogger(__name__)
TRIGGER_SCHEMA = vol.All(vol.Schema({
vol.Required(CONF_PLATFORM): 'time',
CONF_AFTER: cv.time,
CONF_HOURS: vol.Any(vol.Coerce(int), vol.Coerce(str)),
CONF_MINUTES: vol.Any(vol.Coerce(int), vol.Coerce(str)),
CONF_SECONDS: vol.Any(vol.Coerce(int), vol.Coerce(str)),
}), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES,
CONF_SECONDS, CONF_AFTER))
def trigger(hass, config, action):
""" Listen for state changes based on `config`. """
"""Listen for state changes based on configuration."""
if CONF_AFTER in config:
after = dt_util.parse_time_str(config[CONF_AFTER])
if after is None:
_error_time(config[CONF_AFTER], CONF_AFTER)
return False
after = config.get(CONF_AFTER)
hours, minutes, seconds = after.hour, after.minute, after.second
elif (CONF_HOURS in config or CONF_MINUTES in config
or CONF_SECONDS in config):
hours = convert(config.get(CONF_HOURS), int)
minutes = convert(config.get(CONF_MINUTES), int)
seconds = convert(config.get(CONF_SECONDS), int)
else:
_LOGGER.error('One of %s, %s, %s OR %s needs to be specified',
CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AFTER)
return False
hours = config.get(CONF_HOURS)
minutes = config.get(CONF_MINUTES)
seconds = config.get(CONF_SECONDS)
def time_automation_listener(now):
""" Listens for time changes and calls action. """
action()
"""Listen for time changes and calls action."""
action({
'trigger': {
'platform': 'time',
'now': now,
},
})
track_time_change(hass, time_automation_listener,
hour=hours, minute=minutes, second=seconds)
return True
def if_action(hass, config):
""" Wraps action method with time based condition. """
before = config.get(CONF_BEFORE)
after = config.get(CONF_AFTER)
weekday = config.get(CONF_WEEKDAY)
if before is None and after is None and weekday is None:
logging.getLogger(__name__).error(
"Missing if-condition configuration key %s, %s or %s",
CONF_BEFORE, CONF_AFTER, CONF_WEEKDAY)
return None
if before is not None:
before = dt_util.parse_time_str(before)
if before is None:
_error_time(before, CONF_BEFORE)
return None
if after is not None:
after = dt_util.parse_time_str(after)
if after is None:
_error_time(after, CONF_AFTER)
return None
def time_if():
""" Validate time based if-condition """
now = dt_util.now()
if before is not None and now > now.replace(hour=before.hour,
minute=before.minute):
return False
if after is not None and now < now.replace(hour=after.hour,
minute=after.minute):
return False
if weekday is not None:
now_weekday = WEEKDAYS[now.weekday()]
if isinstance(weekday, str) and weekday != now_weekday or \
now_weekday not in weekday:
return False
return True
return time_if
def _error_time(value, key):
""" Helper method to print error. """
_LOGGER.error(
"Received invalid value for '%s': %s", key, value)
if isinstance(value, int):
_LOGGER.error('Make sure you wrap time values in quotes')

View File

@@ -1,88 +1,64 @@
"""
homeassistant.components.automation.zone
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Offers zone automation rules.
Offer zone automation rules.
For more details about this automation rule, please refer to the documentation
at https://home-assistant.io/components/automation/#zone-trigger
"""
import logging
import voluptuous as vol
from homeassistant.components import zone
from homeassistant.helpers.event import track_state_change
from homeassistant.const import (
ATTR_GPS_ACCURACY, ATTR_LATITUDE, ATTR_LONGITUDE, MATCH_ALL)
CONF_EVENT, CONF_ENTITY_ID, CONF_ZONE, MATCH_ALL, CONF_PLATFORM)
from homeassistant.helpers.event import track_state_change
from homeassistant.helpers import (
condition, config_validation as cv, location)
CONF_ENTITY_ID = "entity_id"
CONF_ZONE = "zone"
CONF_EVENT = "event"
EVENT_ENTER = "enter"
EVENT_LEAVE = "leave"
DEFAULT_EVENT = EVENT_ENTER
TRIGGER_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): 'zone',
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Required(CONF_ZONE): cv.entity_id,
vol.Required(CONF_EVENT, default=DEFAULT_EVENT):
vol.Any(EVENT_ENTER, EVENT_LEAVE),
})
def trigger(hass, config, action):
""" Listen for state changes based on `config`. """
"""Listen for state changes based on configuration."""
entity_id = config.get(CONF_ENTITY_ID)
zone_entity_id = config.get(CONF_ZONE)
if entity_id is None or zone_entity_id is None:
logging.getLogger(__name__).error(
"Missing trigger configuration key %s or %s", CONF_ENTITY_ID,
CONF_ZONE)
return False
event = config.get(CONF_EVENT, DEFAULT_EVENT)
event = config.get(CONF_EVENT)
def zone_automation_listener(entity, from_s, to_s):
""" Listens for state changes and calls action. """
if from_s and None in (from_s.attributes.get(ATTR_LATITUDE),
from_s.attributes.get(ATTR_LONGITUDE)) or \
None in (to_s.attributes.get(ATTR_LATITUDE),
to_s.attributes.get(ATTR_LONGITUDE)):
"""Listen for state changes and calls action."""
if from_s and not location.has_location(from_s) or \
not location.has_location(to_s):
return
from_match = _in_zone(hass, zone_entity_id, from_s) if from_s else None
to_match = _in_zone(hass, zone_entity_id, to_s)
zone_state = hass.states.get(zone_entity_id)
if from_s:
from_match = condition.zone(hass, zone_state, from_s)
else:
from_match = False
to_match = condition.zone(hass, zone_state, to_s)
# pylint: disable=too-many-boolean-expressions
if event == EVENT_ENTER and not from_match and to_match or \
event == EVENT_LEAVE and from_match and not to_match:
action()
action({
'trigger': {
'platform': 'zone',
'entity_id': entity,
'from_state': from_s,
'to_state': to_s,
'zone': zone_state,
'event': event,
},
})
track_state_change(
hass, entity_id, zone_automation_listener, MATCH_ALL, MATCH_ALL)
return True
def if_action(hass, config):
""" Wraps action method with zone based condition. """
entity_id = config.get(CONF_ENTITY_ID)
zone_entity_id = config.get(CONF_ZONE)
if entity_id is None or zone_entity_id is None:
logging.getLogger(__name__).error(
"Missing condition configuration key %s or %s", CONF_ENTITY_ID,
CONF_ZONE)
return False
def if_in_zone():
""" Test if condition. """
return _in_zone(hass, zone_entity_id, hass.states.get(entity_id))
return if_in_zone
def _in_zone(hass, zone_entity_id, state):
""" Check if state is in zone. """
if not state or None in (state.attributes.get(ATTR_LATITUDE),
state.attributes.get(ATTR_LONGITUDE)):
return False
zone_state = hass.states.get(zone_entity_id)
return zone_state and zone.in_zone(
zone_state, state.attributes.get(ATTR_LATITUDE),
state.attributes.get(ATTR_LONGITUDE),
state.attributes.get(ATTR_GPS_ACCURACY, 0))

View File

@@ -1,8 +1,5 @@
"""
homeassistant.components.binary_sensor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to interface with binary sensors (sensors which only know two states)
that can be monitored.
Component to interface with binary sensors.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor/
@@ -12,15 +9,33 @@ import logging
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity import Entity
from homeassistant.const import (STATE_ON, STATE_OFF)
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
DOMAIN = 'binary_sensor'
SCAN_INTERVAL = 30
ENTITY_ID_FORMAT = DOMAIN + '.{}'
SENSOR_CLASSES = [
None, # Generic on/off
'cold', # On means cold (or too cold)
'connectivity', # On means connection present, Off = no connection
'gas', # CO, CO2, etc.
'heat', # On means hot (or too hot)
'light', # Lightness threshold
'moisture', # Specifically a wetness sensor
'motion', # Motion sensor
'moving', # On means moving, Off means stopped
'opening', # Door, window, etc.
'power', # Power, over-current, etc
'safety', # Generic on=unsafe, off=safe
'smoke', # Smoke detector
'sound', # On means sound detected, Off means no sound
'vibration', # On means vibration detected, Off means no vibration
]
def setup(hass, config):
""" Track states and offer events for binary sensors. """
"""Track states and offer events for binary sensors."""
component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
@@ -31,19 +46,29 @@ def setup(hass, config):
# pylint: disable=no-self-use
class BinarySensorDevice(Entity):
""" Represents a binary sensor. """
"""Represent a binary sensor."""
@property
def is_on(self):
""" True if the binary sensor is on. """
"""Return True if the binary sensor is on."""
return None
@property
def state(self):
""" Returns the state of the binary sensor. """
"""Return the state of the binary sensor."""
return STATE_ON if self.is_on else STATE_OFF
@property
def friendly_state(self):
""" Returns the friendly state of the binary sensor. """
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return None
@property
def state_attributes(self):
"""Return device specific state attributes."""
attr = {}
if self.sensor_class is not None:
attr['sensor_class'] = self.sensor_class
return attr

View File

@@ -0,0 +1,41 @@
"""
Support for tracking the online status of a UPS.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.apcupsd/
"""
from homeassistant.components import apcupsd
from homeassistant.components.binary_sensor import BinarySensorDevice
DEPENDENCIES = [apcupsd.DOMAIN]
DEFAULT_NAME = "UPS Online Status"
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Instantiate an OnlineStatus binary sensor entity."""
add_entities((OnlineStatus(config, apcupsd.DATA),))
class OnlineStatus(BinarySensorDevice):
"""Represent UPS online status."""
def __init__(self, config, data):
"""Initialize the APCUPSd device."""
self._config = config
self._data = data
self._state = None
self.update()
@property
def name(self):
"""Return the name of the UPS online status sensor."""
return self._config.get("name", DEFAULT_NAME)
@property
def is_on(self):
"""Return true if the UPS is online, else false."""
return self._state == apcupsd.VALUE_ONLINE
def update(self):
"""Get the status report from APCUPSd and set this entity's state."""
self._state = self._data.status[apcupsd.KEY_STATUS]

View File

@@ -1,18 +1,17 @@
"""
homeassistant.components.binary_sensor.arest
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The arest sensor will consume an exposed aREST API of a device.
Support for exposed aREST RESTful API of a device.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.arest/
"""
from datetime import timedelta
import logging
from datetime import timedelta
import requests
from homeassistant.components.binary_sensor import (BinarySensorDevice,
SENSOR_CLASSES)
from homeassistant.util import Throttle
from homeassistant.components.binary_sensor import BinarySensorDevice
_LOGGER = logging.getLogger(__name__)
@@ -24,11 +23,15 @@ CONF_PIN = 'pin'
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the aREST binary sensor. """
"""Setup the aREST binary sensor."""
resource = config.get(CONF_RESOURCE)
pin = config.get(CONF_PIN)
sensor_class = config.get('sensor_class')
if sensor_class not in SENSOR_CLASSES:
_LOGGER.warning('Unknown sensor class: %s', sensor_class)
sensor_class = None
if None in (resource, pin):
_LOGGER.error('Not all required config keys present: %s',
', '.join((CONF_RESOURCE, CONF_PIN)))
@@ -48,20 +51,24 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
arest = ArestData(resource, pin)
add_devices([ArestBinarySensor(arest,
resource,
config.get('name', response['name']),
pin)])
add_devices([ArestBinarySensor(
arest,
resource,
config.get('name', response['name']),
sensor_class,
pin)])
# pylint: disable=too-many-instance-attributes, too-many-arguments
class ArestBinarySensor(BinarySensorDevice):
""" Implements an aREST binary sensor for a pin. """
"""Implement an aREST binary sensor for a pin."""
def __init__(self, arest, resource, name, pin):
def __init__(self, arest, resource, name, sensor_class, pin):
"""Initialize the aREST device."""
self.arest = arest
self._resource = resource
self._name = name
self._sensor_class = sensor_class
self._pin = pin
self.update()
@@ -73,31 +80,37 @@ class ArestBinarySensor(BinarySensorDevice):
@property
def name(self):
""" The name of the binary sensor. """
"""Return the name of the binary sensor."""
return self._name
@property
def is_on(self):
""" True if the binary sensor is on. """
"""Return true if the binary sensor is on."""
return bool(self.arest.data.get('state'))
@property
def sensor_class(self):
"""Return the class of this sensor."""
return self._sensor_class
def update(self):
""" Gets the latest data from aREST API. """
"""Get the latest data from aREST API."""
self.arest.update()
# pylint: disable=too-few-public-methods
class ArestData(object):
""" Class for handling the data retrieval for pins. """
"""Class for handling the data retrieval for pins."""
def __init__(self, resource, pin):
"""Initialize the aREST data object."""
self._resource = resource
self._pin = pin
self.data = {}
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from aREST device. """
"""Get the latest data from aREST device."""
try:
response = requests.get('{}/digital/{}'.format(
self._resource, self._pin), timeout=10)

View File

@@ -0,0 +1,74 @@
"""
Support the binary sensors of a BloomSky weather station.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.bloomsky/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.loader import get_component
DEPENDENCIES = ["bloomsky"]
# These are the available sensors mapped to binary_sensor class
SENSOR_TYPES = {
"Rain": "moisture",
"Night": None,
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the available BloomSky weather binary sensors."""
logger = logging.getLogger(__name__)
bloomsky = get_component('bloomsky')
sensors = config.get('monitored_conditions', SENSOR_TYPES)
for device in bloomsky.BLOOMSKY.devices.values():
for variable in sensors:
if variable in SENSOR_TYPES:
add_devices([BloomSkySensor(bloomsky.BLOOMSKY,
device,
variable)])
else:
logger.error("Cannot find definition for device: %s", variable)
class BloomSkySensor(BinarySensorDevice):
"""Represent a single binary sensor in a BloomSky device."""
def __init__(self, bs, device, sensor_name):
"""Initialize a BloomSky binary sensor."""
self._bloomsky = bs
self._device_id = device["DeviceID"]
self._sensor_name = sensor_name
self._name = "{} {}".format(device["DeviceName"], sensor_name)
self._unique_id = "bloomsky_binary_sensor {}".format(self._name)
self.update()
@property
def name(self):
"""The name of the BloomSky device and this sensor."""
return self._name
@property
def unique_id(self):
"""Return the unique ID for this sensor."""
return self._unique_id
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return SENSOR_TYPES.get(self._sensor_name)
@property
def is_on(self):
"""Return true if binary sensor is on."""
return self._state
def update(self):
"""Request an update from the BloomSky API."""
self._bloomsky.refresh_devices()
self._state = \
self._bloomsky.devices[self._device_id]["Data"][self._sensor_name]

View File

@@ -0,0 +1,95 @@
"""
Support for custom shell commands to retrieve values.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.command_line/
"""
import logging
from datetime import timedelta
from homeassistant.components.binary_sensor import (BinarySensorDevice,
SENSOR_CLASSES)
from homeassistant.components.sensor.command_line import CommandSensorData
from homeassistant.const import CONF_VALUE_TEMPLATE
from homeassistant.helpers import template
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "Binary Command Sensor"
DEFAULT_SENSOR_CLASS = None
DEFAULT_PAYLOAD_ON = 'ON'
DEFAULT_PAYLOAD_OFF = 'OFF'
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Command Sensor."""
if config.get('command') is None:
_LOGGER.error('Missing required variable: "command"')
return False
sensor_class = config.get('sensor_class')
if sensor_class not in SENSOR_CLASSES:
_LOGGER.warning('Unknown sensor class: %s', sensor_class)
sensor_class = DEFAULT_SENSOR_CLASS
data = CommandSensorData(config.get('command'))
add_devices([CommandBinarySensor(
hass,
data,
config.get('name', DEFAULT_NAME),
sensor_class,
config.get('payload_on', DEFAULT_PAYLOAD_ON),
config.get('payload_off', DEFAULT_PAYLOAD_OFF),
config.get(CONF_VALUE_TEMPLATE)
)])
# pylint: disable=too-many-arguments, too-many-instance-attributes
class CommandBinarySensor(BinarySensorDevice):
"""Represent a command line binary sensor."""
def __init__(self, hass, data, name, sensor_class, payload_on,
payload_off, value_template):
"""Initialize the Command line binary sensor."""
self._hass = hass
self.data = data
self._name = name
self._sensor_class = sensor_class
self._state = False
self._payload_on = payload_on
self._payload_off = payload_off
self._value_template = value_template
self.update()
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@ property
def sensor_class(self):
"""Return the class of the binary sensor."""
return self._sensor_class
def update(self):
"""Get the latest data and updates the state."""
self.data.update()
value = self.data.value
if self._value_template is not None:
value = template.render_with_possible_json_value(
self._hass, self._value_template, value, False)
if value == self._payload_on:
self._state = True
elif value == self._payload_off:
self._state = False

View File

@@ -1,37 +1,45 @@
"""
homeassistant.components.binary_sensor.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo platform that has two fake binary sensors.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
from homeassistant.components.binary_sensor import BinarySensorDevice
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Demo binary sensors. """
"""Setup the Demo binary sensor platform."""
add_devices([
DemoBinarySensor('Basement Floor Wet', False),
DemoBinarySensor('Movement Backyard', True),
DemoBinarySensor('Basement Floor Wet', False, 'moisture'),
DemoBinarySensor('Movement Backyard', True, 'motion'),
])
class DemoBinarySensor(BinarySensorDevice):
""" A Demo binary sensor. """
"""A Demo binary sensor."""
def __init__(self, name, state):
def __init__(self, name, state, sensor_class):
"""Initialize the demo sensor."""
self._name = name
self._state = state
self._sensor_type = sensor_class
@property
def sensor_class(self):
"""Return the class of this sensor."""
return self._sensor_type
@property
def should_poll(self):
""" No polling needed for a demo binary sensor. """
"""No polling needed for a demo binary sensor."""
return False
@property
def name(self):
""" Returns the name of the binary sensor. """
"""Return the name of the binary sensor."""
return self._name
@property
def is_on(self):
""" True if the binary sensor is on. """
"""Return true if the binary sensor is on."""
return self._state

View File

@@ -0,0 +1,63 @@
"""
Support for EnOcean binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.enocean/
"""
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components import enocean
from homeassistant.const import CONF_NAME
DEPENDENCIES = ["enocean"]
CONF_ID = "id"
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Binary Sensor platform fo EnOcean."""
dev_id = config.get(CONF_ID, None)
devname = config.get(CONF_NAME, "EnOcean binary sensor")
add_devices([EnOceanBinarySensor(dev_id, devname)])
class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
"""Representation of EnOcean binary sensors such as wall switches."""
def __init__(self, dev_id, devname):
"""Initialize the EnOcean binary sensor."""
enocean.EnOceanDevice.__init__(self)
self.stype = "listener"
self.dev_id = dev_id
self.which = -1
self.onoff = -1
self.devname = devname
@property
def name(self):
"""The default name for the binary sensor."""
return self.devname
def value_changed(self, value, value2):
"""Fire an event with the data that have changed.
This method is called when there is an incoming packet associated
with this platform.
"""
self.update_ha_state()
if value2 == 0x70:
self.which = 0
self.onoff = 0
elif value2 == 0x50:
self.which = 0
self.onoff = 1
elif value2 == 0x30:
self.which = 1
self.onoff = 0
elif value2 == 0x10:
self.which = 1
self.onoff = 1
self.hass.bus.fire('button_pressed', {"id": self.dev_id,
'pushed': value,
'which': self.which,
'onoff': self.onoff})

View File

@@ -0,0 +1,71 @@
"""
Support for Envisalink zone states- represented as binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.envisalink/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.envisalink import (EVL_CONTROLLER,
ZONE_SCHEMA,
CONF_ZONENAME,
CONF_ZONETYPE,
EnvisalinkDevice,
SIGNAL_ZONE_UPDATE)
from homeassistant.const import ATTR_LAST_TRIP_TIME
DEPENDENCIES = ['envisalink']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup Envisalink binary sensor devices."""
_configured_zones = discovery_info['zones']
for zone_num in _configured_zones:
_device_config_data = ZONE_SCHEMA(_configured_zones[zone_num])
_device = EnvisalinkBinarySensor(
zone_num,
_device_config_data[CONF_ZONENAME],
_device_config_data[CONF_ZONETYPE],
EVL_CONTROLLER.alarm_state['zone'][zone_num],
EVL_CONTROLLER)
add_devices_callback([_device])
class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
"""Representation of an Envisalink binary sensor."""
# pylint: disable=too-many-arguments
def __init__(self, zone_number, zone_name, zone_type, info, controller):
"""Initialize the binary_sensor."""
from pydispatch import dispatcher
self._zone_type = zone_type
self._zone_number = zone_number
_LOGGER.debug('Setting up zone: ' + zone_name)
EnvisalinkDevice.__init__(self, zone_name, info, controller)
dispatcher.connect(self._update_callback,
signal=SIGNAL_ZONE_UPDATE,
sender=dispatcher.Any)
@property
def device_state_attributes(self):
"""Return the state attributes."""
attr = {}
attr[ATTR_LAST_TRIP_TIME] = self._info['last_fault']
return attr
@property
def is_on(self):
"""Return true if sensor is on."""
return self._info['status']['open']
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return self._zone_type
def _update_callback(self, zone):
"""Update the zone's state, if needed."""
if zone is None or int(zone) == self._zone_number:
self.update_ha_state()

View File

@@ -0,0 +1,100 @@
"""
Support for Homematic binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.homematic/
"""
import logging
from homeassistant.const import STATE_UNKNOWN
from homeassistant.components.binary_sensor import BinarySensorDevice
import homeassistant.components.homematic as homematic
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['homematic']
SENSOR_TYPES_CLASS = {
"Remote": None,
"ShutterContact": "opening",
"Smoke": "smoke",
"SmokeV2": "smoke",
"Motion": "motion",
"MotionV2": "motion",
"RemoteMotion": None
}
def setup_platform(hass, config, add_callback_devices, discovery_info=None):
"""Setup the Homematic binary sensor platform."""
if discovery_info is None:
return
return homematic.setup_hmdevice_discovery_helper(HMBinarySensor,
discovery_info,
add_callback_devices)
class HMBinarySensor(homematic.HMDevice, BinarySensorDevice):
"""Representation of a binary Homematic device."""
@property
def is_on(self):
"""Return true if switch is on."""
if not self.available:
return False
return bool(self._hm_get_state())
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
if not self.available:
return None
# If state is MOTION (RemoteMotion works only)
if self._state == "MOTION":
return "motion"
return SENSOR_TYPES_CLASS.get(self._hmdevice.__class__.__name__, None)
def _check_hm_to_ha_object(self):
"""Check if possible to use the HM Object as this HA type."""
from pyhomematic.devicetypes.sensors import HMBinarySensor\
as pyHMBinarySensor
# Check compatibility from HMDevice
if not super()._check_hm_to_ha_object():
return False
# check if the Homematic device correct for this HA device
if not isinstance(self._hmdevice, pyHMBinarySensor):
_LOGGER.critical("This %s can't be use as binary", self._name)
return False
# if exists user value?
if self._state and self._state not in self._hmdevice.BINARYNODE:
_LOGGER.critical("This %s have no binary with %s", self._name,
self._state)
return False
# only check and give a warning to the user
if self._state is None and len(self._hmdevice.BINARYNODE) > 1:
_LOGGER.critical("%s have multiple binary params. It use all "
"binary nodes as one. Possible param values: %s",
self._name, str(self._hmdevice.BINARYNODE))
return False
return True
def _init_data_struct(self):
"""Generate a data struct (self._data) from the Homematic metadata."""
super()._init_data_struct()
# object have 1 binary
if self._state is None and len(self._hmdevice.BINARYNODE) == 1:
for value in self._hmdevice.BINARYNODE:
self._state = value
# add state to data struct
if self._state:
_LOGGER.debug("%s init datastruct with main node '%s'", self._name,
self._state)
self._data.update({self._state: STATE_UNKNOWN})

View File

@@ -0,0 +1,24 @@
"""
Contains functionality to use a KNX group address as a binary.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.knx/
"""
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.knx import (
KNXConfig, KNXGroupAddress)
DEPENDENCIES = ["knx"]
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup the KNX binary sensor platform."""
add_entities([
KNXSwitch(hass, KNXConfig(config))
])
class KNXSwitch(KNXGroupAddress, BinarySensorDevice):
"""Representation of a KNX binary sensor device."""
pass

View File

@@ -1,61 +1,75 @@
"""
homeassistant.components.binary_sensor.mqtt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to configure a MQTT binary sensor.
Support for MQTT binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mqtt/
"""
import logging
from homeassistant.const import CONF_VALUE_TEMPLATE
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.util import template
import voluptuous as vol
import homeassistant.components.mqtt as mqtt
from homeassistant.components.binary_sensor import (BinarySensorDevice,
SENSOR_CLASSES)
from homeassistant.const import CONF_NAME, CONF_VALUE_TEMPLATE
from homeassistant.components.mqtt import CONF_STATE_TOPIC, CONF_QOS
from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['mqtt']
CONF_SENSOR_CLASS = 'sensor_class'
CONF_PAYLOAD_ON = 'payload_on'
CONF_PAYLOAD_OFF = 'payload_off'
DEFAULT_NAME = 'MQTT Binary sensor'
DEFAULT_QOS = 0
DEFAULT_PAYLOAD_ON = 'ON'
DEFAULT_PAYLOAD_OFF = 'OFF'
DEPENDENCIES = ['mqtt']
PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_SENSOR_CLASS, default=None):
vol.Any(vol.In(SENSOR_CLASSES), vol.SetTo(None)),
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
})
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Add MQTT binary sensor. """
if config.get('state_topic') is None:
_LOGGER.error('Missing required variable: state_topic')
return False
"""Add MQTT binary sensor."""
add_devices([MqttBinarySensor(
hass,
config.get('name', DEFAULT_NAME),
config.get('state_topic', None),
config.get('qos', DEFAULT_QOS),
config.get('payload_on', DEFAULT_PAYLOAD_ON),
config.get('payload_off', DEFAULT_PAYLOAD_OFF),
config.get(CONF_VALUE_TEMPLATE))])
config[CONF_NAME],
config[CONF_STATE_TOPIC],
config[CONF_SENSOR_CLASS],
config[CONF_QOS],
config[CONF_PAYLOAD_ON],
config[CONF_PAYLOAD_OFF],
config.get(CONF_VALUE_TEMPLATE)
)])
# pylint: disable=too-many-arguments, too-many-instance-attributes
class MqttBinarySensor(BinarySensorDevice):
""" Represents a binary sensor that is updated by MQTT. """
def __init__(self, hass, name, state_topic, qos, payload_on, payload_off,
value_template):
"""Representation a binary sensor that is updated by MQTT."""
def __init__(self, hass, name, state_topic, sensor_class, qos, payload_on,
payload_off, value_template):
"""Initialize the MQTT binary sensor."""
self._hass = hass
self._name = name
self._state = False
self._state_topic = state_topic
self._sensor_class = sensor_class
self._payload_on = payload_on
self._payload_off = payload_off
self._qos = qos
def message_received(topic, payload, qos):
""" A new MQTT message has been received. """
"""A new MQTT message has been received."""
if value_template is not None:
payload = template.render_with_possible_json_value(
hass, value_template, payload)
@@ -70,15 +84,20 @@ class MqttBinarySensor(BinarySensorDevice):
@property
def should_poll(self):
""" No polling needed. """
"""No polling needed."""
return False
@property
def name(self):
""" The name of the binary sensor. """
"""Return the name of the binary sensor."""
return self._name
@property
def is_on(self):
""" True if the binary sensor is on. """
"""Return true if the binary sensor is on."""
return self._state
@property
def sensor_class(self):
"""Return the class of this sensor."""
return self._sensor_class

View File

@@ -0,0 +1,78 @@
"""
Support for MySensors binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.mysensors/
"""
import logging
from homeassistant.components import mysensors
from homeassistant.components.binary_sensor import (SENSOR_CLASSES,
BinarySensorDevice)
from homeassistant.const import STATE_ON
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = []
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the mysensors platform for sensors."""
# Only act if loaded via mysensors by discovery event.
# Otherwise gateway is not setup.
if discovery_info is None:
return
for gateway in mysensors.GATEWAYS.values():
# Define the S_TYPES and V_TYPES that the platform should handle as
# states. Map them in a dict of lists.
pres = gateway.const.Presentation
set_req = gateway.const.SetReq
map_sv_types = {
pres.S_DOOR: [set_req.V_TRIPPED],
pres.S_MOTION: [set_req.V_TRIPPED],
pres.S_SMOKE: [set_req.V_TRIPPED],
}
if float(gateway.version) >= 1.5:
map_sv_types.update({
pres.S_SPRINKLER: [set_req.V_TRIPPED],
pres.S_WATER_LEAK: [set_req.V_TRIPPED],
pres.S_SOUND: [set_req.V_TRIPPED],
pres.S_VIBRATION: [set_req.V_TRIPPED],
pres.S_MOISTURE: [set_req.V_TRIPPED],
})
devices = {}
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
map_sv_types, devices, add_devices, MySensorsBinarySensor))
class MySensorsBinarySensor(
mysensors.MySensorsDeviceEntity, BinarySensorDevice):
"""Represent the value of a MySensors Binary Sensor child node."""
@property
def is_on(self):
"""Return True if the binary sensor is on."""
if self.value_type in self._values:
return self._values[self.value_type] == STATE_ON
return False
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
pres = self.gateway.const.Presentation
class_map = {
pres.S_DOOR: 'opening',
pres.S_MOTION: 'motion',
pres.S_SMOKE: 'smoke',
}
if float(self.gateway.version) >= 1.5:
class_map.update({
pres.S_SPRINKLER: 'sprinkler',
pres.S_WATER_LEAK: 'leak',
pres.S_SOUND: 'sound',
pres.S_VIBRATION: 'vibration',
pres.S_MOISTURE: 'moisture',
})
if class_map.get(self.child_type) in SENSOR_CLASSES:
return class_map.get(self.child_type)

View File

@@ -0,0 +1,49 @@
"""
Support for Nest Thermostat Binary Sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.nest/
"""
import voluptuous as vol
import homeassistant.components.nest as nest
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.sensor.nest import NestSensor
from homeassistant.const import (
CONF_PLATFORM, CONF_SCAN_INTERVAL, CONF_MONITORED_CONDITIONS
)
DEPENDENCIES = ['nest']
BINARY_TYPES = ['fan',
'hvac_ac_state',
'hvac_aux_heater_state',
'hvac_heater_state',
'hvac_heat_x2_state',
'hvac_heat_x3_state',
'hvac_alt_heat_state',
'hvac_alt_heat_x2_state',
'hvac_emer_heat_state',
'online']
PLATFORM_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): nest.DOMAIN,
vol.Optional(CONF_SCAN_INTERVAL):
vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Required(CONF_MONITORED_CONDITIONS): [vol.In(BINARY_TYPES)],
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Nest binary sensors."""
for structure, device in nest.devices():
add_devices([NestBinarySensor(structure, device, variable)
for variable in config[CONF_MONITORED_CONDITIONS]])
class NestBinarySensor(NestSensor, BinarySensorDevice):
"""Represents a Nest binary sensor."""
@property
def is_on(self):
"""True if the binary sensor is on."""
return bool(getattr(self.device, self.variable))

View File

@@ -0,0 +1,134 @@
"""
Support for exposing nx584 elements as sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.nx584/
"""
import logging
import threading
import time
import requests
from homeassistant.components.binary_sensor import (
SENSOR_CLASSES, BinarySensorDevice)
REQUIREMENTS = ['pynx584==0.2']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup nx584 binary sensor platform."""
from nx584 import client as nx584_client
host = config.get('host', 'localhost:5007')
exclude = config.get('exclude_zones', [])
zone_types = config.get('zone_types', {})
if not all(isinstance(zone, int) for zone in exclude):
_LOGGER.error('Invalid excluded zone specified (use zone number)')
return False
if not all(isinstance(zone, int) and ztype in SENSOR_CLASSES
for zone, ztype in zone_types.items()):
_LOGGER.error('Invalid zone_types entry')
return False
try:
client = nx584_client.Client('http://%s' % host)
zones = client.list_zones()
except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NX584: %s', str(ex))
return False
version = [int(v) for v in client.get_version().split('.')]
if version < [1, 1]:
_LOGGER.error('NX584 is too old to use for sensors (>=0.2 required)')
return False
zone_sensors = {
zone['number']: NX584ZoneSensor(
zone,
zone_types.get(zone['number'], 'opening'))
for zone in zones
if zone['number'] not in exclude}
if zone_sensors:
add_devices(zone_sensors.values())
watcher = NX584Watcher(client, zone_sensors)
watcher.start()
else:
_LOGGER.warning('No zones found on NX584')
return True
class NX584ZoneSensor(BinarySensorDevice):
"""Represents a NX584 zone as a sensor."""
def __init__(self, zone, zone_type):
"""Initialize the nx594 binary sensor."""
self._zone = zone
self._zone_type = zone_type
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return self._zone_type
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def name(self):
"""Return the name of the binary sensor."""
return self._zone['name']
@property
def is_on(self):
"""Return true if the binary sensor is on."""
# True means "faulted" or "open" or "abnormal state"
return self._zone['state']
class NX584Watcher(threading.Thread):
"""Event listener thread to process NX584 events."""
def __init__(self, client, zone_sensors):
"""Initialize nx584 watcher thread."""
super(NX584Watcher, self).__init__()
self.daemon = True
self._client = client
self._zone_sensors = zone_sensors
def _process_zone_event(self, event):
zone = event['zone']
zone_sensor = self._zone_sensors.get(zone)
# pylint: disable=protected-access
if not zone_sensor:
return
zone_sensor._zone['state'] = event['zone_state']
zone_sensor.update_ha_state()
def _process_events(self, events):
for event in events:
if event.get('type') == 'zone_status':
self._process_zone_event(event)
def _run(self):
"""Throw away any existing events so we don't replay history."""
self._client.get_events()
while True:
events = self._client.get_events()
if events:
self._process_events(events)
def run(self):
"""Run the watcher."""
while True:
try:
self._run()
except requests.exceptions.ConnectionError:
_LOGGER.error('Failed to reach NX584 server')
time.sleep(10)

View File

@@ -0,0 +1,109 @@
"""
Support for monitoring OctoPrint binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.octoprint/
"""
import logging
import requests
from homeassistant.const import CONF_NAME, STATE_ON, STATE_OFF
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.loader import get_component
DEPENDENCIES = ["octoprint"]
SENSOR_TYPES = {
# API Endpoint, Group, Key, unit
"Printing": ["printer", "state", "printing", None],
"Printing Error": ["printer", "state", "error", None]
}
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the available OctoPrint binary sensors."""
octoprint = get_component('octoprint')
name = config.get(CONF_NAME, "OctoPrint")
monitored_conditions = config.get("monitored_conditions",
SENSOR_TYPES.keys())
devices = []
for octo_type in monitored_conditions:
if octo_type in SENSOR_TYPES:
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)
else:
_LOGGER.error("Unknown OctoPrint sensor type: %s", octo_type)
add_devices(devices)
# pylint: disable=too-many-instance-attributes
class OctoPrintBinarySensor(BinarySensorDevice):
"""Representation an OctoPrint binary sensor."""
# pylint: disable=too-many-arguments
def __init__(self, api, condition, sensor_type, sensor_name,
unit, endpoint, group, tool=None):
"""Initialize a new OctoPrint sensor."""
self.sensor_name = sensor_name
if tool is None:
self._name = sensor_name + ' ' + condition
else:
self._name = sensor_name + ' ' + condition
self.sensor_type = sensor_type
self.api = api
self._state = False
self._unit_of_measurement = unit
self.api_endpoint = endpoint
self.api_group = group
self.api_tool = tool
# Set initial state
self.update()
_LOGGER.debug("Created OctoPrint binary sensor %r", self)
@property
def name(self):
"""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
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return None
def update(self):
"""Update state of sensor."""
try:
self._state = self.api.update(self.sensor_type,
self.api_endpoint,
self.api_group,
self.api_tool)
except requests.exceptions.ConnectionError:
# Error calling the api, already logged in api.update()
return
if self._state is None:
_LOGGER.warning("Unable to locate value for %s", self.sensor_type)

View File

@@ -1,145 +1,92 @@
"""
homeassistant.components.binary_sensor.rest
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The rest binary sensor will consume responses sent by an exposed REST API.
Support for RESTful binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.rest/
"""
from datetime import timedelta
import logging
import requests
from homeassistant.components.binary_sensor import (BinarySensorDevice,
SENSOR_CLASSES)
from homeassistant.components.sensor.rest import RestData
from homeassistant.const import CONF_VALUE_TEMPLATE
from homeassistant.util import template, Throttle
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.helpers import template
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'REST Binary Sensor'
DEFAULT_METHOD = 'GET'
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
# pylint: disable=unused-variable
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the REST binary sensor. """
use_get = False
use_post = False
"""Setup the REST binary sensor."""
resource = config.get('resource', None)
method = config.get('method', DEFAULT_METHOD)
payload = config.get('payload', None)
verify_ssl = config.get('verify_ssl', True)
if method == 'GET':
use_get = True
elif method == 'POST':
use_post = True
sensor_class = config.get('sensor_class')
if sensor_class not in SENSOR_CLASSES:
_LOGGER.warning('Unknown sensor class: %s', sensor_class)
sensor_class = None
try:
if use_get:
response = requests.get(resource, timeout=10, verify=verify_ssl)
elif use_post:
response = requests.post(resource, data=payload, timeout=10,
verify=verify_ssl)
if not response.ok:
_LOGGER.error('Response status is "%s"', response.status_code)
return False
except requests.exceptions.MissingSchema:
_LOGGER.error('Missing resource or schema in configuration. '
'Add http:// to your URL.')
return False
except requests.exceptions.ConnectionError:
_LOGGER.error('No route to resource/endpoint: %s',
resource)
rest = RestData(method, resource, payload, verify_ssl)
rest.update()
if rest.data is None:
_LOGGER.error('Unable to fetch REST data')
return False
if use_get:
rest = RestDataGet(resource, verify_ssl)
elif use_post:
rest = RestDataPost(resource, payload, verify_ssl)
add_devices([RestBinarySensor(hass,
rest,
config.get('name', DEFAULT_NAME),
config.get(CONF_VALUE_TEMPLATE))])
add_devices([RestBinarySensor(
hass,
rest,
config.get('name', DEFAULT_NAME),
sensor_class,
config.get(CONF_VALUE_TEMPLATE))])
# pylint: disable=too-many-arguments
class RestBinarySensor(BinarySensorDevice):
""" Implements a REST binary sensor. """
"""Representation of a REST binary sensor."""
def __init__(self, hass, rest, name, value_template):
def __init__(self, hass, rest, name, sensor_class, value_template):
"""Initialize a REST binary sensor."""
self._hass = hass
self.rest = rest
self._name = name
self._sensor_class = sensor_class
self._state = False
self._previous_data = None
self._value_template = value_template
self.update()
@property
def name(self):
""" The name of the binary sensor. """
"""Return the name of the binary sensor."""
return self._name
@property
def sensor_class(self):
"""Return the class of this sensor."""
return self._sensor_class
@property
def is_on(self):
""" True if the binary sensor is on. """
if self.rest.data is False:
"""Return true if the binary sensor is on."""
if self.rest.data is None:
return False
else:
if self._value_template is not None:
self.rest.data = template.render_with_possible_json_value(
self._hass, self._value_template, self.rest.data, False)
return bool(int(self.rest.data))
if self._value_template is not None:
response = template.render_with_possible_json_value(
self._hass, self._value_template, self.rest.data, False)
try:
return bool(int(response))
except ValueError:
return {"true": True, "on": True, "open": True,
"yes": True}.get(response.lower(), False)
def update(self):
""" Gets the latest data from REST API and updates the state. """
"""Get the latest data from REST API and updates the state."""
self.rest.update()
# pylint: disable=too-few-public-methods
class RestDataGet(object):
""" Class for handling the data retrieval with GET method. """
def __init__(self, resource, verify_ssl):
self._resource = resource
self._verify_ssl = verify_ssl
self.data = False
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from REST service with GET method. """
try:
response = requests.get(self._resource, timeout=10,
verify=self._verify_ssl)
self.data = response.text
except requests.exceptions.ConnectionError:
_LOGGER.error("No route to resource/endpoint: %s", self._resource)
self.data = False
# pylint: disable=too-few-public-methods
class RestDataPost(object):
""" Class for handling the data retrieval with POST method. """
def __init__(self, resource, payload, verify_ssl):
self._resource = resource
self._payload = payload
self._verify_ssl = verify_ssl
self.data = False
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from REST service with POST method. """
try:
response = requests.post(self._resource, data=self._payload,
timeout=10, verify=self._verify_ssl)
self.data = response.text
except requests.exceptions.ConnectionError:
_LOGGER.error("No route to resource/endpoint: %s", self._resource)
self.data = False

View File

@@ -0,0 +1,72 @@
"""
Support for binary sensor using RPi GPIO.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.rpi_gpio/
"""
import logging
import homeassistant.components.rpi_gpio as rpi_gpio
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import DEVICE_DEFAULT_NAME
DEFAULT_PULL_MODE = "UP"
DEFAULT_BOUNCETIME = 50
DEFAULT_INVERT_LOGIC = False
DEPENDENCIES = ['rpi_gpio']
_LOGGER = logging.getLogger(__name__)
# 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)
binary_sensors = []
ports = config.get('ports')
for port_num, port_name in ports.items():
binary_sensors.append(RPiGPIOBinarySensor(
port_name, port_num, pull_mode, bouncetime, invert_logic))
add_devices(binary_sensors)
# pylint: disable=too-many-arguments, too-many-instance-attributes
class RPiGPIOBinarySensor(BinarySensorDevice):
"""Represent a binary sensor that uses Raspberry Pi GPIO."""
def __init__(self, name, port, pull_mode, bouncetime, invert_logic):
"""Initialize the RPi binary sensor."""
# pylint: disable=no-member
self._name = name or DEVICE_DEFAULT_NAME
self._port = port
self._pull_mode = pull_mode
self._bouncetime = bouncetime
self._invert_logic = invert_logic
rpi_gpio.setup_input(self._port, self._pull_mode)
self._state = rpi_gpio.read_input(self._port)
def read_gpio(port):
"""Read state from GPIO."""
self._state = rpi_gpio.read_input(self._port)
self.update_ha_state()
rpi_gpio.edge_detect(self._port, read_gpio, self._bouncetime)
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return the state of the entity."""
return self._state != self._invert_logic

View File

@@ -0,0 +1,32 @@
"""
Provides a binary sensor which gets its values from a TCP socket.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.tcp/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.sensor.tcp import Sensor, CONF_VALUE_ON
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Create the binary sensor."""
if not BinarySensor.validate_config(config):
return False
add_entities((BinarySensor(hass, config),))
class BinarySensor(BinarySensorDevice, Sensor):
"""A binary sensor which is on when its state == CONF_VALUE_ON."""
required = (CONF_VALUE_ON,)
@property
def is_on(self):
"""True if the binary sensor is on."""
return self._state == self._config[CONF_VALUE_ON]

View File

@@ -0,0 +1,131 @@
"""
Support for exposing a templated binary sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.template/
"""
import logging
from homeassistant.components.binary_sensor import (BinarySensorDevice,
ENTITY_ID_FORMAT,
SENSOR_CLASSES)
from homeassistant.const import (ATTR_FRIENDLY_NAME, CONF_VALUE_TEMPLATE,
ATTR_ENTITY_ID, MATCH_ALL)
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers import template
from homeassistant.helpers.event import track_state_change
from homeassistant.util import slugify
CONF_SENSORS = 'sensors'
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup template binary sensors."""
sensors = []
if config.get(CONF_SENSORS) is None:
_LOGGER.error('Missing configuration data for binary_sensor platform')
return False
for device, device_config in config[CONF_SENSORS].items():
if device != slugify(device):
_LOGGER.error('Found invalid key for binary_sensor.template: %s. '
'Use %s instead', device, slugify(device))
continue
if not isinstance(device_config, dict):
_LOGGER.error('Missing configuration data for binary_sensor %s',
device)
continue
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
sensor_class = device_config.get('sensor_class')
value_template = device_config.get(CONF_VALUE_TEMPLATE)
if sensor_class not in SENSOR_CLASSES:
_LOGGER.error('Sensor class is not valid')
continue
if value_template is None:
_LOGGER.error(
'Missing %s for sensor %s', CONF_VALUE_TEMPLATE, device)
continue
entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL)
sensors.append(
BinarySensorTemplate(
hass,
device,
friendly_name,
sensor_class,
value_template,
entity_ids)
)
if not sensors:
_LOGGER.error('No sensors added')
return False
add_devices(sensors)
return True
class BinarySensorTemplate(BinarySensorDevice):
"""A virtual binary sensor that triggers from another sensor."""
# pylint: disable=too-many-arguments
def __init__(self, hass, device, friendly_name, sensor_class,
value_template, entity_ids):
"""Initialize the Template binary sensor."""
self.hass = hass
self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device,
hass=hass)
self._name = friendly_name
self._sensor_class = sensor_class
self._template = value_template
self._state = None
self.update()
def template_bsensor_state_listener(entity, old_state, new_state):
"""Called when the target device changes state."""
self.update_ha_state(True)
track_state_change(hass, entity_ids,
template_bsensor_state_listener)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return true if sensor is on."""
return self._state
@property
def sensor_class(self):
"""Return the sensor class of the sensor."""
return self._sensor_class
@property
def should_poll(self):
"""No polling needed."""
return False
def update(self):
"""Get the latest data and update the state."""
try:
self._state = template.render(self.hass,
self._template).lower() == 'true'
except TemplateError as ex:
if ex.args and ex.args[0].startswith(
"UndefinedError: 'None' has no attribute"):
# Common during HA startup - so just a warning
_LOGGER.warning(ex)
return
_LOGGER.error(ex)
self._state = False

View File

@@ -0,0 +1,68 @@
"""
Support for Vera binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.vera/
"""
import logging
import homeassistant.util.dt as dt_util
from homeassistant.const import (
ATTR_ARMED, ATTR_BATTERY_LEVEL, ATTR_LAST_TRIP_TIME, ATTR_TRIPPED)
from homeassistant.components.binary_sensor import (
BinarySensorDevice)
from homeassistant.components.vera import (
VeraDevice, VERA_DEVICES, VERA_CONTROLLER)
DEPENDENCIES = ['vera']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Perform the setup for Vera controller devices."""
add_devices_callback(
VeraBinarySensor(device, VERA_CONTROLLER)
for device in VERA_DEVICES['binary_sensor'])
class VeraBinarySensor(VeraDevice, BinarySensorDevice):
"""Representation of a Vera Binary Sensor."""
def __init__(self, vera_device, controller):
"""Initialize the binary_sensor."""
self._state = False
VeraDevice.__init__(self, vera_device, controller)
@property
def device_state_attributes(self):
"""Return the state attributes."""
attr = {}
if self.vera_device.has_battery:
attr[ATTR_BATTERY_LEVEL] = self.vera_device.battery_level + '%'
if self.vera_device.is_armable:
armed = self.vera_device.is_armed
attr[ATTR_ARMED] = 'True' if armed else 'False'
if self.vera_device.is_trippable:
last_tripped = self.vera_device.last_trip
if last_tripped is not None:
utc_time = dt_util.utc_from_timestamp(int(last_tripped))
attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat()
else:
attr[ATTR_LAST_TRIP_TIME] = None
tripped = self.vera_device.is_tripped
attr[ATTR_TRIPPED] = 'True' if tripped else 'False'
attr['Vera Device Id'] = self.vera_device.vera_device_id
return attr
@property
def is_on(self):
"""Return true if sensor is on."""
return self._state
def update(self):
"""Get the latest data and update the state."""
self._state = self.vera_device.is_tripped

View File

@@ -0,0 +1,78 @@
"""
Support for WeMo sensors.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.wemo/
"""
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.loader import get_component
DEPENDENCIES = ['wemo']
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument, too-many-function-args
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Register discovered WeMo binary sensors."""
import pywemo.discovery as discovery
if discovery_info is not None:
location = discovery_info[2]
mac = discovery_info[3]
device = discovery.device_from_description(location, mac)
if device:
add_devices_callback([WemoBinarySensor(device)])
class WemoBinarySensor(BinarySensorDevice):
"""Represents a WeMo binary sensor."""
def __init__(self, device):
"""Initialize the WeMo sensor."""
self.wemo = device
self._state = None
wemo = get_component('wemo')
wemo.SUBSCRIPTION_REGISTRY.register(self.wemo)
wemo.SUBSCRIPTION_REGISTRY.on(self.wemo, None, self._update_callback)
def _update_callback(self, _device, _params):
"""Called by the wemo device callback to update state."""
_LOGGER.info(
'Subscription update for %s',
_device)
if not hasattr(self, 'hass'):
self.update()
return
self.update_ha_state(True)
@property
def should_poll(self):
"""No polling needed with subscriptions."""
return False
@property
def unique_id(self):
"""Return the id of this WeMo device."""
return "{}.{}".format(self.__class__, self.wemo.serialnumber)
@property
def name(self):
"""Return the name of the sevice if any."""
return self.wemo.name
@property
def is_on(self):
"""True if sensor is on."""
return self._state
def update(self):
"""Update WeMo state."""
try:
self._state = self.wemo.get_state(True)
except AttributeError:
_LOGGER.warning('Could not update status for %s', self.name)

View File

@@ -0,0 +1,83 @@
"""
Support for Wink sensors.
For more details about this platform, please refer to the documentation at
at https://home-assistant.io/components/sensor.wink/
"""
import logging
import json
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.sensor.wink import WinkDevice
from homeassistant.const import CONF_ACCESS_TOKEN
from homeassistant.helpers.entity import Entity
from homeassistant.loader import get_component
REQUIREMENTS = ['python-wink==0.7.10', 'pubnub==3.8.2']
# These are the available sensors mapped to binary_sensor class
SENSOR_TYPES = {
"opened": "opening",
"brightness": "light",
"vibration": "vibration",
"loudness": "sound"
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink binary sensor platform."""
import pywink
if discovery_info is None:
token = config.get(CONF_ACCESS_TOKEN)
if token is None:
logging.getLogger(__name__).error(
"Missing wink access_token. "
"Get one at https://winkbearertoken.appspot.com/")
return
pywink.set_bearer_token(token)
for sensor in pywink.get_sensors():
if sensor.capability() in SENSOR_TYPES:
add_devices([WinkBinarySensorDevice(sensor)])
for key in pywink.get_keys():
add_devices([WinkBinarySensorDevice(key)])
class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
"""Representation of a Wink binary sensor."""
def __init__(self, wink):
"""Initialize the Wink binary sensor."""
super().__init__(wink)
wink = get_component('wink')
self._unit_of_measurement = self.wink.UNIT
self.capability = self.wink.capability()
def _pubnub_update(self, message, channel):
if 'data' in message:
json_data = json.dumps(message.get('data'))
else:
json_data = message
self.wink.pubnub_update(json.loads(json_data))
self.update_ha_state()
@property
def is_on(self):
"""Return true if the binary sensor is on."""
if self.capability == "loudness":
return self.wink.loudness_boolean()
elif self.capability == "vibration":
return self.wink.vibration_boolean()
elif self.capability == "brightness":
return self.wink.brightness_boolean()
else:
return self.wink.state()
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return SENSOR_TYPES.get(self.capability)

View File

@@ -0,0 +1,24 @@
"""
Contains functionality to use a ZigBee device as a binary sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.zigbee/
"""
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.zigbee import (
ZigBeeDigitalIn, ZigBeeDigitalInConfig)
DEPENDENCIES = ["zigbee"]
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup the ZigBee binary sensor platform."""
add_entities([
ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))
])
class ZigBeeBinarySensor(ZigBeeDigitalIn, BinarySensorDevice):
"""Use ZigBeeDigitalIn as binary sensor."""
pass

View File

@@ -0,0 +1,134 @@
"""
Interfaces with Z-Wave sensors.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/binary_sensor.zwave/
"""
import logging
import datetime
import homeassistant.util.dt as dt_util
from homeassistant.helpers.event import track_point_in_time
from homeassistant.helpers.entity import Entity
from homeassistant.components import zwave
from homeassistant.components.binary_sensor import (
DOMAIN,
BinarySensorDevice)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = []
PHILIO = 0x013c
PHILIO_SLIM_SENSOR = 0x0002
PHILIO_SLIM_SENSOR_MOTION = (PHILIO, PHILIO_SLIM_SENSOR, 0)
WENZHOU = 0x0118
WENZHOU_SLIM_SENSOR_MOTION = (WENZHOU, PHILIO_SLIM_SENSOR, 0)
WORKAROUND_NO_OFF_EVENT = 'trigger_no_off_event'
DEVICE_MAPPINGS = {
PHILIO_SLIM_SENSOR_MOTION: WORKAROUND_NO_OFF_EVENT,
WENZHOU_SLIM_SENSOR_MOTION: WORKAROUND_NO_OFF_EVENT,
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Z-Wave platform for binary sensors."""
if discovery_info is None or zwave.NETWORK is None:
return
node = zwave.NETWORK.nodes[discovery_info[zwave.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.ATTR_VALUE_ID]]
value.set_change_verified(False)
# Make sure that we have values for the key before converting to int
if (value.node.manufacturer_id.strip() and
value.node.product_id.strip()):
specific_sensor_key = (int(value.node.manufacturer_id, 16),
int(value.node.product_id, 16),
value.index)
if specific_sensor_key in DEVICE_MAPPINGS:
if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_NO_OFF_EVENT:
# Default the multiplier to 4
re_arm_multiplier = (zwave.get_config_value(value.node,
9) or 4)
add_devices([
ZWaveTriggerSensor(value, "motion",
hass, re_arm_multiplier * 8)
])
return
if value.command_class == zwave.COMMAND_CLASS_SENSOR_BINARY:
add_devices([ZWaveBinarySensor(value, None)])
class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity, Entity):
"""Representation of a binary sensor within Z-Wave."""
def __init__(self, value, sensor_class):
"""Initialize the sensor."""
self._sensor_type = sensor_class
# pylint: disable=import-error
from openzwave.network import ZWaveNetwork
from pydispatch import dispatcher
zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
dispatcher.connect(
self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._value.data
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return self._sensor_type
@property
def should_poll(self):
"""No polling needed."""
return False
def value_changed(self, value):
"""Called when a value has changed on the network."""
if self._value.value_id == value.value_id:
self.update_ha_state()
class ZWaveTriggerSensor(ZWaveBinarySensor, Entity):
"""Representation of a stateless sensor within Z-Wave."""
def __init__(self, sensor_value, sensor_class, hass, re_arm_sec=60):
"""Initialize the sensor."""
super(ZWaveTriggerSensor, self).__init__(sensor_value, sensor_class)
self._hass = hass
self.re_arm_sec = re_arm_sec
self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
seconds=self.re_arm_sec)
# If it's active make sure that we set the timeout tracker
if sensor_value.data:
track_point_in_time(
self._hass, self.update_ha_state,
self.invalidate_after)
def value_changed(self, value):
"""Called when a value has changed on the network."""
if self._value.value_id == value.value_id:
self.update_ha_state()
if value.data:
# only allow this value to be true for re_arm secs
self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
seconds=self.re_arm_sec)
track_point_in_time(
self._hass, self.update_ha_state,
self.invalidate_after)
@property
def is_on(self):
"""Return True if movement has happened within the rearm time."""
return self._value.data and \
(self.invalidate_after is None or
self.invalidate_after > dt_util.utcnow())

View File

@@ -0,0 +1,77 @@
"""
Support for BloomSky weather station.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/bloomsky/
"""
import logging
from datetime import timedelta
import requests
from homeassistant.const import CONF_API_KEY
from homeassistant.helpers import validate_config, discovery
from homeassistant.util import Throttle
DOMAIN = "bloomsky"
BLOOMSKY = None
_LOGGER = logging.getLogger(__name__)
# The BloomSky only updates every 5-8 minutes as per the API spec so there's
# no point in polling the API more frequently
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300)
# pylint: disable=unused-argument,too-few-public-methods
def setup(hass, config):
"""Setup BloomSky component."""
if not validate_config(
config,
{DOMAIN: [CONF_API_KEY]},
_LOGGER):
return False
api_key = config[DOMAIN][CONF_API_KEY]
global BLOOMSKY
try:
BLOOMSKY = BloomSky(api_key)
except RuntimeError:
return False
for component in 'camera', 'binary_sensor', 'sensor':
discovery.load_platform(hass, component, DOMAIN, {}, config)
return True
class BloomSky(object):
"""Handle all communication with the BloomSky API."""
# API documentation at http://weatherlution.com/bloomsky-api/
API_URL = "https://api.bloomsky.com/api/skydata"
def __init__(self, api_key):
"""Initialize the BookSky."""
self._api_key = api_key
self.devices = {}
_LOGGER.debug("Initial bloomsky device load...")
self.refresh_devices()
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def refresh_devices(self):
"""Use the API to retreive a list of devices."""
_LOGGER.debug("Fetching bloomsky update")
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:
_LOGGER.error("Invalid HTTP response: %s", response.status_code)
return
# Create dictionary keyed off of the device unique id
self.devices.update({
device["DeviceID"]: device for device in response.json()
})

View File

@@ -1,27 +1,29 @@
"""
homeassistant.components.browser
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to launch a webbrowser on the host machine.
Provides functionality to launch a web browser on the host machine.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/browser/
"""
import voluptuous as vol
DOMAIN = "browser"
SERVICE_BROWSE_URL = "browse_url"
ATTR_URL = 'url'
ATTR_URL_DEFAULT = 'https://www.google.com'
SERVICE_BROWSE_URL_SCHEMA = vol.Schema({
vol.Required(ATTR_URL, default=ATTR_URL_DEFAULT): vol.Url,
})
def setup(hass, config):
""" Listen for browse_url events and open
the url in the default webbrowser. """
"""Listen for browse_url events."""
import webbrowser
hass.services.register(DOMAIN, SERVICE_BROWSE_URL,
lambda service:
webbrowser.open(
service.data.get(
'url', 'https://www.google.com')))
webbrowser.open(service.data[ATTR_URL]),
schema=SERVICE_BROWSE_URL_SCHEMA)
return True

View File

@@ -1,198 +1,116 @@
# pylint: disable=too-many-lines
"""
homeassistant.components.camera
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to interface with various cameras.
Component to interface with cameras.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/camera/
"""
import logging
import re
import time
import requests
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.const import (
ATTR_ENTITY_PICTURE,
HTTP_NOT_FOUND,
ATTR_ENTITY_ID,
)
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
from homeassistant.components.http import HomeAssistantView
DOMAIN = 'camera'
DEPENDENCIES = ['http']
GROUP_NAME_ALL_CAMERAS = 'all_cameras'
SCAN_INTERVAL = 30
ENTITY_ID_FORMAT = DOMAIN + '.{}'
SWITCH_ACTION_RECORD = 'record'
SWITCH_ACTION_SNAPSHOT = 'snapshot'
SERVICE_CAMERA = 'camera_service'
STATE_RECORDING = 'recording'
DEFAULT_RECORDING_SECONDS = 30
# Maps discovered services to their platforms
DISCOVERY_PLATFORMS = {}
FILE_DATETIME_FORMAT = '%Y-%m-%d_%H-%M-%S-%f'
DIR_DATETIME_FORMAT = '%Y-%m-%d_%H-%M-%S'
REC_DIR_PREFIX = 'recording-'
REC_IMG_PREFIX = 'recording_image-'
STATE_STREAMING = 'streaming'
STATE_IDLE = 'idle'
CAMERA_PROXY_URL = '/api/camera_proxy_stream/{0}'
CAMERA_STILL_URL = '/api/camera_proxy/{0}'
ENTITY_IMAGE_URL = '/api/camera_proxy/{0}?time={1}'
MULTIPART_BOUNDARY = '--jpegboundary'
MJPEG_START_HEADER = 'Content-type: {0}\r\n\r\n'
ENTITY_IMAGE_URL = '/api/camera_proxy/{0}?token={1}'
# pylint: disable=too-many-branches
def setup(hass, config):
""" Track states and offer events for cameras. """
"""Setup the camera component."""
component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL,
DISCOVERY_PLATFORMS)
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
hass.wsgi.register_view(CameraImageView(hass, component.entities))
hass.wsgi.register_view(CameraMjpegStream(hass, component.entities))
component.setup(config)
# -------------------------------------------------------------------------
# CAMERA COMPONENT ENDPOINTS
# -------------------------------------------------------------------------
# The following defines the endpoints for serving images from the camera
# via the HA http server. This is means that you can access images from
# your camera outside of your LAN without the need for port forwards etc.
# Because the authentication header can't be added in image requests these
# endpoints are secured with session based security.
# pylint: disable=unused-argument
def _proxy_camera_image(handler, path_match, data):
""" Proxies the camera image via the HA server. """
entity_id = path_match.group(ATTR_ENTITY_ID)
camera = component.entities.get(entity_id)
if camera is None:
handler.send_response(HTTP_NOT_FOUND)
handler.end_headers()
return
response = camera.camera_image()
if response is None:
handler.send_response(HTTP_NOT_FOUND)
handler.end_headers()
return
handler.wfile.write(response)
hass.http.register_path(
'GET',
re.compile(r'/api/camera_proxy/(?P<entity_id>[a-zA-Z\._0-9]+)'),
_proxy_camera_image)
# pylint: disable=unused-argument
def _proxy_camera_mjpeg_stream(handler, path_match, data):
"""
Proxies the camera image as an mjpeg stream via the HA server.
This function takes still images from the IP camera and turns them
into an MJPEG stream. This means that HA can return a live video
stream even with only a still image URL available.
"""
entity_id = path_match.group(ATTR_ENTITY_ID)
camera = component.entities.get(entity_id)
if camera is None:
handler.send_response(HTTP_NOT_FOUND)
handler.end_headers()
return
try:
camera.is_streaming = True
camera.update_ha_state()
handler.request.sendall(bytes('HTTP/1.1 200 OK\r\n', 'utf-8'))
handler.request.sendall(bytes(
'Content-type: multipart/x-mixed-replace; \
boundary=--jpgboundary\r\n\r\n', 'utf-8'))
handler.request.sendall(bytes('--jpgboundary\r\n', 'utf-8'))
# MJPEG_START_HEADER.format()
while True:
img_bytes = camera.camera_image()
if img_bytes is None:
continue
headers_str = '\r\n'.join((
'Content-length: {}'.format(len(img_bytes)),
'Content-type: image/jpeg',
)) + '\r\n\r\n'
handler.request.sendall(
bytes(headers_str, 'utf-8') +
img_bytes +
bytes('\r\n', 'utf-8'))
handler.request.sendall(
bytes('--jpgboundary\r\n', 'utf-8'))
time.sleep(0.5)
except (requests.RequestException, IOError):
camera.is_streaming = False
camera.update_ha_state()
hass.http.register_path(
'GET',
re.compile(
r'/api/camera_proxy_stream/(?P<entity_id>[a-zA-Z\._0-9]+)'),
_proxy_camera_mjpeg_stream)
return True
class Camera(Entity):
""" The base class for camera components. """
"""The base class for camera entities."""
def __init__(self):
"""Initialize a camera."""
self.is_streaming = False
@property
# pylint: disable=no-self-use
def is_recording(self):
""" Returns true if the device is recording. """
def access_token(self):
"""Access token for this camera."""
return str(id(self))
@property
def should_poll(self):
"""No need to poll cameras."""
return False
@property
def entity_picture(self):
"""Return a link to the camera feed as entity picture."""
return ENTITY_IMAGE_URL.format(self.entity_id, self.access_token)
@property
def is_recording(self):
"""Return true if the device is recording."""
return False
@property
# pylint: disable=no-self-use
def brand(self):
""" Should return a string of the camera brand. """
"""Camera brand."""
return None
@property
# pylint: disable=no-self-use
def model(self):
""" Returns string of camera model. """
"""Camera model."""
return None
def camera_image(self):
""" Return bytes of camera image. """
"""Return bytes of camera image."""
raise NotImplementedError()
def mjpeg_stream(self, response):
"""Generate an HTTP MJPEG stream from camera images."""
def stream():
"""Stream images as mjpeg stream."""
try:
last_image = None
while True:
img_bytes = self.camera_image()
if img_bytes is not None and img_bytes != last_image:
yield bytes(
'--jpegboundary\r\n'
'Content-Type: image/jpeg\r\n'
'Content-Length: {}\r\n\r\n'.format(
len(img_bytes)), 'utf-8') + img_bytes + b'\r\n'
last_image = img_bytes
time.sleep(0.5)
except GeneratorExit:
pass
return response(
stream(),
content_type=('multipart/x-mixed-replace; '
'boundary=--jpegboundary')
)
@property
def state(self):
""" Returns the state of the entity. """
"""Camera state."""
if self.is_recording:
return STATE_RECORDING
elif self.is_streaming:
@@ -202,10 +120,9 @@ class Camera(Entity):
@property
def state_attributes(self):
""" Returns optional state attributes. """
"""Camera state attributes."""
attr = {
ATTR_ENTITY_PICTURE: ENTITY_IMAGE_URL.format(
self.entity_id, time.time()),
'access_token': self.access_token,
}
if self.model:
@@ -215,3 +132,60 @@ class Camera(Entity):
attr['brand'] = self.brand
return attr
class CameraView(HomeAssistantView):
"""Base CameraView."""
requires_auth = False
def __init__(self, hass, entities):
"""Initialize a basic camera view."""
super().__init__(hass)
self.entities = entities
def get(self, request, entity_id):
"""Start a get request."""
camera = self.entities.get(entity_id)
if camera is None:
return self.Response(status=404)
authenticated = (request.authenticated or
request.args.get('token') == camera.access_token)
if not authenticated:
return self.Response(status=401)
return self.handle(camera)
def handle(self, camera):
"""Hanlde the camera request."""
raise NotImplementedError()
class CameraImageView(CameraView):
"""Camera view to serve an image."""
url = "/api/camera_proxy/<entity(domain=camera):entity_id>"
name = "api:camera:image"
def handle(self, camera):
"""Serve camera image."""
response = camera.camera_image()
if response is None:
return self.Response(status=500)
return self.Response(response)
class CameraMjpegStream(CameraView):
"""Camera View to serve an MJPEG stream."""
url = "/api/camera_proxy_stream/<entity(domain=camera):entity_id>"
name = "api:camera:stream"
def handle(self, camera):
"""Serve camera image."""
return camera.mjpeg_stream(self.Response)

View File

@@ -0,0 +1,61 @@
"""
Support for a camera of a BloomSky weather station.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/camera.bloomsky/
"""
import logging
import requests
from homeassistant.components.camera import Camera
from homeassistant.loader import get_component
DEPENDENCIES = ["bloomsky"]
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup access to BloomSky cameras."""
bloomsky = get_component('bloomsky')
for device in bloomsky.BLOOMSKY.devices.values():
add_devices_callback([BloomSkyCamera(bloomsky.BLOOMSKY, device)])
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."""
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
# frequent updates in home-assistant don't keep poking the server
# to download the same image over and over.
self._last_image = ""
self._logger = logging.getLogger(__name__)
def camera_image(self):
"""Update the camera's image if it has changed."""
try:
self._url = self._bloomsky.devices[self._id]["Data"]["ImageURL"]
self._bloomsky.refresh_devices()
# If the URL hasn't changed then the image hasn't changed.
if self._url != self._last_url:
response = requests.get(self._url, timeout=10)
self._last_url = self._url
self._last_image = response.content
except requests.exceptions.RequestException as error:
self._logger.error("Error getting bloomsky image: %s", error)
return None
return self._last_image
@property
def name(self):
"""Return the name of this BloomSky device."""
return self._name

View File

@@ -1,29 +1,32 @@
"""
homeassistant.components.camera.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo platform that has a fake camera.
Demo camera platform that has a fake camera.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
import os
from homeassistant.components.camera import Camera
import homeassistant.util.dt as dt_util
from homeassistant.components.camera import Camera
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Demo camera. """
"""Setup the Demo camera platform."""
add_devices([
DemoCamera('Demo camera')
])
class DemoCamera(Camera):
""" A Demo camera. """
"""The representation of a Demo camera."""
def __init__(self, name):
"""Initialize demo camera component."""
super().__init__()
self._name = name
def camera_image(self):
""" Return a faked still image response. """
"""Return a faked still image response."""
now = dt_util.utcnow()
image_path = os.path.join(os.path.dirname(__file__),
@@ -33,5 +36,5 @@ class DemoCamera(Camera):
@property
def name(self):
""" Return the name of this device. """
"""Return the name of this camera."""
return self._name

View File

@@ -1,6 +1,4 @@
"""
homeassistant.components.camera.foscam
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This component provides basic support for Foscam IP cameras.
For more details about this platform, please refer to the documentation at
@@ -10,15 +8,15 @@ import logging
import requests
from homeassistant.helpers import validate_config
from homeassistant.components.camera import DOMAIN, Camera
from homeassistant.helpers import validate_config
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Adds a Foscam IP Camera. """
"""Setup a Foscam IP Camera."""
if not validate_config({DOMAIN: config},
{DOMAIN: ['username', 'password', 'ip']}, _LOGGER):
return None
@@ -28,9 +26,10 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
# pylint: disable=too-many-instance-attributes
class FoscamCamera(Camera):
""" An implementation of a Foscam IP camera. """
"""An implementation of a Foscam IP camera."""
def __init__(self, device_info):
"""Initialize a Foscam camera."""
super(FoscamCamera, self).__init__()
ip_address = device_info.get('ip')
@@ -48,14 +47,13 @@ class FoscamCamera(Camera):
self._name, self._snap_picture_url)
def camera_image(self):
""" Return a still image reponse from the camera. """
"""Return a still image reponse from the camera."""
# Send the request to snap a picture and return raw jpg data
response = requests.get(self._snap_picture_url)
response = requests.get(self._snap_picture_url, timeout=10)
return response.content
@property
def name(self):
""" Return the name of this device. """
"""Return the name of this camera."""
return self._name

View File

@@ -1,6 +1,4 @@
"""
homeassistant.components.camera.generic
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for IP Cameras.
For more details about this platform, please refer to the documentation at
@@ -11,15 +9,15 @@ import logging
import requests
from requests.auth import HTTPBasicAuth
from homeassistant.helpers import validate_config
from homeassistant.components.camera import DOMAIN, Camera
from homeassistant.helpers import validate_config
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Adds a generic IP Camera. """
"""Setup a generic IP Camera."""
if not validate_config({DOMAIN: config}, {DOMAIN: ['still_image_url']},
_LOGGER):
return None
@@ -29,11 +27,10 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
# pylint: disable=too-many-instance-attributes
class GenericCamera(Camera):
"""
A generic implementation of an IP camera that is reachable over a URL.
"""
"""A generic implementation of an IP camera."""
def __init__(self, device_info):
"""Initialize a generic camera."""
super().__init__()
self._name = device_info.get('name', 'Generic Camera')
self._username = device_info.get('username')
@@ -41,18 +38,19 @@ class GenericCamera(Camera):
self._still_image_url = device_info['still_image_url']
def camera_image(self):
""" Return a still image response from the camera. """
"""Return a still image response from the camera."""
if self._username and self._password:
try:
response = requests.get(
self._still_image_url,
auth=HTTPBasicAuth(self._username, self._password))
auth=HTTPBasicAuth(self._username, self._password),
timeout=10)
except requests.exceptions.RequestException as error:
_LOGGER.error('Error getting camera image: %s', error)
return None
else:
try:
response = requests.get(self._still_image_url)
response = requests.get(self._still_image_url, timeout=10)
except requests.exceptions.RequestException as error:
_LOGGER.error('Error getting camera image: %s', error)
return None
@@ -61,5 +59,5 @@ class GenericCamera(Camera):
@property
def name(self):
""" Return the name of this device. """
"""Return the name of this device."""
return self._name

View File

@@ -0,0 +1,53 @@
"""Camera that loads a picture from a local file."""
import logging
import os
from homeassistant.components.camera import Camera
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera."""
# check for missing required configuration variable
if config.get("file_path") is None:
_LOGGER.error("Missing required variable: file_path")
return False
setup_config = (
{
"name": config.get("name", "Local File"),
"file_path": config.get("file_path")
}
)
# check filepath given is readable
if not os.access(setup_config["file_path"], os.R_OK):
_LOGGER.error("file path is not readable")
return False
add_devices([
LocalFile(setup_config)
])
class LocalFile(Camera):
"""Local camera."""
def __init__(self, device_info):
"""Initialize Local File Camera component."""
super().__init__()
self._name = device_info["name"]
self._config = device_info
def camera_image(self):
"""Return image response."""
with open(self._config["file_path"], 'rb') as file:
return file.read()
@property
def name(self):
"""Return the name of this camera."""
return self._name

View File

@@ -1,26 +1,26 @@
"""
homeassistant.components.camera.mjpeg
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for IP Cameras.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.mjpeg/
"""
from contextlib import closing
import logging
from contextlib import closing
import requests
from requests.auth import HTTPBasicAuth
from homeassistant.helpers import validate_config
from homeassistant.components.camera import DOMAIN, Camera
from homeassistant.helpers import validate_config
CONTENT_TYPE_HEADER = 'Content-Type'
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Adds a mjpeg IP Camera. """
"""Setup a MJPEG IP Camera."""
if not validate_config({DOMAIN: config}, {DOMAIN: ['mjpeg_url']},
_LOGGER):
return None
@@ -30,22 +30,30 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
# pylint: disable=too-many-instance-attributes
class MjpegCamera(Camera):
"""
A generic implementation of an IP camera that is reachable over a URL.
"""
"""An implementation of an IP camera that is reachable over a URL."""
def __init__(self, device_info):
"""Initialize a MJPEG camera."""
super().__init__()
self._name = device_info.get('name', 'Mjpeg Camera')
self._username = device_info.get('username')
self._password = device_info.get('password')
self._mjpeg_url = device_info['mjpeg_url']
def camera_image(self):
""" Return a still image response from the camera. """
def camera_stream(self):
"""Return a MJPEG stream image response directly from the camera."""
if self._username and self._password:
return requests.get(self._mjpeg_url,
auth=HTTPBasicAuth(self._username,
self._password),
stream=True, timeout=10)
else:
return requests.get(self._mjpeg_url, stream=True, timeout=10)
def camera_image(self):
"""Return a still image response from the camera."""
def process_response(response):
""" Take in a response object, return the jpg from it. """
"""Take in a response object, return the jpg from it."""
data = b''
for chunk in response.iter_content(1024):
data += chunk
@@ -55,18 +63,19 @@ class MjpegCamera(Camera):
jpg = data[jpg_start:jpg_end + 2]
return jpg
if self._username and self._password:
with closing(requests.get(self._mjpeg_url,
auth=HTTPBasicAuth(self._username,
self._password),
stream=True)) as response:
return process_response(response)
else:
with closing(requests.get(self._mjpeg_url,
stream=True)) as response:
return process_response(response)
with closing(self.camera_stream()) as response:
return process_response(response)
def mjpeg_stream(self, response):
"""Generate an HTTP MJPEG stream from the camera."""
stream = self.camera_stream()
return response(
stream.iter_content(chunk_size=1024),
mimetype=stream.headers[CONTENT_TYPE_HEADER],
direct_passthrough=True
)
@property
def name(self):
""" Return the name of this device. """
"""Return the name of this camera."""
return self._name

View File

@@ -0,0 +1,104 @@
"""
Support for the Netatmo Welcome camera.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.netatmo/
"""
import logging
from datetime import timedelta
import requests
from homeassistant.util import Throttle
from homeassistant.components.camera import Camera
from homeassistant.loader import get_component
DEPENDENCIES = ["netatmo"]
_LOGGER = logging.getLogger(__name__)
CONF_HOME = 'home'
ATTR_CAMERAS = 'cameras'
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup access to Netatmo Welcome cameras."""
netatmo = get_component('netatmo')
home = config.get(CONF_HOME, None)
data = WelcomeData(netatmo.NETATMO_AUTH, home)
for camera_name in data.get_camera_names():
if ATTR_CAMERAS in config:
if camera_name not in config[ATTR_CAMERAS]:
continue
add_devices_callback([WelcomeCamera(data, camera_name, home)])
class WelcomeCamera(Camera):
"""Representation of the images published from Welcome camera."""
def __init__(self, data, camera_name, home):
"""Setup for access to the BloomSky camera images."""
super(WelcomeCamera, self).__init__()
self._data = data
self._camera_name = camera_name
if home:
self._name = home + ' / ' + camera_name
else:
self._name = camera_name
self._vpnurl, self._localurl = self._data.welcomedata.cameraUrls(
camera=camera_name
)
def camera_image(self):
"""Return a still image response from the camera."""
try:
if self._localurl:
response = requests.get('{0}/live/snapshot_720.jpg'.format(
self._localurl), timeout=10)
else:
response = requests.get('{0}/live/snapshot_720.jpg'.format(
self._vpnurl), timeout=10)
except requests.exceptions.RequestException as error:
_LOGGER.error('Welcome VPN url changed: %s', error)
self._data.update()
(self._vpnurl, self._localurl) = \
self._data.welcomedata.cameraUrls(camera=self._camera_name)
return None
return response.content
@property
def name(self):
"""Return the name of this Netatmo Welcome device."""
return self._name
class WelcomeData(object):
"""Get the latest data from NetAtmo."""
def __init__(self, auth, home=None):
"""Initialize the data object."""
self.auth = auth
self.welcomedata = None
self.camera_names = []
self.home = home
def get_camera_names(self):
"""Return all module available on the API as a list."""
self.update()
if not self.home:
for home in self.welcomedata.cameras:
for camera in self.welcomedata.cameras[home].values():
self.camera_names.append(camera['name'])
else:
for camera in self.welcomedata.cameras[self.home].values():
self.camera_names.append(camera['name'])
return self.camera_names
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Call the NetAtmo API to update the data."""
import lnetatmo
self.welcomedata = lnetatmo.WelcomeData(self.auth)

View File

@@ -0,0 +1,90 @@
"""
Camera platform that has a Raspberry Pi camera.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.rpi_camera/
"""
import os
import subprocess
import logging
import shutil
from homeassistant.components.camera import Camera
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Raspberry Camera."""
if shutil.which("raspistill") is None:
_LOGGER.error("Error: raspistill not found")
return False
setup_config = (
{
"name": config.get("name", "Raspberry Pi Camera"),
"image_width": int(config.get("image_width", "640")),
"image_height": int(config.get("image_height", "480")),
"image_quality": int(config.get("image_quality", "7")),
"image_rotation": int(config.get("image_rotation", "0")),
"timelapse": int(config.get("timelapse", "2000")),
"horizontal_flip": int(config.get("horizontal_flip", "0")),
"vertical_flip": int(config.get("vertical_flip", "0")),
"file_path": config.get("file_path",
os.path.join(os.path.dirname(__file__),
'image.jpg'))
}
)
# check filepath given is writable
if not os.access(setup_config["file_path"], os.W_OK):
_LOGGER.error("Error: file path is not writable")
return False
add_devices([
RaspberryCamera(setup_config)
])
class RaspberryCamera(Camera):
"""Representation of a Raspberry Pi camera."""
def __init__(self, device_info):
"""Initialize Raspberry Pi camera component."""
super().__init__()
self._name = device_info["name"]
self._config = device_info
# kill if there's raspistill instance
subprocess.Popen(['killall', 'raspistill'],
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT)
cmd_args = [
'raspistill', '--nopreview', '-o', str(device_info["file_path"]),
'-t', '0', '-w', str(device_info["image_width"]),
'-h', str(device_info["image_height"]),
'-tl', str(device_info["timelapse"]),
'-q', str(device_info["image_quality"]),
'-rot', str(device_info["image_rotation"])
]
if device_info["horizontal_flip"]:
cmd_args.append("-hf")
if device_info["vertical_flip"]:
cmd_args.append("-vf")
subprocess.Popen(cmd_args,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT)
def camera_image(self):
"""Return raspstill image response."""
with open(self._config["file_path"], 'rb') as file:
return file.read()
@property
def name(self):
"""Return the name of this camera."""
return self._name

View File

@@ -0,0 +1,165 @@
"""
Support for Ubiquiti's UVC cameras.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.uvc/
"""
import logging
import socket
import requests
from homeassistant.components.camera import DOMAIN, Camera
from homeassistant.helpers import validate_config
REQUIREMENTS = ['uvcclient==0.9.0']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Discover cameras on a Unifi NVR."""
if not validate_config({DOMAIN: config}, {DOMAIN: ['nvr', 'key']},
_LOGGER):
return None
addr = config.get('nvr')
key = config.get('key')
try:
port = int(config.get('port', 7080))
except ValueError:
_LOGGER.error('Invalid port number provided')
return False
from uvcclient import nvr
nvrconn = nvr.UVCRemote(addr, port, key)
try:
cameras = nvrconn.index()
except nvr.NotAuthorized:
_LOGGER.error('Authorization failure while connecting to NVR')
return False
except nvr.NvrError:
_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))
return False
identifier = nvrconn.server_version >= (3, 2, 0) and 'id' or 'uuid'
# Filter out airCam models, which are not supported in the latest
# version of UnifiVideo and which are EOL by Ubiquiti
cameras = [
camera for camera in cameras
if 'airCam' not in nvrconn.get_camera(camera[identifier])['model']]
add_devices([UnifiVideoCamera(nvrconn,
camera[identifier],
camera['name'])
for camera in cameras])
return True
class UnifiVideoCamera(Camera):
"""A Ubiquiti Unifi Video Camera."""
def __init__(self, nvr, uuid, name):
"""Initialize an Unifi camera."""
super(UnifiVideoCamera, self).__init__()
self._nvr = nvr
self._uuid = uuid
self._name = name
self.is_streaming = False
self._connect_addr = None
self._camera = None
@property
def name(self):
"""Return the name of this camera."""
return self._name
@property
def is_recording(self):
"""Return true if the camera is recording."""
caminfo = self._nvr.get_camera(self._uuid)
return caminfo['recordingSettings']['fullTimeRecordEnabled']
@property
def brand(self):
"""Return the brand of this camera."""
return 'Ubiquiti'
@property
def model(self):
"""Return the model of this camera."""
caminfo = self._nvr.get_camera(self._uuid)
return caminfo['model']
def _login(self):
"""Login to the camera."""
from uvcclient import camera as uvc_camera
from uvcclient import store as uvc_store
caminfo = self._nvr.get_camera(self._uuid)
if self._connect_addr:
addrs = [self._connect_addr]
else:
addrs = [caminfo['host'], caminfo['internalHost']]
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',
dict(name=self._name))
password = 'ubnt'
if self._nvr.server_version >= (3, 2, 0):
client_cls = uvc_camera.UVCCameraClientV320
else:
client_cls = uvc_camera.UVCCameraClient
camera = None
for addr in addrs:
try:
camera = client_cls(addr,
caminfo['username'],
password)
camera.login()
_LOGGER.debug('Logged into UVC camera %(name)s via %(addr)s',
dict(name=self._name, addr=addr))
self._connect_addr = addr
break
except socket.error:
pass
except uvc_camera.CameraConnectError:
pass
except uvc_camera.CameraAuthError:
pass
if not self._connect_addr:
_LOGGER.error('Unable to login to camera')
return None
self._camera = camera
return True
def camera_image(self):
"""Return the image of this camera."""
from uvcclient import camera as uvc_camera
if not self._camera:
if not self._login():
return
def _get_image(retry=True):
try:
return self._camera.get_snapshot()
except uvc_camera.CameraConnectError:
_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')
raise
return _get_image()

View File

@@ -1,8 +1,5 @@
"""
homeassistant.components.configurator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A component to allow pieces of code to request configuration from the user.
Support to allow pieces of code to request configuration from the user.
Initiate a request by calling the `request_config` method with a callback.
This will return a request id that has to be used for future calls.
@@ -11,8 +8,8 @@ the user has submitted configuration information.
"""
import logging
from homeassistant.helpers import generate_entity_id
from homeassistant.const import EVENT_TIME_CHANGED
from homeassistant.const import EVENT_TIME_CHANGED, ATTR_FRIENDLY_NAME
from homeassistant.helpers.entity import generate_entity_id
DOMAIN = "configurator"
ENTITY_ID_FORMAT = DOMAIN + ".{}"
@@ -22,6 +19,8 @@ SERVICE_CONFIGURE = "configure"
STATE_CONFIGURE = "configure"
STATE_CONFIGURED = "configured"
ATTR_LINK_NAME = "link_name"
ATTR_LINK_URL = "link_url"
ATTR_CONFIGURE_ID = "configure_id"
ATTR_DESCRIPTION = "description"
ATTR_DESCRIPTION_IMAGE = "description_image"
@@ -37,15 +36,17 @@ _LOGGER = logging.getLogger(__name__)
# pylint: disable=too-many-arguments
def request_config(
hass, name, callback, description=None, description_image=None,
submit_caption=None, fields=None):
""" Create a new request for config.
Will return an ID to be used for sequent calls. """
submit_caption=None, fields=None, link_name=None, link_url=None):
"""Create a new request for configuration.
Will return an ID to be used for sequent calls.
"""
instance = _get_instance(hass)
request_id = instance.request_config(
name, callback,
description, description_image, submit_caption, fields)
description, description_image, submit_caption,
fields, link_name, link_url)
_REQUESTS[request_id] = instance
@@ -53,7 +54,7 @@ def request_config(
def notify_errors(request_id, error):
""" Add errors to a config request. """
"""Add errors to a config request."""
try:
_REQUESTS[request_id].notify_errors(request_id, error)
except KeyError:
@@ -62,7 +63,7 @@ def notify_errors(request_id, error):
def request_done(request_id):
""" Mark a config request as done. """
"""Mark a configuration request as done."""
try:
_REQUESTS.pop(request_id).request_done(request_id)
except KeyError:
@@ -71,12 +72,12 @@ def request_done(request_id):
def setup(hass, config):
""" Set up Configurator. """
"""Setup the configurator component."""
return True
def _get_instance(hass):
""" Get an instance per hass object. """
"""Get an instance per hass object."""
try:
return _INSTANCES[hass]
except KeyError:
@@ -89,11 +90,10 @@ def _get_instance(hass):
class Configurator(object):
"""
Class to keep track of current configuration requests.
"""
"""The class to keep track of current configuration requests."""
def __init__(self, hass):
"""Initialize the configurator."""
self.hass = hass
self._cur_id = 0
self._requests = {}
@@ -103,9 +103,9 @@ class Configurator(object):
# pylint: disable=too-many-arguments
def request_config(
self, name, callback,
description, description_image, submit_caption, fields):
""" Setup a request for configuration. """
description, description_image, submit_caption,
fields, link_name, link_url):
"""Setup a request for configuration."""
entity_id = generate_entity_id(ENTITY_ID_FORMAT, name, hass=self.hass)
if fields is None:
@@ -118,6 +118,7 @@ class Configurator(object):
data = {
ATTR_CONFIGURE_ID: request_id,
ATTR_FIELDS: fields,
ATTR_FRIENDLY_NAME: name,
}
data.update({
@@ -125,6 +126,8 @@ class Configurator(object):
(ATTR_DESCRIPTION, description),
(ATTR_DESCRIPTION_IMAGE, description_image),
(ATTR_SUBMIT_CAPTION, submit_caption),
(ATTR_LINK_NAME, link_name),
(ATTR_LINK_URL, link_url),
] if value is not None
})
@@ -133,7 +136,7 @@ class Configurator(object):
return request_id
def notify_errors(self, request_id, error):
""" Update the state with errors. """
"""Update the state with errors."""
if not self._validate_request_id(request_id):
return
@@ -141,13 +144,13 @@ class Configurator(object):
state = self.hass.states.get(entity_id)
new_data = state.attributes
new_data = dict(state.attributes)
new_data[ATTR_ERRORS] = error
self.hass.states.set(entity_id, STATE_CONFIGURE, new_data)
def request_done(self, request_id):
""" Remove the config request. """
"""Remove the configuration request."""
if not self._validate_request_id(request_id):
return
@@ -160,13 +163,13 @@ class Configurator(object):
self.hass.states.set(entity_id, STATE_CONFIGURED)
def deferred_remove(event):
""" Remove the request state. """
"""Remove the request state."""
self.hass.states.remove(entity_id)
self.hass.bus.listen_once(EVENT_TIME_CHANGED, deferred_remove)
def handle_service_call(self, call):
""" Handle a configure service call. """
"""Handle a configure service call."""
request_id = call.data.get(ATTR_CONFIGURE_ID)
if not self._validate_request_id(request_id):
@@ -180,10 +183,10 @@ class Configurator(object):
callback(call.data.get(ATTR_FIELDS, {}))
def _generate_unique_id(self):
""" Generates a unique configurator id. """
"""Generate a unique configurator ID."""
self._cur_id += 1
return "{}-{}".format(id(self), self._cur_id)
def _validate_request_id(self, request_id):
""" Validate that the request belongs to this instance. """
"""Validate that the request belongs to this instance."""
return request_id in self._requests

View File

@@ -1,18 +1,19 @@
"""
homeassistant.components.conversation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to have conversations with Home Assistant.
Support for functionality to have conversations with Home Assistant.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/conversation/
"""
import logging
import re
import warnings
import voluptuous as vol
from homeassistant import core
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF)
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON)
import homeassistant.helpers.config_validation as cv
DOMAIN = "conversation"
@@ -20,25 +21,25 @@ SERVICE_PROCESS = "process"
ATTR_TEXT = "text"
SERVICE_PROCESS_SCHEMA = vol.Schema({
vol.Required(ATTR_TEXT): vol.All(cv.string, vol.Lower),
})
REGEX_TURN_COMMAND = re.compile(r'turn (?P<name>(?: |\w)+) (?P<command>\w+)')
REQUIREMENTS = ['fuzzywuzzy==0.8.0']
REQUIREMENTS = ['fuzzywuzzy==0.11.0']
def setup(hass, config):
""" Registers the process service. """
"""Register the process service."""
warnings.filterwarnings('ignore', module='fuzzywuzzy')
from fuzzywuzzy import process as fuzzyExtract
logger = logging.getLogger(__name__)
def process(service):
""" Parses text into commands for Home Assistant. """
if ATTR_TEXT not in service.data:
logger.error("Received process service call without a text")
return
text = service.data[ATTR_TEXT].lower()
"""Parse text into commands."""
text = service.data[ATTR_TEXT]
match = REGEX_TURN_COMMAND.match(text)
if not match:
@@ -46,11 +47,8 @@ def setup(hass, config):
return
name, command = match.groups()
entities = {state.entity_id: state.name for state in hass.states.all()}
entity_ids = fuzzyExtract.extractOne(name,
entities,
entity_ids = fuzzyExtract.extractOne(name, entities,
score_cutoff=65)[2]
if not entity_ids:
@@ -69,9 +67,9 @@ def setup(hass, config):
}, blocking=True)
else:
logger.error(
'Got unsupported command %s from text %s', command, text)
hass.services.register(DOMAIN, SERVICE_PROCESS, process)
logger.error('Got unsupported command %s from text %s',
command, text)
hass.services.register(DOMAIN, SERVICE_PROCESS, process,
schema=SERVICE_PROCESS_SCHEMA)
return True

View File

@@ -1,16 +1,15 @@
"""
homeassistant.components.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets up a demo environment that mimics interaction with devices.
For more details about this component, please refer to the documentation
https://home-assistant.io/components/demo/
"""
import time
import homeassistant.core as ha
import homeassistant.bootstrap as bootstrap
import homeassistant.core as ha
import homeassistant.loader as loader
from homeassistant.const import (
CONF_PLATFORM, ATTR_ENTITY_ID)
from homeassistant.const import ATTR_ENTITY_ID, CONF_PLATFORM
DOMAIN = "demo"
@@ -21,6 +20,8 @@ COMPONENTS_WITH_DEMO_PLATFORM = [
'binary_sensor',
'camera',
'device_tracker',
'garage_door',
'hvac',
'light',
'lock',
'media_player',
@@ -33,9 +34,10 @@ COMPONENTS_WITH_DEMO_PLATFORM = [
def setup(hass, config):
""" Setup a demo environment. """
"""Setup a demo environment."""
group = loader.get_component('group')
configurator = loader.get_component('configurator')
persistent_notification = loader.get_component('persistent_notification')
config.setdefault(ha.DOMAIN, {})
config.setdefault(DOMAIN, {})
@@ -58,14 +60,42 @@ def setup(hass, config):
demo_config[component] = {CONF_PLATFORM: 'demo'}
bootstrap.setup_component(hass, component, demo_config)
# Setup example persistent notification
persistent_notification.create(
hass, 'This is an example of a persistent notification.',
title='Example Notification')
# Setup room groups
lights = sorted(hass.states.entity_ids('light'))
switches = sorted(hass.states.entity_ids('switch'))
media_players = sorted(hass.states.entity_ids('media_player'))
group.setup_group(hass, 'living room', [lights[2], lights[1], switches[0],
media_players[1]])
group.setup_group(hass, 'bedroom', [lights[0], switches[1],
media_players[0]])
group.Group(hass, 'living room', [
lights[1], switches[0], 'input_select.living_room_preset',
'rollershutter.living_room_window', media_players[1],
'scene.romantic_lights'])
group.Group(hass, 'bedroom', [
lights[0], switches[1], media_players[0],
'input_slider.noise_allowance'])
group.Group(hass, 'kitchen', [
lights[2], 'rollershutter.kitchen_window', 'lock.kitchen_door'])
group.Group(hass, 'doors', [
'lock.front_door', 'lock.kitchen_door',
'garage_door.right_garage_door', 'garage_door.left_garage_door'])
group.Group(hass, 'automations', [
'input_select.who_cooks', 'input_boolean.notify', ])
group.Group(hass, 'people', [
'device_tracker.demo_anne_therese', 'device_tracker.demo_home_boy',
'device_tracker.demo_paulus'])
group.Group(hass, 'thermostats', [
'thermostat.nest', 'thermostat.thermostat'])
group.Group(hass, 'downstairs', [
'group.living_room', 'group.kitchen',
'scene.romantic_lights', 'rollershutter.kitchen_window',
'rollershutter.living_room_window', 'group.doors', 'thermostat.nest',
], view=True)
group.Group(hass, 'Upstairs', [
'thermostat.thermostat', 'group.bedroom',
], view=True)
# Setup scripts
bootstrap.setup_component(
@@ -74,18 +104,18 @@ def setup(hass, config):
'demo': {
'alias': 'Toggle {}'.format(lights[0].split('.')[1]),
'sequence': [{
'execute_service': 'light.turn_off',
'service_data': {ATTR_ENTITY_ID: lights[0]}
'service': 'light.turn_off',
'data': {ATTR_ENTITY_ID: lights[0]}
}, {
'delay': {'seconds': 5}
}, {
'execute_service': 'light.turn_on',
'service_data': {ATTR_ENTITY_ID: lights[0]}
'service': 'light.turn_on',
'data': {ATTR_ENTITY_ID: lights[0]}
}, {
'delay': {'seconds': 5}
}, {
'execute_service': 'light.turn_off',
'service_data': {ATTR_ENTITY_ID: lights[0]}
'service': 'light.turn_off',
'data': {ATTR_ENTITY_ID: lights[0]}
}]
}}})
@@ -106,11 +136,44 @@ def setup(hass, config):
}},
]})
# Set up input select
bootstrap.setup_component(
hass, 'input_select',
{'input_select':
{'living_room_preset': {'options': ['Visitors',
'Visitors with kids',
'Home Alone']},
'who_cooks': {'icon': 'mdi:panda',
'initial': 'Anne Therese',
'name': 'Cook today',
'options': ['Paulus', 'Anne Therese']}}})
# Set up input boolean
bootstrap.setup_component(
hass, 'input_boolean',
{'input_boolean': {'notify': {'icon': 'mdi:car',
'initial': False,
'name': 'Notify Anne Therese is home'}}})
# Set up input boolean
bootstrap.setup_component(
hass, 'input_slider',
{'input_slider': {
'noise_allowance': {'icon': 'mdi:bell-ring',
'min': 0,
'max': 10,
'name': 'Allowed Noise',
'unit_of_measurement': 'dB'}}})
# Set up weblink
bootstrap.setup_component(
hass, 'weblink',
{'weblink': {'entities': [{'name': 'Router',
'url': 'http://192.168.1.1'}]}})
# Setup configurator
configurator_ids = []
def hue_configuration_callback(data):
""" Fake callback, mark config as done. """
"""Fake callback, mark config as done."""
time.sleep(2)
# First time it is called, pretend it failed.

View File

@@ -1,8 +1,5 @@
"""
homeassistant.components.device_sun_light_trigger
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to turn on lights based on the state of the sun and
devices.
Provides functionality to turn on lights based on the states.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/device_sun_light_trigger/
@@ -10,10 +7,11 @@ https://home-assistant.io/components/device_sun_light_trigger/
import logging
from datetime import timedelta
from homeassistant.helpers.event import track_point_in_time, track_state_change
import homeassistant.util.dt as dt_util
from homeassistant.const import STATE_HOME, STATE_NOT_HOME
from . import light, sun, device_tracker, group
from homeassistant.helpers.event import track_point_in_time
from homeassistant.helpers.event_decorators import track_state_change
from homeassistant.loader import get_component
DOMAIN = "device_sun_light_trigger"
DEPENDENCIES = ['light', 'device_tracker', 'group', 'sun']
@@ -28,28 +26,26 @@ CONF_LIGHT_GROUP = 'light_group'
CONF_DEVICE_GROUP = 'device_group'
# pylint: disable=too-many-branches
# pylint: disable=too-many-locals
def setup(hass, config):
""" Triggers to turn lights on or off based on device precense. """
"""The triggers to turn lights on or off based on device presence."""
logger = logging.getLogger(__name__)
device_tracker = get_component('device_tracker')
group = get_component('group')
light = get_component('light')
sun = get_component('sun')
disable_turn_off = 'disable_turn_off' in config[DOMAIN]
light_group = config[DOMAIN].get(CONF_LIGHT_GROUP,
light.ENTITY_ID_ALL_LIGHTS)
light_profile = config[DOMAIN].get(CONF_LIGHT_PROFILE, LIGHT_PROFILE)
device_group = config[DOMAIN].get(CONF_DEVICE_GROUP,
device_tracker.ENTITY_ID_ALL_DEVICES)
logger = logging.getLogger(__name__)
device_entity_ids = group.get_entity_ids(hass, device_group,
device_tracker.DOMAIN)
if not device_entity_ids:
logger.error("No devices found to track")
return False
# Get the light IDs from the specified group
@@ -57,116 +53,105 @@ def setup(hass, config):
if not light_ids:
logger.error("No lights found to turn on ")
return False
def calc_time_for_light_when_sunset():
""" Calculates the time when to start fading lights in when sun sets.
Returns None if no next_setting data available. """
"""Calculate the time when to start fading lights in when sun sets.
Returns None if no next_setting data available.
"""
next_setting = sun.next_setting(hass)
if next_setting:
return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)
else:
if not next_setting:
return None
return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)
def schedule_light_on_sun_rise(entity, old_state, new_state):
"""The moment sun sets we want to have all the lights on.
We will schedule to have each light start after one another
and slowly transition in."""
def turn_light_on_before_sunset(light_id):
"""Helper function to turn on lights.
def turn_light_on_before_sunset(light_id):
""" Helper function to turn on lights slowly if there
are devices home and the light is not on yet. """
if device_tracker.is_on(hass) and not light.is_on(hass, light_id):
light.turn_on(hass, light_id,
transition=LIGHT_TRANSITION_TIME.seconds,
profile=light_profile)
def turn_on(light_id):
""" Lambda can keep track of function parameters but not local
parameters. If we put the lambda directly in the below statement
only the last light will be turned on.. """
return lambda now: turn_light_on_before_sunset(light_id)
start_point = calc_time_for_light_when_sunset()
if start_point:
for index, light_id in enumerate(light_ids):
track_point_in_time(
hass, turn_on(light_id),
(start_point + index * LIGHT_TRANSITION_TIME))
Speed is slow if there are devices home and the light is not on yet.
"""
if not device_tracker.is_on(hass) or light.is_on(hass, light_id):
return
light.turn_on(hass, light_id,
transition=LIGHT_TRANSITION_TIME.seconds,
profile=light_profile)
# Track every time sun rises so we can schedule a time-based
# pre-sun set event
track_state_change(hass, sun.ENTITY_ID, schedule_light_on_sun_rise,
sun.STATE_BELOW_HORIZON, sun.STATE_ABOVE_HORIZON)
@track_state_change(sun.ENTITY_ID, sun.STATE_BELOW_HORIZON,
sun.STATE_ABOVE_HORIZON)
def schedule_lights_at_sun_set(hass, entity, old_state, new_state):
"""The moment sun sets we want to have all the lights on.
# If the sun is already above horizon
# schedule the time-based pre-sun set event
We will schedule to have each light start after one another
and slowly transition in.
"""
start_point = calc_time_for_light_when_sunset()
if not start_point:
return
def turn_on(light_id):
"""Lambda can keep track of function parameters.
No local parameters. If we put the lambda directly in the below
statement only the last light will be turned on.
"""
return lambda now: turn_light_on_before_sunset(light_id)
for index, light_id in enumerate(light_ids):
track_point_in_time(hass, turn_on(light_id),
start_point + index * LIGHT_TRANSITION_TIME)
# If the sun is already above horizon schedule the time-based pre-sun set
# event.
if sun.is_on(hass):
schedule_light_on_sun_rise(None, None, None)
schedule_lights_at_sun_set(hass, None, None, None)
def check_light_on_dev_state_change(entity, old_state, new_state):
""" Function to handle tracked device state changes. """
@track_state_change(device_entity_ids, STATE_NOT_HOME, STATE_HOME)
def check_light_on_dev_state_change(hass, entity, old_state, new_state):
"""Handle tracked device state changes."""
# pylint: disable=unused-variable
lights_are_on = group.is_on(hass, light_group)
light_needed = not (lights_are_on or sun.is_on(hass))
# Specific device came home ?
if entity != device_tracker.ENTITY_ID_ALL_DEVICES and \
new_state.state == STATE_HOME:
# These variables are needed for the elif check
now = dt_util.now()
start_point = calc_time_for_light_when_sunset()
# These variables are needed for the elif check
now = dt_util.now()
start_point = calc_time_for_light_when_sunset()
# Do we need lights?
if light_needed:
logger.info("Home coming event for %s. Turning lights on", entity)
light.turn_on(hass, light_ids, profile=light_profile)
# Do we need lights?
if light_needed:
# Are we in the time span were we would turn on the lights
# if someone would be home?
# Check this by seeing if current time is later then the point
# in time when we would start putting the lights on.
elif (start_point and
start_point < now < sun.next_setting(hass)):
logger.info(
"Home coming event for %s. Turning lights on", entity)
# Check for every light if it would be on if someone was home
# when the fading in started and turn it on if so
for index, light_id in enumerate(light_ids):
if now > start_point + index * LIGHT_TRANSITION_TIME:
light.turn_on(hass, light_id)
light.turn_on(hass, light_ids, profile=light_profile)
else:
# If this light didn't happen to be turned on yet so
# will all the following then, break.
break
# Are we in the time span were we would turn on the lights
# if someone would be home?
# Check this by seeing if current time is later then the point
# in time when we would start putting the lights on.
elif (start_point and
start_point < now < sun.next_setting(hass)):
# Check for every light if it would be on if someone was home
# when the fading in started and turn it on if so
for index, light_id in enumerate(light_ids):
if now > start_point + index * LIGHT_TRANSITION_TIME:
light.turn_on(hass, light_id)
else:
# If this light didn't happen to be turned on yet so
# will all the following then, break.
break
# Did all devices leave the house?
elif (entity == device_group and
new_state.state == STATE_NOT_HOME and lights_are_on and
not disable_turn_off):
if not disable_turn_off:
@track_state_change(device_group, STATE_HOME, STATE_NOT_HOME)
def turn_off_lights_when_all_leave(hass, entity, old_state, new_state):
"""Handle device group state change."""
# pylint: disable=unused-variable
if not group.is_on(hass, light_group):
return
logger.info(
"Everyone has left but there are lights on. Turning them off")
light.turn_off(hass, light_ids)
# Track home coming of each device
track_state_change(
hass, device_entity_ids, check_light_on_dev_state_change,
STATE_NOT_HOME, STATE_HOME)
# Track when all devices are gone to shut down lights
track_state_change(
hass, device_group, check_light_on_dev_state_change,
STATE_HOME, STATE_NOT_HOME)
return True

View File

@@ -1,33 +1,33 @@
"""
homeassistant.components.device_tracker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to keep track of devices.
Provide functionality to keep track of devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/device_tracker/
"""
# pylint: disable=too-many-instance-attributes, too-many-arguments
# pylint: disable=too-many-locals
import csv
from datetime import timedelta
import logging
import os
import threading
from homeassistant.bootstrap import prepare_setup_platform
from homeassistant.components import discovery, group, zone
from homeassistant.components import group, zone
from homeassistant.components.discovery import SERVICE_NETGEAR
from homeassistant.config import load_yaml_config_file
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_per_platform
from homeassistant.helpers import config_per_platform, discovery
from homeassistant.helpers.entity import Entity
import homeassistant.helpers.config_validation as cv
import homeassistant.util as util
import homeassistant.util.dt as dt_util
from homeassistant.helpers.event import track_utc_time_change
from homeassistant.const import (
ATTR_ENTITY_PICTURE, ATTR_GPS_ACCURACY, ATTR_LATITUDE, ATTR_LONGITUDE,
ATTR_GPS_ACCURACY, ATTR_LATITUDE, ATTR_LONGITUDE,
DEVICE_DEFAULT_NAME, STATE_HOME, STATE_NOT_HOME)
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
DOMAIN = "device_tracker"
DEPENDENCIES = ['zone']
@@ -36,7 +36,6 @@ ENTITY_ID_ALL_DEVICES = group.ENTITY_ID_FORMAT.format('all_devices')
ENTITY_ID_FORMAT = DOMAIN + '.{}'
CSV_DEVICES = "known_devices.csv"
YAML_DEVICES = 'known_devices.yaml'
CONF_TRACK_NEW = "track_new_devices"
@@ -64,7 +63,7 @@ ATTR_GPS = 'gps'
ATTR_BATTERY = 'battery'
DISCOVERY_PLATFORMS = {
discovery.SERVICE_NETGEAR: 'netgear',
SERVICE_NETGEAR: 'netgear',
}
_LOGGER = logging.getLogger(__name__)
@@ -72,7 +71,7 @@ _LOGGER = logging.getLogger(__name__)
def is_on(hass, entity_id=None):
""" Returns if any or specified device is home. """
"""Return the state if any or a specified device is home."""
entity = entity_id or ENTITY_ID_ALL_DEVICES
return hass.states.is_state(entity, STATE_HOME)
@@ -80,27 +79,28 @@ def is_on(hass, entity_id=None):
def see(hass, mac=None, dev_id=None, host_name=None, location_name=None,
gps=None, gps_accuracy=None, battery=None):
""" Call service to notify you see device. """
"""Call service to notify you see device."""
data = {key: value for key, value in
((ATTR_MAC, mac),
(ATTR_DEV_ID, dev_id),
(ATTR_HOST_NAME, host_name),
(ATTR_LOCATION_NAME, location_name),
(ATTR_GPS, gps)) if value is not None}
(ATTR_GPS, gps),
(ATTR_GPS_ACCURACY, gps_accuracy),
(ATTR_BATTERY, battery)) if value is not None}
hass.services.call(DOMAIN, SERVICE_SEE, data)
def setup(hass, config):
""" Setup device tracker """
"""Setup device tracker."""
yaml_path = hass.config.path(YAML_DEVICES)
csv_path = hass.config.path(CSV_DEVICES)
if os.path.isfile(csv_path) and not os.path.isfile(yaml_path) and \
convert_csv_config(csv_path, yaml_path):
os.remove(csv_path)
conf = config.get(DOMAIN, {})
# Config can be an empty list. In that case, substitute a dict
if isinstance(conf, list):
conf = conf[0]
conf = conf[0] if len(conf) > 0 else {}
consider_home = timedelta(
seconds=util.convert(conf.get(CONF_CONSIDER_HOME), int,
DEFAULT_CONSIDER_HOME))
@@ -114,7 +114,7 @@ def setup(hass, config):
devices)
def setup_platform(p_type, p_config, disc_info=None):
""" Setup a device tracker platform. """
"""Setup a device tracker platform."""
platform = prepare_setup_platform(hass, config, DOMAIN, p_type)
if platform is None:
return
@@ -135,26 +135,25 @@ def setup(hass, config):
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error setting up platform %s', p_type)
for p_type, p_config in \
config_per_platform(config, DOMAIN, _LOGGER):
for p_type, p_config in config_per_platform(config, DOMAIN):
setup_platform(p_type, p_config)
def device_tracker_discovered(service, info):
""" Called when a device tracker platform is discovered. """
"""Called when a device tracker platform is discovered."""
setup_platform(DISCOVERY_PLATFORMS[service], {}, info)
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(),
device_tracker_discovered)
def update_stale(now):
""" Clean up stale devices. """
"""Clean up stale devices."""
tracker.update_stale(now)
track_utc_time_change(hass, update_stale, second=range(0, 60, 5))
tracker.setup_group()
def see_service(call):
""" Service to see a device. """
"""Service to see a device."""
args = {key: value for key, value in call.data.items() if key in
(ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME,
ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY)}
@@ -169,8 +168,10 @@ def setup(hass, config):
class DeviceTracker(object):
""" Track devices """
"""Representation of a device tracker."""
def __init__(self, hass, consider_home, track_new, home_range, devices):
"""Initialize a device tracker."""
self.hass = hass
self.devices = {dev.dev_id: dev for dev in devices}
self.mac_to_dev = {dev.mac: dev for dev in devices if dev.mac}
@@ -187,7 +188,7 @@ class DeviceTracker(object):
def see(self, mac=None, dev_id=None, host_name=None, location_name=None,
gps=None, gps_accuracy=None, battery=None):
""" Notify device tracker that you see a device. """
"""Notify the device tracker that you see a device."""
with self.lock:
if mac is None and dev_id is None:
raise HomeAssistantError('Neither mac or device id passed in')
@@ -197,7 +198,7 @@ class DeviceTracker(object):
if not device:
dev_id = util.slugify(host_name or '') or util.slugify(mac)
else:
dev_id = str(dev_id).lower()
dev_id = cv.slug(str(dev_id).lower())
device = self.devices.get(dev_id)
if device:
@@ -208,6 +209,7 @@ class DeviceTracker(object):
return
# If no device can be found, create it
dev_id = util.ensure_unique_string(dev_id, self.devices.keys())
device = Device(
self.hass, self.consider_home, self.home_range, self.track_new,
dev_id, mac, (host_name or dev_id).replace('_', ' '))
@@ -226,14 +228,14 @@ class DeviceTracker(object):
update_config(self.hass.config.path(YAML_DEVICES), dev_id, device)
def setup_group(self):
""" Initializes group for all tracked devices. """
"""Initialize group for all tracked devices."""
entity_ids = (dev.entity_id for dev in self.devices.values()
if dev.track)
self.group = group.setup_group(
self.group = group.Group(
self.hass, GROUP_NAME_ALL_DEVICES, entity_ids, False)
def update_stale(self, now):
""" Update stale devices. """
"""Update stale devices."""
with self.lock:
for device in self.devices.values():
if (device.track and device.last_update_home and
@@ -242,7 +244,7 @@ class DeviceTracker(object):
class Device(Entity):
""" Tracked device. """
"""Represent a tracked device."""
host_name = None
location_name = None
@@ -251,12 +253,13 @@ class Device(Entity):
last_seen = None
battery = None
# Track if the last update of this device was HOME
# Track if the last update of this device was HOME.
last_update_home = False
_state = STATE_NOT_HOME
def __init__(self, hass, consider_home, home_range, track, dev_id, mac,
name=None, picture=None, away_hide=False):
"""Initialize a device."""
self.hass = hass
self.entity_id = ENTITY_ID_FORMAT.format(dev_id)
@@ -282,28 +285,30 @@ class Device(Entity):
@property
def gps_home(self):
""" Return if device is within range of home. """
"""Return if device is within range of home."""
distance = max(
0, self.hass.config.distance(*self.gps) - self.gps_accuracy)
return self.gps is not None and distance <= self.home_range
@property
def name(self):
""" Returns the name of the entity. """
"""Return the name of the entity."""
return self.config_name or self.host_name or DEVICE_DEFAULT_NAME
@property
def state(self):
""" State of the device. """
"""Return the state of the device."""
return self._state
@property
def state_attributes(self):
""" Device state attributes. """
attr = {}
def entity_picture(self):
"""Return the picture of the device."""
return self.config_picture
if self.config_picture:
attr[ATTR_ENTITY_PICTURE] = self.config_picture
@property
def state_attributes(self):
"""Return the device state attributes."""
attr = {}
if self.gps:
attr[ATTR_LATITUDE] = self.gps[0]
@@ -317,12 +322,12 @@ class Device(Entity):
@property
def hidden(self):
""" If device should be hidden. """
"""If device should be hidden."""
return self.away_hide and self.state != STATE_HOME
def seen(self, host_name=None, location_name=None, gps=None,
gps_accuracy=0, battery=None):
""" Mark the device as seen. """
"""Mark the device as seen."""
self.last_seen = dt_util.utcnow()
self.host_name = host_name
self.location_name = location_name
@@ -340,12 +345,12 @@ class Device(Entity):
self.update()
def stale(self, now=None):
""" Return if device state is stale. """
"""Return if device state is stale."""
return self.last_seen and \
(now or dt_util.utcnow()) - self.last_seen > self.consider_home
def update(self):
""" Update state of entity. """
"""Update state of entity."""
if not self.last_seen:
return
elif self.location_name:
@@ -368,35 +373,24 @@ class Device(Entity):
self.last_update_home = True
def convert_csv_config(csv_path, yaml_path):
""" Convert CSV config file format to YAML. """
used_ids = set()
with open(csv_path) as inp:
for row in csv.DictReader(inp):
dev_id = util.ensure_unique_string(
(util.slugify(row['name']) or DEVICE_DEFAULT_NAME).lower(),
used_ids)
used_ids.add(dev_id)
device = Device(None, None, None, row['track'] == '1', dev_id,
row['device'], row['name'], row['picture'])
update_config(yaml_path, dev_id, device)
return True
def load_config(path, hass, consider_home, home_range):
""" Load devices from YAML config file. """
"""Load devices from YAML configuration file."""
if not os.path.isfile(path):
return []
return [
Device(hass, consider_home, home_range, device.get('track', False),
str(dev_id).lower(), str(device.get('mac')).upper(),
device.get('name'), device.get('picture'),
device.get(CONF_AWAY_HIDE, DEFAULT_AWAY_HIDE))
for dev_id, device in load_yaml_config_file(path).items()]
try:
return [
Device(hass, consider_home, home_range, device.get('track', False),
str(dev_id).lower(), str(device.get('mac')).upper(),
device.get('name'), device.get('picture'),
device.get(CONF_AWAY_HIDE, DEFAULT_AWAY_HIDE))
for dev_id, device in load_yaml_config_file(path).items()]
except HomeAssistantError:
# When YAML file could not be loaded/did not contain a dict
return []
def setup_scanner_platform(hass, config, scanner, see_device):
""" Helper method to connect scanner-based platform to device tracker. """
"""Helper method to connect scanner-based platform to device tracker."""
interval = util.convert(config.get(CONF_SCAN_INTERVAL), int,
DEFAULT_SCAN_INTERVAL)
@@ -404,7 +398,7 @@ def setup_scanner_platform(hass, config, scanner, see_device):
seen = set()
def device_tracker_scan(now):
""" Called when interval matches. """
"""Called when interval matches."""
for mac in scanner.scan_devices():
if mac in seen:
host_name = None
@@ -420,7 +414,7 @@ def setup_scanner_platform(hass, config, scanner, see_device):
def update_config(path, dev_id, device):
""" Add device to YAML config file. """
"""Add device to YAML configuration file."""
with open(path, 'a') as out:
out.write('\n')
out.write('{}:\n'.format(device.dev_id))

View File

@@ -1,26 +1,23 @@
"""
homeassistant.components.device_tracker.actiontec
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning an Actiontec MI424WR
(Verizon FIOS) router for device presence.
Support for Actiontec MI424WR (Verizon FIOS) routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.actiontec/
"""
import logging
from datetime import timedelta
from collections import namedtuple
import re
import threading
import telnetlib
import threading
from collections import namedtuple
from datetime import timedelta
import homeassistant.util.dt as dt_util
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
@@ -34,7 +31,7 @@ _LEASES_REGEX = re.compile(
# pylint: disable=unused-argument
def get_scanner(hass, config):
""" Validates config and returns an Actiontec scanner. """
"""Validate the configuration and return an Actiontec scanner."""
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER):
@@ -46,12 +43,10 @@ Device = namedtuple("Device", ["mac", "ip", "last_update"])
class ActiontecDeviceScanner(object):
"""
This class queries a an actiontec router for connected devices.
Adapted from DD-WRT scanner.
"""
"""This class queries a an actiontec router for connected devices."""
def __init__(self, config):
"""Initialize the scanner."""
self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME]
self.password = config[CONF_PASSWORD]
@@ -62,15 +57,12 @@ class ActiontecDeviceScanner(object):
_LOGGER.info("actiontec scanner initialized")
def scan_devices(self):
"""
Scans for new devices and return a list containing found device ids.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return [client.mac for client in self.last_results]
def get_device_name(self, device):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
if not self.last_results:
return None
for client in self.last_results:
@@ -80,9 +72,9 @@ class ActiontecDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Ensures the information from the Actiontec MI424WR router is up
to date. Returns boolean if scanning successful.
"""Ensure the information from the router is up to date.
Return boolean if scanning successful.
"""
_LOGGER.info("Scanning")
if not self.success_init:
@@ -100,7 +92,7 @@ class ActiontecDeviceScanner(object):
return True
def get_actiontec_data(self):
""" Retrieve data from Actiontec MI424WR and return parsed result. """
"""Retrieve data from Actiontec MI424WR and return parsed result."""
try:
telnet = telnetlib.Telnet(self.host)
telnet.read_until(b'Username: ')

View File

@@ -1,26 +1,23 @@
"""
homeassistant.components.device_tracker.aruba
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a Aruba Access Point for device
presence.
Support for Aruba Access Points.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.aruba/
"""
import logging
from datetime import timedelta
import re
import threading
import telnetlib
from datetime import timedelta
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
REQUIREMENTS = ['pexpect==4.0.1']
_LOGGER = logging.getLogger(__name__)
_DEVICES_REGEX = re.compile(
@@ -31,7 +28,7 @@ _DEVICES_REGEX = re.compile(
# pylint: disable=unused-argument
def get_scanner(hass, config):
""" Validates config and returns a Aruba scanner. """
"""Validate the configuration and return a Aruba scanner."""
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER):
@@ -43,8 +40,10 @@ def get_scanner(hass, config):
class ArubaDeviceScanner(object):
""" This class queries a Aruba Acces Point for connected devices. """
"""This class queries a Aruba Access Point for connected devices."""
def __init__(self, config):
"""Initialize the scanner."""
self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME]
self.password = config[CONF_PASSWORD]
@@ -53,20 +52,17 @@ class ArubaDeviceScanner(object):
self.last_results = {}
# Test the router is accessible
# Test the router is accessible.
data = self.get_aruba_data()
self.success_init = data is not None
def scan_devices(self):
"""
Scans for new devices and return a list containing found device IDs.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return [client['mac'] for client in self.last_results]
def get_device_name(self, device):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
if not self.last_results:
return None
for client in self.last_results:
@@ -76,9 +72,9 @@ class ArubaDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Ensures the information from the Aruba Access Point is up to date.
Returns boolean if scanning successful.
"""Ensure the information from the Aruba Access Point is up to date.
Return boolean if scanning successful.
"""
if not self.success_init:
return False
@@ -92,24 +88,39 @@ class ArubaDeviceScanner(object):
return True
def get_aruba_data(self):
""" Retrieve data from Aruba Access Point and return parsed result. """
try:
telnet = telnetlib.Telnet(self.host)
telnet.read_until(b'User: ')
telnet.write((self.username + '\r\n').encode('ascii'))
telnet.read_until(b'Password: ')
telnet.write((self.password + '\r\n').encode('ascii'))
telnet.read_until(b'#')
telnet.write(('show clients\r\n').encode('ascii'))
devices_result = telnet.read_until(b'#').split(b'\r\n')
telnet.write('exit\r\n'.encode('ascii'))
except EOFError:
_LOGGER.exception("Unexpected response from router")
"""Retrieve data from Aruba Access Point and return parsed result."""
import pexpect
connect = "ssh {}@{}"
ssh = pexpect.spawn(connect.format(self.username, self.host))
query = ssh.expect(['password:', pexpect.TIMEOUT, pexpect.EOF,
'continue connecting (yes/no)?',
'Host key verification failed.',
'Connection refused',
'Connection timed out'], timeout=120)
if query == 1:
_LOGGER.error("Timeout")
return
except ConnectionRefusedError:
_LOGGER.exception("Connection refused by router," +
" is telnet enabled?")
elif query == 2:
_LOGGER.error("Unexpected response from router")
return
elif query == 3:
ssh.sendline('yes')
ssh.expect('password:')
elif query == 4:
_LOGGER.error("Host key Changed")
return
elif query == 5:
_LOGGER.error("Connection refused by server")
return
elif query == 6:
_LOGGER.error("Connection timed out")
return
ssh.sendline(self.password)
ssh.expect('#')
ssh.sendline('show clients')
ssh.expect('#')
devices_result = ssh.before.split(b'\r\n')
ssh.sendline('exit')
devices = {}
for device in devices_result:
@@ -119,5 +130,5 @@ class ArubaDeviceScanner(object):
'ip': match.group('ip'),
'mac': match.group('mac').upper(),
'name': match.group('name')
}
}
return devices

View File

@@ -1,34 +1,51 @@
"""
homeassistant.components.device_tracker.asuswrt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a ASUSWRT router for device
presence.
Support for ASUSWRT routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.asuswrt/
"""
import logging
from datetime import timedelta
import re
import threading
import socket
import telnetlib
import threading
from collections import namedtuple
from datetime import timedelta
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pexpect==4.0.1']
_LEASES_CMD = 'cat /var/lib/misc/dnsmasq.leases'
_LEASES_REGEX = re.compile(
r'\w+\s' +
r'(?P<mac>(([0-9a-f]{2}[:-]){5}([0-9a-f]{2})))\s' +
r'(?P<ip>([0-9]{1,3}[\.]){3}[0-9]{1,3})\s' +
r'(?P<host>([^\s]+))')
# command to get both 5GHz and 2.4GHz clients
_WL_CMD = '{ wl -i eth2 assoclist & wl -i eth1 assoclist ; }'
_WL_REGEX = re.compile(
r'\w+\s' +
r'(?P<mac>(([0-9A-F]{2}[:-]){5}([0-9A-F]{2})))')
_ARP_CMD = 'arp -n'
_ARP_REGEX = re.compile(
r'.+\s' +
r'\((?P<ip>([0-9]{1,3}[\.]){3}[0-9]{1,3})\)\s' +
r'.+\s' +
r'(?P<mac>(([0-9a-f]{2}[:-]){5}([0-9a-f]{2})))' +
r'\s' +
r'.*')
_IP_NEIGH_CMD = 'ip neigh'
_IP_NEIGH_REGEX = re.compile(
r'(?P<ip>([0-9]{1,3}[\.]){3}[0-9]{1,3})\s' +
r'\w+\s' +
@@ -39,46 +56,54 @@ _IP_NEIGH_REGEX = re.compile(
# pylint: disable=unused-argument
def get_scanner(hass, config):
""" Validates config and returns an ASUS-WRT scanner. """
"""Validate the configuration and return an ASUS-WRT scanner."""
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
{DOMAIN: [CONF_HOST, CONF_USERNAME]},
_LOGGER):
return None
elif CONF_PASSWORD not in config[DOMAIN] and \
'ssh_key' not in config[DOMAIN] and \
'pub_key' not in config[DOMAIN]:
_LOGGER.error('Either a private key or password must be provided')
return None
scanner = AsusWrtDeviceScanner(config[DOMAIN])
return scanner if scanner.success_init else None
AsusWrtResult = namedtuple('AsusWrtResult', 'neighbors leases arp')
class AsusWrtDeviceScanner(object):
"""
This class queries a router running ASUSWRT firmware
for connected devices. Adapted from DD-WRT scanner.
"""
"""This class queries a router running ASUSWRT firmware."""
# pylint: disable=too-many-instance-attributes, too-many-branches
# Eighth attribute needed for mode (AP mode vs router mode)
def __init__(self, config):
"""Initialize the scanner."""
self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME]
self.password = config[CONF_PASSWORD]
self.username = str(config[CONF_USERNAME])
self.password = str(config.get(CONF_PASSWORD, ''))
self.ssh_key = str(config.get('ssh_key', config.get('pub_key', '')))
self.protocol = config.get('protocol')
self.mode = config.get('mode')
self.lock = threading.Lock()
self.last_results = {}
# Test the router is accessible
# Test the router is accessible.
data = self.get_asuswrt_data()
self.success_init = data is not None
def scan_devices(self):
"""
Scans for new devices and return a list containing found device IDs.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return [client['mac'] for client in self.last_results]
def get_device_name(self, device):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
if not self.last_results:
return None
for client in self.last_results:
@@ -88,15 +113,15 @@ class AsusWrtDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Ensures the information from the ASUSWRT router is up to date.
Returns boolean if scanning successful.
"""Ensure the information from the ASUSWRT router is up to date.
Return boolean if scanning successful.
"""
if not self.success_init:
return False
with self.lock:
_LOGGER.info("Checking ARP")
_LOGGER.info('Checking ARP')
data = self.get_asuswrt_data()
if not data:
return False
@@ -108,8 +133,45 @@ class AsusWrtDeviceScanner(object):
self.last_results = active_clients
return True
def get_asuswrt_data(self):
""" Retrieve data from ASUSWRT and return parsed result. """
def ssh_connection(self):
"""Retrieve data from ASUSWRT via the ssh protocol."""
from pexpect import pxssh, exceptions
try:
ssh = pxssh.pxssh()
if self.ssh_key:
ssh.login(self.host, self.username, ssh_key=self.ssh_key)
elif self.password:
ssh.login(self.host, self.username, self.password)
else:
_LOGGER.error('No password or private key specified')
return None
ssh.sendline(_IP_NEIGH_CMD)
ssh.prompt()
neighbors = ssh.before.split(b'\n')[1:-1]
if self.mode == 'ap':
ssh.sendline(_ARP_CMD)
ssh.prompt()
arp_result = ssh.before.split(b'\n')[1:-1]
ssh.sendline(_WL_CMD)
ssh.prompt()
leases_result = ssh.before.split(b'\n')[1:-1]
else:
arp_result = ['']
ssh.sendline(_LEASES_CMD)
ssh.prompt()
leases_result = ssh.before.split(b'\n')[1:-1]
ssh.logout()
return AsusWrtResult(neighbors, leases_result, arp_result)
except pxssh.ExceptionPxssh as exc:
_LOGGER.error('Unexpected response from router: %s', exc)
return None
except exceptions.EOF:
_LOGGER.error('Connection refused or no route to host')
return None
def telnet_connection(self):
"""Retrieve data from ASUSWRT via the telnet protocol."""
try:
telnet = telnetlib.Telnet(self.host)
telnet.read_until(b'login: ')
@@ -117,45 +179,104 @@ class AsusWrtDeviceScanner(object):
telnet.read_until(b'Password: ')
telnet.write((self.password + '\n').encode('ascii'))
prompt_string = telnet.read_until(b'#').split(b'\n')[-1]
telnet.write('ip neigh\n'.encode('ascii'))
telnet.write('{}\n'.format(_IP_NEIGH_CMD).encode('ascii'))
neighbors = telnet.read_until(prompt_string).split(b'\n')[1:-1]
telnet.write('cat /var/lib/misc/dnsmasq.leases\n'.encode('ascii'))
leases_result = telnet.read_until(prompt_string).split(b'\n')[1:-1]
if self.mode == 'ap':
telnet.write('{}\n'.format(_ARP_CMD).encode('ascii'))
arp_result = (telnet.read_until(prompt_string).
split(b'\n')[1:-1])
telnet.write('{}\n'.format(_WL_CMD).encode('ascii'))
leases_result = (telnet.read_until(prompt_string).
split(b'\n')[1:-1])
else:
arp_result = ['']
telnet.write('{}\n'.format(_LEASES_CMD).encode('ascii'))
leases_result = (telnet.read_until(prompt_string).
split(b'\n')[1:-1])
telnet.write('exit\n'.encode('ascii'))
return AsusWrtResult(neighbors, leases_result, arp_result)
except EOFError:
_LOGGER.exception("Unexpected response from router")
return
_LOGGER.error('Unexpected response from router')
return None
except ConnectionRefusedError:
_LOGGER.exception("Connection refused by router," +
" is telnet enabled?")
return
_LOGGER.error('Connection refused by router, is telnet enabled?')
return None
except socket.gaierror as exc:
_LOGGER.error('Socket exception: %s', exc)
return None
except OSError as exc:
_LOGGER.error('OSError: %s', exc)
return None
def get_asuswrt_data(self):
"""Retrieve data from ASUSWRT and return parsed result."""
if self.protocol == 'ssh':
result = self.ssh_connection()
elif self.protocol == 'telnet':
result = self.telnet_connection()
else:
# autodetect protocol
result = self.ssh_connection()
if result:
self.protocol = 'ssh'
else:
result = self.telnet_connection()
if result:
self.protocol = 'telnet'
if not result:
return {}
devices = {}
for lease in leases_result:
match = _LEASES_REGEX.search(lease.decode('utf-8'))
if self.mode == 'ap':
for lease in result.leases:
match = _WL_REGEX.search(lease.decode('utf-8'))
if not match:
_LOGGER.warning("Could not parse lease row: %s", lease)
continue
if not match:
_LOGGER.warning('Could not parse wl row: %s', lease)
continue
# For leases where the client doesn't set a hostname, ensure
# it is blank and not '*', which breaks the entity_id down
# the line
host = match.group('host')
if host == '*':
host = ''
devices[match.group('ip')] = {
'host': host,
'status': '',
'ip': match.group('ip'),
'mac': match.group('mac').upper(),
}
# match mac addresses to IP addresses in ARP table
for arp in result.arp:
if match.group('mac').lower() in arp.decode('utf-8'):
arp_match = _ARP_REGEX.search(arp.decode('utf-8'))
if not arp_match:
_LOGGER.warning('Could not parse arp row: %s', arp)
continue
for neighbor in neighbors:
devices[arp_match.group('ip')] = {
'host': host,
'status': '',
'ip': arp_match.group('ip'),
'mac': match.group('mac').upper(),
}
else:
for lease in result.leases:
match = _LEASES_REGEX.search(lease.decode('utf-8'))
if not match:
_LOGGER.warning('Could not parse lease row: %s', lease)
continue
# For leases where the client doesn't set a hostname, ensure it
# is blank and not '*', which breaks entity_id down the line.
host = match.group('host')
if host == '*':
host = ''
devices[match.group('ip')] = {
'host': host,
'status': '',
'ip': match.group('ip'),
'mac': match.group('mac').upper(),
}
for neighbor in result.neighbors:
match = _IP_NEIGH_REGEX.search(neighbor.decode('utf-8'))
if not match:
_LOGGER.warning("Could not parse neighbor row: %s", neighbor)
_LOGGER.warning('Could not parse neighbor row: %s', neighbor)
continue
if match.group('ip') in devices:
devices[match.group('ip')]['status'] = match.group('status')

View File

@@ -0,0 +1,91 @@
"""Tracking for bluetooth devices."""
import logging
from datetime import timedelta
from homeassistant.helpers.event import track_point_in_utc_time
from homeassistant.components.device_tracker import (
YAML_DEVICES,
CONF_TRACK_NEW,
CONF_SCAN_INTERVAL,
DEFAULT_SCAN_INTERVAL,
load_config,
)
import homeassistant.util as util
import homeassistant.util.dt as dt_util
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pybluez==0.22']
BT_PREFIX = 'BT_'
def setup_scanner(hass, config, see):
"""Setup the Bluetooth Scanner."""
# pylint: disable=import-error
import bluetooth
def see_device(device):
"""Mark a device as seen."""
see(mac=BT_PREFIX + device[0], host_name=device[1])
def discover_devices():
"""Discover bluetooth devices."""
result = bluetooth.discover_devices(duration=8,
lookup_names=True,
flush_cache=True,
lookup_class=False)
_LOGGER.debug("Bluetooth devices discovered = " + str(len(result)))
return result
yaml_path = hass.config.path(YAML_DEVICES)
devs_to_track = []
devs_donot_track = []
# Load all known devices.
# We just need the devices so set consider_home and home range
# to 0
for device in load_config(yaml_path, hass, 0, 0):
# check if device is a valid bluetooth device
if device.mac and device.mac[:3].upper() == BT_PREFIX:
if device.track:
devs_to_track.append(device.mac[3:])
else:
devs_donot_track.append(device.mac[3:])
# if track new devices is true discover new devices
# on startup.
track_new = util.convert(config.get(CONF_TRACK_NEW), bool,
len(devs_to_track) == 0)
if track_new:
for dev in discover_devices():
if dev[0] not in devs_to_track and \
dev[0] not in devs_donot_track:
devs_to_track.append(dev[0])
see_device(dev)
if not devs_to_track:
_LOGGER.warning("No bluetooth devices to track!")
return False
interval = util.convert(config.get(CONF_SCAN_INTERVAL), int,
DEFAULT_SCAN_INTERVAL)
def update_bluetooth(now):
"""Lookup bluetooth device and update status."""
try:
for mac in devs_to_track:
_LOGGER.debug("Scanning " + mac)
result = bluetooth.lookup_name(mac, timeout=5)
if not result:
# Could not lookup device name
continue
see_device((mac, result))
except bluetooth.BluetoothError:
_LOGGER.exception('Error looking up bluetooth device!')
track_point_in_utc_time(hass, update_bluetooth,
now + timedelta(seconds=interval))
update_bluetooth(dt_util.utcnow())
return True

View File

@@ -0,0 +1,141 @@
"""
Support for BT Home Hub 5.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.bt_home_hub_5/
"""
import logging
import re
import threading
from datetime import timedelta
import xml.etree.ElementTree as ET
import json
from urllib.parse import unquote
import requests
from homeassistant.helpers import validate_config
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST
from homeassistant.util import Throttle
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
_LOGGER = logging.getLogger(__name__)
_MAC_REGEX = re.compile(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})')
# pylint: disable=unused-argument
def get_scanner(hass, config):
"""Return a BT Home Hub 5 scanner if successful."""
if not validate_config(config,
{DOMAIN: [CONF_HOST]},
_LOGGER):
return None
scanner = BTHomeHub5DeviceScanner(config[DOMAIN])
return scanner if scanner.success_init else None
class BTHomeHub5DeviceScanner(object):
"""This class queries a BT Home Hub 5."""
def __init__(self, config):
"""Initialise the scanner."""
_LOGGER.info("Initialising BT Home Hub 5")
self.host = config.get(CONF_HOST, '192.168.1.254')
self.lock = threading.Lock()
self.last_results = {}
self.url = 'http://{}/nonAuth/home_status.xml'.format(self.host)
# Test the router is accessible
data = _get_homehub_data(self.url)
self.success_init = data is not None
def scan_devices(self):
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return (device for device in self.last_results)
def get_device_name(self, device):
"""Return the name of the given device or None if we don't know."""
with self.lock:
# If not initialised and not already scanned and not found.
if device not in self.last_results:
self._update_info()
if not self.last_results:
return None
return self.last_results.get(device)
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""Ensure the information from the BT Home Hub 5 is up to date.
Return boolean if scanning successful.
"""
if not self.success_init:
return False
with self.lock:
_LOGGER.info("Scanning")
data = _get_homehub_data(self.url)
if not data:
_LOGGER.warning('Error scanning devices')
return False
self.last_results = data
return True
def _get_homehub_data(url):
"""Retrieve data from BT Home Hub 5 and return parsed result."""
try:
response = requests.get(url, timeout=5)
except requests.exceptions.Timeout:
_LOGGER.exception("Connection to the router timed out")
return
if response.status_code == 200:
return _parse_homehub_response(response.text)
else:
_LOGGER.error("Invalid response from Home Hub: %s", response)
def _parse_homehub_response(data_str):
"""Parse the BT Home Hub 5 data format."""
root = ET.fromstring(data_str)
dirty_json = root.find('known_device_list').get('value')
# Normalise the JavaScript data to JSON.
clean_json = unquote(dirty_json.replace('\'', '\"')
.replace('{', '{\"')
.replace(':\"', '\":\"')
.replace('\",', '\",\"'))
known_devices = [x for x in json.loads(clean_json) if x]
devices = {}
for device in known_devices:
name = device.get('name')
mac = device.get('mac')
if _MAC_REGEX.match(mac) or ',' in mac:
for mac_addr in mac.split(','):
if _MAC_REGEX.match(mac_addr):
devices[mac_addr] = name
else:
devices[mac] = name
return devices

View File

@@ -1,24 +1,22 @@
"""
homeassistant.components.device_tracker.ddwrt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a DD-WRT router for device
presence.
Support for DD-WRT routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.ddwrt/
"""
import logging
from datetime import timedelta
import re
import threading
from datetime import timedelta
import requests
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
@@ -29,7 +27,7 @@ _MAC_REGEX = re.compile(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})')
# pylint: disable=unused-argument
def get_scanner(hass, config):
""" Validates config and returns a DD-WRT scanner. """
"""Validate the configuration and return a DD-WRT scanner."""
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER):
@@ -42,12 +40,10 @@ def get_scanner(hass, config):
# pylint: disable=too-many-instance-attributes
class DdWrtDeviceScanner(object):
"""
This class queries a wireless router running DD-WRT firmware
for connected devices. Adapted from Tomato scanner.
"""
"""This class queries a wireless router running DD-WRT firmware."""
def __init__(self, config):
"""Initialize the scanner."""
self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME]
self.password = config[CONF_PASSWORD]
@@ -64,19 +60,15 @@ class DdWrtDeviceScanner(object):
self.success_init = data is not None
def scan_devices(self):
"""
Scans for new devices and return a list containing found device ids.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return self.last_results
def get_device_name(self, device):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
with self.lock:
# if not initialised and not already scanned and not found
# If not initialised and not already scanned and not found.
if device not in self.mac2name:
url = 'http://{}/Status_Lan.live.asp'.format(self.host)
data = self.get_ddwrt_data(url)
@@ -89,15 +81,15 @@ class DdWrtDeviceScanner(object):
if not dhcp_leases:
return None
# remove leading and trailing single quotes
# Remove leading and trailing single quotes.
cleaned_str = dhcp_leases.strip().strip('"')
elements = cleaned_str.split('","')
num_clients = int(len(elements)/5)
self.mac2name = {}
for idx in range(0, num_clients):
# this is stupid but the data is a single array
# This is stupid but the data is a single array
# every 5 elements represents one hosts, the MAC
# is the third element and the name is the first
# is the third element and the name is the first.
mac_index = (idx * 5) + 2
if mac_index < len(elements):
mac = elements[mac_index]
@@ -107,9 +99,9 @@ class DdWrtDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Ensures the information from the DD-WRT router is up to date.
Returns boolean if scanning successful.
"""Ensure the information from the DD-WRT router is up to date.
Return boolean if scanning successful.
"""
if not self.success_init:
return False
@@ -134,7 +126,7 @@ class DdWrtDeviceScanner(object):
# regex's out values so I guess I have to do the same,
# LAME!!!
# remove leading and trailing single quotes
# Remove leading and trailing single quotes.
clean_str = active_clients.strip().strip("'")
elements = clean_str.split("','")
@@ -144,7 +136,7 @@ class DdWrtDeviceScanner(object):
return True
def get_ddwrt_data(self, url):
""" Retrieve data from DD-WRT and return parsed result. """
"""Retrieve data from DD-WRT and return parsed result."""
try:
response = requests.get(
url,
@@ -166,7 +158,7 @@ class DdWrtDeviceScanner(object):
def _parse_ddwrt_response(data_str):
""" Parse the DD-WRT data format. """
"""Parse the DD-WRT data format."""
return {
key: val for key, val in _DDWRT_DATA_REGEX
.findall(data_str)}

View File

@@ -1,25 +1,17 @@
"""
homeassistant.components.device_tracker.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo platform for the device tracker.
device_tracker:
platform: demo
"""
"""Demo platform for the device tracker."""
import random
from homeassistant.components.device_tracker import DOMAIN
def setup_scanner(hass, config, see):
""" Set up a demo tracker. """
"""Setup the demo tracker."""
def offset():
""" Return random offset. """
"""Return random offset."""
return (random.randrange(500, 2000)) / 2e5 * random.choice((-1, 1))
def random_see(dev_id, name):
""" Randomize a sighting. """
"""Randomize a sighting."""
see(
dev_id=dev_id,
host_name=name,
@@ -30,7 +22,7 @@ def setup_scanner(hass, config, see):
)
def observe(call=None):
""" Observe three entities. """
"""Observe three entities."""
random_see('demo_paulus', 'Paulus')
random_see('demo_anne_therese', 'Anne Therese')

View File

@@ -1,8 +1,5 @@
"""
homeassistant.components.device_tracker.fritz
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a FRITZ!Box router for device
presence.
Support for FRITZ!Box routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.fritz/
@@ -10,20 +7,23 @@ https://home-assistant.io/components/device_tracker.fritz/
import logging
from datetime import timedelta
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
REQUIREMENTS = ['https://github.com/deisi/fritzconnection/archive/'
'b5c14515e1c8e2652b06b6316a7f3913df942841.zip'
'#fritzconnection==0.4.6']
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
# noinspection PyUnusedLocal
def get_scanner(hass, config):
""" Validates config and returns FritzBoxScanner. """
"""Validate the configuration and return FritzBoxScanner."""
if not validate_config(config,
{DOMAIN: []},
_LOGGER):
@@ -35,36 +35,18 @@ def get_scanner(hass, config):
# pylint: disable=too-many-instance-attributes
class FritzBoxScanner(object):
"""
This class queries a FRITZ!Box router. It is using the
fritzconnection library for communication with the router.
"""This class queries a FRITZ!Box router."""
The API description can be found under:
https://pypi.python.org/pypi/fritzconnection/0.4.6
This scanner retrieves the list of known hosts and checks their
corresponding states (on, or off).
Due to a bug of the fritzbox api (router side) it is not possible
to track more than 16 hosts.
"""
def __init__(self, config):
"""Initialize the scanner."""
self.last_results = []
self.host = '169.254.1.1' # This IP is valid for all fritzboxes
self.host = '169.254.1.1' # This IP is valid for all FRITZ!Box router.
self.username = 'admin'
self.password = ''
self.success_init = True
# Try to import the fritzconnection library
try:
# noinspection PyPackageRequirements,PyUnresolvedReferences
import fritzconnection as fc
except ImportError:
_LOGGER.exception("""Failed to import Python library
fritzconnection. Please run
<home-assistant>/setup to install it.""")
self.success_init = False
return
# pylint: disable=import-error
import fritzconnection as fc
# Check for user specific configuration
if CONF_HOST in config.keys():
@@ -74,7 +56,7 @@ class FritzBoxScanner(object):
if CONF_PASSWORD in config.keys():
self.password = config[CONF_PASSWORD]
# Establish a connection to the FRITZ!Box
# Establish a connection to the FRITZ!Box.
try:
self.fritz_box = fc.FritzHosts(address=self.host,
user=self.username,
@@ -83,7 +65,7 @@ class FritzBoxScanner(object):
self.fritz_box = None
# At this point it is difficult to tell if a connection is established.
# So just check for null objects ...
# So just check for null objects.
if self.fritz_box is None or not self.fritz_box.modelname:
self.success_init = False
@@ -96,7 +78,7 @@ class FritzBoxScanner(object):
"with IP: %s", self.host)
def scan_devices(self):
""" Scan for new devices and return a list of found device ids. """
"""Scan for new devices and return a list of found device ids."""
self._update_info()
active_hosts = []
for known_host in self.last_results:
@@ -105,7 +87,7 @@ class FritzBoxScanner(object):
return active_hosts
def get_device_name(self, mac):
""" Returns the name of the given device or None if is not known. """
"""Return the name of the given device or None if is not known."""
ret = self.fritz_box.get_specific_host_entry(mac)["NewHostName"]
if ret == {}:
return None
@@ -113,7 +95,7 @@ class FritzBoxScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
""" Retrieves latest information from the FRITZ!Box. """
"""Retrieve latest information from the FRITZ!Box."""
if not self.success_init:
return False

View File

@@ -1,70 +0,0 @@
"""
homeassistant.components.device_tracker.geofancy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Geofancy platform for the device tracker.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.geofancy/
"""
from homeassistant.const import (
HTTP_UNPROCESSABLE_ENTITY, HTTP_INTERNAL_SERVER_ERROR)
DEPENDENCIES = ['http']
_SEE = 0
URL_API_GEOFANCY_ENDPOINT = "/api/geofancy"
def setup_scanner(hass, config, see):
""" Set up an endpoint for the Geofancy app. """
# Use a global variable to keep setup_scanner compact when using a callback
global _SEE
_SEE = see
# POST would be semantically better, but that currently does not work
# since Geofancy sends the data as key1=value1&key2=value2
# in the request body, while Home Assistant expects json there.
hass.http.register_path(
'GET', URL_API_GEOFANCY_ENDPOINT, _handle_get_api_geofancy)
return True
def _handle_get_api_geofancy(handler, path_match, data):
""" Geofancy message received. """
if not isinstance(data, dict):
handler.write_json_message(
"Error while parsing Geofancy message.",
HTTP_INTERNAL_SERVER_ERROR)
return
if 'latitude' not in data or 'longitude' not in data:
handler.write_json_message(
"Location not specified.",
HTTP_UNPROCESSABLE_ENTITY)
return
if 'device' not in data or 'id' not in data:
handler.write_json_message(
"Device id or location id not specified.",
HTTP_UNPROCESSABLE_ENTITY)
return
try:
gps_coords = (float(data['latitude']), float(data['longitude']))
except ValueError:
# If invalid latitude / longitude format
handler.write_json_message(
"Invalid latitude / longitude format.",
HTTP_UNPROCESSABLE_ENTITY)
return
# entity id's in Home Assistant must be alphanumerical
device_uuid = data['device']
device_entity_id = device_uuid.replace('-', '')
_SEE(dev_id=device_entity_id, gps=gps_coords, location_name=data['id'])
handler.write_json_message("Geofancy message processed")

View File

@@ -1,32 +1,30 @@
"""
homeassistant.components.device_tracker.icloud
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning iCloud devices.
Support for iCloud connected devices.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.icloud/
"""
import logging
import re
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers.event import track_utc_time_change
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pyicloud==0.7.2']
REQUIREMENTS = ['pyicloud==0.8.3']
CONF_INTERVAL = 'interval'
DEFAULT_INTERVAL = 8
def setup_scanner(hass, config, see):
""" Set up the iCloud Scanner. """
"""Setup the iCloud Scanner."""
from pyicloud import PyiCloudService
from pyicloud.exceptions import PyiCloudFailedLoginException
from pyicloud.exceptions import PyiCloudNoDevicesException
# Get the username and password from the configuration
# Get the username and password from the configuration.
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
@@ -45,14 +43,14 @@ def setup_scanner(hass, config, see):
return False
def keep_alive(now):
""" Keeps authenticating iCloud connection. """
"""Keep authenticating iCloud connection."""
api.authenticate()
_LOGGER.info("Authenticate against iCloud")
track_utc_time_change(hass, keep_alive, second=0)
def update_icloud(now):
""" Authenticate against iCloud and scan for devices. """
"""Authenticate against iCloud and scan for devices."""
try:
# The session timeouts if we are not using it so we
# have to re-authenticate. This will send an email.

View File

@@ -0,0 +1,96 @@
"""
Support for the Locative platform.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.locative/
"""
import logging
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import HTTP_UNPROCESSABLE_ENTITY, STATE_NOT_HOME
from homeassistant.components.http import HomeAssistantView
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['http']
def setup_scanner(hass, config, see):
"""Setup an endpoint for the Locative application."""
hass.wsgi.register_view(LocativeView(hass, see))
return True
class LocativeView(HomeAssistantView):
"""View to handle locative requests."""
url = "/api/locative"
name = "api:locative"
def __init__(self, hass, see):
"""Initialize Locative url endpoints."""
super().__init__(hass)
self.see = see
def get(self, request):
"""Locative message received as GET."""
return self.post(request)
def post(self, request):
"""Locative message received."""
# pylint: disable=too-many-return-statements
data = request.values
if 'latitude' not in data or 'longitude' not in data:
return ("Latitude and longitude not specified.",
HTTP_UNPROCESSABLE_ENTITY)
if 'device' not in data:
_LOGGER.error("Device id not specified.")
return ("Device id not specified.",
HTTP_UNPROCESSABLE_ENTITY)
if 'id' not in data:
_LOGGER.error("Location id not specified.")
return ("Location id not specified.",
HTTP_UNPROCESSABLE_ENTITY)
if 'trigger' not in data:
_LOGGER.error("Trigger is not specified.")
return ("Trigger is not specified.",
HTTP_UNPROCESSABLE_ENTITY)
device = data['device'].replace('-', '')
location_name = data['id'].lower()
direction = data['trigger']
if direction == 'enter':
self.see(dev_id=device, location_name=location_name)
return "Setting location to {}".format(location_name)
elif direction == 'exit':
current_state = self.hass.states.get(
"{}.{}".format(DOMAIN, device))
if current_state is None or current_state.state == location_name:
self.see(dev_id=device, location_name=STATE_NOT_HOME)
return "Setting location to not home"
else:
# Ignore the message if it is telling us to exit a zone that we
# aren't currently in. This occurs when a zone is entered
# before the previous zone was exited. The enter message will
# be sent first, then the exit message will be sent second.
return 'Ignoring exit from {} (already in {})'.format(
location_name, current_state)
elif direction == 'test':
# In the app, a test message can be sent. Just return something to
# the user to let them know that it works.
return "Received test message."
else:
_LOGGER.error("Received unidentified message from Locative: %s",
direction)
return ("Received unidentified message: {}".format(direction),
HTTP_UNPROCESSABLE_ENTITY)

View File

@@ -1,32 +1,30 @@
"""
homeassistant.components.device_tracker.luci
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a OpenWRT router for device
presence.
Support for OpenWRT (luci) routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.luci/
"""
import logging
import json
from datetime import timedelta
import logging
import re
import threading
from datetime import timedelta
import requests
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
def get_scanner(hass, config):
""" Validates config and returns a Luci scanner. """
"""Validate the configuration and return a Luci scanner."""
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER):
@@ -39,20 +37,13 @@ def get_scanner(hass, config):
# pylint: disable=too-many-instance-attributes
class LuciDeviceScanner(object):
"""
This class queries a wireless router running OpenWrt firmware
for connected devices. Adapted from Tomato scanner.
"""This class queries a wireless router running OpenWrt firmware.
# opkg install luci-mod-rpc
for this to work on the router.
The API is described here:
http://luci.subsignal.org/trac/wiki/Documentation/JsonRpcHowTo
(Currently, we do only wifi iwscan, and no DHCP lease access.)
Adapted from Tomato scanner.
"""
def __init__(self, config):
"""Initialize the scanner."""
host = config[CONF_HOST]
username, password = config[CONF_USERNAME], config[CONF_PASSWORD]
@@ -69,17 +60,12 @@ class LuciDeviceScanner(object):
self.success_init = self.token is not None
def scan_devices(self):
"""
Scans for new devices and return a list containing found device ids.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return self.last_results
def get_device_name(self, device):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
with self.lock:
if self.mac2name is None:
url = 'http://{}/cgi-bin/luci/rpc/uci'.format(self.host)
@@ -99,8 +85,8 @@ class LuciDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Ensures the information from the Luci router is up to date.
"""Ensure the information from the Luci router is up to date.
Returns boolean if scanning successful.
"""
if not self.success_init:
@@ -126,7 +112,7 @@ class LuciDeviceScanner(object):
def _req_json_rpc(url, method, *args, **kwargs):
""" Perform one JSON RPC operation. """
"""Perform one JSON RPC operation."""
data = json.dumps({'method': method, 'params': args})
try:
res = requests.post(url, data=data, timeout=5, **kwargs)
@@ -156,6 +142,6 @@ def _req_json_rpc(url, method, *args, **kwargs):
def _get_token(host, username, password):
""" Get authentication token for the given host+username+password. """
"""Get authentication token for the given host+username+password."""
url = 'http://{}/cgi-bin/luci/rpc/auth'.format(host)
return _req_json_rpc(url, 'login', username, password)

View File

@@ -1,39 +1,37 @@
"""
homeassistant.components.device_tracker.mqtt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MQTT platform for the device tracker.
Support for tracking MQTT enabled devices.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.mqtt/
"""
import logging
from homeassistant import util
import voluptuous as vol
import homeassistant.components.mqtt as mqtt
from homeassistant.components.mqtt import CONF_QOS
import homeassistant.helpers.config_validation as cv
DEPENDENCIES = ['mqtt']
CONF_QOS = 'qos'
CONF_DEVICES = 'devices'
DEFAULT_QOS = 0
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
vol.Required(CONF_DEVICES): {cv.string: mqtt.valid_subscribe_topic},
})
def setup_scanner(hass, config, see):
""" Set up a MQTT tracker. """
devices = config.get(CONF_DEVICES)
qos = util.convert(config.get(CONF_QOS), int, DEFAULT_QOS)
if not isinstance(devices, dict):
_LOGGER.error('Expected %s to be a dict, found %s', CONF_DEVICES,
devices)
return False
"""Setup the MQTT tracker."""
devices = config[CONF_DEVICES]
qos = config[CONF_QOS]
dev_id_lookup = {}
def device_tracker_message_received(topic, payload, qos):
""" MQTT message received. """
"""MQTT message received."""
see(dev_id=dev_id_lookup[topic], location_name=payload)
for dev_id, topic in devices.items():

View File

@@ -1,47 +1,47 @@
"""
homeassistant.components.device_tracker.netgear
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a Netgear router for device
presence.
Support for Netgear routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.netgear/
"""
import logging
from datetime import timedelta
import threading
from datetime import timedelta
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, \
CONF_PORT
from homeassistant.util import Throttle
# Return cached results if last scan was less then this time ago
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pynetgear==0.3']
REQUIREMENTS = ['pynetgear==0.3.3']
def get_scanner(hass, config):
""" Validates config and returns a Netgear scanner. """
"""Validate the configuration and returns a Netgear scanner."""
info = config[DOMAIN]
host = info.get(CONF_HOST)
username = info.get(CONF_USERNAME)
password = info.get(CONF_PASSWORD)
port = info.get(CONF_PORT)
if password is not None and host is None:
_LOGGER.warning('Found username or password but no host')
return None
scanner = NetgearDeviceScanner(host, username, password)
scanner = NetgearDeviceScanner(host, username, password, port)
return scanner if scanner.success_init else None
class NetgearDeviceScanner(object):
""" This class queries a Netgear wireless router using the SOAP-API. """
"""Queries a Netgear wireless router using the SOAP-API."""
def __init__(self, host, username, password):
def __init__(self, host, username, password, port):
"""Initialize the scanner."""
import pynetgear
self.last_results = []
@@ -51,8 +51,10 @@ class NetgearDeviceScanner(object):
self._api = pynetgear.Netgear()
elif username is None:
self._api = pynetgear.Netgear(password, host)
else:
elif port is None:
self._api = pynetgear.Netgear(password, host, username)
else:
self._api = pynetgear.Netgear(password, host, username, port)
_LOGGER.info("Logging in")
@@ -66,15 +68,13 @@ class NetgearDeviceScanner(object):
_LOGGER.error("Failed to Login")
def scan_devices(self):
"""
Scans for new devices and return a list containing found device ids.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return (device.mac for device in self.last_results)
def get_device_name(self, mac):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
try:
return next(device.name for device in self.last_results
if device.mac == mac)
@@ -83,8 +83,8 @@ class NetgearDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Retrieves latest information from the Netgear router.
"""Retrieve latest information from the Netgear router.
Returns boolean if scanning successful.
"""
if not self.success_init:
@@ -93,4 +93,9 @@ class NetgearDeviceScanner(object):
with self.lock:
_LOGGER.info("Scanning")
self.last_results = self._api.get_attached_devices() or []
results = self._api.get_attached_devices()
if results is None:
_LOGGER.warning('Error scanning devices')
self.last_results = results or []

View File

@@ -1,22 +1,20 @@
"""
homeassistant.components.device_tracker.nmap
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a network with nmap.
Support for scanning a network with nmap.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.nmap_scanner/
"""
import logging
from datetime import timedelta
from collections import namedtuple
import subprocess
import re
import subprocess
from collections import namedtuple
from datetime import timedelta
import homeassistant.util.dt as dt_util
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOSTS
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle, convert
from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
@@ -26,11 +24,11 @@ _LOGGER = logging.getLogger(__name__)
# interval in minutes to exclude devices from a scan while they are home
CONF_HOME_INTERVAL = "home_interval"
REQUIREMENTS = ['python-nmap==0.4.3']
REQUIREMENTS = ['python-nmap==0.6.0']
def get_scanner(hass, config):
""" Validates config and returns a Nmap scanner. """
"""Validate the configuration and return a Nmap scanner."""
if not validate_config(config, {DOMAIN: [CONF_HOSTS]},
_LOGGER):
return None
@@ -43,7 +41,7 @@ Device = namedtuple("Device", ["mac", "name", "ip", "last_update"])
def _arp(ip_address):
""" Get the MAC address for a given IP. """
"""Get the MAC address for a given IP."""
cmd = ['arp', '-n', ip_address]
arp = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out, _ = arp.communicate()
@@ -55,9 +53,10 @@ def _arp(ip_address):
class NmapDeviceScanner(object):
""" This class scans for devices using nmap. """
"""This class scans for devices using nmap."""
def __init__(self, config):
"""Initialize the scanner."""
self.last_results = []
self.hosts = config[CONF_HOSTS]
@@ -68,17 +67,13 @@ class NmapDeviceScanner(object):
_LOGGER.info("nmap scanner initialized")
def scan_devices(self):
"""
Scans for new devices and return a list containing found device ids.
"""
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return [device.mac for device in self.last_results]
def get_device_name(self, mac):
""" Returns the name of the given device or None if we don't know. """
"""Return the name of the given device or None if we don't know."""
filter_named = [device.name for device in self.last_results
if device.mac == mac]
@@ -89,8 +84,8 @@ class NmapDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Scans the network for devices.
"""Scan the network for devices.
Returns boolean if scanning successful.
"""
_LOGGER.info("Scanning")

View File

@@ -1,53 +1,211 @@
"""
homeassistant.components.device_tracker.owntracks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OwnTracks platform for the device tracker.
Support the OwnTracks platform.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.owntracks/
"""
import json
import logging
import threading
from collections import defaultdict
import homeassistant.components.mqtt as mqtt
from homeassistant.const import STATE_HOME
from homeassistant.util import convert, slugify
DEPENDENCIES = ['mqtt']
REGIONS_ENTERED = defaultdict(list)
MOBILE_BEACONS_ACTIVE = defaultdict(list)
BEACON_DEV_ID = 'beacon'
LOCATION_TOPIC = 'owntracks/+/+'
EVENT_TOPIC = 'owntracks/+/+/event'
_LOGGER = logging.getLogger(__name__)
LOCK = threading.Lock()
CONF_MAX_GPS_ACCURACY = 'max_gps_accuracy'
def setup_scanner(hass, config, see):
""" Set up a OwnTracksks tracker. """
"""Setup an OwnTracks tracker."""
max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY)
def owntracks_location_update(topic, payload, qos):
""" MQTT message received. """
# Docs on available data:
# http://owntracks.org/booklet/tech/json/#_typelocation
def validate_payload(payload, data_type):
"""Validate OwnTracks payload."""
try:
data = json.loads(payload)
except ValueError:
# If invalid JSON
logging.getLogger(__name__).error(
'Unable to parse payload as JSON: %s', payload)
_LOGGER.error('Unable to parse payload as JSON: %s', payload)
return None
if not isinstance(data, dict) or data.get('_type') != data_type:
_LOGGER.debug('Skipping %s update for following data '
'because of missing or malformatted data: %s',
data_type, data)
return None
if max_gps_accuracy is not None and \
convert(data.get('acc'), float, 0.0) > max_gps_accuracy:
_LOGGER.debug('Skipping %s update because expected GPS '
'accuracy %s is not met: %s',
data_type, max_gps_accuracy, data)
return None
if convert(data.get('acc'), float, 1.0) == 0.0:
_LOGGER.debug('Skipping %s update because GPS accuracy'
'is zero',
data_type)
return None
return data
def owntracks_location_update(topic, payload, qos):
"""MQTT message received."""
# Docs on available data:
# http://owntracks.org/booklet/tech/json/#_typelocation
data = validate_payload(payload, 'location')
if not data:
return
if not isinstance(data, dict) or data.get('_type') != 'location':
dev_id, kwargs = _parse_see_args(topic, data)
# Block updates if we're in a region
with LOCK:
if REGIONS_ENTERED[dev_id]:
_LOGGER.debug(
"location update ignored - inside region %s",
REGIONS_ENTERED[-1])
return
see(**kwargs)
see_beacons(dev_id, kwargs)
def owntracks_event_update(topic, payload, qos):
"""MQTT event (geofences) received."""
# Docs on available data:
# http://owntracks.org/booklet/tech/json/#_typetransition
data = validate_payload(payload, 'transition')
if not data:
return
parts = topic.split('/')
kwargs = {
'dev_id': '{}_{}'.format(parts[1], parts[2]),
'host_name': parts[1],
'gps': (data['lat'], data['lon']),
}
if 'acc' in data:
kwargs['gps_accuracy'] = data['acc']
if 'batt' in data:
kwargs['battery'] = data['batt']
if data.get('desc') is None:
_LOGGER.error(
"Location missing from `Entering/Leaving` message - "
"please turn `Share` on in OwnTracks app")
return
# OwnTracks uses - at the start of a beacon zone
# to switch on 'hold mode' - ignore this
location = slugify(data['desc'].lstrip("-"))
if location.lower() == 'home':
location = STATE_HOME
see(**kwargs)
dev_id, kwargs = _parse_see_args(topic, data)
def enter_event():
"""Execute enter event."""
zone = hass.states.get("zone.{}".format(location))
with LOCK:
if zone is None and data.get('t') == 'b':
# Not a HA zone, and a beacon so assume mobile
beacons = MOBILE_BEACONS_ACTIVE[dev_id]
if location not in beacons:
beacons.append(location)
_LOGGER.info("Added beacon %s", location)
else:
# Normal region
regions = REGIONS_ENTERED[dev_id]
if location not in regions:
regions.append(location)
_LOGGER.info("Enter region %s", location)
_set_gps_from_zone(kwargs, location, zone)
see(**kwargs)
see_beacons(dev_id, kwargs)
def leave_event():
"""Execute leave event."""
with LOCK:
regions = REGIONS_ENTERED[dev_id]
if location in regions:
regions.remove(location)
new_region = regions[-1] if regions else None
if new_region:
# Exit to previous region
zone = hass.states.get("zone.{}".format(new_region))
_set_gps_from_zone(kwargs, new_region, zone)
_LOGGER.info("Exit to %s", new_region)
see(**kwargs)
see_beacons(dev_id, kwargs)
else:
_LOGGER.info("Exit to GPS")
# Check for GPS accuracy
if not ('acc' in data and
max_gps_accuracy is not None and
data['acc'] > max_gps_accuracy):
see(**kwargs)
see_beacons(dev_id, kwargs)
else:
_LOGGER.info("Inaccurate GPS reported")
beacons = MOBILE_BEACONS_ACTIVE[dev_id]
if location in beacons:
beacons.remove(location)
_LOGGER.info("Remove beacon %s", location)
if data['event'] == 'enter':
enter_event()
elif data['event'] == 'leave':
leave_event()
else:
_LOGGER.error(
'Misformatted mqtt msgs, _type=transition, event=%s',
data['event'])
return
def see_beacons(dev_id, kwargs_param):
"""Set active beacons to the current location."""
kwargs = kwargs_param.copy()
# the battery state applies to the tracking device, not the beacon
kwargs.pop('battery', None)
for beacon in MOBILE_BEACONS_ACTIVE[dev_id]:
kwargs['dev_id'] = "{}_{}".format(BEACON_DEV_ID, beacon)
kwargs['host_name'] = beacon
see(**kwargs)
mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1)
mqtt.subscribe(hass, EVENT_TOPIC, owntracks_event_update, 1)
return True
def _parse_see_args(topic, data):
"""Parse the OwnTracks location parameters, into the format see expects."""
parts = topic.split('/')
dev_id = slugify('{}_{}'.format(parts[1], parts[2]))
host_name = parts[1]
kwargs = {
'dev_id': dev_id,
'host_name': host_name,
'gps': (data['lat'], data['lon'])
}
if 'acc' in data:
kwargs['gps_accuracy'] = data['acc']
if 'batt' in data:
kwargs['battery'] = data['batt']
return dev_id, kwargs
def _set_gps_from_zone(kwargs, location, zone):
"""Set the see parameters from the zone parameters."""
if zone is not None:
kwargs['gps'] = (
zone.attributes['latitude'],
zone.attributes['longitude'])
kwargs['gps_accuracy'] = zone.attributes['radius']
kwargs['location_name'] = location
return kwargs

View File

@@ -0,0 +1,33 @@
# Describes the format for available device tracker services
see:
description: Control tracked device
fields:
mac:
description: MAC address of device
example: 'FF:FF:FF:FF:FF:FF'
dev_id:
description: Id of device (find id in known_devices.yaml)
example: 'phonedave'
host_name:
description: Hostname of device
example: 'Dave'
location_name:
description: Name of location where device is located (not_home is away)
example: 'home'
gps:
description: GPS coordinates where device is located (latitude, longitude)
example: '[51.509802, -0.086692]'
gps_accuracy:
description: Accuracy of GPS coordinates
example: '80'
battery:
description: Battery level of device
example: '100'

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