1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
import logging
from bellows import types as t
LOGGER = logging.getLogger(__name__)
class Multicast:
"""Multicast table controller for EZSP."""
def __init__(self, ezsp):
self._ezsp = ezsp
self._multicast = {}
self._available = set()
async def _initialize(self) -> None:
self._multicast = {}
self._available = set()
status, size = await self._ezsp.getConfigurationValue(
t.EzspConfigId.CONFIG_MULTICAST_TABLE_SIZE
)
if t.sl_Status.from_ember_status(status) != t.sl_Status.OK:
return
for i in range(0, size):
status, entry = await self._ezsp.getMulticastTableEntry(i)
if t.sl_Status.from_ember_status(status) != t.sl_Status.OK:
LOGGER.error("Couldn't get MulticastTableEntry #%s: %s", i, status)
continue
LOGGER.debug("MulticastTableEntry[%s] = %s", i, entry)
if entry.endpoint != 0:
self._multicast[entry.multicastId] = (entry, i)
else:
self._available.add(i)
async def startup(self, coordinator) -> None:
await self._initialize()
for ep_id, ep in coordinator.endpoints.items():
if ep_id == 0:
continue
for group_id in ep.member_of:
await self.subscribe(group_id)
async def subscribe(self, group_id) -> t.sl_Status:
if group_id in self._multicast:
LOGGER.debug("%s is already subscribed", t.EmberMulticastId(group_id))
return t.sl_Status.OK
try:
idx = self._available.pop()
except KeyError:
LOGGER.error("No more available slots MulticastId subscription")
return t.sl_Status.INVALID_INDEX
entry = t.EmberMulticastTableEntry()
entry.endpoint = t.uint8_t(1)
entry.multicastId = t.EmberMulticastId(group_id)
entry.networkIndex = t.uint8_t(0)
status = await self._ezsp.setMulticastTableEntry(idx, entry)
if t.sl_Status.from_ember_status(status[0]) != t.sl_Status.OK:
LOGGER.warning(
"Set MulticastTableEntry #%s for %s multicast id: %s",
idx,
entry.multicastId,
status,
)
self._available.add(idx)
return status[0]
self._multicast[entry.multicastId] = (entry, idx)
LOGGER.debug(
"Set MulticastTableEntry #%s for %s multicast id: %s",
idx,
entry.multicastId,
status,
)
return status[0]
async def unsubscribe(self, group_id) -> t.sl_Status:
try:
entry, idx = self._multicast[group_id]
except KeyError:
LOGGER.error(
"Couldn't find MulticastTableEntry for %s multicast_id", group_id
)
return t.sl_Status.INVALID_INDEX
entry.endpoint = t.uint8_t(0)
status = await self._ezsp.setMulticastTableEntry(idx, entry)
if t.sl_Status.from_ember_status(status[0]) != t.sl_Status.OK:
LOGGER.warning(
"Set MulticastTableEntry #%s for %s multicast id: %s",
idx,
entry.multicastId,
status,
)
return status[0]
self._multicast.pop(group_id)
self._available.add(idx)
LOGGER.debug(
"Set MulticastTableEntry #%s for %s multicast id: %s",
idx,
entry.multicastId,
status,
)
return status[0]
|