Add Zigbee group binding to ZHA (#30433)
* initial group binding work * add group cluster binding
This commit is contained in:
parent
967fe89f6d
commit
6c89b6c5a2
3 changed files with 132 additions and 0 deletions
|
@ -10,10 +10,12 @@ from enum import Enum
|
|||
import logging
|
||||
import time
|
||||
|
||||
from zigpy import types
|
||||
import zigpy.exceptions
|
||||
from zigpy.profiles import zha, zll
|
||||
import zigpy.quirks
|
||||
from zigpy.zcl.clusters.general import Groups
|
||||
import zigpy.zdo.types as zdo_types
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
|
@ -526,6 +528,70 @@ class ZHADevice(LogMixin):
|
|||
"""Remove this device from the provided zigbee group."""
|
||||
await self._zigpy_device.remove_from_group(group_id)
|
||||
|
||||
async def async_bind_to_group(self, group_id, cluster_bindings):
|
||||
"""Directly bind this device to a group for the given clusters."""
|
||||
await self._async_group_binding_operation(
|
||||
group_id, zdo_types.ZDOCmd.Bind_req, cluster_bindings
|
||||
)
|
||||
|
||||
async def async_unbind_from_group(self, group_id, cluster_bindings):
|
||||
"""Unbind this device from a group for the given clusters."""
|
||||
await self._async_group_binding_operation(
|
||||
group_id, zdo_types.ZDOCmd.Unbind_req, cluster_bindings
|
||||
)
|
||||
|
||||
async def _async_group_binding_operation(
|
||||
self, group_id, operation, cluster_bindings
|
||||
):
|
||||
"""Create or remove a direct zigbee binding between a device and a group."""
|
||||
|
||||
zdo = self._zigpy_device.zdo
|
||||
op_msg = "0x%04x: %s %s, ep: %s, cluster: %s to group: 0x%04x"
|
||||
destination_address = zdo_types.MultiAddress()
|
||||
destination_address.addrmode = types.uint8_t(1)
|
||||
destination_address.nwk = types.uint16_t(group_id)
|
||||
|
||||
tasks = []
|
||||
|
||||
for cluster_binding in cluster_bindings:
|
||||
if cluster_binding.endpoint_id == 0:
|
||||
continue
|
||||
if (
|
||||
cluster_binding.id
|
||||
in self._zigpy_device.endpoints[
|
||||
cluster_binding.endpoint_id
|
||||
].out_clusters
|
||||
):
|
||||
op_params = (
|
||||
self.nwk,
|
||||
operation.name,
|
||||
str(self.ieee),
|
||||
cluster_binding.endpoint_id,
|
||||
cluster_binding.id,
|
||||
group_id,
|
||||
)
|
||||
zdo.debug("processing " + op_msg, *op_params)
|
||||
tasks.append(
|
||||
(
|
||||
zdo.request(
|
||||
operation,
|
||||
self.ieee,
|
||||
cluster_binding.endpoint_id,
|
||||
cluster_binding.id,
|
||||
destination_address,
|
||||
),
|
||||
op_msg,
|
||||
op_params,
|
||||
)
|
||||
)
|
||||
res = await asyncio.gather(*(t[0] for t in tasks), return_exceptions=True)
|
||||
for outcome, log_msg in zip(res, tasks):
|
||||
if isinstance(outcome, Exception):
|
||||
fmt = log_msg[1] + " failed: %s"
|
||||
else:
|
||||
fmt = log_msg[1] + " completed: %s"
|
||||
zdo.debug(fmt, *(log_msg[2] + (outcome,)))
|
||||
|
||||
def log(self, level, msg, *args):
|
||||
"""Log a message."""
|
||||
msg = f"[%s](%s): {msg}"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue