secop_psi.entangle.AnalogInput: fix main value

when the unit of parameter 'value' is taken from tango, the
'$' units of other parameters are already replaced by the configured
value and are not updated. this change fixes this.

not yet tested on entangle, but a test with similar code works

Change-Id: I87ad112b0965b39bb204d6c3d1fc1de6d4e14f60
Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/29357
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
zolliker 2022-09-22 10:25:50 +02:00
parent e09c365ea5
commit 05edf98dfe
3 changed files with 51 additions and 2 deletions

View File

@ -461,8 +461,7 @@ class Module(HasAccessibles):
if mainvalue:
mainunit = mainvalue.datatype.unit
if mainunit:
for pname, pobj in self.parameters.items():
pobj.datatype.set_main_unit(mainunit)
self.applyMainUnit(mainunit)
# 6) check complete configuration of * properties
if not errors:
@ -485,6 +484,11 @@ class Module(HasAccessibles):
def __getitem__(self, item):
return self.accessibles.__getitem__(item)
def applyMainUnit(self, mainunit):
"""replace $ in units of parameters by mainunit"""
for pobj in self.parameters.values():
pobj.datatype.set_main_unit(mainunit)
def announceUpdate(self, pname, value=None, err=None, timestamp=None):
"""announce a changed value or readerror"""

View File

@ -376,6 +376,12 @@ class AnalogInput(PyTangoDevice, Readable):
"""
The AnalogInput handles all devices only delivering an analogue value.
"""
__main_unit = None
def applyMainUnit(self, mainunit):
# called from __init__ method
# replacement of '$' by main unit must be done later
self.__main_unit = mainunit
def startModule(self, start_events):
super().startModule(start_events)
@ -386,8 +392,11 @@ class AnalogInput(PyTangoDevice, Readable):
# update
if attrInfo.unit != 'No unit':
self.accessibles['value'].datatype.setProperty('unit', attrInfo.unit)
self.__main_unit = attrInfo.unit
except Exception as e:
self.log.error(e)
if self.__main_unit:
super().applyMainUnit(self.__main_unit)
def read_value(self):
return self._dev.value

View File

@ -659,3 +659,39 @@ def test_problematic_value_range():
obj = Mod4('obj', logger, {
'value.min': 0, 'value.max': 10,
'target.min': 0, 'target.max': 10, 'description': ''}, srv)
@pytest.mark.parametrize('config, dynamicunit, finalunit, someunit', [
({}, 'K', 'K', 'K'),
({'value.unit': 'K'}, 'C', 'C', 'C'),
({'value.unit': 'K'}, '', 'K', 'K'),
({'value.unit': 'K', 'someparam.unit': 'A'}, 'C', 'C', 'A'),
])
def test_deferred_main_unit(config, dynamicunit, finalunit, someunit):
# this pattern is used in secop_mlz.entangle.AnalogInput
class Mod(Drivable):
ramp = Parameter('', datatype=FloatRange(unit='$/min'))
someparam = Parameter('', datatype=FloatRange(unit='$'))
__main_unit = None
def applyMainUnit(self, mainunit):
# called from __init__ method
# replacement of '$' by main unit must be done later
self.__main_unit = mainunit
def startModule(self, start_events):
super().startModule(start_events)
if dynamicunit:
self.accessibles['value'].datatype.setProperty('unit', dynamicunit)
self.__main_unit = dynamicunit
if self.__main_unit:
super().applyMainUnit(self.__main_unit)
srv = ServerStub({})
m = Mod('m', logger, {'description': '', **config}, srv)
m.startModule(None)
assert m.parameters['value'].datatype.unit == finalunit
assert m.parameters['target'].datatype.unit == finalunit
assert m.parameters['ramp'].datatype.unit == finalunit + '/min'
# when someparam.unit is configured, this differs from finalunit
assert m.parameters['someparam'].datatype.unit == someunit