File: multicast.py

package info (click to toggle)
python-bellows 0.40.5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 996 kB
  • sloc: python: 13,630; sh: 7; makefile: 5
file content (107 lines) | stat: -rw-r--r-- 3,606 bytes parent folder | download
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]