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:
shbatm 2020-05-09 19:48:51 -05:00 committed by GitHub
parent 0fabd73ad4
commit 0cf1ca7736
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 4 deletions

View File

@ -11,6 +11,7 @@ from homeassistant import config_entries
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
import homeassistant.helpers.device_registry as dr
from homeassistant.helpers.typing import ConfigType
from .const import (
@ -26,6 +27,7 @@ from .const import (
ISY994_ISY,
ISY994_NODES,
ISY994_PROGRAMS,
MANUFACTURER,
SUPPORTED_PLATFORMS,
SUPPORTED_PROGRAM_PLATFORMS,
UNDO_UPDATE_LISTENER,
@ -156,6 +158,7 @@ async def async_setup_entry(
_LOGGER.info(repr(isy.clock))
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.
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)
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(
hass: HomeAssistant, entry: config_entries.ConfigEntry
) -> bool:

View File

@ -5,6 +5,8 @@ from pyisy.constants import (
EMPTY_TIME,
EVENT_PROPS_IGNORED,
ISY_VALUE_UNKNOWN,
PROTO_GROUP,
PROTO_ZWAVE,
)
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.typing import Dict
from .const import DOMAIN
class ISYEntity(Entity):
"""Representation of an ISY994 device."""
@ -53,6 +57,53 @@ class ISYEntity(Entity):
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
def unique_id(self) -> str:
"""Get the unique identifier of the device."""

View File

@ -74,7 +74,7 @@ async def test_form(hass: HomeAssistantType):
PATCH_ASYNC_SETUP_ENTRY, return_value=True,
) as mock_setup_entry:
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
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], MOCK_USER_INPUT,
@ -154,7 +154,7 @@ async def test_form_existing_config_entry(hass: HomeAssistantType):
PATCH_CONNECTION
) as mock_connection_class:
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
result2 = await hass.config_entries.flow.async_configure(
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,
):
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
result = await hass.config_entries.flow.async_init(
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,
):
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
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=MOCK_IMPORT_FULL_CONFIG,