Fix abslimits reading from entangle device
Fixes: #4864 Related: #4866 Change-Id: I393a35784766c0e09367a90debfc8b59b290626e Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/33672 Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
parent
6dfb3bcee8
commit
caaefec6db
@ -30,6 +30,7 @@ MLZ TANGO interface for the respective device classes.
|
|||||||
# pylint: disable=too-many-lines, consider-using-f-string
|
# pylint: disable=too-many-lines, consider-using-f-string
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import threading
|
import threading
|
||||||
from time import sleep, time as currenttime
|
from time import sleep, time as currenttime
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ import PyTango
|
|||||||
from frappy.datatypes import ArrayOf, EnumType, FloatRange, IntRange, \
|
from frappy.datatypes import ArrayOf, EnumType, FloatRange, IntRange, \
|
||||||
LimitsType, StatusType, StringType, TupleOf, ValueType
|
LimitsType, StatusType, StringType, TupleOf, ValueType
|
||||||
from frappy.errors import CommunicationFailedError, ConfigError, \
|
from frappy.errors import CommunicationFailedError, ConfigError, \
|
||||||
HardwareError, ProgrammingError, WrongTypeError
|
HardwareError, ProgrammingError, WrongTypeError, RangeError
|
||||||
from frappy.lib import lazy_property
|
from frappy.lib import lazy_property
|
||||||
from frappy.modules import Command, Drivable, Module, Parameter, Property, \
|
from frappy.modules import Command, Drivable, Module, Parameter, Property, \
|
||||||
Readable, Writable
|
Readable, Writable
|
||||||
@ -440,6 +441,7 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
|||||||
)
|
)
|
||||||
abslimits = Parameter('Absolute limits of device value',
|
abslimits = Parameter('Absolute limits of device value',
|
||||||
datatype=LimitsType(FloatRange(unit='$')),
|
datatype=LimitsType(FloatRange(unit='$')),
|
||||||
|
export=False,
|
||||||
)
|
)
|
||||||
precision = Parameter('Precision of the device value (allowed deviation '
|
precision = Parameter('Precision of the device value (allowed deviation '
|
||||||
'of stable values from target)',
|
'of stable values from target)',
|
||||||
@ -466,30 +468,52 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
|||||||
# replacement of '$' by main unit must be done later
|
# replacement of '$' by main unit must be done later
|
||||||
self.__main_unit = mainunit
|
self.__main_unit = mainunit
|
||||||
|
|
||||||
def _init_abslimits(self):
|
def _init_limits(self):
|
||||||
"""Get abslimits from tango if not configured. Otherwise, check if both
|
"""Get abslimits from tango if not configured. Otherwise, check if both
|
||||||
ranges are compatible."""
|
ranges are compatible."""
|
||||||
|
|
||||||
|
def intersect_limits(first, second, first_kind, second_kind):
|
||||||
|
lower = max(first[0], second[0])
|
||||||
|
upper = min(first[1], second[1])
|
||||||
|
if lower >= upper:
|
||||||
|
raise WrongTypeError(f"{first_kind} limits '{first}' are not "
|
||||||
|
f"compatible with {second_kind} limits "
|
||||||
|
f"'{second}'!")
|
||||||
|
return lower, upper
|
||||||
|
|
||||||
|
tangoabslim = (-sys.float_info.max, sys.float_info.max)
|
||||||
try:
|
try:
|
||||||
tangoabslim = (
|
read_tangoabslim = (float(self._getProperty('absmin')),
|
||||||
float(self._getProperty('absmin')),
|
float(self._getProperty('absmax')))
|
||||||
float(self._getProperty('absmax'))
|
# Entangle convention for "unrestricted"
|
||||||
)
|
if read_tangoabslim != (0, 0):
|
||||||
|
tangoabslim = read_tangoabslim
|
||||||
|
except Exception as e:
|
||||||
|
self.log.error('could not read Tango abslimits: %s' % e)
|
||||||
|
|
||||||
if self.parameters['abslimits'].readerror:
|
if self.parameters['abslimits'].readerror:
|
||||||
# no abslimits configured in frappy. read from entangle
|
# no abslimits configured in frappy
|
||||||
self.parameters['abslimits'].readerror = None
|
self.parameters['abslimits'].readerror = None
|
||||||
self.abslimits = tangoabslim
|
self.abslimits = tangoabslim
|
||||||
except Exception as e:
|
|
||||||
self.log.error(e)
|
|
||||||
# check if compatible
|
|
||||||
try:
|
|
||||||
dt = FloatRange(*tangoabslim)
|
|
||||||
dt.validate(self.parameters['abslimits'].datatype.min)
|
|
||||||
dt.validate(self.parameters['abslimits'].datatype.max)
|
|
||||||
except WrongTypeError as e:
|
|
||||||
raise WrongTypeError(f'Absolute limits configured in frappy \''
|
|
||||||
f'{self.abslimits}\' extend beyond the limits '
|
|
||||||
f'defined in entangle \'{tangoabslim}\'!') from e
|
|
||||||
|
|
||||||
|
# check both abslimits against each other
|
||||||
|
self.abslimits = intersect_limits(self.abslimits, tangoabslim,
|
||||||
|
'frappy absolute',
|
||||||
|
'entangle absolute')
|
||||||
|
|
||||||
|
# set abslimits as hard target limits
|
||||||
|
self.parameters['target'].datatype.set_properties(
|
||||||
|
min=self.abslimits[0], max=self.abslimits[1])
|
||||||
|
|
||||||
|
# restrict current user limits by abslimits
|
||||||
|
self.userlimits = intersect_limits(self.userlimits, self.abslimits,
|
||||||
|
'user', 'absolute')
|
||||||
|
|
||||||
|
# restrict settable user limits by abslimits
|
||||||
|
self.parameters['userlimits'].datatype.members[0].set_properties(
|
||||||
|
min=self.abslimits[0], max=self.abslimits[1])
|
||||||
|
self.parameters['userlimits'].datatype.members[1].set_properties(
|
||||||
|
min=self.abslimits[0], max=self.abslimits[1])
|
||||||
|
|
||||||
def initModule(self):
|
def initModule(self):
|
||||||
super().initModule()
|
super().initModule()
|
||||||
@ -509,9 +533,8 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
|||||||
self.__main_unit = attrInfo.unit
|
self.__main_unit = attrInfo.unit
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error(e)
|
self.log.error(e)
|
||||||
if self.__main_unit:
|
|
||||||
super().applyMainUnit(self.__main_unit)
|
super().applyMainUnit(self.__main_unit)
|
||||||
self._init_abslimits()
|
self._init_limits()
|
||||||
|
|
||||||
def doPoll(self):
|
def doPoll(self):
|
||||||
super().doPoll()
|
super().doPoll()
|
||||||
@ -601,8 +624,8 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
|||||||
umin, umax = limits
|
umin, umax = limits
|
||||||
amin, amax = self.abslimits
|
amin, amax = self.abslimits
|
||||||
if umin > umax:
|
if umin > umax:
|
||||||
raise ValueError(
|
raise RangeError(
|
||||||
self, f'user minimum ({umin}) above the user maximum ({umax})')
|
f'user minimum ({umin}) above the user maximum ({umax})')
|
||||||
if umin < amin - abs(amin * 1e-12):
|
if umin < amin - abs(amin * 1e-12):
|
||||||
umin = amin
|
umin = amin
|
||||||
if umax > amax + abs(amax * 1e-12):
|
if umax > amax + abs(amax * 1e-12):
|
||||||
@ -613,6 +636,10 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
|||||||
return self._checkLimits(value)
|
return self._checkLimits(value)
|
||||||
|
|
||||||
def write_target(self, value=FloatRange()):
|
def write_target(self, value=FloatRange()):
|
||||||
|
umin, umax = self.userlimits
|
||||||
|
if not umin <= value <= umax:
|
||||||
|
raise RangeError(
|
||||||
|
f'target value {value} must be between {umin} and {umax}')
|
||||||
if self.status[0] == self.Status.BUSY:
|
if self.status[0] == self.Status.BUSY:
|
||||||
# changing target value during movement is not allowed by the
|
# changing target value during movement is not allowed by the
|
||||||
# Tango base class state machine. If we are moving, stop first.
|
# Tango base class state machine. If we are moving, stop first.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user