Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
4517876
Base implementation of component, no sensors yet
Kane610 Oct 29, 2017
6845f5a
Added senor files
Kane610 Oct 29, 2017
89927fe
First fully working chain of sensors and binary sensors going from ha…
Kane610 Oct 29, 2017
d96f520
Clean up
Kane610 Oct 30, 2017
eff5bf9
Clean up
Kane610 Oct 30, 2017
f673578
Added light platform
Kane610 Oct 30, 2017
85a27f8
Turning lights on and off and set brightness now works
Kane610 Nov 1, 2017
cd19c4e
Pydeconz is now a proper pypi package
Kane610 Nov 3, 2017
1fb7050
Updated pydocstrings
Kane610 Nov 3, 2017
07c4636
Clean up
Kane610 Nov 5, 2017
f9e72a4
Updated requirements_all.txt
Kane610 Nov 5, 2017
d4ab28f
Updated Codeowners to include deconz.py
Kane610 Nov 5, 2017
c7ec2ef
Bump requirement
Kane610 Nov 5, 2017
88e396d
Bumped to v2
Kane610 Nov 6, 2017
6192018
Removed global DECONZ since it wasn't relevant any more
Kane610 Nov 6, 2017
a0ee176
Username and password is only relevant in the context of getting a AP…
Kane610 Nov 8, 2017
e46c63f
Add support for additional sensors
Kane610 Nov 8, 2017
c78d931
Added support for groups
Kane610 Nov 8, 2017
1866cf6
Moved import of component library to inside of methods
Kane610 Nov 9, 2017
09ff292
Moved the need for device id to library
Kane610 Nov 9, 2017
de0920a
Bump pydeconz to v5
Kane610 Nov 9, 2017
347cecf
Add support for colored lights
Kane610 Nov 10, 2017
e00375c
Pylint and flake8 import improvements
Kane610 Nov 10, 2017
2c65b95
DATA_DECONZ TO DECONZ_DATA
Kane610 Nov 11, 2017
f00cd0b
Add support for transition time
Kane610 Nov 11, 2017
6b2ba8b
Add support for flash
Kane610 Nov 11, 2017
e9d1ff1
Bump to v7
Kane610 Nov 11, 2017
992241d
ZHASwitch devices will now only generate events by default, instead o…
Kane610 Nov 11, 2017
92b7c53
Clean up
Kane610 Nov 11, 2017
c24381e
Add battery sensor when device signals through an event
Kane610 Nov 11, 2017
e9870ed
Third-party library communicates with service
Kane610 Nov 11, 2017
924a7ef
Add support for effect colorloop
Kane610 Nov 11, 2017
9230d28
Bump to pydeconz v8
Kane610 Nov 12, 2017
1cdced2
Same domain everywhere
Kane610 Nov 12, 2017
8a08cf7
Clean up
Kane610 Nov 12, 2017
b217cdf
Updated requirements_all
Kane610 Nov 12, 2017
ec02ca1
Generated API key will now be stored in a config file
Kane610 Nov 12, 2017
44d2337
Change battery sensor to register to callback since library now suppo…
Kane610 Nov 14, 2017
d216677
Improve entity attributes
Kane610 Nov 15, 2017
e402b87
Change end of battery name to battery level
Kane610 Nov 15, 2017
66aea41
Bump requirement to v10
Kane610 Nov 15, 2017
0bfe78d
Improve pydocstring for DeconzEvent
Kane610 Nov 15, 2017
08d4e67
Allow separate brightness to override RGB brightness
Kane610 Nov 15, 2017
87972e3
Expose device.reachable in entity available property
Kane610 Nov 15, 2017
bc8d2b1
Bump requirement to 11 (it goes up to 11!)
Kane610 Nov 15, 2017
aaf0a55
Pylint comment
Kane610 Nov 15, 2017
a756a3f
Binary sensors don't have unit of measurement
Kane610 Nov 15, 2017
de7bcc9
Removed service to generate API key in favor of just generating it as…
Kane610 Nov 16, 2017
51fddf8
Replace clear text to attribute definitions
Kane610 Nov 16, 2017
f10ecb4
Use more constants
Kane610 Nov 16, 2017
d674367
Bump requirements to v12
Kane610 Nov 16, 2017
f3d4041
Color temp requires xy color support
Kane610 Nov 16, 2017
4afa90c
Only ZHASwitch should be an event
Kane610 Nov 16, 2017
b64216c
Bump requirements to v13
Kane610 Nov 17, 2017
8f81605
Added effect_list property
Kane610 Nov 17, 2017
cf38661
Add attribute to battery sensor to easy find event id
Kane610 Nov 18, 2017
ac0cd59
Bump requirements to v14
Kane610 Nov 18, 2017
743ed28
Fix hound comment
Kane610 Nov 18, 2017
c4e4d4a
Bumped requirements_all information to v14
Kane610 Nov 19, 2017
d6a6ec6
Add service to configure devices on deCONZ
Kane610 Nov 19, 2017
c4f93c9
Add initial support for scenes
Kane610 Nov 19, 2017
1dd7940
Bump requirements to v15
Kane610 Nov 19, 2017
85ed7d6
Fix review comments
Kane610 Nov 19, 2017
b00cbb2
Python doc string improvement
Kane610 Nov 19, 2017
8da145d
Improve setup and error handling during setup
Kane610 Nov 19, 2017
c3c920f
Changed how to evaluate light features
Kane610 Nov 19, 2017
7a34a66
Remove 'ghost' events by not triggering updates if the signal origina…
Kane610 Nov 20, 2017
7d091f2
Fix pylint issue by moving scene ownership in to groups in requiremen…
Kane610 Nov 21, 2017
a147f51
Added configurator option to register to deCONZ when unlocking gatewa…
Kane610 Nov 21, 2017
bed7978
Improve async configurator
Kane610 Nov 24, 2017
c06b38d
No user interaction for deconz.conf
Kane610 Nov 24, 2017
ce075f7
No file management in event loop
Kane610 Nov 24, 2017
3474381
Improve readability of load platform
Kane610 Nov 24, 2017
f5de075
Fewer entity attributes
Kane610 Nov 24, 2017
51c07b6
Use values() instead of items() for dicts where applicable
Kane610 Nov 24, 2017
09d789d
Do one add devices per platform
Kane610 Nov 24, 2017
6f57b23
Clean up of unused attributes
Kane610 Nov 24, 2017
70c5cd9
Make sure that discovery info is not None
Kane610 Nov 24, 2017
eb2953b
Only register configure service and shutdown service when deconz has …
Kane610 Nov 24, 2017
87af434
Move description
Kane610 Nov 24, 2017
2940fa8
Fix lines longer than 80
Kane610 Nov 24, 2017
7f3ff1f
Moved deconz services to a separate file and moved hub to deconz/__in…
Kane610 Nov 24, 2017
5ba8593
Remove option to configure switch as entity
Kane610 Nov 24, 2017
c833426
Moved DeconzEvent to sensor since it is only Switch buttonpress that …
Kane610 Nov 24, 2017
098cd01
Added support for automatic discovery of deconz
Kane610 Nov 25, 2017
0f00960
Use markup for configuration description
Kane610 Nov 25, 2017
2be977e
Fix coveragerc
Kane610 Nov 25, 2017
acd19e5
Remove deCONZ support from Hue component
Kane610 Nov 25, 2017
2b62ab8
Improved docstrings and readability
Kane610 Nov 25, 2017
24a367a
Remove unnecessary extra name for storing in hass.data, using domain …
Kane610 Nov 25, 2017
7762687
Improve readability by renaming all async methods
Kane610 Nov 25, 2017
d335d62
Fix first line not being in imperative mood
Kane610 Nov 26, 2017
f9a280a
Added logo to configurator
Kane610 Nov 26, 2017
e0c5ce1
Removed bridge_type from new unit tests as part of removing deconz su…
Kane610 Dec 11, 2017
46de840
Capitalize first letters of Battery Level
Kane610 Dec 17, 2017
a02ce0f
Properly update state of sensor as well as reachable and battery
Kane610 Dec 27, 2017
3f82d98
Fix flake8 Multi-line docstring closing quotes should be on a separat…
Kane610 Dec 27, 2017
b0582b1
Fix martinhjelmares comments
Kane610 Dec 31, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ omit =
homeassistant/components/comfoconnect.py
homeassistant/components/*/comfoconnect.py

homeassistant/components/deconz/*
homeassistant/components/*/deconz.py

homeassistant/components/digital_ocean.py
homeassistant/components/*/digital_ocean.py

Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ homeassistant/components/switch/rainmachine.py @bachya
homeassistant/components/switch/tplink.py @rytilahti
homeassistant/components/xiaomi_aqara.py @danielhiversen @syssi

homeassistant/components/*/axis.py @kane610
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this part of the deconz PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It got overridden in a separate PR so I just add it again here out of pure laziness

homeassistant/components/*/broadlink.py @danielhiversen
homeassistant/components/hive.py @Rendili @KJonline
homeassistant/components/*/hive.py @Rendili @KJonline
homeassistant/components/*/deconz.py @kane610
homeassistant/components/*/rfxtrx.py @danielhiversen
homeassistant/components/velux.py @Julius2342
homeassistant/components/*/velux.py @Julius2342
Expand Down
97 changes: 97 additions & 0 deletions homeassistant/components/binary_sensor/deconz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""
Support for deCONZ binary sensor.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.deconz/
"""

import asyncio

from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.deconz import DOMAIN as DECONZ_DATA
from homeassistant.const import ATTR_BATTERY_LEVEL
from homeassistant.core import callback

DEPENDENCIES = ['deconz']


@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup binary sensor for deCONZ component."""
if discovery_info is None:
return

from pydeconz.sensor import DECONZ_BINARY_SENSOR
sensors = hass.data[DECONZ_DATA].sensors
entities = []

for sensor in sensors.values():
if sensor.type in DECONZ_BINARY_SENSOR:
entities.append(DeconzBinarySensor(sensor))
async_add_devices(entities, True)


class DeconzBinarySensor(BinarySensorDevice):
"""Representation of a binary sensor."""

def __init__(self, sensor):
"""Setup sensor and add update callback to get data from websocket."""
self._sensor = sensor

@asyncio.coroutine
def async_added_to_hass(self):
"""Subscribe sensors events."""
self._sensor.register_async_callback(self.async_update_callback)

@callback
def async_update_callback(self, reason):
"""Update the sensor's state.

If reason is that state is updated,
or reachable has changed or battery has changed.
"""
if reason['state'] or \
'reachable' in reason['attr'] or \
'battery' in reason['attr']:
self.async_schedule_update_ha_state()

@property
def is_on(self):
"""Return true if sensor is on."""
return self._sensor.is_tripped

@property
def name(self):
"""Return the name of the sensor."""
return self._sensor.name

@property
def device_class(self):
"""Class of the sensor."""
return self._sensor.sensor_class

@property
def icon(self):
"""Return the icon to use in the frontend."""
return self._sensor.sensor_icon

@property
def available(self):
"""Return True if sensor is available."""
return self._sensor.reachable

@property
def should_poll(self):
"""No polling needed."""
return False

@property
def device_state_attributes(self):
"""Return the state attributes of the sensor."""
from pydeconz.sensor import PRESENCE
attr = {
ATTR_BATTERY_LEVEL: self._sensor.battery,
}
if self._sensor.type == PRESENCE:
attr['dark'] = self._sensor.dark
return attr
176 changes: 176 additions & 0 deletions homeassistant/components/deconz/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
"""
Support for deCONZ devices.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/deconz/
"""

import asyncio
import logging
import os
import voluptuous as vol

from homeassistant.config import load_yaml_config_file
from homeassistant.const import (
CONF_API_KEY, CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP)
from homeassistant.components.discovery import SERVICE_DECONZ
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.util.json import load_json, save_json

REQUIREMENTS = ['pydeconz==23']

_LOGGER = logging.getLogger(__name__)

DOMAIN = 'deconz'

CONFIG_FILE = 'deconz.conf'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please prefix the name with a dot, to make the file hidden, if users shouldn't interact with it, ie '.deconz.conf'.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no easy way for users to get a hold of the API key if needed, so if possible I'd like to leave this as is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.


CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_HOST): cv.string,
vol.Optional(CONF_API_KEY): cv.string,
vol.Optional(CONF_PORT, default=80): cv.port,
})
}, extra=vol.ALLOW_EXTRA)

SERVICE_FIELD = 'field'
SERVICE_DATA = 'data'

SERVICE_SCHEMA = vol.Schema({
vol.Required(SERVICE_FIELD): cv.string,
vol.Required(SERVICE_DATA): cv.string,
})

CONFIG_INSTRUCTIONS = """
Unlock your deCONZ gateway to register with Home Assistant.

1. [Go to deCONZ system settings](http://{}:{}/edit_system.html)
2. Press "Unlock Gateway" button

[deCONZ platform documentation](https://home-assistant.io/components/deconz/)
"""


@asyncio.coroutine
def async_setup(hass, config):
"""Setup services and configuration for deCONZ component."""
result = False
config_file = yield from hass.async_add_job(
load_json, hass.config.path(CONFIG_FILE))

@asyncio.coroutine
def async_deconz_discovered(service, discovery_info):
"""Called when deCONZ gateway has been found."""
deconz_config = {}
deconz_config[CONF_HOST] = discovery_info.get(CONF_HOST)
deconz_config[CONF_PORT] = discovery_info.get(CONF_PORT)
yield from async_request_configuration(hass, config, deconz_config)

if config_file:
result = yield from async_setup_deconz(hass, config, config_file)

if not result and DOMAIN in config and CONF_HOST in config[DOMAIN]:
deconz_config = config[DOMAIN]
if CONF_API_KEY in deconz_config:
result = yield from async_setup_deconz(hass, config, deconz_config)
else:
yield from async_request_configuration(hass, config, deconz_config)
return True

if not result:
discovery.async_listen(hass, SERVICE_DECONZ, async_deconz_discovered)

return True


@asyncio.coroutine
def async_setup_deconz(hass, config, deconz_config):
"""Setup deCONZ session.

Load config, group, light and sensor data for server information.
Start websocket for push notification of state changes from deCONZ.
"""
from pydeconz import DeconzSession
websession = async_get_clientsession(hass)
deconz = DeconzSession(hass.loop, websession, **deconz_config)
result = yield from deconz.async_load_parameters()
if result is False:
_LOGGER.error("Failed to communicate with deCONZ.")
return False

hass.data[DOMAIN] = deconz

for component in ['binary_sensor', 'light', 'scene', 'sensor']:
hass.async_add_job(discovery.async_load_platform(
hass, component, DOMAIN, {}, config))
deconz.start()

descriptions = yield from hass.async_add_job(
load_yaml_config_file,
os.path.join(os.path.dirname(__file__), 'services.yaml'))

@asyncio.coroutine
def async_configure(call):
"""Set attribute of device in deCONZ.

Field is a string representing a specific device in deCONZ
e.g. field='/lights/1/state'.
Data is a json object with what data you want to alter
e.g. data={'on': true}.
{
"field": "/lights/1/state",
"data": {"on": true}
}
See Dresden Elektroniks REST API documentation for details:
http://dresden-elektronik.github.io/deconz-rest-doc/rest/
"""
deconz = hass.data[DOMAIN]
field = call.data.get(SERVICE_FIELD)
data = call.data.get(SERVICE_DATA)
yield from deconz.async_put_state(field, data)
hass.services.async_register(
DOMAIN, 'configure', async_configure,
descriptions['configure'], schema=SERVICE_SCHEMA)

hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz.close)
return True


@asyncio.coroutine
def async_request_configuration(hass, config, deconz_config):
"""Request configuration steps from the user."""
configurator = hass.components.configurator

@asyncio.coroutine
def async_configuration_callback(data):
"""Set up actions to do when our configuration callback is called."""
from pydeconz.utils import async_get_api_key
api_key = yield from async_get_api_key(hass.loop, **deconz_config)
if api_key:
deconz_config[CONF_API_KEY] = api_key
result = yield from async_setup_deconz(hass, config, deconz_config)
if result:
yield from hass.async_add_job(save_json,
hass.config.path(CONFIG_FILE),
deconz_config)
configurator.async_request_done(request_id)
return
else:
configurator.async_notify_errors(
request_id, "Couldn't load configuration.")
else:
configurator.async_notify_errors(
request_id, "Couldn't get an API key.")
return

instructions = CONFIG_INSTRUCTIONS.format(
deconz_config[CONF_HOST], deconz_config[CONF_PORT])

request_id = configurator.async_request_config(
"deCONZ", async_configuration_callback,
description=instructions,
entity_picture="/static/images/logo_deconz.jpeg",
submit_caption="I have unlocked the gateway",
)
10 changes: 10 additions & 0 deletions homeassistant/components/deconz/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

configure:
description: Set attribute of device in Deconz. See Dresden Elektroniks REST API documentation for details http://dresden-elektronik.github.io/deconz-rest-doc/rest/
fields:
field:
description: Field is a string representing a specific device in Deconz.
example: '/lights/1/state'
data:
description: Data is a json object with what data you want to alter.
example: '{"on": true}'
2 changes: 2 additions & 0 deletions homeassistant/components/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
SERVICE_XIAOMI_GW = 'xiaomi_gw'
SERVICE_TELLDUSLIVE = 'tellstick'
SERVICE_HUE = 'philips_hue'
SERVICE_DECONZ = 'deconz'

SERVICE_HANDLERS = {
SERVICE_HASS_IOS_APP: ('ios', None),
Expand All @@ -50,6 +51,7 @@
SERVICE_XIAOMI_GW: ('xiaomi_aqara', None),
SERVICE_TELLDUSLIVE: ('tellduslive', None),
SERVICE_HUE: ('hue', None),
SERVICE_DECONZ: ('deconz', None),
'google_cast': ('media_player', 'cast'),
'panasonic_viera': ('media_player', 'panasonic_viera'),
'plex_mediaserver': ('media_player', 'plex'),
Expand Down
Loading