class lsst.ts.salobj.Controller(name: str, index: int | None = None, *, do_callbacks: bool = False, write_only: bool = False, allow_missing_callbacks: bool = False)

Bases: object

A class that receives commands for a SAL component and sends telemetry and events from that component.

This class provides much of the behavior for BaseCsc, basically everything except the standard summary states and associated transition commands.


Name of SAL component.

indexint or None, optional

SAL component index, or 0 or None if the component is not indexed. A value is required if the component is indexed.

do_callbacksbool, optional

Set do_{command} methods as callbacks for commands? If true then there must be exactly one do_{command} method for each command. Cannot be true if write_only is true.

write_onlybool, optional

If true then the Controller will have no command topics and will not read any SAL data. Cannot be true if do_callbacks is true.

allow_missing_callbacksbool, optional

Allow missing do_{command} callback methods? Missing method will be replaced with one that raises salobj.ExpectedError. This is intended for mock controllers, which may only support a subset of commands. Cannot be true unless do_callbacks is true.


If do_callbacks and write_only are both true, or if allow_missing_callbacks is true and do_callbacks is not.


If do_callbacks true and one or more do_{command} methods is present that has no corresponding command, or if do_callbacks true, allow_missing_callbacks false, and one or more do_{command} methods is missing.


Writing a Controller

(To write a CSC see Writing a CSC, instead)

To write a controller that is not a CSC (one that does not provide the standard summary states and associated state transition commands):

Here is an example that makes a Test controller and displays the topic-related attributes, but has no code to do anything useful with those topics (see TestCsc for that):

include salobj

# the index is arbitrary, but a remote must use the same index
# to talk to this controller
test_controller = salobj.Controller("Test", index=5)

You should see the following topic-related attributes:

  • Commands, each an instance of topics.ControllerCommand:

    • cmd_standby

    • cmd_start

    • … and so on for all other standard CSC commands

    • cmd_setArrays

    • cmd_setScalars

  • Events, each an instance of topics.ControllerEvent:

    • evt_authList

    • evt_configurationApplied

    • … and so on for all other standard CSC events

    • evt_arrays

    • evt_scalars

  • Telemetry, each an instance of topics.ControllerTelemetry (note that there are no standard CSC telemetry topics):

    • tel_arrays

    • tel_scalars

Required Logging Attributes

Each Controller must support the following topics, as specified in ts_xml in SALGenerics.xml:

  • setLogLevel command

  • logLevel event

  • logMessage event


A logger.


SAL info.


Is this instance open? True until close is called. The instance is fully closed when done_task is done.


Has the start method been called? The instance is fully started when start_task is done.


A task which is finished when close or basic_close is done.


A task which is finished when start is done, or to an exception if start fails.


Controller command topic. There is one for each command supported by the SAL component.


Controller event topic. There is one for each event topic supported by the SAL component.


Controller telemetry topic. There is one for each telemetry topic supported by the SAL component.

Attributes Summary


Methods Summary

close([exception, cancel_start])

Shut down, clean up resources and set done_task done.


Shut down pending tasks.


Update the authorization list.


Set logging level.


Output the logLevel event.


Finish construction.


Additional work after start before fully started.

Attributes Documentation


Methods Documentation

async close(exception: Exception | None = None, cancel_start: bool = True) None

Shut down, clean up resources and set done_task done.

May be called multiple times. The first call closes the Controller; subsequent calls wait until the Controller is closed.

Subclasses should override close_tasks instead of close, unless you have a good reason to do otherwise.

exceptionException, optional

The exception that caused stopping, if any, in which case the self.done_task exception is set to this value. Specify None for a normal exit, in which case the self.done_task result is set to None.

cancel_startbool, optional

Cancel the start task? Leave this true unless calling this from the start task.


Removes the SAL log handler, calls close_tasks to stop all background tasks, pauses briefly to allow final SAL messages to be sent, then closes the dds domain.

async close_tasks() None

Shut down pending tasks. Called by close.

Perform all cleanup other than disabling logging to SAL and closing the dds domain.

async do_setAuthList(data: BaseMsgType) None

Update the authorization list.


Authorization lists.


Add items if the data string starts with “+”, ignoring duplicates (both with respect to the existing items and within the data string). Remove items if the data string starts with “-”, ignoring missing items (items specified for removal that do not exist). Ignore whitespace after each comma and after the +/- prefix.

async do_setLogLevel(data: BaseMsgType) None

Set logging level.


Logging level.

async put_log_level() None

Output the logLevel event.

async start() None

Finish construction.

async start_phase2() None

Additional work after start before fully started.

Used by BaseCsc to transition to handle the initial state.