mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Add Device Registry support and Device Info for ISY994 (#35435)
* ISY994 Add device info properties * Fix test string literal per review. * Change Mfr ID to Devtype_gen
This commit is contained in:
parent
0fabd73ad4
commit
0cf1ca7736
@ -11,6 +11,7 @@ from homeassistant import config_entries
|
|||||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
import homeassistant.helpers.device_registry as dr
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -26,6 +27,7 @@ from .const import (
|
|||||||
ISY994_ISY,
|
ISY994_ISY,
|
||||||
ISY994_NODES,
|
ISY994_NODES,
|
||||||
ISY994_PROGRAMS,
|
ISY994_PROGRAMS,
|
||||||
|
MANUFACTURER,
|
||||||
SUPPORTED_PLATFORMS,
|
SUPPORTED_PLATFORMS,
|
||||||
SUPPORTED_PROGRAM_PLATFORMS,
|
SUPPORTED_PROGRAM_PLATFORMS,
|
||||||
UNDO_UPDATE_LISTENER,
|
UNDO_UPDATE_LISTENER,
|
||||||
@ -156,6 +158,7 @@ async def async_setup_entry(
|
|||||||
_LOGGER.info(repr(isy.clock))
|
_LOGGER.info(repr(isy.clock))
|
||||||
|
|
||||||
hass_isy_data[ISY994_ISY] = isy
|
hass_isy_data[ISY994_ISY] = isy
|
||||||
|
await _async_get_or_create_isy_device_in_registry(hass, entry, isy)
|
||||||
|
|
||||||
# Load platforms for the devices in the ISY controller that we support.
|
# Load platforms for the devices in the ISY controller that we support.
|
||||||
for platform in SUPPORTED_PLATFORMS:
|
for platform in SUPPORTED_PLATFORMS:
|
||||||
@ -203,6 +206,22 @@ def _async_import_options_from_data_if_missing(
|
|||||||
hass.config_entries.async_update_entry(entry, options=options)
|
hass.config_entries.async_update_entry(entry, options=options)
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_get_or_create_isy_device_in_registry(
|
||||||
|
hass: HomeAssistant, entry: config_entries.ConfigEntry, isy
|
||||||
|
) -> None:
|
||||||
|
device_registry = await dr.async_get_registry(hass)
|
||||||
|
|
||||||
|
device_registry.async_get_or_create(
|
||||||
|
config_entry_id=entry.entry_id,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, isy.configuration["uuid"])},
|
||||||
|
identifiers={(DOMAIN, isy.configuration["uuid"])},
|
||||||
|
manufacturer=MANUFACTURER,
|
||||||
|
name=isy.configuration["name"],
|
||||||
|
model=isy.configuration["model"],
|
||||||
|
sw_version=isy.configuration["firmware"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(
|
async def async_unload_entry(
|
||||||
hass: HomeAssistant, entry: config_entries.ConfigEntry
|
hass: HomeAssistant, entry: config_entries.ConfigEntry
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
@ -5,6 +5,8 @@ from pyisy.constants import (
|
|||||||
EMPTY_TIME,
|
EMPTY_TIME,
|
||||||
EVENT_PROPS_IGNORED,
|
EVENT_PROPS_IGNORED,
|
||||||
ISY_VALUE_UNKNOWN,
|
ISY_VALUE_UNKNOWN,
|
||||||
|
PROTO_GROUP,
|
||||||
|
PROTO_ZWAVE,
|
||||||
)
|
)
|
||||||
from pyisy.helpers import NodeProperty
|
from pyisy.helpers import NodeProperty
|
||||||
|
|
||||||
@ -12,6 +14,8 @@ from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNKNOWN
|
|||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.typing import Dict
|
from homeassistant.helpers.typing import Dict
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
class ISYEntity(Entity):
|
class ISYEntity(Entity):
|
||||||
"""Representation of an ISY994 device."""
|
"""Representation of an ISY994 device."""
|
||||||
@ -53,6 +57,53 @@ class ISYEntity(Entity):
|
|||||||
|
|
||||||
self.hass.bus.fire("isy994_control", event_data)
|
self.hass.bus.fire("isy994_control", event_data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self):
|
||||||
|
"""Return the device_info of the device."""
|
||||||
|
if hasattr(self._node, "protocol") and self._node.protocol == PROTO_GROUP:
|
||||||
|
# not a device
|
||||||
|
return None
|
||||||
|
uuid = self._node.isy.configuration["uuid"]
|
||||||
|
node = self._node
|
||||||
|
basename = self.name
|
||||||
|
|
||||||
|
if hasattr(self._node, "parent_node") and self._node.parent_node is not None:
|
||||||
|
# This is not the parent node, get the parent node.
|
||||||
|
node = self._node.parent_node
|
||||||
|
basename = node.name
|
||||||
|
|
||||||
|
device_info = {
|
||||||
|
"name": basename,
|
||||||
|
"identifiers": {},
|
||||||
|
"model": "Unknown",
|
||||||
|
"manufacturer": "Unknown",
|
||||||
|
"via_device": (DOMAIN, uuid),
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasattr(node, "address"):
|
||||||
|
device_info["name"] += f" ({node.address})"
|
||||||
|
if hasattr(node, "primary_node"):
|
||||||
|
device_info["identifiers"] = {(DOMAIN, f"{uuid}_{node.address}")}
|
||||||
|
# ISYv5 Device Types
|
||||||
|
if hasattr(node, "node_def_id") and node.node_def_id is not None:
|
||||||
|
device_info["model"] = node.node_def_id
|
||||||
|
# Numerical Device Type
|
||||||
|
if hasattr(node, "type") and node.type is not None:
|
||||||
|
device_info["model"] += f" {node.type}"
|
||||||
|
if hasattr(node, "protocol"):
|
||||||
|
device_info["manufacturer"] = node.protocol
|
||||||
|
if node.protocol == PROTO_ZWAVE:
|
||||||
|
# Get extra information for Z-Wave Devices
|
||||||
|
device_info["manufacturer"] += f" MfrID:{node.zwave_props.mfr_id}"
|
||||||
|
device_info["model"] += (
|
||||||
|
f" Type:{node.zwave_props.devtype_gen} "
|
||||||
|
f"ProductTypeID:{node.zwave_props.prod_type_id} "
|
||||||
|
f"ProductID:{node.zwave_props.product_id}"
|
||||||
|
)
|
||||||
|
# Note: sw_version is not exposed by the ISY for the individual devices.
|
||||||
|
|
||||||
|
return device_info
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
"""Get the unique identifier of the device."""
|
"""Get the unique identifier of the device."""
|
||||||
|
@ -74,7 +74,7 @@ async def test_form(hass: HomeAssistantType):
|
|||||||
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
|
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
|
||||||
) as mock_setup_entry:
|
) as mock_setup_entry:
|
||||||
isy_conn = mock_connection_class.return_value
|
isy_conn = mock_connection_class.return_value
|
||||||
isy_conn.get_config.return_value = "<xml></xml>"
|
isy_conn.get_config.return_value = None
|
||||||
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], MOCK_USER_INPUT,
|
result["flow_id"], MOCK_USER_INPUT,
|
||||||
@ -154,7 +154,7 @@ async def test_form_existing_config_entry(hass: HomeAssistantType):
|
|||||||
PATCH_CONNECTION
|
PATCH_CONNECTION
|
||||||
) as mock_connection_class:
|
) as mock_connection_class:
|
||||||
isy_conn = mock_connection_class.return_value
|
isy_conn = mock_connection_class.return_value
|
||||||
isy_conn.get_config.return_value = "<xml></xml>"
|
isy_conn.get_config.return_value = None
|
||||||
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], MOCK_USER_INPUT,
|
result["flow_id"], MOCK_USER_INPUT,
|
||||||
@ -170,7 +170,7 @@ async def test_import_flow_some_fields(hass: HomeAssistantType) -> None:
|
|||||||
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
|
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
|
||||||
):
|
):
|
||||||
isy_conn = mock_connection_class.return_value
|
isy_conn = mock_connection_class.return_value
|
||||||
isy_conn.get_config.return_value = "<xml></xml>"
|
isy_conn.get_config.return_value = None
|
||||||
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=MOCK_IMPORT_BASIC_CONFIG,
|
DOMAIN, context={"source": SOURCE_IMPORT}, data=MOCK_IMPORT_BASIC_CONFIG,
|
||||||
@ -190,7 +190,7 @@ async def test_import_flow_all_fields(hass: HomeAssistantType) -> None:
|
|||||||
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
|
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
|
||||||
):
|
):
|
||||||
isy_conn = mock_connection_class.return_value
|
isy_conn = mock_connection_class.return_value
|
||||||
isy_conn.get_config.return_value = "<xml></xml>"
|
isy_conn.get_config.return_value = None
|
||||||
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
mock_config_class.return_value = MOCK_VALIDATED_RESPONSE
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=MOCK_IMPORT_FULL_CONFIG,
|
DOMAIN, context={"source": SOURCE_IMPORT}, data=MOCK_IMPORT_FULL_CONFIG,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user