ControllerCommand

class lsst.ts.salobj.topics.ControllerCommand(salinfo: SalInfo, name: str, queue_len: int = 100)

Bases: ReadTopic

Read a specified command topic.

Parameters
salinfoSalInfo

SAL component information.

namestr

Command name, with no prefix, e.g. “start”.

queue_lenint, optional

Number of elements that can be queued for get_oldest.

Notes

Each command must be acknowledged by writing an appropriate ackcmd message. If you use a callback function to process the command then this happens automatically, as follows:

  • If the callback function returns None then send a final acknowledgement with ack=SalRetCode.CMD_COMPLETE.

  • If the callback function returns an acknowledgement (instance of SalInfo.AckCmdType) instead of None, then send that as the final acknowledgement. This is very unusual, but might be useful if the callback wants to exit early and leave some background task or thread processing the rest of the command.

  • If the callback function raises asyncio.TimeoutError then send a final acknowledgement with ack=SalRetCode.CMD_TIMEOUT.

  • If the callback function raises asyncio.CancelledError then send a final acknowledgement with ack=SalRetCode.CMD_ABORTED.

  • If the callback function raises ExpectedError then send a final acknowledgement with ack=SalRetCode.CMD_FAILED and result=f"Failed: {exception}".

  • If the callback function raises any other Exception then do the same as ExpectedError and also log a traceback.

Attributes Summary

DataType

The type (class) for a message of this topic.

allow_multiple_callbacks

Can callbacks can run simultaneously?

callback

Asynchronous callback function, or None if there is not one.

has_callback

Return True if there is a callback function.

has_data

Has any data ever been seen for this topic?

max_history

metadata

Get topic metadata as a TopicMetadata, if available,else None.

nqueued

Return the number of messages in the Python queue.

volatile

Does this topic have volatile durability?

Methods Summary

ack(data, ackcmd)

Acknowledge a command by writing a new state.

ack_in_progress(data, timeout[, result])

Ackowledge this command as "in progress".

aget([timeout])

Get the most recently seen message (with no delay), or wait for data if no data has ever been seen (has_data False).

basic_close()

A synchronous and possibly less thorough version of close.

close()

Shut down and release resources.

flush()

Flush the queue used by get_oldest and next.

get()

Get the most recent message, or None if no data has ever been seen (has_data False).

get_oldest()

Pop and return the oldest message from the queue, or None if the queue is empty.

next(*[, timeout])

Wait for data, returning old data if found.

Attributes Documentation

DataType

The type (class) for a message of this topic.

When you read or write a message for this topic you are reading or writing an instance of DataType.

Notes

The preferred way to write a message for a topic is:

  • RemoteCommand.start to start a command.

  • CommandEvent.write to write an event.

  • CommandTelemetry.write to write a telemetry message.

allow_multiple_callbacks

Can callbacks can run simultaneously?

Notes

Ignored for synchronous callbacks because those block while running. In particular, if the callback is synchronous but launches one or more background jobs then the number of those jobs cannot be limited by this class.

callback

Asynchronous callback function, or None if there is not one.

Synchronous callback functions are deprecated.

The callback function is called when a new message is received; it receives one argument: the message (an object of type topics.BaseTopic.DataType).

Raises
TypeError

When setting a new callback if the callback is not None and is not callable.

Notes

Setting a callback flushes the queue, and it will remain empty as long as there is a callback.

get_oldest and next are prohibited if there is a callback function. Technically they could both work, but get_oldest would always return None and next would miss messages if they arrived while waiting for something else. It seems safer to raise an exception.

has_callback

Return True if there is a callback function.

has_data

Has any data ever been seen for this topic?

Raises
RuntimeError

If the salinfo has not started reading.

max_history
metadata

Get topic metadata as a TopicMetadata, if available,else None.

nqueued

Return the number of messages in the Python queue.

volatile

Does this topic have volatile durability?

Methods Documentation

async ack(data: BaseMsgType, ackcmd: AckCmdDataType) None

Acknowledge a command by writing a new state.

Parameters
dataDataType

Data for the command being acknowledged.

ackcmdsalobj.AckCmdType

Command acknowledgement data.

async ack_in_progress(data: BaseMsgType, timeout: float, result: str = '') None

Ackowledge this command as “in progress”.

Parameters
dataDataType

Data for the command being acknowledged.

timeoutfloat

Estimated command duration (sec).

resultstr, optional

Reason for acknowledgement. Typically left “”.

async aget(timeout: float | None = None) BaseMsgType

Get the most recently seen message (with no delay), or wait for data if no data has ever been seen (has_data False).

This is almost exactly like get. The only difference: if no data has ever been received by this topic it will wait for data. Once the topic has received any data, calling aget is identical to calling get (except for the need to use await) and the call will return almost instantly.

Please avoid aget, if possible, because it tends to confuse users. Use get to get the current data or next to wait for new data (you will almost never need both for the same topic).

Parameters
timeoutfloat, optional

Time limit, in seconds. If None then no time limit.

Returns
dataDataType

The current or next message.

Raises
asyncio.TimeoutError

If no message is available within the specified time limit.

RuntimeError

If a callback function is present, or if the salinfo has not started reading.

Notes

This method does not remove data from the queue, so it does not change which data is returned by next. In that respect it is not quite identical to this snippet, which otherwise does the same thing as aget:

data = self.get()
if data is None:
    data = await self.next(flush=False, timeout=timeout)
return data

Do not modify the returned data. To make a copy that you can safely modify, use copy.copy(data).

basic_close() None

A synchronous and possibly less thorough version of close.

Intended for exit handlers and constructor error handlers.

async close() None

Shut down and release resources.

Intended to be called by SalInfo.close(), since that tracks all topics.

flush() None

Flush the queue used by get_oldest and next.

This makes get_oldest return None and next wait, until a new message arrives. It does not change which message will be returned by aget or get.

Raises
RuntimeError

If a callback function is present.

get() lsst.ts.salobj.type_hints.BaseMsgType | None

Get the most recent message, or None if no data has ever been seen (has_data False).

This method does not change which message will be returned by aget, get_oldest, and next.

Returns
dataself.DataType or None

Return self.data if data has been read, else None.

Raises
RuntimeError

If the salinfo has not started reading.

get_oldest() lsst.ts.salobj.type_hints.BaseMsgType | None

Pop and return the oldest message from the queue, or None if the queue is empty.

This is a variant of next that does not wait for a new message. This method affects which message will be returned by next, but not which message will be returned by aget or get.

Returns
dataself.DataType or None

The oldest message found on the queue, if any, else None.

Raises
RuntimeError

If a callback function is present, or if the salinfo has not started reading.

Notes

Use with caution when mixing with next, since that also consumes data from the queue.

async next(*, timeout: float | None = None) BaseMsgType

Wait for data, returning old data if found.

Unlike RemoteEvent.next and RemoteTelemetry.next, the flush argument is not allowed; the only way to flush old commands is to call flush.

Parameters
timeoutfloat, optional

Time limit, in seconds. If None then no time limit.

Returns
dataDataType

Command data.

Raises
asyncio.TimeoutError

If no message is available within the specified time limit.

RuntimeError

If a callback function is present.

Notes

Do not modify the data or assume that it will be static. If you need a private copy, then copy it yourself.