"""The device class used to represent a particular function of an accelerator element.
A physical element in an accelerator may have multiple devices: an example at DLS
is a sextupole magnet that contains also horizontal and vertical corrector magnets
and a skew quadrupole.
"""
from pytac.exceptions import PvException
import pytac
[docs]class Device(object):
"""A device attached to an element.
Contains a control system, readback and setpoint pvs. A readback
or setpoint pv is required when creating a device otherwise a
PvException is raised. The device is enabled by default.
"""
def __init__(self, name, cs, enabled=True, rb_suffix=None, sp_suffix=None):
"""Device constructor.
Args:
name: prefix of EPICS PVs for this device
cs (ControlSystem): Control system object used to get and set
the value of a pv.
enabled (bool-like): Whether the device is enabled. May be
a PvEnabler object.
rb_suffix (string): suffix of EPICS readback pv
sp_suffix (string): suffix of EPICS setpoint pv
"""
self.name = name
self._cs = cs
if rb_suffix is not None:
self.rb_pv = name + rb_suffix
if sp_suffix is not None:
self.sp_pv = name + sp_suffix
self._enabled = True
[docs] def is_enabled(self):
"""Whether the device is enabled.
Returns:
boolean: whether the device is enabled
"""
return self._enabled
[docs] def put_value(self, value):
"""Set the device value.
Args:
value(Number): The value to set on the pv.
Raises:
PvException: An exception occured when no setpoint pv exists.
"""
try:
self._cs.put(self.sp_pv, value)
except AttributeError:
raise PvException("""This device {0} has no setpoint pv."""
.format(self.name))
[docs] def get_value(self, handle):
"""Read the value of a readback or setpoint pv.
If neither readback or setpoint pvs exist then a PvException is raised.
Args:
handle(string): Handle used to get the value off a readback or setpoint
pv.
Returns:
Number: The value of the pv.
Raises:
PvException: In case the requested pv doesn't exist.
"""
if handle == pytac.RB and self.rb_pv:
return self._cs.get(self.rb_pv)
elif handle == pytac.SP and self.sp_pv:
return self._cs.get(self.sp_pv)
raise PvException("""This device {0} has no {1} pv."""
.format(self.name, handle))
[docs] def get_pv_name(self, handle):
"""Get a pv name on a specified handle.
Args:
handle(string): The readback or setpoint handle to be returned.
Returns:
string: A readback or setpoint pv.
"""
if handle == '*':
return [self.rb_pv, self.sp_pv]
elif handle == pytac.RB:
return self.rb_pv
elif handle == pytac.SP:
return self.sp_pv
[docs] def get_cs(self):
return self._cs
[docs]class PvEnabler(object):
def __init__(self, pv, enabled_value, cs):
"""A PvEnabler class to check whether a device is enabled.
The class will behave like True if the pv value equals enabled_value,
and False otherwise.
Args:
pv(string): pv name
enabled_value(string): value for pv for which the device should
be considered enabled
cs: Control system object
"""
self._pv = pv
self._enabled_value = str(int(float(enabled_value)))
self._cs = cs
def __nonzero__(self):
"""Used to override the 'if object' clause.
Support for Python 2.7.
Returns:
boolean: True if the device should be considered enabled
"""
pv_value = self._cs.get(self._pv)
return self._enabled_value == str(int(float(pv_value)))
def __bool__(self):
"""Used to override the 'if object' clause.
Support for Python 3.x.
Returns:
boolean: True if the device should be considered enabled
"""
return self.__nonzero__()