aboutsummaryrefslogtreecommitdiff
path: root/endpoint.py
diff options
context:
space:
mode:
Diffstat (limited to 'endpoint.py')
-rw-r--r--endpoint.py105
1 files changed, 105 insertions, 0 deletions
diff --git a/endpoint.py b/endpoint.py
new file mode 100644
index 0000000..7458326
--- /dev/null
+++ b/endpoint.py
@@ -0,0 +1,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)