How to invoke a long running command

The recommended way to invoke a long running command on a device is to use the invoke_lrc() function. The function will initiate the LRC on the device and call the LRCCallbackType provided whenever there are updates for the LRC.

import tango
import threading
import typing
import ska_control_model as scm
import ska_tango_base as stb

def invoke_on(device: tango.DeviceProxy) -> scm.ResultCode:
    """Invoking the On LRC on a device.

    As an example, this function blocks until the LRC has completed,
    however, this is not required.  The `lrc_callback` is called
    asynchronously and so it is possible to wait for long running command
    to complete without blocking.

    :return: ResultCode.OK if the command succeed, ResultCode.FAILED
        otherwise.
    """

    done = threading.Event()
    returned = None

    # We must accept unknown kwargs here as future versions of invoke_lrc
    # may pass additional arguments
    def lrc_callback(
        result: list[typing.Any] | None = None, **kwargs: typing.Any
    ) -> None:
        nonlocal returned
        if result is not None:
            returned = result
            done.set()

    try:
        # We have to keep this lrc_subscriptions alive for as long as we are
        # interested in this LRC
        lrc_subscriptions = stb.long_running_commands.invoke_lrc(
            lrc_callback, device, "On"
        )
    except stb.faults.CommandError:
        # handle rejection
        return scm.ResultCode.FAILED
    except tango.DevFailed:
        # handle error
        return scm.ResultCode.FAILED

    if not done.wait(timeout=10):
        # handle timeout
        return scm.ResultCode.FAILED

    # result has been populated here as done is set
    assert returned is not None
    lrc_subscriptions.unsubscribe_lrc_events()

    if scm.ResultCode(returned[0]) != scm.ResultCode.OK:
        # handle failure
        return scm.ResultCode.FAILED

    return scm.ResultCode.OK

Behind the scenes invoke_lrc() is subscribing to CHANGE_EVENTs from the LRC attributes and prior to ska-tango-base version 1.1 the only way to monitor a long running command was to subscribe to these attributes directly. You may see code doing this if it pre-dates ska-tango-base version 1.1.

Since ska-tango-base 1.2 directly subscribing to attributes has been deprecated and the only supported method to monitor the LRC is via the invoke_lrc() function. If the invoke_lrc function is not sufficient for you to migrate to, please contact Team Wombat who can work out an additional interface to suit your use case.