fix transport and display of node-properties
Change-Id: I35a3021768e386a5ce922c8e24128d0bc3a039be
This commit is contained in:
@ -317,7 +317,8 @@ class Client(object):
|
||||
if data:
|
||||
self._cache.setdefault(modname, {})[pname] = Value(*data)
|
||||
else:
|
||||
self.log.warning('got malformed answer! (spec data)' % (spec, data))
|
||||
self.log.warning(
|
||||
'got malformed answer! (spec data)' % (spec, data))
|
||||
# self.log.info('cache: %s:%s=%r (was: %s)', modname, pname, data, previous)
|
||||
if spec in self.callbacks:
|
||||
for func in self.callbacks[spec]:
|
||||
|
@ -340,25 +340,30 @@ class BoolType(DataType):
|
||||
|
||||
class ArrayOf(DataType):
|
||||
|
||||
def __init__(self, subtype, minsize_or_size=None, maxsize=None):
|
||||
if maxsize is None:
|
||||
maxsize = minsize_or_size
|
||||
self.minsize = minsize_or_size
|
||||
self.maxsize = maxsize
|
||||
if self.minsize is not None and self.maxsize is not None and \
|
||||
self.minsize > self.maxsize:
|
||||
raise ValueError('minsize must be less than or equal to maxsize!')
|
||||
def __init__(self, subtype, minsize=0, maxsize=None):
|
||||
if not isinstance(subtype, DataType):
|
||||
raise ValueError(
|
||||
'ArrayOf only works with DataType objs as first argument!')
|
||||
# if only one arg is given, it is maxsize!
|
||||
if minsize and not maxsize:
|
||||
maxsize = minsize
|
||||
minsize = 0
|
||||
self.as_json = ['array', subtype.as_json, maxsize]
|
||||
elif maxsize:
|
||||
self.as_json = ['array', subtype.as_json, maxsize, minsize]
|
||||
else:
|
||||
self.as_json = ['array', subtype.as_json]
|
||||
self.minsize = minsize or 0
|
||||
self.maxsize = maxsize
|
||||
self.subtype = subtype
|
||||
self.as_json = ['array', self.subtype.as_json,
|
||||
self.maxsize, self.minsize]
|
||||
if self.minsize is not None and self.minsize < 0:
|
||||
if self.maxsize is not None and self.minsize > maxsize:
|
||||
raise ValueError('minsize must be less than or equal to maxsize!')
|
||||
|
||||
if self.minsize < 0:
|
||||
raise ValueError('Minimum size must be >= 0!')
|
||||
if self.maxsize is not None and self.maxsize < 1:
|
||||
raise ValueError('Maximum size must be >= 1!')
|
||||
if self.minsize is not None and self.maxsize is not None and self.minsize > self.maxsize:
|
||||
if self.maxsize is not None and self.minsize > self.maxsize:
|
||||
raise ValueError('Maximum size must be >= Minimum size')
|
||||
|
||||
def __repr__(self):
|
||||
@ -534,10 +539,12 @@ DATATYPES = dict(
|
||||
bool=lambda: BoolType(),
|
||||
int=lambda _min=None, _max=None: IntRange(_min, _max),
|
||||
double=lambda _min=None, _max=None: FloatRange(_min, _max),
|
||||
blob=lambda _min=None, _max=None: BLOBType(_min, _max),
|
||||
string=lambda _min=None, _max=None: StringType(_min, _max),
|
||||
array=lambda subtype, _min=None, _max=None: ArrayOf(
|
||||
get_datatype(subtype), _min, _max),
|
||||
blob=lambda _max=None, _min=None: BLOBType(
|
||||
_min, _max) if _min else BLOBType(_max),
|
||||
string=lambda _max=None, _min=None: StringType(
|
||||
_min, _max) if _min else StringType(_max),
|
||||
array=lambda subtype, _max=None, _min=None: ArrayOf(
|
||||
get_datatype(subtype), _min, _max) if _min else ArrayOf(getdatatype(subtype), _min),
|
||||
tuple=lambda subtypes: TupleOf(*map(get_datatype, subtypes)),
|
||||
enum=lambda kwds: EnumType(**kwds),
|
||||
struct=lambda named_subtypes: StructOf(
|
||||
|
@ -43,7 +43,8 @@ class NodeCtrl(QWidget):
|
||||
self.contactPointLabel.setText(self._node.contactPoint)
|
||||
self.equipmentIdLabel.setText(self._node.equipmentId)
|
||||
self.protocolVersionLabel.setText(self._node.protocolVersion)
|
||||
self.nodeDescriptionLabel.setText(self._node.describingData.get('description','no description available'))
|
||||
self.nodeDescriptionLabel.setText(self._node.describingData['properties'].get(
|
||||
'description', 'no description available'))
|
||||
self._clearLog()
|
||||
|
||||
# now populate modules tab
|
||||
@ -168,7 +169,8 @@ class ReadableWidget(QWidget):
|
||||
self._node = node
|
||||
self._module = module
|
||||
|
||||
self._status_type = self._node.getProperties(self._module, 'status').get('datatype')
|
||||
self._status_type = self._node.getProperties(
|
||||
self._module, 'status').get('datatype')
|
||||
|
||||
params = self._node.getProperties(self._module, 'value')
|
||||
datatype = params.get('datatype', StringType())
|
||||
@ -198,9 +200,11 @@ class ReadableWidget(QWidget):
|
||||
if pname in params:
|
||||
return params[pname].value
|
||||
try:
|
||||
# if queried, we get the qualifiers as well, but don't want them here
|
||||
# if queried, we get the qualifiers as well, but don't want them
|
||||
# here
|
||||
import mlzlog
|
||||
mlzlog.getLogger('cached values').warn('no cached value for %s:%s' % (self._module, pname))
|
||||
mlzlog.getLogger('cached values').warn(
|
||||
'no cached value for %s:%s' % (self._module, pname))
|
||||
val = self._node.getParameter(self._module, pname)[0]
|
||||
return val
|
||||
except Exception:
|
||||
|
@ -82,109 +82,119 @@ p, li { white-space: pre-wrap; }
|
||||
<string>NodeInfo</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Contact point:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="contactPointLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Equipment ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="equipmentIdLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Protocol version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="protocolVersionLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="nodeDescriptionLabel">
|
||||
<property name="text">
|
||||
<string>Description
|
||||
long line</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="QScrollArea" name="scrollArea_2">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>610</width>
|
||||
<height>413</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Contact point:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="contactPointLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Equipment ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="equipmentIdLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Protocol version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="protocolVersionLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="nodeDescriptionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>aaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaa</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>label_2</zorder>
|
||||
<zorder>gridLayoutWidget</zorder>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -49,7 +49,6 @@ CONFIG = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
class lazy_property(object):
|
||||
"""A property that calculates its value only once."""
|
||||
|
||||
|
@ -49,7 +49,12 @@ from secop.lib import formatExtendedStack, formatException
|
||||
class Dispatcher(object):
|
||||
|
||||
def __init__(self, logger, options):
|
||||
self.equipment_id = options.pop('equipment_id')
|
||||
# to avoid errors, we want to eat all options here
|
||||
self.equipment_id = options['equipment_id']
|
||||
self.nodeopts = {}
|
||||
for k in list(options):
|
||||
self.nodeopts[k] = options.pop(k)
|
||||
|
||||
self.log = logger
|
||||
# map ALL modulename -> moduleobj
|
||||
self._modules = {}
|
||||
@ -227,6 +232,7 @@ class Dispatcher(object):
|
||||
result['equipment_id'] = self.equipment_id
|
||||
result['firmware'] = 'The SECoP playground'
|
||||
result['version'] = "2017.07"
|
||||
result.update(self.nodeopts)
|
||||
# XXX: what else?
|
||||
return result
|
||||
|
||||
|
@ -107,7 +107,8 @@ class Server(object):
|
||||
|
||||
deviceopts = []
|
||||
interfaceopts = []
|
||||
equipment_id = 'unknown'
|
||||
equipment_id = None
|
||||
nodeopts = []
|
||||
for section in parser.sections():
|
||||
if section.lower().startswith('device '):
|
||||
# device section
|
||||
@ -135,11 +136,30 @@ class Server(object):
|
||||
(self._cfgfile, ifname))
|
||||
# all went well so far
|
||||
interfaceopts.append([ifname, ifopts])
|
||||
if parser.has_option('equipment', 'id'):
|
||||
equipment_id = parser.get('equipment', 'id').replace(' ', '_')
|
||||
if section.lower().startswith('equipment ') or section.lower().startswith('node '):
|
||||
if equipment_id is not None:
|
||||
raise ConfigError('cfgfile %r: only one [node <id>] section allowed, found another [%s]!' % (
|
||||
self._cfgfile, section))
|
||||
# equipment/node settings
|
||||
equipment_id = section.split(' ', 1)[1].replace(' ', '_')
|
||||
nodeopts = dict(item for item in parser.items(section))
|
||||
nodeopts['equipment_id'] = equipment_id
|
||||
nodeopts['id'] = equipment_id
|
||||
# MAGIC: transform \n.\n into \n\n which are normally stripped
|
||||
# by the ini parser
|
||||
for k in nodeopts:
|
||||
v = nodeopts[k]
|
||||
while '\n.\n' in v:
|
||||
v = v.replace('\n.\n', '\n\n')
|
||||
nodeopts[k] = v
|
||||
|
||||
if equipment_id is None:
|
||||
self.log.error('Need a [node <id>] section, none found!')
|
||||
raise ConfigError(
|
||||
'cfgfile %r: need an [node <id>] option!' % (self._cfgfile))
|
||||
|
||||
self._dispatcher = self._buildObject(
|
||||
'Dispatcher', Dispatcher, dict(equipment_id=equipment_id))
|
||||
'Dispatcher', Dispatcher, nodeopts)
|
||||
self._processInterfaceOptions(interfaceopts)
|
||||
self._processModuleOptions(deviceopts)
|
||||
|
||||
|
Reference in New Issue
Block a user