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)
|