Mid CSP LMC Tango Clients Examples

In the following sections some itango interface examples are provided, to be easily applied to a generic python client.

Basic assumptions for each example are:

  1. the system has been fresh initialized

  2. the only CSP sub-system deployed is the CBF

  3. CBF supports up to 4 VCCs and 4 FSPs

  4. all TANGO operations (read/write/command_inout) are always successful. No check on the results is done in the following examples.

To control CSP with itango, a proxy to CSP Controller and Subarrays has to be created:

csp_ctrl = tango.DeviceProxy('mid-csp/control/0')
csp_sub1 = tango.DeviceProxy('mid-csp/subarray/01')
csp_sub2 = tango.DeviceProxy('mid-csp/subarray/02')
csp_sub3 = tango.DeviceProxy('mid-csp/subarray/03')

It is possible also to create proxies to CBF controller and subarrays, in order to check their states and mode after a command is issued:

cbf_ctrl = tango.DeviceProxy('mid_csp_cbf/sub_elt/controller')
cbf_sub1 = tango.DeviceProxy('mid_csp_cbf/sub_elt/subarray_01')
cbf_sub2 = tango.DeviceProxy('mid_csp_cbf/sub_elt/subarray_02')
cbf_sub3 = tango.DeviceProxy('mid_csp_cbf/sub_elt/subarray_03')

To monitor the VCCs and FSPs, it is possible to create a proxies to the CSP LMC Capabilities:

fsp_cap = tango.DeviceProxy('mid-csp/capability-fsp/0')
vcc_cap = tango.DeviceProxy('mid-csp/capability-vcc/0')

Please note that all commands on subarray follow the ObsState state model defined in ADR-8. A CSP.LMC Subarray doesn’t allow commands from observing states other than those specified in this model.

After the deployment, all the Mid CSP.LMC devices a part from the capabilities are in following conditions:

- state DISABLE.
- healthState UNKNOWN
- adminMode OFFLINE
- obstState EMPTY (subarrays)

The capabilities start in ON state.

From now on, all the examples refers to these proxy objects. For Subarray commands, the proxy to subarray 1 will be used.

Mid CSP.LMC start communication

The Mid CSP.LMC Devices adminMode is a memorized attribute. That means that it is stored in the TANGO DB and its value is written to the devices just after the initialization. If the adminMode is ENGINEERING(2)/ONLINE(0) the connection between Mid CSP.LMC Devices and the subsystem starts immediately. Otherwise, to start the communication use the following command:

csp_ctrl.adminMode = 2  #set to ENGINEERING

or

csp_ctrl.adminMode = 0  #set to ONLINE

Mid CSP.LMC Controller forwards the adminMode value to its Subarrays and subordinated systems devices. When adminMode is set to ENGINEERING(2)/ONLINE(0) in Mid CSP.LMC controller, before it is forwarded to CBF controller, simulationMode attribute is written to CBF controller to the value that is set in Mid CSP.LMC controller attribute cbfSimulationMode. This value is True by default, but it can be changed by the user before writing adminMode. Simulation mode can be modified from CSP Controller at anytime during the operation by writing to attribute cbfSimulationMode. The new states are the following for all the devices:

- state OFF
- healthState OK
- adminMode ENGINEERING(2)/ONLINE(0)
- obstState EMPTY (subarrays)

Configure DishID-VCC map

Before turning ON the CSP LMC, it is mandatory to issue the LoadDishCfg command to the controller. It requires as input a JSON string that could contains the DishId-VCC map itself or the CAR URI at which the map could be found (here. ):

csp_ctrl.loadDishCfg(json_string)

The command returns immediately the following list:

[array([2], dtype=int32), ['1679401117.9451234_224758016395799_loadDishCfg']]

In case of failure, to highlight the result of the command, the attribute alarmDishIdCfg is raised on the CSP.LMC Controller. Moreover, the health state of all the deployed CSP.LMC Subarrays is forced to FAILED since they are not able to work without the proper dishId-VCC map:

csp_ctrl.alarmDishIdCfg = True
csp_sub1.healthState = HelathState.FAILED
csp_sub2.healthState = HealthState.FAILED
csp_sub3.healthState = HealthSate.FAILED

As soon as the command LoadDishCfg is executed with success, the alarn flag is reset and each CSP.LMC Subarray re-evalauate its health state:

csp_ctrl.alarmDishIdCfg = False
csp_sub1.healthState = OK
csp_sub2.healthState = OK
csp_sub3.healthState  = OK

It is now possible to invoke the power-on command.

Power-on (off/standby) the Mid.CSP

To power on the Mid.CSP devices, issue the command:

csp_ctrl.On([]) # empty list: power on all the available sub-systems (CBF, PSS, PST)

or

csp_ctrl.On(['mid_csp_cbf/sub_elt/controller', ]) # 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 element 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 command On invoked on the Mid.CSP Controller is forwarded to the Mid CBF sub-system Controller and to all the Mid.CSP Subarrays. This can be checked by the state of all controllers and subarrays:

csp_ctrl.state() -> ON
csp_sub1.state() -> ON
csp_sub2.state() -> ON
csp_sub3.state() -> ON

cbf_ctrl.state() -> ON
cbf_sub1.state() -> ON
cbf_sub2.state() -> ON
cbf_sub3.state() -> ON

The same logic and syntax apply also for Off and Standby commands.

Assign resources to a Mid CSP.LMC Subarray

To assign resources to a subarray both the subarray and controller devices must be in ON operational state. To move the system in such a state, please follow the previous example. Please note that right now only the receptor ids SKA001, SKA036, SKA103, SKA104 can be assigned to a subarray.

The following JSON string can be used to assign receptors to the Mid CSP.LMC:

json_string = '{"subarray_id": 1,"dish":{ "receptor_ids":["SKA001", "SKA036"]}}'

On successfully assignment, the receptors SKA001 and SKA036 are affiliated to subarray 1.

Invoke the AssignResources command on Mid.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'

The receptors assigned to Mid.CSP Subarray 1 are:

csp_sub1.assignedReceptors -> ("SKA001", "SKA036")

Information about resources availability are provided by the Mid.CSP Controller.

To get the list of all the receptors:

csp_ctrl.receptorsList -> ("SKA001", "SKA036", "SKA103", "SKA104")

To get the list of the available receptors:

csp_ctrl.unassignedReceptorIDs -> ("SKA103", "SKA104")

To get the affiliation of the receptors to the subarrays:

csp_ctrl.receptorMembership -> [1, 1, 0, 0]

After resource allocation the Mid CSP.LMC and Mid CBF Subarray obsState attribute value changes from EMPTY to IDLE. To check the observing state of the devices:

csp_sub1.obsstate -> IDLE
cbf_sub1.obsstate -> IDLE

Configure, issue and end a scan

After a Subarray has resources assigned, it is possible to configure it and then start a scan.

The json_string to be used for configure and scan can be found here. They have to be assigned to a variable and sent as command input as showed above for assignresources.

First of all, Configure command has to be issued:

csp_sub1.configure(json_string_configure)

The observimg state 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

The subarray in READY observing state can be re-configured with a new configuration that overwrites the previous one.

When the subarray is READY, a scan can be started, issuing the Scan command:

csp_sub1.scan(json_string_scan)

If the command is successful:

csp_sub1.commandResult -> ('scan', '1')
csp_sub1.obsstate -> SCANNING
cbf_sub1.obsstate -> SCANNING

Note that the result code associated to the Scan command will remain ‘1’ for all the duration of the scanning process. In fact, according to ADR-8 a scan can be interrupted by the EndScan 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 ensures that all the processes are correctly managed.

To end a scan, just issue:

csp_sub1.endscan()

After EndScan is successful, the subarray obsState 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 ABORTED state 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 resources of a subarray can only be released when its obsState is IDLE. When the subarray is in READY (as happens after the end of a scan) it must first be sent to IDLE with the command:

csp_sub1.gotoidle()

Upon successful completion of the command, the obsState will be IDLE and the resources can be partially or totally removed from the subarray.

To partially remove some of the allocated resources, a json string, like the one used for assign resources (see above) should be sent. This string must specify the receptors to be removed.

Following the previous example, to remove the receptor 1 from the list of the assigned receptors to the Mid CSP.LMC Subarray 1:

json_string = '{"subarray_id": 1,"dish":{ "receptor_ids":["SKA001"]}}
csp_sub1.ReleaseResources(json_string)

On command success, the subarray will have only receptor 2 assigned to it, and its obsState will stay in IDLE. The released receptor (1) will now appear in the pool of the Mid CSP.LMC available resources. This can be verified, accessing the proper attributes of the Mid CSP.LMC Subarray and Controller devices:

csp_sub1.commandResult -> ('releaseresources', '0')
csp_sub1.obsstate -> IDLE

csp_sub1.assignedReceptors -> ["SKA036"]
csp_ctrl.receptorsList -> ["SKA001", "SKA036", "SKA103", "SKA104"]
csp_ctrl.unassignedReceptorIDs -> ["SKA001", "SKA103", "SKA104"]
csp_ctrl.receptorMembership -> [0, 1, 0, 0]

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:

csp_sub1.commandResult -> ('releaseallresources', '0')
csp_sub1.obsstate -> EMPTY

csp_sub1.assignedReceptors -> []
csp_ctrl.unassignedReceptorIDs -> ["SKA001", "SKA036", "SKA103", "SKA104"]
csp_ctrl.receptorMembership -> [0, 0, 0, 0]

Connect to the FSP Processing Modes Capability Device

To connect to the capability device:

fsp_cap = tango.DeviceProxy('mid-csp/capability-fsp/0')
fsp_cap.state() = DevState.ON

After Controller power-up:

fsp_cap.fspAvailable = [1,2,3,4]

After configuring Mid CSP Subarray 1 for correlation using FSP1 and FSP2:

fsp_cap.fspCorrelation = [1]
fsp_cap.fspFunctionMode = ['CORR', 'CORR', 'IDLE', 'IDLE']
fsp_cap.Available = 2

Connect to the VCC Capability Device

To connect to the capability device:

vcc_cap = tango.DeviceProxy('mid-csp/capability-vcc/0')

The default state is On, since it is a monitoring device:

vcc_cap.state()

Then, it is possible to verify some parameters like:

vcc_cap.versionId
vcc_cap.vccFqdn
vcc_cap.vccsDeployed