###################### Tango Clients Examples ###################### Basic assumptions for each example are: 1. the system has been fresh initialized 2. CSP sub-system are the CBF and PST. **If Pst is not deployed, just ignore the commands and check related to it.** 3. All TANGO operations (read/write/command_inout) are always successful. No check on the results is done in the following examples. To get instruction on how to deploy a working system, please refer to the project's `README `_. Be sure that both the charts for ``ska-low-cbf`` and ``ska-low-cbf-proc`` , as stated in the `'low-umbrella-chart' `_ are deployed. To control CSP with itango, a proxy to CSP Controller and Subarrays has to be created:: csp_ctrl = tango.DeviceProxy('low-csp/control/0') csp_sub1 = tango.DeviceProxy('low-csp/subarray/01') csp_sub2 = tango.DeviceProxy('low-csp/subarray/02') csp_sub3 = tango.DeviceProxy('low-csp/subarray/03') csp_sub4 = tango.DeviceProxy('low-csp/subarray/04') It is possible also to create proxies to CBF controller and subarrays, as well as to PST Beam, in order to check their states and mode after the command is issued:: cbf_ctrl = tango.DeviceProxy('low-cbf/control/0') cbf_sub1 = tango.DeviceProxy('low-cbf/subarray/01') cbf_sub2 = tango.DeviceProxy('low-cbf/subarray/02') cbf_sub3 = tango.DeviceProxy('low-cbf/subarray/03') csp_sub4 = tango.DeviceProxy('low-csp/subarray/04') pst_beam1 = tango.DeviceProxy("low-pst/beam/01") To monitor the Pst beams and the Fsp processors, it is possible to create proxies to the CSP LMC Capabilities (see section below): :: pst_cap = tango.DeviceProxy('low-csp/capability-pst/0') fsp_cap = tango.DeviceProxy('low-csp/capability-fsp/0') The capabilities start in ON state. Please note that the Low CBF is currently deploying 4 subarrays. If a Low CBF subarray is not deployed, the corresponding Low CSP.LMC subarray state is FAULT and can't be used for operations. Also note that all commands on subarrays follow the `ObsState state model `_ defined in ADR-8. CSP/LMC doesn't allow commands from obstate other than those specified in this model. From now on, all the examples refers to these proxy objects. For Subarray commands, the proxy to subarray 1 will be used. ******************************** Low CSP.LMC state after deployed ******************************** When the deployment finish (see *low-csp-umbrella* to get the deployment charts versions), the state and modes of the Low.CSP controller, subarrays and subsystems are the following:: csp_ctrl.state() = DISABLE csp_sub1.state() = DISABLE cbf_sub1.state() = DISABLE pst_beam1.state() = DISABLE csp_ctrl.healthstate = UNKNOWN csp_sub1.healthstate = UNKNOWN cbf_sub1.healthstate = UNKNOWN pst_beam1.healthstate = UNKNOWN csp_ctrl.adminMode = OFFLINE csp_sub1.adminMode = OFFLINE cbf_sub1.healthstate = UNKNOWN pst_beam1.adminMode = OFFLINE csp_sub1.obsstate = EMPTY cbf_sub1.obsstate = EMPTY pst_beam1.obsstate = IDLE (NOTE: only one subarray is displayed but the behavior is espected for all 4 of them) Low CSP.LMC Controller and Subarrays adminMode have to be set to ENGINEERING or ONLINE to start the connection with the subordinate Low CBF TANGO Devices. To start the communication use the following command:: csp_ctrl.adminMode = 2 #set to ENGINEERING or :: csp_ctrl.adminMode = 0 #set to ONLINE Low CSP.LMC Controller forwards the *adminMode* value to its Subarrays and subordinated systems devices. After this step, all devices goes in adminMode=ONLINE, obstates remain the same as after initialisation. For states and healthstates :: cbf_ctrl.state() = ON csp_sub1.state() = ON cbf_sub1.state() = ON pst_beam1.state() = OFF csp_ctrl.healthstate = UNKNOWN (It will be fixed to OK in one of the next releases) csp_sub1.healthstate = UNKNOWN (It will be fixed to OK in one of the next releases) cbf_sub1.healthstate = UNKNOWN (It will be fixed to OK in one of the next releases) pst_beam1.healthstate = OK ********************************** Power-on (off/standby) the Low.CSP ********************************** .. note:: CBF Devices start in ON state and so CSP. Anyway the command ON can be still meaningful for turning on other subsystems. If only cbf is present, this section can be dropped To power-on all the device, send the ON command towards the Low.CSP Controller. The sub-systems already in ON state will be skipped by the command. :: csp_ctrl.On([]) # empty list: power on all the available sub-systems (CBF, PSS, PST) or :: csp_ctrl.On(['low-pst/beam/01', ]) # power-on only the specified sub-systems The command returns immediately the following list:: [array([2], dtype=int32), ['1679401117.9451234_224758016395799_On']] Where: - 2 is the command status (2 means QUEUED) - '1679401117.9451234_224758016395799_On' is a unique id assigned to the command. It can be used to track the execution status of the command It is possible to read the command result state using:: cmd_result = csp_ctrl.commandResult *cmd_result* is a Tuple of two strings: - the first one is the name of last executed CSP task - the second one is the result code: allowed values for the result code are defined in SKA Base Classes module `ska_tango_base.commands `_ Possible results for the current example are: - ('on', '0') # *On* task completed successfully - ('on', '1') # *On* task started - ('on', '3') # *On* task completed with failure Some of the long running command attributes can also be accessed. Long running command result can be read using: :: long_running_command_result = csp_ctrl.longRunningCommandResult *long_running_command_result* is a Tuple of a string and a list: - the first element is a command id assigned when command is invoked - the second element is a list of result code (matching the value in command result attribute described above) and result message Possible results: - ('1684312814.139426_265125881596693_On', '[0, "on completed 1/1"]') # *On* task completed successfully on one devices - ('1684312814.139426_265125881596693_Configure', '[0, "configure completed on components 2/2"]') # *Configure* task completed successfully on two devices - ('1684312814.139426_265125881596693_Off', '[3, "off completed 1/1"]') # *Off* task completed with failure on one device It is also possible to access long running command status at the various stages of command execution. This attribute can be read using:: long_running_command_status = csp_ctrl.longRunningCommandStatus *long_running_command_status* is a Tuple of pairs of strings. In each pair the elements represent the following: - the first element is a command id assigned when command is invoked - the second element is the task status: allowed values for the task status are defined in SKA Base Classes module `ska_tango_base.executor `_ Possible results: - ('1684312814.139426_265125881596693_On', 'QUEUED') - ('1684312814.139426_265125881596693_On', 'IN_PROGRESS') - ('1684312814.139426_265125881596693_On', 'COMPLETED') - ('1684312814.139426_265125881596693_On', 'ABORTED') - ('1684312814.139426_265125881596693_On', 'FAILED') - ('1684312814.139426_265125881596693_On', 'REJECTED') Note that there can be more than one pair of command id and task status in the attribute, if there are more commands invoked. The possible values of *commandResult* and *longRunningCommandResult* are the same for all commands, so they will be skipped in the next sections. The command *On* invoked on the Low.CSP Controller is forwarded to the CBF sub-system Controller, to all the Low.CSP Subarrays and to all PST Beams. Since CSP and CBF are already ON, the command is not executed on them. Otherwise the state of pst beam will change to OFF:: pst_beam1.state() -> ON The same logic and syntax apply also for *Off* and *Standby* command. ****************************************** Assign resources to the Low.CSP Subarray ****************************************** To assign resources on a subarray both the subarray and controller are needed to be on. To do this please follow the previous example. A ``json_string`` variable needs to be create containing the proper json structure for assignment of resources. Working templates can be found :ref:`here `, with and without the assignment of one PST beam. Invoke the AssignResources command on Low.CSP Subarray 1:: csp_sub1.assignresources(json_string) If command is successful, the command result will report:: csp_sub1.commandResult -> ('assignresources', '0') csp_sub1.commandResultName -> 'assignresources' csp_sub1.commandResultCode -> '0' After the assignment of resources the CSP.LMC and CBF Subarray osbstate move from EMPTY to IDLE. Pst Beam remains IDLE. It can be checked by:: csp_sub1.obsstate -> IDLE cbf_sub1.obsstate -> IDLE pst_beam1.obsstate -> IDLE PST will be assigned to Subarray01, It can be checked by: :: csp_sub1.assignedtimingbeamids = [1] ******************************** Configure, issue and end a Scan ******************************** After the Subarray has resources assigned, it is possible to configure and run a scan on the subarray. When Low-CBF is simulated, i.e. no fpga-hardware is controlled, some preliminary steps are needed in order to perform a simulated observation. In particular, some serial numbers need to be associated to the Processors device and registered to the Allocator device. If not, the configuration of subarray will fail because CBF does not recognize the presence of *fsps* To do this: :: cbf_proc1 = tango.DeviceProxy('low-cbf/processor/0.0.0') cbf_proc2 = tango.DeviceProxy('low-cbf/processor/0.0.1') cbf_proc1.serialnumber = "XFL14SLO1LIF" cbf_proc1.subscribetoallocator("low-cbf/allocator/0") cbf_proc1.register() cbf_proc2.serialnumber = "XFL1HOOQ1Y44" cbf_proc2.subscribetoallocator("low-cbf/allocator/0") cbf_proc2.register() If this is not performed, the configure command will fail. NOTE: in this procedure we have registered two processor, as they are needed to perform commands with the control of a PST Beam. For only CBF control, can be registered only one processor. The ``json_string`` to be used for configure and scan can be found :ref:`here `. They have to be assigned to a variable and send as a command input as showed above for assignresources. First of all, Configure command has to be issued:: csp_sub1.configure(json_string_configure) The obsstate will be in CONFIGURING during the execution. After that, if the command is successful:: csp_sub1.commandResult -> ('configure', '0') csp_sub1.obsstate -> READY cbf_sub1.obsstate -> READY pst_beam1.obsstate -> READY A new configuration can be sent also in READY state, overwriting the old one. After the subarray is READY, a scan can be issued:: csp_sub1.scan(json_string_scan) if the command is successful:: csp_sub1.commandResult -> ('scan', '0') csp_sub1.obsstate -> SCANNING cbf_sub1.obsstate -> SCANNING pst_beam1.obsstate -> SCANNING It as been decided that the command *scan* has to be considered as a normal command that return the status 0 when all the subsystems are moved to SCANNING status. The scan behavior is documented in `Scan handling `_ . According to `ADR-8 `_ a Scan can be interrupted by the EndScan Command or the Abort Command. The Abort Command has to be intended as an emergency call that interrupts abruptly the Scan process. On the other side, the EndScan first ensure that all the processes are correctly managed. To end a scan, just issue:: csp_sub1.endscan() After End Scan is successful, the ObState of subarray is READY, and another Scan can be issued with the same configuration. On the other side, if the Scan is aborted, the obsstate will go (after a short time in ABORTING) to be ABORTED. To perform a new scanning, the subarray observation should be restarted (via the ObsReset command) and a new configuration need to be sent ( `ADR-8 `_) The sequence of operation is:: csp_sub1.abort() csp_sub1.commandResult -> ('abort', '1') csp_sub1.obsstate -> ABORTING csp_sub1.commandResult -> ('abort', '0') csp_sub1.obsstate -> ABORTED csp_sub1.obsreset() csp_sub1.commandResult -> ('obsreset', '1') csp_sub1.obsstate -> RESETTING csp_sub1.commandResult -> ('obsreset', '0') csp_sub1.obsstate -> IDLE ******************************** Go To Idle and Release Resources ******************************** The release of the resources of a subarray can be done only in IDLE obsstate. For this reason, if the subarray is in READY firstly must be sent to IDLE with the command:: csp_sub1.gotoidle() if the command is successful, the obsstate will be IDLE. After that, the resources can be partially or totally removed. To partially remove some resources, a json string, like the one used for assign resources (see above) should be sent. In this string, please specify the resources to be removed. csp_sub1.releaseresources(json_string) On command success:: csp_sub1.commandResult -> ('releaseresources', '0') csp_sub1.obsstate -> IDLE pst_beam1.obsstate -> IDLE Otherwise, if all resources are meant to be removed, this can be done with the ReleaseAllResouces command:: csp_sub1.releaseallresources() On command success, the subarray will be EMPTY again, and some resouces need to be added to perform a new operation:: csp_sub1.commandResult -> ('releaseallresources', '0') csp_sub1.obsstate -> EMPTY pst_beam1.obsstate -> IDLE csp_sub1.assignedtimingbeams = [] ***************************************************** Connect to the PST Capability Device ***************************************************** To connect to the capability device:: pst_cap = tango.DeviceProxy('low-csp/capability-pst/0') After the capability inizialization the capability is in the following condition:: pst_cap.State() -> ON pst_cap.healthState -> OK pst_cap.adminMode -> ONLINE The list of the capability attributes can be found :ref:`here `. Note that in case there is no Pst beam deployed, the capability modify its healthState :: pst_cap.State() -> ON pst_cap.healthState -> FAILED whilest in case the capability is not able to connect to the CSP controller, its State will be :: pst_cap.State() -> FAULT pst_cap.healthState -> FAILED ***************************************************** Connect to the FSP Capability Device ***************************************************** To connect to the capability device:: fsp_cap = tango.DeviceProxy('low-csp/capability-fsp/0') After the capability inizialization the capability is in the following condition:: pst_cap.State() -> DISABLE pst_cap.healthState -> OK pst_cap.adminMode -> ONLINE The list of the capability attributes can be found :ref:`here `.