How to use the control mode
Important
The original ska_control_model.ControlMode enum has been deprecated since ska-control-model 1.3.0 used in ska-tango-base 1.7.0. This guide explains how the new ska_control_model.future.ControlMode should be used according to ADR-114.
The optional controlMode Tango attribute can be added to a device by inheriting from ControlModeMixin. This will allow clients to instruct your Tango device when to monitor its component and when to allow commands that affect its component.
Subclasses must override the start_monitoring_component() and stop_monitoring_component() methods, which will be called whenever the controlMode transitions to/from a monitoring state. The start_monitoring_component() method should call report_health() before returning. If the connection to the component happens asynchronously, then use healthState.FAILED to report that the connection has not yet been established.
Subclasses can also call the check_component_controlled() method from their is-allowed methods to raise an informative exception if we are not in ControlMode.MONITOR_AND_CONTROL when a command is invoked. Typically, when using long running commands, this will want to be done at enqueue time.
For example, the following PoweredInterface device starts and stops communicating with its component when it is requested to start/stop monitoring and checks if it is controlling before adjusting the power level via its long running commands.
import ska_control_model as scm
import ska_tango_base.future as stb
class MyDevice(stb.ControlModeMixin, stb.LRCMixin, stb.PoweredInterface):
...
def start_monitoring_component(self) -> None:
self.report_health(scm.HealthState.FAILED, ["Initial communication not yet established."])
self.component.connect()
def stop_monitoring_component(self) -> None:
self.component.disconnect()
...
def is_On_allowed(
self,
request_type: stb.LRCReqType = stb.LRCReqType.ENQUEUE_REQ, # type: ignore[override]
) -> bool:
"""Return True if On is allowed."""
if request_type == stb.LRCReqType.ENQUEUE_REQ:
self.check_component_controlled()
return super().is_On_allowed(request_type)
@stb.submit_lrc_task
def execute_On(self) -> stb.type_hints.TaskFunctionType:
...
def is_Off_allowed(
self,
request_type: stb.LRCReqType = stb.LRCReqType.ENQUEUE_REQ, # type: ignore[override]
) -> bool:
"""Return True if On is allowed."""
if request_type == stb.LRCReqType.ENQUEUE_REQ:
self.check_component_controlled()
return super().is_Off_allowed(request_type)
@stb.submit_lrc_task
def execute_Off(self) -> stb.type_hints.TaskFunctionType:
...
...