mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Allow ZHA coordinator binding/unbinding (#42854)
* Allow coordinator ZDO binding/unbinding operations * Let coordinator to provide endpoint it * Refactor ClusterPair to a dataclass * Rename ClusterPair
This commit is contained in:
parent
121872c546
commit
4b7829d777
@ -807,18 +807,12 @@ async def async_binding_operation(zha_gateway, source_ieee, target_ieee, operati
|
|||||||
|
|
||||||
clusters_to_bind = await get_matched_clusters(source_device, target_device)
|
clusters_to_bind = await get_matched_clusters(source_device, target_device)
|
||||||
|
|
||||||
|
zdo = source_device.device.zdo
|
||||||
bind_tasks = []
|
bind_tasks = []
|
||||||
for cluster_pair in clusters_to_bind:
|
for binding_pair in clusters_to_bind:
|
||||||
destination_address = zdo_types.MultiAddress()
|
|
||||||
destination_address.addrmode = 3
|
|
||||||
destination_address.ieee = target_device.ieee
|
|
||||||
destination_address.endpoint = cluster_pair.target_cluster.endpoint.endpoint_id
|
|
||||||
|
|
||||||
zdo = cluster_pair.source_cluster.endpoint.device.zdo
|
|
||||||
|
|
||||||
op_msg = "cluster: %s %s --> [%s]"
|
op_msg = "cluster: %s %s --> [%s]"
|
||||||
op_params = (
|
op_params = (
|
||||||
cluster_pair.source_cluster.cluster_id,
|
binding_pair.source_cluster.cluster_id,
|
||||||
operation.name,
|
operation.name,
|
||||||
target_ieee,
|
target_ieee,
|
||||||
)
|
)
|
||||||
@ -829,9 +823,9 @@ async def async_binding_operation(zha_gateway, source_ieee, target_ieee, operati
|
|||||||
zdo.request(
|
zdo.request(
|
||||||
operation,
|
operation,
|
||||||
source_device.ieee,
|
source_device.ieee,
|
||||||
cluster_pair.source_cluster.endpoint.endpoint_id,
|
binding_pair.source_cluster.endpoint.endpoint_id,
|
||||||
cluster_pair.source_cluster.cluster_id,
|
binding_pair.source_cluster.cluster_id,
|
||||||
destination_address,
|
binding_pair.destination_address,
|
||||||
),
|
),
|
||||||
op_msg,
|
op_msg,
|
||||||
op_params,
|
op_params,
|
||||||
|
@ -7,7 +7,7 @@ https://home-assistant.io/integrations/zha/
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import binascii
|
import binascii
|
||||||
import collections
|
from dataclasses import dataclass
|
||||||
import functools
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
@ -19,13 +19,29 @@ import voluptuous as vol
|
|||||||
import zigpy.exceptions
|
import zigpy.exceptions
|
||||||
import zigpy.types
|
import zigpy.types
|
||||||
import zigpy.util
|
import zigpy.util
|
||||||
|
import zigpy.zdo.types as zdo_types
|
||||||
|
|
||||||
from homeassistant.core import State, callback
|
from homeassistant.core import State, callback
|
||||||
|
|
||||||
from .const import CLUSTER_TYPE_IN, CLUSTER_TYPE_OUT, DATA_ZHA, DATA_ZHA_GATEWAY
|
from .const import CLUSTER_TYPE_IN, CLUSTER_TYPE_OUT, DATA_ZHA, DATA_ZHA_GATEWAY
|
||||||
from .registries import BINDABLE_CLUSTERS
|
from .registries import BINDABLE_CLUSTERS
|
||||||
|
from .typing import ZhaDeviceType, ZigpyClusterType
|
||||||
|
|
||||||
ClusterPair = collections.namedtuple("ClusterPair", "source_cluster target_cluster")
|
|
||||||
|
@dataclass
|
||||||
|
class BindingPair:
|
||||||
|
"""Information for binding."""
|
||||||
|
|
||||||
|
source_cluster: ZigpyClusterType
|
||||||
|
target_ieee: zigpy.types.EUI64
|
||||||
|
target_ep_id: int
|
||||||
|
|
||||||
|
@property
|
||||||
|
def destination_address(self) -> zdo_types.MultiAddress:
|
||||||
|
"""Return a ZDO multi address instance."""
|
||||||
|
return zdo_types.MultiAddress(
|
||||||
|
addrmode=3, ieee=self.target_ieee, endpoint=self.target_ep_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def safe_read(
|
async def safe_read(
|
||||||
@ -49,7 +65,9 @@ async def safe_read(
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
async def get_matched_clusters(source_zha_device, target_zha_device):
|
async def get_matched_clusters(
|
||||||
|
source_zha_device: ZhaDeviceType, target_zha_device: ZhaDeviceType
|
||||||
|
) -> List[BindingPair]:
|
||||||
"""Get matched input/output cluster pairs for 2 devices."""
|
"""Get matched input/output cluster pairs for 2 devices."""
|
||||||
source_clusters = source_zha_device.async_get_std_clusters()
|
source_clusters = source_zha_device.async_get_std_clusters()
|
||||||
target_clusters = target_zha_device.async_get_std_clusters()
|
target_clusters = target_zha_device.async_get_std_clusters()
|
||||||
@ -59,15 +77,26 @@ async def get_matched_clusters(source_zha_device, target_zha_device):
|
|||||||
for cluster_id in source_clusters[endpoint_id][CLUSTER_TYPE_OUT]:
|
for cluster_id in source_clusters[endpoint_id][CLUSTER_TYPE_OUT]:
|
||||||
if cluster_id not in BINDABLE_CLUSTERS:
|
if cluster_id not in BINDABLE_CLUSTERS:
|
||||||
continue
|
continue
|
||||||
|
if target_zha_device.nwk == 0x0000:
|
||||||
|
cluster_pair = BindingPair(
|
||||||
|
source_cluster=source_clusters[endpoint_id][CLUSTER_TYPE_OUT][
|
||||||
|
cluster_id
|
||||||
|
],
|
||||||
|
target_ieee=target_zha_device.ieee,
|
||||||
|
target_ep_id=target_zha_device.device.application.get_endpoint_id(
|
||||||
|
cluster_id, is_server_cluster=True
|
||||||
|
),
|
||||||
|
)
|
||||||
|
clusters_to_bind.append(cluster_pair)
|
||||||
|
continue
|
||||||
for t_endpoint_id in target_clusters:
|
for t_endpoint_id in target_clusters:
|
||||||
if cluster_id in target_clusters[t_endpoint_id][CLUSTER_TYPE_IN]:
|
if cluster_id in target_clusters[t_endpoint_id][CLUSTER_TYPE_IN]:
|
||||||
cluster_pair = ClusterPair(
|
cluster_pair = BindingPair(
|
||||||
source_cluster=source_clusters[endpoint_id][CLUSTER_TYPE_OUT][
|
source_cluster=source_clusters[endpoint_id][CLUSTER_TYPE_OUT][
|
||||||
cluster_id
|
cluster_id
|
||||||
],
|
],
|
||||||
target_cluster=target_clusters[t_endpoint_id][CLUSTER_TYPE_IN][
|
target_ieee=target_zha_device.ieee,
|
||||||
cluster_id
|
target_ep_id=t_endpoint_id,
|
||||||
],
|
|
||||||
)
|
)
|
||||||
clusters_to_bind.append(cluster_pair)
|
clusters_to_bind.append(cluster_pair)
|
||||||
return clusters_to_bind
|
return clusters_to_bind
|
||||||
@ -76,6 +105,9 @@ async def get_matched_clusters(source_zha_device, target_zha_device):
|
|||||||
@callback
|
@callback
|
||||||
def async_is_bindable_target(source_zha_device, target_zha_device):
|
def async_is_bindable_target(source_zha_device, target_zha_device):
|
||||||
"""Determine if target is bindable to source."""
|
"""Determine if target is bindable to source."""
|
||||||
|
if target_zha_device.nwk == 0x0000:
|
||||||
|
return True
|
||||||
|
|
||||||
source_clusters = source_zha_device.async_get_std_clusters()
|
source_clusters = source_zha_device.async_get_std_clusters()
|
||||||
target_clusters = target_zha_device.async_get_std_clusters()
|
target_clusters = target_zha_device.async_get_std_clusters()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user