-
-
Notifications
You must be signed in to change notification settings - Fork 37.8k
ZHA - add events for remote like devices #18493
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
Changes from 8 commits
8c69c15
c4af1e2
9076fe5
3b1e44a
d050473
e13745b
857c2a2
e3a4ff7
867ad95
d0194d4
3189973
0a0938b
b3a0020
f0a2d97
93f38e1
9d6f00c
96445b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,6 +144,8 @@ def __init__(self, hass, config): | |
| self._config = config | ||
| self._component = EntityComponent(_LOGGER, DOMAIN, hass) | ||
| self._device_registry = collections.defaultdict(list) | ||
| import homeassistant.components.zha.const as zha_const | ||
| self._events = [] | ||
| hass.data[DISCOVERY_KEY] = hass.data.get(DISCOVERY_KEY, {}) | ||
|
|
||
| def device_joined(self, device): | ||
|
|
@@ -177,6 +179,7 @@ def device_removed(self, device): | |
| async def async_device_initialized(self, device, join): | ||
| """Handle device joined and basic information discovered (async).""" | ||
| import zigpy.profiles | ||
| import homeassistant.components.zha.event | ||
|
dmulcahey marked this conversation as resolved.
Outdated
|
||
| import homeassistant.components.zha.const as zha_const | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please move this too.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a design issue w/ the modules that causes circular imports. I have it corrected in another branch and can fix this in a subsequent PR if that is ok. |
||
| zha_const.populate_data() | ||
|
|
||
|
|
@@ -197,6 +200,46 @@ async def async_device_initialized(self, device, join): | |
| node_config = self._config[DOMAIN][CONF_DEVICE_CONFIG].get( | ||
| device_key, {}) | ||
|
|
||
| _LOGGER.debug( | ||
| "Manufacturer: %s model: %s", | ||
| endpoint.manufacturer, | ||
| endpoint.model | ||
| ) | ||
|
|
||
| supported_remote_models = zha_const.REMOTE_DEVICE_TYPES.get( | ||
| endpoint.profile_id, {}).get(endpoint.manufacturer, []) | ||
|
|
||
| _LOGGER.debug( | ||
| "Supported remote models: %s", | ||
| supported_remote_models | ||
| ) | ||
|
|
||
| if endpoint.profile_id in zigpy.profiles.PROFILES and \ | ||
| endpoint.model in supported_remote_models: | ||
| profile = zigpy.profiles.PROFILES[endpoint.profile_id] | ||
| profile_clusters = profile.CLUSTERS[endpoint.device_type] | ||
| in_clusters = [endpoint.in_clusters[c] | ||
| for c in profile_clusters[0] | ||
| if c in endpoint.in_clusters] | ||
| out_clusters = [endpoint.out_clusters[c] | ||
| for c in profile_clusters[1] | ||
| if c in endpoint.out_clusters] | ||
| discovery_info = { | ||
| 'application_listener': self, | ||
| 'endpoint': endpoint, | ||
| 'in_clusters': in_clusters, | ||
| 'out_clusters': out_clusters, | ||
| 'manufacturer': endpoint.manufacturer, | ||
| 'model': endpoint.model, | ||
| 'new_join': join, | ||
| 'unique_id': device_key, | ||
| } | ||
| created_events = await event.async_setup_event( | ||
|
dmulcahey marked this conversation as resolved.
Outdated
|
||
| self._hass, | ||
| discovery_info | ||
| ) | ||
| self._events.extend(created_events) | ||
|
|
||
| if endpoint.profile_id in zigpy.profiles.PROFILES: | ||
| profile = zigpy.profiles.PROFILES[endpoint.profile_id] | ||
| if zha_const.DEVICE_CLASS.get(endpoint.profile_id, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| """ | ||
| Support for Zigbee Home Automation devices that should fire events. | ||
|
|
||
| For more details about this component, please refer to the documentation at | ||
| https://home-assistant.io/components/zha/ | ||
| """ | ||
| import logging | ||
| from homeassistant.util import slugify | ||
| from homeassistant.core import EventOrigin, callback | ||
|
|
||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| async def async_setup_event(hass, discovery_info): | ||
| """Set up events for devices that have been registered in const.py. | ||
|
|
||
| Will create events for devices registered in REMOTE_DEVICE_TYPES. | ||
| """ | ||
| from homeassistant.components.zha import const as zha_const | ||
|
dmulcahey marked this conversation as resolved.
Outdated
|
||
| from homeassistant.components.zha import configure_reporting | ||
| out_clusters = discovery_info['out_clusters'] | ||
| in_clusters = discovery_info['in_clusters'] | ||
| events = [] | ||
| for in_cluster in in_clusters: | ||
| event = ZHAEvent(hass, in_cluster, discovery_info) | ||
| if discovery_info['new_join']: | ||
| await configure_reporting(event.event_id, in_cluster, 0, | ||
| False, 0, 600, 1) | ||
| events.append(event) | ||
| for out_cluster in out_clusters: | ||
| event = ZHAEvent(hass, out_cluster, discovery_info) | ||
| if discovery_info['new_join']: | ||
| await configure_reporting(event.event_id, out_cluster, 0, | ||
| False, 0, 600, 1) | ||
| events.append(event) | ||
| return events | ||
|
|
||
|
|
||
| class ZHAEvent(): | ||
| """When you want signals instead of entities. | ||
| Stateless sensors such as remotes are expected to generate an event | ||
| instead of a sensor entity in hass. | ||
| """ | ||
|
|
||
| def __init__(self, hass, cluster, discovery_info): | ||
| """Register callback that will be used for signals.""" | ||
| self._hass = hass | ||
| self._cluster = cluster | ||
| self._cluster.add_listener(self) | ||
| ieee = discovery_info['endpoint'].device.ieee | ||
| ieeetail = ''.join(['%02x' % (o, ) for o in ieee[-4:]]) | ||
| if discovery_info['manufacturer'] and discovery_info['model'] is not \ | ||
| None: | ||
| self.event_id = "{}.{}_{}_{}{}".format( | ||
| slugify(discovery_info['manufacturer']), | ||
| slugify(discovery_info['model']), | ||
| ieeetail, | ||
| discovery_info['endpoint'].endpoint_id, | ||
| discovery_info.get('entity_suffix', '') | ||
| ) | ||
| else: | ||
| self.event_id = "{}.event_{}{}".format( | ||
| ieeetail, | ||
| discovery_info['endpoint'].endpoint_id, | ||
| discovery_info.get('entity_suffix', '') | ||
| ) | ||
|
|
||
| @callback | ||
| def cluster_command(self, tsn, command_id, args): | ||
| """Handle commands received to this cluster.""" | ||
| self._hass.bus.async_fire( | ||
| 'zha_' + self._cluster.server_commands.get(command_id)[0], | ||
| {'device': self.event_id, 'args': args}, | ||
| EventOrigin.remote | ||
| ) | ||
| _LOGGER.debug( | ||
|
dmulcahey marked this conversation as resolved.
Outdated
|
||
| "%s: fired %s event with arguments: %s", self.event_id, | ||
| self._cluster.server_commands.get(command_id)[0], | ||
| args | ||
| ) | ||
|
|
||
| @callback | ||
| def attribute_updated(self, attrid, value): | ||
| """Handle attribute updates.""" | ||
| self._hass.bus.async_fire( | ||
| 'zha_attribute_updated', | ||
| {'device': self.event_id, | ||
| 'attribute': self._cluster.attributes.get(attrid, ['Unknown'])[0], | ||
| 'attribute_id': attrid, | ||
| 'value': value}, | ||
| EventOrigin.remote | ||
| ) | ||
| _LOGGER.debug( | ||
|
dmulcahey marked this conversation as resolved.
Outdated
|
||
| "%s: updated attribute %s with value: %s and id: %s", | ||
| self.event_id, | ||
| self._cluster.attributes.get(attrid, ['Unknown'])[0], | ||
| value, | ||
| attrid | ||
| ) | ||
|
|
||
| @callback | ||
| def zdo_command(self, *args, **kwargs): | ||
|
MartinHjelmare marked this conversation as resolved.
|
||
| """log zdo commands for debugging.""" | ||
| _LOGGER.debug( | ||
| "%s: issued zdo command %s with args: %s", self.event_id, | ||
| args, | ||
| kwargs | ||
| ) | ||
Uh oh!
There was an error while loading. Please reload this page.