mercury, ips, sea, triton, convergence

after gerrit

Change-Id: Iff14047ecc476589aef10c96fae9970133b8bd14
This commit is contained in:
2023-05-09 14:57:34 +02:00
parent 750b5a7794
commit 8039351395
12 changed files with 426 additions and 357 deletions

View File

@@ -250,16 +250,9 @@ class ProxyClient:
return bool(cblist)
def updateValue(self, module, param, value, timestamp, readerror):
entry = CacheItem(value, timestamp, readerror,
self.modules[module]['parameters'][param]['datatype'])
self.cache[(module, param)] = entry
self.callback(None, 'updateItem', module, param, entry)
self.callback(module, 'updateItem', module, param, entry)
self.callback((module, param), 'updateItem', module, param, entry)
# TODO: change clients to use updateItem instead of updateEvent
self.callback(None, 'updateEvent', module, param, *entry)
self.callback(module, 'updateEvent', module, param, *entry)
self.callback((module, param), 'updateEvent', module, param, *entry)
self.callback(None, 'updateEvent', module, param, value, timestamp, readerror)
self.callback(module, 'updateEvent', module, param, value, timestamp, readerror)
self.callback((module, param), 'updateEvent', module, param,value, timestamp, readerror)
class SecopClient(ProxyClient):
@@ -651,6 +644,16 @@ class SecopClient(ProxyClient):
data = datatype.import_value(data)
return data, qualifiers
def updateValue(self, module, param, value, timestamp, readerror):
entry = CacheItem(value, timestamp, readerror,
self.modules[module]['parameters'][param]['datatype'])
self.cache[(module, param)] = entry
self.callback(None, 'updateItem', module, param, entry)
self.callback(module, 'updateItem', module, param, entry)
self.callback((module, param), 'updateItem', module, param, entry)
# TODO: change clients to use updateItem instead of updateEvent
super().updateValue(module, param, value, timestamp, readerror)
# the following attributes may be/are intended to be overwritten by a subclass
PREDEFINED_NAMES = set(frappy.params.PREDEFINED_ACCESSIBLES)

View File

@@ -126,13 +126,15 @@ class Config(dict):
self.modules.append(mod)
def process_file(config_text):
def process_file(filename):
with open(filename, 'rb') as f:
config_text = f.read()
node = NodeCollector()
mods = Collector(Mod)
ns = {'Node': node.add, 'Mod': mods.add, 'Param': Param, 'Command': Param, 'Group': Group}
# pylint: disable=exec-used
exec(config_text, ns)
exec(compile(config_text, filename, 'exec'), ns)
return Config(node, mods)
@@ -175,9 +177,7 @@ def load_config(cfgfiles, log):
for cfgfile in cfgfiles.split(','):
filename = to_config_path(cfgfile, log)
log.debug('Parsing config file %s...', filename)
with open(filename, 'rb') as f:
config_text = f.read()
cfg = process_file(config_text)
cfg = process_file(filename)
if config:
config.merge_modules(cfg)
else:

View File

@@ -274,9 +274,8 @@ class FloatRange(HasUnit, DataType):
def compatible(self, other):
if not isinstance(other, (FloatRange, ScaledInteger)):
raise WrongTypeError('incompatible datatypes')
# avoid infinity
other.validate(max(sys.float_info.min, self.min))
other.validate(min(sys.float_info.max, self.max))
other.validate(self.min)
other.validate(self.max)
class IntRange(DataType):

View File

@@ -396,3 +396,13 @@ class UniqueObject:
def __repr__(self):
return self.name
def merge_status(*args):
"""merge status
the status with biggest code wins
texts matching maximal code are joined with ', '
"""
maxcode = max(a[0] for a in args)
return maxcode, ', '.join([a[1] for a in args if a[0] == maxcode and a[1]])

View File

@@ -21,16 +21,17 @@
# *****************************************************************************
from frappy.datatypes import BoolType, EnumType, Enum
from frappy.core import Parameter, Writable, Attached
from frappy.core import Parameter, Attached
class HasControlledBy(Writable):
class HasControlledBy:
"""mixin for modules with controlled_by
in the :meth:`write_target` the hardware action to switch to own control should be done
and in addition self.self_controlled() should be called
"""
controlled_by = Parameter('source of target value', EnumType(members={'self': 0}), default=0)
target = Parameter() # make sure target is a parameter
inputCallbacks = ()
def register_input(self, name, deactivate_control):
@@ -57,7 +58,7 @@ class HasControlledBy(Writable):
deactivate_control(self.name)
class HasOutputModule(Writable):
class HasOutputModule:
"""mixin for modules having an output module
in the :meth:`write_target` the hardware action to switch to own control should be done
@@ -66,6 +67,7 @@ class HasOutputModule(Writable):
# mandatory=False: it should be possible to configure a module with fixed control
output_module = Attached(HasControlledBy, mandatory=False)
control_active = Parameter('control mode', BoolType(), default=False)
target = Parameter() # make sure target is a parameter
def initModule(self):
super().initModule()
@@ -85,8 +87,8 @@ class HasOutputModule(Writable):
out.controlled_by = self.name
self.control_active = True
def deactivate_control(self, switched_by):
def deactivate_control(self, source):
"""called when an other module takes over control"""
if self.control_active:
self.control_active = False
self.log.warning(f'switched to manual mode by {switched_by}')
self.log.warning(f'switched to manual mode by {source}')

View File

@@ -245,7 +245,6 @@ class Feature(HasAccessibles):
a mixin with Feature as a direct base class is recognized as a SECoP feature
and reported in the module property 'features'
"""
featureName = None
class PollInfo:
@@ -377,10 +376,10 @@ class Module(HasAccessibles):
# b.__name__ for b in mycls.__mro__ if b.__module__.startswith('frappy.modules')]
# list of only the 'highest' secop module class
self.interface_classes = [
b.__name__ for b in mycls.__mro__ if issubclass(Drivable, b)][0:1]
b.__name__ for b in mycls.__mro__ if b in SECoP_BASE_CLASSES][:1]
# handle Features
self.features = [b.featureName or b.__name__ for b in mycls.__mro__ if Feature in b.__bases__]
self.features = [b.__name__ for b in mycls.__mro__ if Feature in b.__bases__]
# handle accessibles
# 1) make local copies of parameter objects
@@ -898,6 +897,7 @@ class Communicator(HasComlog, Module):
"""
raise NotImplementedError()
SECoP_BASE_CLASSES = {Readable, Writable, Drivable, Communicator}
class Attached(Property):
"""a special property, defining an attached module