Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion homeassistant/components/binary_sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,18 @@

async def async_setup(hass, config):
"""Track states and offer events for binary sensors."""
component = EntityComponent(
component = hass.data[DOMAIN] = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)

await component.async_setup(config)
return True


async def async_setup_entry(hass, entry):
"""Setup a config entry."""
return await hass.data[DOMAIN].async_setup_entry(entry)


# pylint: disable=no-self-use
class BinarySensorDevice(Entity):
"""Represent a binary sensor."""
Expand Down
8 changes: 5 additions & 3 deletions homeassistant/components/binary_sensor/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@

async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Set up the deCONZ binary sensor."""
if discovery_info is None:
return
"""Old way of setting up deCONZ binary sensors."""
pass


async def async_setup_entry(hass, config_entry, async_add_devices):
"""Set up the deCONZ binary sensor."""
from pydeconz.sensor import DECONZ_BINARY_SENSOR
sensors = hass.data[DATA_DECONZ].sensors
entities = []
Expand Down
31 changes: 11 additions & 20 deletions homeassistant/components/deconz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
from homeassistant.const import (
CONF_API_KEY, CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP)
from homeassistant.core import callback
from homeassistant.helpers import (
aiohttp_client, discovery, config_validation as cv)
from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.util.json import load_json

# Loading the config flow file will register the flow
Expand Down Expand Up @@ -58,28 +57,20 @@ async def async_setup(hass, config):
return True


async def async_setup_entry(hass, entry):
"""Set up a deCONZ bridge for a config entry."""
if DOMAIN in hass.data:
_LOGGER.error(
"Config entry failed since one deCONZ instance already exists")
return False
result = await async_setup_deconz(hass, None, entry.data)
if result:
return True
return False


async def async_setup_deconz(hass, config, deconz_config):
"""Set up a deCONZ session.
async def async_setup_entry(hass, config_entry):
"""Set up a deCONZ bridge for a config entry.

Load config, group, light and sensor data for server information.
Start websocket for push notification of state changes from deCONZ.
"""
_LOGGER.debug("deCONZ config %s", deconz_config)
from pydeconz import DeconzSession
if DOMAIN in hass.data:
_LOGGER.error(
"Config entry failed since one deCONZ instance already exists")
return False

session = aiohttp_client.async_get_clientsession(hass)
deconz = DeconzSession(hass.loop, session, **deconz_config)
deconz = DeconzSession(hass.loop, session, **config_entry.data)
result = await deconz.async_load_parameters()
if result is False:
_LOGGER.error("Failed to communicate with deCONZ")
Expand All @@ -89,8 +80,8 @@ async def async_setup_deconz(hass, config, deconz_config):
hass.data[DATA_DECONZ_ID] = {}

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

async def async_configure(call):
Expand Down
8 changes: 5 additions & 3 deletions homeassistant/components/light/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Set up the deCONZ light."""
if discovery_info is None:
return
"""Old way of setting up deCONZ lights."""
pass


async def async_setup_entry(hass, config_entry, async_add_devices):
"""Set up the deCONZ lights from a config entry."""
lights = hass.data[DATA_DECONZ].lights
groups = hass.data[DATA_DECONZ].groups
entities = []
Expand Down
7 changes: 6 additions & 1 deletion homeassistant/components/scene/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def activate(hass, entity_id=None):
async def async_setup(hass, config):
"""Set up the scenes."""
logger = logging.getLogger(__name__)
component = EntityComponent(logger, DOMAIN, hass)
component = hass.data[DOMAIN] = EntityComponent(logger, DOMAIN, hass)

await component.async_setup(config)

Expand All @@ -90,6 +90,11 @@ async def async_handle_scene_service(service):
return True


async def async_setup_entry(hass, entry):
"""Setup a config entry."""
return await hass.data[DOMAIN].async_setup_entry(entry)


class Scene(Entity):
"""A scene is a group of entities and the states we want them to be."""

Expand Down
8 changes: 5 additions & 3 deletions homeassistant/components/scene/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@

async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Set up scenes for deCONZ component."""
if discovery_info is None:
return
"""Old way of setting up deCONZ scenes."""
pass


async def async_setup_entry(hass, config_entry, async_add_devices):
"""Set up scenes for deCONZ component."""
scenes = hass.data[DATA_DECONZ].scenes
entities = []

Expand Down
7 changes: 6 additions & 1 deletion homeassistant/components/sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@

async def async_setup(hass, config):
"""Track states and offer events for sensors."""
component = EntityComponent(
component = hass.data[DOMAIN] = EntityComponent(
_LOGGER, DOMAIN, hass, SCAN_INTERVAL)

await component.async_setup(config)
return True


async def async_setup_entry(hass, entry):
"""Setup a config entry."""
return await hass.data[DOMAIN].async_setup_entry(entry)
8 changes: 5 additions & 3 deletions homeassistant/components/sensor/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@

async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Set up the deCONZ sensors."""
if discovery_info is None:
return
"""Old way of setting up deCONZ sensors."""
pass


async def async_setup_entry(hass, config_entry, async_add_devices):
"""Set up the deCONZ sensors."""
from pydeconz.sensor import DECONZ_SENSOR, SWITCH as DECONZ_REMOTE
sensors = hass.data[DATA_DECONZ].sensors
entities = []
Expand Down
55 changes: 55 additions & 0 deletions tests/components/binary_sensor/test_deconz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""deCONZ binary sensor platform tests."""
from unittest.mock import Mock, patch

from homeassistant import config_entries
from homeassistant.components import deconz

from tests.common import mock_coro


SENSOR = {
"1": {
"id": "Sensor 1 id",
"name": "Sensor 1 name",
"type": "ZHAPresence",
"state": {"presence": False},
"config": {}
}
}


async def setup_bridge(hass, data):
"""Load the deCONZ binary sensor platform."""
from pydeconz import DeconzSession
loop = Mock()
session = Mock()
entry = Mock()
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
bridge = DeconzSession(loop, session, **entry.data)
with patch('pydeconz.DeconzSession.async_get_state',
return_value=mock_coro(data)):
await bridge.async_load_parameters()
hass.data[deconz.DOMAIN] = bridge
hass.data[deconz.DATA_DECONZ_ID] = {}
config_entry = config_entries.ConfigEntry(
1, deconz.DOMAIN, 'Mock Title', {'host': 'mock-host'}, 'test')
await hass.config_entries.async_forward_entry_setup(
config_entry, 'binary_sensor')
# To flush out the service call to update the group
await hass.async_block_till_done()


async def test_no_binary_sensors(hass):
"""Test the update_lights function with some lights."""
data = {}
await setup_bridge(hass, data)
assert len(hass.data[deconz.DATA_DECONZ_ID]) == 0
assert len(hass.states.async_all()) == 0


async def test_binary_sensors(hass):
"""Test the update_lights function with some lights."""
data = {"sensors": SENSOR}
await setup_bridge(hass, data)
assert "binary_sensor.sensor_1_name" in hass.data[deconz.DATA_DECONZ_ID]
assert len(hass.states.async_all()) == 1
42 changes: 41 additions & 1 deletion tests/components/deconz/test_init.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Test deCONZ component setup process."""
from unittest.mock import patch
from unittest.mock import Mock, patch

from homeassistant.setup import async_setup_component
from homeassistant.components import deconz

from tests.common import mock_coro


async def test_config_with_host_passed_to_config_entry(hass):
"""Test that configured options for a host are loaded via config entry."""
Expand Down Expand Up @@ -67,3 +69,41 @@ async def test_config_discovery(hass):
assert await async_setup_component(hass, deconz.DOMAIN, {}) is True
# No flow started
assert len(mock_config_entries.flow.mock_calls) == 0


async def test_setup_entry_already_registered_bridge(hass):
"""Test setup entry doesn't allow more than one instance of deCONZ."""
hass.data[deconz.DOMAIN] = True
assert await deconz.async_setup_entry(hass, {}) is False


async def test_setup_entry_no_available_bridge(hass):
"""Test setup entry fails if deCONZ is not available."""
entry = Mock()
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
with patch('pydeconz.DeconzSession.async_load_parameters',
return_value=mock_coro(False)):
assert await deconz.async_setup_entry(hass, entry) is False


async def test_setup_entry_successful(hass):
"""Test setup entry is successful."""
entry = Mock()
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
with patch.object(hass, 'async_add_job') as mock_add_job, \
patch.object(hass, 'config_entries') as mock_config_entries, \
patch('pydeconz.DeconzSession.async_load_parameters',
return_value=mock_coro(True)):
assert await deconz.async_setup_entry(hass, entry) is True
assert hass.data[deconz.DOMAIN]
assert hass.data[deconz.DATA_DECONZ_ID] == {}
assert len(mock_add_job.mock_calls) == 4
assert len(mock_config_entries.async_forward_entry_setup.mock_calls) == 4
assert mock_config_entries.async_forward_entry_setup.mock_calls[0][1] == \
(entry, 'binary_sensor')
assert mock_config_entries.async_forward_entry_setup.mock_calls[1][1] == \
(entry, 'light')
assert mock_config_entries.async_forward_entry_setup.mock_calls[2][1] == \
(entry, 'scene')
assert mock_config_entries.async_forward_entry_setup.mock_calls[3][1] == \
(entry, 'sensor')
74 changes: 74 additions & 0 deletions tests/components/light/test_deconz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""deCONZ light platform tests."""
from unittest.mock import Mock, patch

from homeassistant import config_entries
from homeassistant.components import deconz

from tests.common import mock_coro


LIGHT = {
"1": {
"id": "Light 1 id",
"name": "Light 1 name",
"state": {}
}
}

GROUP = {
"1": {
"id": "Group 1 id",
"name": "Group 1 name",
"state": {},
"action": {},
"scenes": [],
"lights": [
"1",
"2"
]
},
"2": {
"id": "Group 2 id",
"name": "Group 2 name",
"state": {},
"action": {},
"scenes": []
},
}


async def setup_bridge(hass, data):
"""Load the deCONZ light platform."""
from pydeconz import DeconzSession
loop = Mock()
session = Mock()
entry = Mock()
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
bridge = DeconzSession(loop, session, **entry.data)
with patch('pydeconz.DeconzSession.async_get_state',
return_value=mock_coro(data)):
await bridge.async_load_parameters()
hass.data[deconz.DOMAIN] = bridge
hass.data[deconz.DATA_DECONZ_ID] = {}
config_entry = config_entries.ConfigEntry(
1, deconz.DOMAIN, 'Mock Title', {'host': 'mock-host'}, 'test')
await hass.config_entries.async_forward_entry_setup(config_entry, 'light')
# To flush out the service call to update the group
await hass.async_block_till_done()


async def test_no_lights_or_groups(hass):
"""Test the update_lights function with some lights."""
data = {}
await setup_bridge(hass, data)
assert len(hass.data[deconz.DATA_DECONZ_ID]) == 0
assert len(hass.states.async_all()) == 0


async def test_lights_and_groups(hass):
"""Test the update_lights function with some lights."""
await setup_bridge(hass, {"lights": LIGHT, "groups": GROUP})
assert "light.light_1_name" in hass.data[deconz.DATA_DECONZ_ID]
assert "light.group_1_name" in hass.data[deconz.DATA_DECONZ_ID]
assert "light.group_2_name" not in hass.data[deconz.DATA_DECONZ_ID]
assert len(hass.states.async_all()) == 3
Loading