aboutsummaryrefslogtreecommitdiff
path: root/endpoint.py
blob: 7458326a8a3c526b8db9fbe91d41631e54a49eba (plain)
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
import logging
import transport

def import_class(cl):
    d = cl.rfind(".")
    classname = cl[d+1:len(cl)]
    m = __import__(cl[0:d], globals(), locals(), [classname])
    return getattr(m, classname)

    # Master object
class Endpoint:
    def __init__(self, name, config):
        transports = {}
        commands = {}
        states = {}

        # sweet mother of jesus, you are ugly
        for tp_key in config['transports']:
            tp_cfg = config['transports'][tp_key]
            logging.debug(f'loading transport "{tp_key}"')

            # TODO Handle failure
            tp_class = import_class(tp_cfg['class'])
            del tp_cfg['class']

            transports[tp_key] = tp_class(**tp_cfg)

        for cmd_key in config['commands']:
            cmd_cfg = config['commands'][cmd_key]
            logging.debug(f'loading command "{cmd_key}"')

            # TODO Handle failure
            cmd_class = import_class(cmd_cfg['class'])
            del cmd_cfg['class']

            if cmd_cfg['transport'] not in transports:
                # TODO should we be lenient with errors?
                logging.error(f'transport "{cmd_cfg["transport"]}" for command "{cmd_key}" was not found.')
                continue

            tp = transports[cmd_cfg['transport']]
            del cmd_cfg['transport']

            commands[cmd_key] = cmd_class(tp, **cmd_cfg)

        # you look familiar
        for stt_key in config['states']:
            stt_cfg = config['states'][stt_key]
            logging.debug(f'loading state "{stt_key}"')

            # TODO Handle failure
            stt_class = import_class(stt_cfg['class'])
            del stt_cfg['class']

            if stt_cfg['transport'] not in transports:
                # TODO should we be lenient with errors?
                logging.error(f'transport "{stt_cfg["transport"]}" for command "{stt_key}" was not found.')
                continue

            tp = transports[stt_cfg['transport']]
            del stt_cfg['transport']

            states[stt_key] = stt_class(tp, **stt_cfg)

        # TODO How does the init step look like? Do it here?
        # transports prbly need to be connected here

        self._name = name
        self._transports = transports
        self._commands = commands
        self._states = states

    def connectTransport(self):
        for k in self._transports:
            if   self._transports[k].CONNECTION == transport.HOLD:
                self._transports[k].connect()
            elif self._transports[k].CONNECTION == transport.THROWAWAY:
                self._transports[k].check()
            else:
                logging.error(f'"{self._transports[k].CONNECTION}" is an unknown connection type in transport "{k}"')

    # forces a recollect of all states. should not be needed, states should
    # handle that themselves via TTL
    # we shouldn't need it
    #def collectState(self):
    #    # TODO we need a interface here
    #    for k in self._states:
    #        self._states[k].collect()

    # Format: <state>.<key>
    def getState(self, state_key: str):
        state, key = state_key.split('.', 1)

        if state not in self._states:
            logging.error(f'State "{state}" was not found for "{self._name}"')
            return None

        return self._states[state].get(key)


    def executeCommand(self, cmd: str, **kwargs):
        if cmd not in self._commands:
            raise Exception(f'Command "{cmd}" is not defined for "{self._name}"')

        self._commands[cmd].execute(**kwargs)