How to use optional attributes

Standard attributes constructors

The Control System Guidelines define a set of “additional SKA Control Model attributes” which can optionally be used in addition to the “Core SKA Control Model Attributes”. These attributes are the controlMode, simulationMode and testMode. The guidelines do not prescribe precisely what each of the attributes should do, instead it is left to developers of Tango devices to use these attributes as appropriate.

The BaseInterface does not provide any of these additional attributes by default, instead a standard implementation of these can be created using one of standard_control_mode(), standard_simulation_mode() or standard_test_mode().

These functions return a signal, attribute pair and require that your Tango device inherits from SignalBusMixin.

If required, the read/write methods for the attribute can be overridden using the attribute.read/write decorators to override the behaviour. The default implementation for these methods can be accessed with self.__class__.<attr>.do_read(self) and self.__class__.<attr>.do_write(self, value).

For example:

from ska_control_model import SimulationMode
from ska_tango_base.base import BaseInterface, standard_simulation_mode
from ska_tango_base.software_bus import Signal, attribute_from_signal

class MyDevice(BaseInterface):
    _simulation_mode: Signal[SimulationMode]
    simulationMode: attribute_from_signal
    _simulation_mode, simulationMode = standard_simulation_mode()

    @simulationMode.write
    def write_simulationMode(self, value: SimulationMode) -> None:
        if value == SimulationMode.TRUE:
            self.start_simulation()
        else:
            self.stop_simulation()

        self.__class__.simulationMode.do_write(self, value)

    ...

The SKABaseDevice includes all the optional attributes provide by the base interface. It also provides override hooks for changing the behaviour of each attribute, so that for example, a subclass only has to override the write_simulationMode() to change the behaviour of the simulationMode attribute.

For example, the following behaves similarly as previous example using the SKABaseDevice

from ska_control_model import SimulationMode
from ska_tango_base.base import BaseInterface, standard_simulation_mode

class MyDevice(SKABaseDevice):
    def write_simulationMode(self, value: SimulationMode) -> None:
        if value == SimulationMode.TRUE:
            self.start_simulation()
        else:
            self.stop_simulation()

        super().write_simulationMode(value)

    ...

TestModeOverrideMixin

The TestModeOverrideMixin mix-in class provides the optional testMode attribute, along with a default behaviour for this attribute. When the testMode attribute is TEST, it is possible to override the value of attributes marked with the overridable() decorator.

For example, the following device has a myAttr attribute which is overridable.

from ska_tango_base.base import BaseInterface
from ska_tango_base.software_bus import Signal, attribute_from_signal
from ska_tango_base.test_mode_mixin import TestModeOverrideMixin, overridable

class MyDevice(TestModeOverrideMixin, BaseInterface):
    _my_attr = Signal[int]()
    myAttr = attribute_from_signal(_my_attr, dtype=int, abs_change=1)

    @myAttr.read
    @overridable
    def read_myAttr(self) -> ReadAttrType[int]:
        return self.__class__.myAttr.do_read(self)

    def init_device(self) -> None:
        super().init_device()
        self._my_attr = 0