Switch descriptive data to new format
Change-Id: Ic8afe976564824d14394ed6a1b4b36df226648df
This commit is contained in:
parent
2d27c6dd93
commit
8a63a6c63f
@ -27,6 +27,7 @@ import serial
|
|||||||
from select import select
|
from select import select
|
||||||
import threading
|
import threading
|
||||||
import Queue
|
import Queue
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
import mlzlog
|
import mlzlog
|
||||||
|
|
||||||
@ -151,7 +152,17 @@ class Client(object):
|
|||||||
stopflag = False
|
stopflag = False
|
||||||
|
|
||||||
def __init__(self, opts, autoconnect=True):
|
def __init__(self, opts, autoconnect=True):
|
||||||
self.log = mlzlog.log.getChild('client', True)
|
if 'testing' not in opts:
|
||||||
|
self.log = mlzlog.log.getChild('client', True)
|
||||||
|
else:
|
||||||
|
class logStub(object):
|
||||||
|
def info(self, *args):
|
||||||
|
pass
|
||||||
|
debug = info
|
||||||
|
error = info
|
||||||
|
warning = info
|
||||||
|
exception = info
|
||||||
|
self.log = logStub()
|
||||||
self._cache = dict()
|
self._cache = dict()
|
||||||
if 'device' in opts:
|
if 'device' in opts:
|
||||||
# serial port
|
# serial port
|
||||||
@ -161,11 +172,15 @@ class Client(object):
|
|||||||
self.connection = serial.Serial(
|
self.connection = serial.Serial(
|
||||||
devport, baudrate=baudrate, timeout=1)
|
devport, baudrate=baudrate, timeout=1)
|
||||||
self.connection.callbacks = []
|
self.connection.callbacks = []
|
||||||
else:
|
elif 'testing' not in opts:
|
||||||
host = opts.pop('connectto', 'localhost')
|
host = opts.pop('connectto', 'localhost')
|
||||||
port = int(opts.pop('port', 10767))
|
port = int(opts.pop('port', 10767))
|
||||||
self.contactPoint = "tcp://%s:%d" % (host, port)
|
self.contactPoint = "tcp://%s:%d" % (host, port)
|
||||||
self.connection = TCPConnection(host, port)
|
self.connection = TCPConnection(host, port)
|
||||||
|
else:
|
||||||
|
self.contactPoint = 'testing'
|
||||||
|
self.connection = opts.pop('testing')
|
||||||
|
|
||||||
# maps an expected reply to a list containing a single Event()
|
# maps an expected reply to a list containing a single Event()
|
||||||
# upon rcv of that reply, entry is appended with False and
|
# upon rcv of that reply, entry is appended with False and
|
||||||
# the data of the reply.
|
# the data of the reply.
|
||||||
@ -305,15 +320,43 @@ class Client(object):
|
|||||||
def _getDescribingParameterData(self, module, parameter):
|
def _getDescribingParameterData(self, module, parameter):
|
||||||
return self._getDescribingModuleData(module)['parameters'][parameter]
|
return self._getDescribingModuleData(module)['parameters'][parameter]
|
||||||
|
|
||||||
def _issueDescribe(self):
|
def _decode_list_to_ordereddict(self, data):
|
||||||
_, self.equipment_id, self.describing_data = self._communicate(
|
# takes a list of 2*N <key>, <value> entries and
|
||||||
'describe')
|
# return an orderedDict from it
|
||||||
|
result = OrderedDict()
|
||||||
|
while len(data) > 1:
|
||||||
|
key = data.pop(0)
|
||||||
|
value = data.pop(0)
|
||||||
|
result[key] = value
|
||||||
|
return result
|
||||||
|
|
||||||
for module, moduleData in self.describing_data['modules'].items():
|
def _decode_substruct(self, specialkeys=[], data={}):
|
||||||
for parameter, parameterData in moduleData['parameters'].items():
|
# take a dict and move all keys which are not in specialkeys
|
||||||
datatype = get_datatype(parameterData['datatype'])
|
# into a 'properties' subdict
|
||||||
self.describing_data['modules'][module]['parameters'] \
|
# specialkeys entries are converted from list to ordereddict
|
||||||
[parameter]['datatype'] = datatype
|
result = {}
|
||||||
|
for k in specialkeys:
|
||||||
|
result[k] = self._decode_list_to_ordereddict(data.pop(k, []))
|
||||||
|
result['properties'] = data
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _issueDescribe(self):
|
||||||
|
_, self.equipment_id, describing_data = self._communicate('describe')
|
||||||
|
try:
|
||||||
|
describing_data = self._decode_substruct(['modules'], describing_data)
|
||||||
|
for modname, module in describing_data['modules'].items():
|
||||||
|
describing_data['modules'][modname] = self._decode_substruct(['parameters', 'commands'], module)
|
||||||
|
|
||||||
|
self.describing_data = describing_data
|
||||||
|
|
||||||
|
for module, moduleData in self.describing_data['modules'].items():
|
||||||
|
for parameter, parameterData in moduleData['parameters'].items():
|
||||||
|
datatype = get_datatype(parameterData['datatype'])
|
||||||
|
self.describing_data['modules'][module]['parameters'] \
|
||||||
|
[parameter]['datatype'] = datatype
|
||||||
|
except Exception as exc:
|
||||||
|
print formatException(verbose=True)
|
||||||
|
raise
|
||||||
|
|
||||||
def register_callback(self, module, parameter, cb):
|
def register_callback(self, module, parameter, cb):
|
||||||
self.log.debug('registering callback %r for %s:%s' %
|
self.log.debug('registering callback %r for %s:%s' %
|
||||||
|
@ -79,7 +79,11 @@ def formatExtendedFrame(frame):
|
|||||||
ret.append('\n')
|
ret.append('\n')
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def formatExtendedTraceback(etype, value, tb):
|
def formatExtendedTraceback(exc_info=None):
|
||||||
|
if exc_info is None:
|
||||||
|
etype, value, tb = sys.exc_info()
|
||||||
|
else:
|
||||||
|
etype, value, tb = exc_info
|
||||||
ret = ['Traceback (most recent call last):\n']
|
ret = ['Traceback (most recent call last):\n']
|
||||||
while tb is not None:
|
while tb is not None:
|
||||||
frame = tb.tb_frame
|
frame = tb.tb_frame
|
||||||
@ -116,10 +120,12 @@ def formatExtendedStack(level=1):
|
|||||||
f = f.f_back
|
f = f.f_back
|
||||||
return ''.join(ret).rstrip('\n')
|
return ''.join(ret).rstrip('\n')
|
||||||
|
|
||||||
def formatException(cut=0, exc_info=None):
|
def formatException(cut=0, exc_info=None, verbose=False):
|
||||||
"""Format an exception with traceback, but leave out the first `cut`
|
"""Format an exception with traceback, but leave out the first `cut`
|
||||||
number of frames.
|
number of frames.
|
||||||
"""
|
"""
|
||||||
|
if verbose:
|
||||||
|
return formatExtendedTraceback(exc_info)
|
||||||
if exc_info is None:
|
if exc_info is None:
|
||||||
typ, val, tb = sys.exc_info()
|
typ, val, tb = sys.exc_info()
|
||||||
else:
|
else:
|
||||||
|
@ -208,6 +208,28 @@ class Dispatcher(object):
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
def get_descriptive_data(self):
|
def get_descriptive_data(self):
|
||||||
|
"""returns a python object which upon serialisation results in the descriptive data"""
|
||||||
|
# XXX: be lazy and cache this?
|
||||||
|
# format: {[{[{[, specific entries first
|
||||||
|
result = {'modules': []}
|
||||||
|
for modulename in self._export:
|
||||||
|
module = self.get_module(modulename)
|
||||||
|
# some of these need rework !
|
||||||
|
mod_desc = {'parameters':[], 'commands':[]}
|
||||||
|
for pname, param in self.list_module_params(modulename, only_static=True).items():
|
||||||
|
mod_desc['parameters'].extend([pname, param])
|
||||||
|
for cname, cmd in self.list_module_cmds(modulename).items():
|
||||||
|
mod_desc['commands'].extend([cname, cmd])
|
||||||
|
for propname, prop in module.PROPERTIES.items():
|
||||||
|
mod_desc[propname] = prop
|
||||||
|
result['modules'].extend([modulename, mod_desc])
|
||||||
|
result['equipment_id'] = self.equipment_id
|
||||||
|
result['firmware'] = 'The SECoP playground'
|
||||||
|
result['version'] = "2017.07"
|
||||||
|
# XXX: what else?
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_descriptive_data_old(self):
|
||||||
# XXX: be lazy and cache this?
|
# XXX: be lazy and cache this?
|
||||||
result = {'modules': {}}
|
result = {'modules': {}}
|
||||||
for modulename in self._export:
|
for modulename in self._export:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user