|
10 | 10 | import zigpy.util |
11 | 11 | import zigpy_deconz.exception |
12 | 12 | from zigpy_deconz import types as t |
13 | | -from zigpy_deconz.api import NetworkParameter, NetworkState |
| 13 | +from zigpy_deconz.api import NetworkParameter, NetworkState, Status |
14 | 14 |
|
15 | 15 | LOGGER = logging.getLogger(__name__) |
16 | 16 |
|
@@ -83,6 +83,61 @@ async def form_network(self, channel=15, pan_id=None, extended_pan_id=None): |
83 | 83 | await asyncio.sleep(CHANGE_NETWORK_WAIT) |
84 | 84 | raise Exception("Could not form network.") |
85 | 85 |
|
| 86 | + async def mrequest( |
| 87 | + self, |
| 88 | + group_id, |
| 89 | + profile, |
| 90 | + cluster, |
| 91 | + src_ep, |
| 92 | + sequence, |
| 93 | + data, |
| 94 | + *, |
| 95 | + hops=0, |
| 96 | + non_member_radius=3 |
| 97 | + ): |
| 98 | + """Submit and send data out as a multicast transmission. |
| 99 | +
|
| 100 | + :param group_id: destination multicast address |
| 101 | + :param profile: Zigbee Profile ID to use for outgoing message |
| 102 | + :param cluster: cluster id where the message is being sent |
| 103 | + :param src_ep: source endpoint id |
| 104 | + :param sequence: transaction sequence number of the message |
| 105 | + :param data: Zigbee message payload |
| 106 | + :param hops: the message will be delivered to all nodes within this number of |
| 107 | + hops of the sender. A value of zero is converted to MAX_HOPS |
| 108 | + :param non_member_radius: the number of hops that the message will be forwarded |
| 109 | + by devices that are not members of the group. A value |
| 110 | + of 7 or greater is treated as infinite |
| 111 | + :returns: return a tuple of a status and an error_message. Original requestor |
| 112 | + has more context to provide a more meaningful error message |
| 113 | + """ |
| 114 | + req_id = self.get_sequence() |
| 115 | + LOGGER.debug("Sending Zigbee multicast with tsn %s under %s request id, data: %s", |
| 116 | + sequence, req_id, binascii.hexlify(data)) |
| 117 | + dst_addr_ep = t.DeconzAddressEndpoint() |
| 118 | + dst_addr_ep.address_mode = t.ADDRESS_MODE.GROUP |
| 119 | + dst_addr_ep.address = group_id |
| 120 | + |
| 121 | + with self._pending.new(req_id) as req: |
| 122 | + try: |
| 123 | + await self._api.aps_data_request( |
| 124 | + req_id, |
| 125 | + dst_addr_ep, |
| 126 | + profile, |
| 127 | + cluster, |
| 128 | + min(1, src_ep), |
| 129 | + data |
| 130 | + ) |
| 131 | + except zigpy_deconz.exception.CommandError as ex: |
| 132 | + return ex.status, "Couldn't enqueue send data request: {}".format(ex) |
| 133 | + |
| 134 | + r = await asyncio.wait_for(req.result, SEND_CONFIRM_TIMEOUT) |
| 135 | + if r: |
| 136 | + LOGGER.warning("Error while sending %s req id frame: 0x%02x", req_id, r) |
| 137 | + return r, "message send failure" |
| 138 | + |
| 139 | + return Status.SUCCESS, "message send success" |
| 140 | + |
86 | 141 | @zigpy.util.retryable_request |
87 | 142 | async def request(self, device, profile, cluster, src_ep, dst_ep, sequence, data, |
88 | 143 | expect_reply=True, use_ieee=False): |
|
0 commit comments