Look at registry before pulling zwave config values (#14408)
* Look at registry before deciding on ID for zwave values * Reuse the new functionpull/14431/head
parent
7aec098a05
commit
d1228d5cf4
|
@ -16,10 +16,11 @@ from homeassistant.loader import get_platform
|
|||
from homeassistant.helpers import discovery
|
||||
from homeassistant.helpers.entity import generate_entity_id
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.entity_registry import async_get_registry
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
|
||||
from homeassistant.helpers.entity_values import EntityValues
|
||||
from homeassistant.helpers.event import track_time_change
|
||||
from homeassistant.helpers.event import async_track_time_change
|
||||
from homeassistant.util import convert
|
||||
import homeassistant.util.dt as dt_util
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
@ -218,7 +219,7 @@ async def async_setup_platform(hass, config, async_add_devices,
|
|||
|
||||
|
||||
# pylint: disable=R0914
|
||||
def setup(hass, config):
|
||||
async def async_setup(hass, config):
|
||||
"""Set up Z-Wave.
|
||||
|
||||
Will automatically load components to support devices found on the network.
|
||||
|
@ -286,7 +287,7 @@ def setup(hass, config):
|
|||
continue
|
||||
|
||||
values = ZWaveDeviceEntityValues(
|
||||
hass, schema, value, config, device_config)
|
||||
hass, schema, value, config, device_config, registry)
|
||||
|
||||
# We create a new list and update the reference here so that
|
||||
# the list can be safely iterated over in the main thread
|
||||
|
@ -294,6 +295,7 @@ def setup(hass, config):
|
|||
hass.data[DATA_ENTITY_VALUES] = new_values
|
||||
|
||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||
registry = await async_get_registry(hass)
|
||||
|
||||
def node_added(node):
|
||||
"""Handle a new node on the network."""
|
||||
|
@ -702,9 +704,9 @@ def setup(hass, config):
|
|||
# Setup autoheal
|
||||
if autoheal:
|
||||
_LOGGER.info("Z-Wave network autoheal is enabled")
|
||||
track_time_change(hass, heal_network, hour=0, minute=0, second=0)
|
||||
async_track_time_change(hass, heal_network, hour=0, minute=0, second=0)
|
||||
|
||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave)
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, start_zwave)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -713,7 +715,7 @@ class ZWaveDeviceEntityValues():
|
|||
"""Manages entity access to the underlying zwave value objects."""
|
||||
|
||||
def __init__(self, hass, schema, primary_value, zwave_config,
|
||||
device_config):
|
||||
device_config, registry):
|
||||
"""Initialize the values object with the passed entity schema."""
|
||||
self._hass = hass
|
||||
self._zwave_config = zwave_config
|
||||
|
@ -722,6 +724,7 @@ class ZWaveDeviceEntityValues():
|
|||
self._values = {}
|
||||
self._entity = None
|
||||
self._workaround_ignore = False
|
||||
self._registry = registry
|
||||
|
||||
for name in self._schema[const.DISC_VALUES].keys():
|
||||
self._values[name] = None
|
||||
|
@ -794,9 +797,13 @@ class ZWaveDeviceEntityValues():
|
|||
workaround_component, component)
|
||||
component = workaround_component
|
||||
|
||||
value_name = _value_name(self.primary)
|
||||
generated_id = generate_entity_id(component + '.{}', value_name, [])
|
||||
node_config = self._device_config.get(generated_id)
|
||||
entity_id = self._registry.async_get_entity_id(
|
||||
component, DOMAIN,
|
||||
compute_value_unique_id(self._node, self.primary))
|
||||
if entity_id is None:
|
||||
value_name = _value_name(self.primary)
|
||||
entity_id = generate_entity_id(component + '.{}', value_name, [])
|
||||
node_config = self._device_config.get(entity_id)
|
||||
|
||||
# Configure node
|
||||
_LOGGER.debug("Adding Node_id=%s Generic_command_class=%s, "
|
||||
|
@ -809,7 +816,7 @@ class ZWaveDeviceEntityValues():
|
|||
|
||||
if node_config.get(CONF_IGNORED):
|
||||
_LOGGER.info(
|
||||
"Ignoring entity %s due to device settings", generated_id)
|
||||
"Ignoring entity %s due to device settings", entity_id)
|
||||
# No entity will be created for this value
|
||||
self._workaround_ignore = True
|
||||
return
|
||||
|
@ -964,6 +971,10 @@ class ZWaveDeviceEntity(ZWaveBaseEntity):
|
|||
if (is_node_parsed(self.node) and
|
||||
self.values.primary.label != "Unknown") or \
|
||||
self.node.is_ready:
|
||||
return "{}-{}".format(self.node.node_id,
|
||||
self.values.primary.object_id)
|
||||
return compute_value_unique_id(self.node, self.values.primary)
|
||||
return None
|
||||
|
||||
|
||||
def compute_value_unique_id(node, value):
|
||||
"""Compute unique_id a value would get if it were to get one."""
|
||||
return "{}-{}".format(node.node_id, value.object_id)
|
||||
|
|
|
@ -83,6 +83,15 @@ class EntityRegistry:
|
|||
"""Check if an entity_id is currently registered."""
|
||||
return entity_id in self.entities
|
||||
|
||||
@callback
|
||||
def async_get_entity_id(self, domain: str, platform: str, unique_id: str):
|
||||
"""Check if an entity_id is currently registered."""
|
||||
for entity in self.entities.values():
|
||||
if entity.domain == domain and entity.platform == platform and \
|
||||
entity.unique_id == unique_id:
|
||||
return entity.entity_id
|
||||
return None
|
||||
|
||||
@callback
|
||||
def async_generate_entity_id(self, domain, suggested_object_id):
|
||||
"""Generate an entity ID that does not conflict.
|
||||
|
@ -99,10 +108,9 @@ class EntityRegistry:
|
|||
def async_get_or_create(self, domain, platform, unique_id, *,
|
||||
suggested_object_id=None):
|
||||
"""Get entity. Create if it doesn't exist."""
|
||||
for entity in self.entities.values():
|
||||
if entity.domain == domain and entity.platform == platform and \
|
||||
entity.unique_id == unique_id:
|
||||
return entity
|
||||
entity_id = self.async_get_entity_id(domain, platform, unique_id)
|
||||
if entity_id:
|
||||
return self.entities[entity_id]
|
||||
|
||||
entity_id = self.async_generate_entity_id(
|
||||
domain, suggested_object_id or '{}_{}'.format(platform, unique_id))
|
||||
|
|
|
@ -13,6 +13,7 @@ from homeassistant.components.binary_sensor.zwave import get_device
|
|||
from homeassistant.components.zwave import (
|
||||
const, CONFIG_SCHEMA, CONF_DEVICE_CONFIG_GLOB, DATA_NETWORK)
|
||||
from homeassistant.setup import setup_component
|
||||
from tests.common import mock_registry
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -468,6 +469,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
"""Initialize values for this testcase class."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.start()
|
||||
self.registry = mock_registry(self.hass)
|
||||
|
||||
setup_component(self.hass, 'zwave', {'zwave': {}})
|
||||
self.hass.block_till_done()
|
||||
|
@ -487,7 +489,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
const.DISC_OPTIONAL: True,
|
||||
}}}
|
||||
self.primary = MockValue(
|
||||
command_class='mock_primary_class', node=self.node)
|
||||
command_class='mock_primary_class', node=self.node, value_id=1000)
|
||||
self.secondary = MockValue(
|
||||
command_class='mock_secondary_class', node=self.node)
|
||||
self.duplicate_secondary = MockValue(
|
||||
|
@ -521,6 +523,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
|
||||
assert values.primary is self.primary
|
||||
|
@ -592,6 +595,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
self.hass.block_till_done()
|
||||
|
||||
|
@ -630,6 +634,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
values._check_entity_ready()
|
||||
self.hass.block_till_done()
|
||||
|
@ -639,7 +644,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
@patch.object(zwave, 'get_platform')
|
||||
@patch.object(zwave, 'discovery')
|
||||
def test_entity_workaround_component(self, discovery, get_platform):
|
||||
"""Test ignore workaround."""
|
||||
"""Test component workaround."""
|
||||
discovery.async_load_platform.return_value = mock_coro()
|
||||
mock_platform = MagicMock()
|
||||
get_platform.return_value = mock_platform
|
||||
|
@ -666,6 +671,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
values._check_entity_ready()
|
||||
self.hass.block_till_done()
|
||||
|
@ -697,6 +703,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
values._check_entity_ready()
|
||||
self.hass.block_till_done()
|
||||
|
@ -720,12 +727,42 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
values._check_entity_ready()
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert not discovery.async_load_platform.called
|
||||
|
||||
@patch.object(zwave, 'get_platform')
|
||||
@patch.object(zwave, 'discovery')
|
||||
def test_entity_config_ignore_with_registry(self, discovery, get_platform):
|
||||
"""Test ignore config.
|
||||
|
||||
The case when the device is in entity registry.
|
||||
"""
|
||||
self.node.values = {
|
||||
self.primary.value_id: self.primary,
|
||||
self.secondary.value_id: self.secondary,
|
||||
}
|
||||
self.device_config = {'mock_component.registry_id': {
|
||||
zwave.CONF_IGNORED: True
|
||||
}}
|
||||
self.registry.async_get_or_create(
|
||||
'mock_component', zwave.DOMAIN, '567-1000',
|
||||
suggested_object_id='registry_id')
|
||||
zwave.ZWaveDeviceEntityValues(
|
||||
hass=self.hass,
|
||||
schema=self.mock_schema,
|
||||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert not discovery.async_load_platform.called
|
||||
|
||||
@patch.object(zwave, 'get_platform')
|
||||
@patch.object(zwave, 'discovery')
|
||||
def test_entity_platform_ignore(self, discovery, get_platform):
|
||||
|
@ -743,6 +780,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
self.hass.block_till_done()
|
||||
|
||||
|
@ -770,6 +808,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||
primary_value=self.primary,
|
||||
zwave_config=self.zwave_config,
|
||||
device_config=self.device_config,
|
||||
registry=self.registry
|
||||
)
|
||||
values._check_entity_ready()
|
||||
self.hass.block_till_done()
|
||||
|
|
|
@ -180,3 +180,13 @@ test.disabled_hass:
|
|||
assert entry_disabled_hass.disabled_by == entity_registry.DISABLED_HASS
|
||||
assert entry_disabled_user.disabled
|
||||
assert entry_disabled_user.disabled_by == entity_registry.DISABLED_USER
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_async_get_entity_id(registry):
|
||||
"""Test that entity_id is returned."""
|
||||
entry = registry.async_get_or_create('light', 'hue', '1234')
|
||||
assert entry.entity_id == 'light.hue_1234'
|
||||
assert registry.async_get_entity_id(
|
||||
'light', 'hue', '1234') == 'light.hue_1234'
|
||||
assert registry.async_get_entity_id('light', 'hue', '123') is None
|
||||
|
|
|
@ -178,6 +178,7 @@ class MockValue(MagicMock):
|
|||
MockValue._mock_value_id += 1
|
||||
value_id = MockValue._mock_value_id
|
||||
self.value_id = value_id
|
||||
self.object_id = value_id
|
||||
for attr_name in kwargs:
|
||||
setattr(self, attr_name, kwargs[attr_name])
|
||||
|
||||
|
|
Loading…
Reference in New Issue