mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Look at registry before pulling zwave config values (#14408)
* Look at registry before deciding on ID for zwave values * Reuse the new function
This commit is contained in:
parent
7aec098a05
commit
d1228d5cf4
@ -16,10 +16,11 @@ from homeassistant.loader import get_platform
|
|||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.helpers.entity import generate_entity_id
|
from homeassistant.helpers.entity import generate_entity_id
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
|
from homeassistant.helpers.entity_registry import async_get_registry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
|
ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
|
||||||
from homeassistant.helpers.entity_values import EntityValues
|
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
|
from homeassistant.util import convert
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
@ -218,7 +219,7 @@ async def async_setup_platform(hass, config, async_add_devices,
|
|||||||
|
|
||||||
|
|
||||||
# pylint: disable=R0914
|
# pylint: disable=R0914
|
||||||
def setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
"""Set up Z-Wave.
|
"""Set up Z-Wave.
|
||||||
|
|
||||||
Will automatically load components to support devices found on the network.
|
Will automatically load components to support devices found on the network.
|
||||||
@ -286,7 +287,7 @@ def setup(hass, config):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
values = ZWaveDeviceEntityValues(
|
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
|
# We create a new list and update the reference here so that
|
||||||
# the list can be safely iterated over in the main thread
|
# 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
|
hass.data[DATA_ENTITY_VALUES] = new_values
|
||||||
|
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
registry = await async_get_registry(hass)
|
||||||
|
|
||||||
def node_added(node):
|
def node_added(node):
|
||||||
"""Handle a new node on the network."""
|
"""Handle a new node on the network."""
|
||||||
@ -702,9 +704,9 @@ def setup(hass, config):
|
|||||||
# Setup autoheal
|
# Setup autoheal
|
||||||
if autoheal:
|
if autoheal:
|
||||||
_LOGGER.info("Z-Wave network autoheal is enabled")
|
_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
|
return True
|
||||||
|
|
||||||
@ -713,7 +715,7 @@ class ZWaveDeviceEntityValues():
|
|||||||
"""Manages entity access to the underlying zwave value objects."""
|
"""Manages entity access to the underlying zwave value objects."""
|
||||||
|
|
||||||
def __init__(self, hass, schema, primary_value, zwave_config,
|
def __init__(self, hass, schema, primary_value, zwave_config,
|
||||||
device_config):
|
device_config, registry):
|
||||||
"""Initialize the values object with the passed entity schema."""
|
"""Initialize the values object with the passed entity schema."""
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._zwave_config = zwave_config
|
self._zwave_config = zwave_config
|
||||||
@ -722,6 +724,7 @@ class ZWaveDeviceEntityValues():
|
|||||||
self._values = {}
|
self._values = {}
|
||||||
self._entity = None
|
self._entity = None
|
||||||
self._workaround_ignore = False
|
self._workaround_ignore = False
|
||||||
|
self._registry = registry
|
||||||
|
|
||||||
for name in self._schema[const.DISC_VALUES].keys():
|
for name in self._schema[const.DISC_VALUES].keys():
|
||||||
self._values[name] = None
|
self._values[name] = None
|
||||||
@ -794,9 +797,13 @@ class ZWaveDeviceEntityValues():
|
|||||||
workaround_component, component)
|
workaround_component, component)
|
||||||
component = workaround_component
|
component = workaround_component
|
||||||
|
|
||||||
value_name = _value_name(self.primary)
|
entity_id = self._registry.async_get_entity_id(
|
||||||
generated_id = generate_entity_id(component + '.{}', value_name, [])
|
component, DOMAIN,
|
||||||
node_config = self._device_config.get(generated_id)
|
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
|
# Configure node
|
||||||
_LOGGER.debug("Adding Node_id=%s Generic_command_class=%s, "
|
_LOGGER.debug("Adding Node_id=%s Generic_command_class=%s, "
|
||||||
@ -809,7 +816,7 @@ class ZWaveDeviceEntityValues():
|
|||||||
|
|
||||||
if node_config.get(CONF_IGNORED):
|
if node_config.get(CONF_IGNORED):
|
||||||
_LOGGER.info(
|
_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
|
# No entity will be created for this value
|
||||||
self._workaround_ignore = True
|
self._workaround_ignore = True
|
||||||
return
|
return
|
||||||
@ -964,6 +971,10 @@ class ZWaveDeviceEntity(ZWaveBaseEntity):
|
|||||||
if (is_node_parsed(self.node) and
|
if (is_node_parsed(self.node) and
|
||||||
self.values.primary.label != "Unknown") or \
|
self.values.primary.label != "Unknown") or \
|
||||||
self.node.is_ready:
|
self.node.is_ready:
|
||||||
return "{}-{}".format(self.node.node_id,
|
return compute_value_unique_id(self.node, self.values.primary)
|
||||||
self.values.primary.object_id)
|
|
||||||
return None
|
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."""
|
"""Check if an entity_id is currently registered."""
|
||||||
return entity_id in self.entities
|
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
|
@callback
|
||||||
def async_generate_entity_id(self, domain, suggested_object_id):
|
def async_generate_entity_id(self, domain, suggested_object_id):
|
||||||
"""Generate an entity ID that does not conflict.
|
"""Generate an entity ID that does not conflict.
|
||||||
@ -99,10 +108,9 @@ class EntityRegistry:
|
|||||||
def async_get_or_create(self, domain, platform, unique_id, *,
|
def async_get_or_create(self, domain, platform, unique_id, *,
|
||||||
suggested_object_id=None):
|
suggested_object_id=None):
|
||||||
"""Get entity. Create if it doesn't exist."""
|
"""Get entity. Create if it doesn't exist."""
|
||||||
for entity in self.entities.values():
|
entity_id = self.async_get_entity_id(domain, platform, unique_id)
|
||||||
if entity.domain == domain and entity.platform == platform and \
|
if entity_id:
|
||||||
entity.unique_id == unique_id:
|
return self.entities[entity_id]
|
||||||
return entity
|
|
||||||
|
|
||||||
entity_id = self.async_generate_entity_id(
|
entity_id = self.async_generate_entity_id(
|
||||||
domain, suggested_object_id or '{}_{}'.format(platform, unique_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 (
|
from homeassistant.components.zwave import (
|
||||||
const, CONFIG_SCHEMA, CONF_DEVICE_CONFIG_GLOB, DATA_NETWORK)
|
const, CONFIG_SCHEMA, CONF_DEVICE_CONFIG_GLOB, DATA_NETWORK)
|
||||||
from homeassistant.setup import setup_component
|
from homeassistant.setup import setup_component
|
||||||
|
from tests.common import mock_registry
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -468,6 +469,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
"""Initialize values for this testcase class."""
|
"""Initialize values for this testcase class."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.start()
|
self.hass.start()
|
||||||
|
self.registry = mock_registry(self.hass)
|
||||||
|
|
||||||
setup_component(self.hass, 'zwave', {'zwave': {}})
|
setup_component(self.hass, 'zwave', {'zwave': {}})
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
@ -487,7 +489,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
const.DISC_OPTIONAL: True,
|
const.DISC_OPTIONAL: True,
|
||||||
}}}
|
}}}
|
||||||
self.primary = MockValue(
|
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(
|
self.secondary = MockValue(
|
||||||
command_class='mock_secondary_class', node=self.node)
|
command_class='mock_secondary_class', node=self.node)
|
||||||
self.duplicate_secondary = MockValue(
|
self.duplicate_secondary = MockValue(
|
||||||
@ -521,6 +523,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
|
|
||||||
assert values.primary is self.primary
|
assert values.primary is self.primary
|
||||||
@ -592,6 +595,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
@ -630,6 +634,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
values._check_entity_ready()
|
values._check_entity_ready()
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
@ -639,7 +644,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
@patch.object(zwave, 'get_platform')
|
@patch.object(zwave, 'get_platform')
|
||||||
@patch.object(zwave, 'discovery')
|
@patch.object(zwave, 'discovery')
|
||||||
def test_entity_workaround_component(self, discovery, get_platform):
|
def test_entity_workaround_component(self, discovery, get_platform):
|
||||||
"""Test ignore workaround."""
|
"""Test component workaround."""
|
||||||
discovery.async_load_platform.return_value = mock_coro()
|
discovery.async_load_platform.return_value = mock_coro()
|
||||||
mock_platform = MagicMock()
|
mock_platform = MagicMock()
|
||||||
get_platform.return_value = mock_platform
|
get_platform.return_value = mock_platform
|
||||||
@ -666,6 +671,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
values._check_entity_ready()
|
values._check_entity_ready()
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
@ -697,6 +703,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
values._check_entity_ready()
|
values._check_entity_ready()
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
@ -720,12 +727,42 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
values._check_entity_ready()
|
values._check_entity_ready()
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert not discovery.async_load_platform.called
|
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, 'get_platform')
|
||||||
@patch.object(zwave, 'discovery')
|
@patch.object(zwave, 'discovery')
|
||||||
def test_entity_platform_ignore(self, discovery, get_platform):
|
def test_entity_platform_ignore(self, discovery, get_platform):
|
||||||
@ -743,6 +780,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
@ -770,6 +808,7 @@ class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|||||||
primary_value=self.primary,
|
primary_value=self.primary,
|
||||||
zwave_config=self.zwave_config,
|
zwave_config=self.zwave_config,
|
||||||
device_config=self.device_config,
|
device_config=self.device_config,
|
||||||
|
registry=self.registry
|
||||||
)
|
)
|
||||||
values._check_entity_ready()
|
values._check_entity_ready()
|
||||||
self.hass.block_till_done()
|
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_hass.disabled_by == entity_registry.DISABLED_HASS
|
||||||
assert entry_disabled_user.disabled
|
assert entry_disabled_user.disabled
|
||||||
assert entry_disabled_user.disabled_by == entity_registry.DISABLED_USER
|
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
|
MockValue._mock_value_id += 1
|
||||||
value_id = MockValue._mock_value_id
|
value_id = MockValue._mock_value_id
|
||||||
self.value_id = value_id
|
self.value_id = value_id
|
||||||
|
self.object_id = value_id
|
||||||
for attr_name in kwargs:
|
for attr_name in kwargs:
|
||||||
setattr(self, attr_name, kwargs[attr_name])
|
setattr(self, attr_name, kwargs[attr_name])
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user