Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZHA component rewrite part 3 - update helpers #20463

Merged
merged 4 commits into from
Jan 29, 2019
Merged
Changes from 1 commit
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
50 changes: 43 additions & 7 deletions homeassistant/components/zha/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import asyncio
import logging

from homeassistant.util import slugify

from .const import (
DEFAULT_BAUDRATE, REPORT_CONFIG_MAX_INT, REPORT_CONFIG_MIN_INT,
REPORT_CONFIG_RPT_CHANGE, RadioType)
Expand Down Expand Up @@ -55,7 +57,7 @@ async def bind_cluster(entity_id, cluster):
)


async def configure_reporting(entity_id, cluster, attr, skip_bind=False,
async def configure_reporting(entity_id, cluster, attr,
min_report=REPORT_CONFIG_MIN_INT,
max_report=REPORT_CONFIG_MAX_INT,
reportable_change=REPORT_CONFIG_RPT_CHANGE,
Expand All @@ -68,12 +70,13 @@ async def configure_reporting(entity_id, cluster, attr, skip_bind=False,
from zigpy.exceptions import DeliveryError

attr_name = cluster.attributes.get(attr, [attr])[0]
attr_id = get_attr_id_by_name(cluster, attr_name)
cluster_name = cluster.ep_attribute
kwargs = {}
if manufacturer:
kwargs['manufacturer'] = manufacturer
try:
res = await cluster.configure_reporting(attr, min_report,
res = await cluster.configure_reporting(attr_id, min_report,
max_report, reportable_change,
**kwargs)
_LOGGER.debug(
Expand Down Expand Up @@ -101,11 +104,11 @@ async def bind_configure_reporting(entity_id, cluster, attr, skip_bind=False,
if not skip_bind:
await bind_cluster(entity_id, cluster)

await configure_reporting(entity_id, cluster, attr, skip_bind=False,
min_report=REPORT_CONFIG_MIN_INT,
max_report=REPORT_CONFIG_MAX_INT,
reportable_change=REPORT_CONFIG_RPT_CHANGE,
manufacturer=None)
await configure_reporting(entity_id, cluster, attr,
min_report=min_report,
max_report=max_report,
reportable_change=reportable_change,
manufacturer=manufacturer)


async def check_zigpy_connection(usb_path, radio_type, database_path):
Expand Down Expand Up @@ -136,3 +139,36 @@ def convert_ieee(ieee_str):
"""Convert given ieee string to EUI64."""
from zigpy.types import EUI64, uint8_t
return EUI64([uint8_t(p, base=16) for p in ieee_str.split(':')])


def construct_unique_id(cluster):
"""Construct a unique id from a cluster."""
ieee = cluster.endpoint.device.ieee
ieeetail = ''.join(['%02x' % (o, ) for o in ieee[-4:]])
manufacturer = cluster.endpoint.manufacturer
model = cluster.endpoint.model
unique_id = None
if manufacturer and model is not None:
unique_id = "{}_{}_{}_{}_{}".format(
slugify(manufacturer),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would we include manufacturer and model in unique ID? Could they otherwise overlap?

Copy link
Contributor Author

@dmulcahey dmulcahey Jan 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really. This keeps them in line with the existing entity Id structure that is already in place. It makes it a lot easier to eyeball debug logs too. I know that isn't the best reason but the entity ids for ZHA are already like this and I figured the consistency and the easier identification in debug logs were worth it.

EDIT The plan is to also make a slight modification to it in the future and use it here So I would like to avoid a breaking change when I do this if it is permissible.

Copy link
Contributor

@Adminiuga Adminiuga Jan 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I say we leave the unique_id based on IEEE + Endpoint (for ZHA profile devices) or IEEE + Endpoint + Cluster_ID (for zha single cluster devices). My opinion: it is fine for entity_id to include manufacturer/model etc, but unique ID should be left as it was prior.
And it also going to be a big breaking change. I'd rather rename this into construct_entity_id()

Copy link
Contributor Author

@dmulcahey dmulcahey Jan 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do ieee + endpoint + cluster

To be clear this is currently only used in listeners (later PR). I did it this way to align them with entity ids so the logic could be shared in the future but I can def change to what is suggested above. This will have nothing to do with entity ids at that point so the name won’t change

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just didn't want this to become a HA entity unique_id. I guess no restrictions for use inside the listeners, but as you mentioned it does rise a question of easily identifiable names in listeners debug output.
If we go by the premise that listeners are more closely related to Zigpy, have you dismissed idea of using the [0xNWK:EP_ID:Cluster_ID] format for logging, same as it is in Zigpy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. Was just making sure the intent was clear. I’ll align on that it will make our lives a lot easier!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should never change unique IDs. It gives a really bad user experience, as all entities will get new entity IDs, as their old ones are reserved for their previous unique IDs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if this is new code, leave the unique ids.

Copy link
Contributor Author

@dmulcahey dmulcahey Jan 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All new and not anything that will affect the users. This is to identify different listener implementations (coming in future PR) and they have no tie to entities. I was going to unify them in a non breaking fashion later but we decided against it. I can rename this to listener_id to avoid confusion in the future if that helps.

slugify(model),
ieeetail,
cluster.endpoint.endpoint_id,
cluster.cluster_id,
)
else:
unique_id = "zha_{}_{}_{}".format(
ieeetail,
cluster.endpoint.endpoint_id,
cluster.cluster_id,
)
return unique_id


def get_attr_id_by_name(cluster, attr_name):
"""Get the attribute id for a cluster attribute by its name."""
cluster_attributes = {}
# pylint: disable=W0612
for attrid, (attrname, datatype) in cluster.attributes.items():
cluster_attributes[attrname] = attrid
dmulcahey marked this conversation as resolved.
Show resolved Hide resolved
return cluster_attributes[attr_name]