mercury, ips, sea, triton, convergence
after gerrit Change-Id: Iff14047ecc476589aef10c96fae9970133b8bd14
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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]])
|
||||
|
||||
@@ -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}')
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user