diff --git a/csp-lmc-common/HISTORY b/csp-lmc-common/HISTORY index 5d3e2752b39d01971c3030247d3e4c6e63cd5549..9b9265bc9ff6eff76a07e7b2ac7d567ac0106e78 100644 --- a/csp-lmc-common/HISTORY +++ b/csp-lmc-common/HISTORY @@ -1,3 +1,7 @@ +0.7.1 +- Off command in Subarray drives each sub-element component to the final OFF/EMPTY state. +- CspMaster On/Standby commands are executed synchronously + 0.7.0 - Align CSP.LMC to be compliant with the SKA Base Classes API: add of Assign/ReleaseResources commands. diff --git a/csp-lmc-common/csp_lmc_common/CspMaster.py b/csp-lmc-common/csp_lmc_common/CspMaster.py index 89d082d76d520482170b006318cd6ea5cdbeca15..69a3ea9d4d1244116f433e2951d76fdc4034334b 100644 --- a/csp-lmc-common/csp_lmc_common/CspMaster.py +++ b/csp-lmc-common/csp_lmc_common/CspMaster.py @@ -592,42 +592,48 @@ class CspMaster(SKAMaster): # reset the CSP command execution flag with self._cmd_exec_state_lock: self._cmd_execution_state[cmd_name] = CmdExecState.IDLE - self._update_csp_state() - self.logger.info("CSP State:{}".format(self.get_state())) - self._enable_subarrays(tango_cmd_name) def _enable_subarrays(self, tango_cmd_name): - enable = False - subarray_cmd = tango_cmd_name - if tango_cmd_name == 'On': - enable = True - if tango_cmd_name == 'Standby': - subarray_cmd = 'Off' + """ + Helper method to execute the On[Off] command on the CSP subarrays. + + :param tangp_cmd_name: The command to execute + :type tamgo_cmd_name: string + :return: None + """ + subarray_action = tango_cmd_name.lower() + if subarray_action not in ['on', 'off']: + self.logger.warning(f"Invalid command {subarray_action} to issue on CSP subarray") + return master_state = self.get_state() - if (enable, master_state) not in [(True, tango.DevState.ON), (False, tango.DevState.STANDBY)]: + if (subarray_action, master_state) not in [('on', tango.DevState.ON), ('off', tango.DevState.STANDBY)]: self.logger.warning("CSPMaster is not in the proper state ({})".format(self.get_state())) return try: subarray_group = tango.Group("CSPSubarray") for subarray in self.CspSubarrays: subarray_group.add(subarray) - self.logger.info("Issue command {} on subarray group".format(subarray_cmd)) - answers = subarray_group.command_inout(subarray_cmd) + self.logger.info("Going to switch-{} the subarrays".format(subarray_action)) + answers = subarray_group.command_inout(subarray_action) for reply in answers: if reply.has_failed(): self.logger.info("stack: {}".format(len(reply.get_err_stack()))) for err in reply.get_err_stack(): self.logger.info("err {} reason {}".format(err.desc, err.reason) ) self.logger.warning("Subarray {} failed executing command {}".format(reply.dev_name(), - subarray_cmd)) + subarray_action)) else: (result_code, msg) = reply.get_data() if result_code == ResultCode.FAILED: - self.logger.error(msg[0]) + self.logger.error(f"Subarray {reply.dev_name()}: {msg[0]}") elif result_code == ResultCode.OK: - self.logger.info(msg[0]) + self.logger.info(f"Subarray {reply.dev_name()}: {msg[0]}") + except tango.DevFailed as df: + log_msg = (f"Failure in command {subarray_action} " + "for device {str(fqdn)}: {str(df.args[0].reason)}") + self.logger.error(log_msg) except Exception: - self.logger.error("TANGO Group command failed") + self.logger.error("command {} failed on subarray".format(subarray_action)) def _se_write_adminMode(self, value, device_fqdn): """ @@ -1885,8 +1891,11 @@ class CspMaster(SKAMaster): self._cmd_execution_state['on'] = CmdExecState.RUNNING self._command_thread['on'].start() self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) - # sleep for a while to let the thread start - #time.sleep(0.1) + # To temporarily solve SKB-26 -> join the thread to synchronize the command + self._command_thread['on'].join() + self._update_csp_state() + self.logger.info("CSP State:{}".format(self.get_state())) + self._enable_subarrays('On') except Exception: # reset the sub-element command exec state self._se_cmd_execution_state.clear() @@ -1970,8 +1979,9 @@ class CspMaster(SKAMaster): self._cmd_execution_state['off'] = CmdExecState.RUNNING # start the thread self._command_thread['off'].start() - # sleep for a while to let the thread start - #time.sleep(0.1) + self._command_thread['off'].join() + self._update_csp_state() + self.logger.info("CSP State:{}".format(self.get_state())) except Exception: # reset the sub-element command exec state self._se_cmd_execution_state.clear() @@ -2054,8 +2064,11 @@ class CspMaster(SKAMaster): # start the thread self._command_thread['standby'].start() self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) - # sleep for a while to let the thread start - #time.sleep(0.1) + # To temprarily solve the SKB-26 -> join the thread to synchronize the command + self._command_thread['standby'].join() + self._update_csp_state() + self.logger.info("CSP State:{}".format(self.get_state())) + self._enable_subarrays('Off') except Exception: # reset the sub-element command exec state self._se_cmd_execution_state.clear() diff --git a/csp-lmc-common/csp_lmc_common/CspSubarray.py b/csp-lmc-common/csp_lmc_common/CspSubarray.py index ee878103231b1526ffeebbe220e65baa32b60aa8..889ab06c3dad523f432620c2bbf8cb789250d1cc 100644 --- a/csp-lmc-common/csp_lmc_common/CspSubarray.py +++ b/csp-lmc-common/csp_lmc_common/CspSubarray.py @@ -38,7 +38,7 @@ from tango import AttrWriteType, DeviceProxy from ska.base import SKASubarray, SKASubarrayStateModel #from ska.base import utils from ska.base.commands import ActionCommand, ResultCode -from ska.base.faults import CapabilityValidationError +from ska.base.faults import CapabilityValidationError, CommandError from ska.base.control_model import HealthState, AdminMode, ObsState, ObsMode from .utils.cspcommons import CmdExecState from .utils.decorators import transaction_id @@ -351,39 +351,90 @@ class CspSubarray(SKASubarray): def do(self): self.logger.info("Call Off Command") device = self.target + subelement_thr = {} + self.thread_succeeded = {} + off_failed = False + # First loop that start the sub-element threads to get the ObsState.EMPTY for fqdn in device._sc_subarray_fqdn: - try: - # check if the sub-element subarray is already in the - # requested state - if device._sc_subarray_state[fqdn] == tango.DevState.OFF: - continue - (result_code, message) = device._sc_subarray_proxies[fqdn].Off() - if result_code == ResultCode.FAILED: - self.logger.error("Off command failed on device {}".format(fqdn)) - if fqdn != device.CbfSubarray: - device._health_state = HealthState.DEGRADED - continue - else: - return (ResultCode.FAILED, message) - except tango.DevFailed as tango_err: - message = str(tango_err.args[0].desc) - return (ResultCode.FAILED, message) + # check if the sub-element subarray is already in the + # requested state + if device._sc_subarray_state[fqdn] == tango.DevState.OFF: + continue + if device._sc_subarray_obs_state[fqdn] != ObsState.EMPTY: + subelement_thr[fqdn] = threading.Thread(target=self.off_sequence, + name="Thread-OffSequence", + args=(fqdn,)) + subelement_thr[fqdn].start() + else: + self.logger.info(f'ObsState of device {fqdn} is not EMPTY. ObsState:{device._sc_subarray_obs_state[fqdn]}') + # Second loop check if the thread is succeeded and send the Off command to sub-element + for fqdn in subelement_thr.keys(): + subelement_thr[fqdn].join() + + if any(self.thread_succeeded[fqdn] == True for fqdn in subelement_thr.keys()): + for fqdn in subelement_thr.keys(): + try: + (result_code, message) = device._sc_subarray_proxies[fqdn].Off() + except tango.DevFailed as tango_err: + message = str(tango_err.args[0].desc) + result_code = ResultCode.FAILED + + if result_code == ResultCode.FAILED: + self.logger.error("Off command failed on device {}".format(fqdn)) + self.logger.info(message) + off_failed = True + + if off_failed: + return ResultCode.FAILED, 'Off command Failed' + message = "Off command completed OK" self.logger.info(message) - return (ResultCode.OK, message) - - class AssignResourcesCommand(SKASubarray.AssignResourcesCommand): + return ResultCode.OK, message + def off_sequence(self, fqdn): + #Off command send the device in the state:OFF, ObsState:EMPTY + self.logger.info('off sequence started!') + self.logger.info(f'FQDN: {fqdn}') + device = self.target + starting_time = time.time() + timeout = device._sc_subarray_cmd_duration_expected[fqdn]['off'] + while (time.time() - starting_time) < timeout and (device._sc_subarray_obs_state[fqdn] != ObsState.EMPTY): + # Try to send Abort Command. + # Device goes to ABORTED in case ObsState is: IDLE, READY, CONFIGURING, SCANNING, RESETTING + try: + self.logger.info('Try to execute Abort command') + self.logger.info(f'ObState: {device._sc_subarray_obs_state[fqdn]}') + device._sc_subarray_proxies[fqdn].Abort() + while (time.time() - starting_time) < timeout and (device._sc_subarray_obs_state[fqdn] != ObsState.ABORTED): + if device._sc_subarray_obs_state[fqdn] == ObsState.FAULT: + break + time.sleep(0.1) + except Exception as msg: + self.logger.info(msg) + # Try to send Restart Command. + # Device goes to EMPTY if ObsState is: FAULT, ABORTED + # ObsState could be aborted from above try section + try: + self.logger.info('Try to execute Restart command') + device._sc_subarray_proxies[fqdn].Restart() + except Exception as msg: + self.logger.info(msg) + time.sleep(0.1) + # if ObsState is: RESOURCING, ABORTING start again to wait end of the transition + + if device._sc_subarray_obs_state[fqdn] == ObsState.EMPTY: + self.thread_succeeded[fqdn] = True + else: + self.thread_succeeded[fqdn] = False + + class AssignResourcesCommand(SKASubarray.AssignResourcesCommand): @transaction_id def do(self, argin): #TODO: Edit the logger self.logger.info('Assign resource command ... ') return (ResultCode.OK, "Assign Resources command completed OK") - - class ConfigureCommand(SKASubarray.ConfigureCommand): - @transaction_id def do(self, argin): # checks on State, adminMode and obsState values are performed inside the diff --git a/csp-lmc-common/csp_lmc_common/release.py b/csp-lmc-common/csp_lmc_common/release.py index b93729c3f1b99ada8755f6c9825522449b04065d..45a477e4f9c7b206dddd4769966b30dcdc33b0e9 100755 --- a/csp-lmc-common/csp_lmc_common/release.py +++ b/csp-lmc-common/csp_lmc_common/release.py @@ -10,7 +10,7 @@ """Release information for Python Package""" name = """csp-lmc-common""" -version = "0.7.0" +version = "0.7.1" version_info = version.split(".") description = """SKA CSP.LMC Common Software""" author = "INAF-OAA" diff --git a/csp-lmc-mid/.release b/csp-lmc-mid/.release index 689fa9b5760d9975d1a39d5ee44b8008e1e63798..f6a1b63db596c81a981f4d2fc907818d948e9e45 100644 --- a/csp-lmc-mid/.release +++ b/csp-lmc-mid/.release @@ -9,7 +9,7 @@ """Release information for Python Package""" name = """MID CSP.LMC""" -version = "0.7.0" +version = "0.7.1" version_info = version.split(".") description = """SKA MID CSP.LMC Classes""" author = "E.G" diff --git a/csp-lmc-mid/HISTORY b/csp-lmc-mid/HISTORY index 9eccdf71ce27e491d1d98ded4f510e77784e64d4..f1dc1f5c5049ddde614495bba9c018d766ebfc70 100644 --- a/csp-lmc-mid/HISTORY +++ b/csp-lmc-mid/HISTORY @@ -1,3 +1,7 @@ +0.7.1 +- use csp-lmc-common 0.7.1 +- updated integration tests + 0.7.0 - use csp-lmc-common 0.7.0 - align Mid CSP.LMC to the SKA Base Classes API diff --git a/csp-lmc-mid/charts/mid-csp-umbrella/Chart.yaml b/csp-lmc-mid/charts/mid-csp-umbrella/Chart.yaml index fe6a5dd535c862076c6f551c17e0efd2019cf1ec..188a21074a2adbc24dafd40d2c3d84dc21107080 100644 --- a/csp-lmc-mid/charts/mid-csp-umbrella/Chart.yaml +++ b/csp-lmc-mid/charts/mid-csp-umbrella/Chart.yaml @@ -15,5 +15,5 @@ dependencies: version: 0.1.1 repository: https://nexus.engageska-portugal.pt/repository/helm-chart - name: mid-csp - version: 0.1.2 + version: 0.1.3 repository: "file://../mid-csp" diff --git a/csp-lmc-mid/charts/mid-csp/Chart.yaml b/csp-lmc-mid/charts/mid-csp/Chart.yaml index 6158b39c4410506e2929dc1fe8ebc7ca22fde876..47b2f3794ac66b706dfb071fb4e6e0965737ef13 100644 --- a/csp-lmc-mid/charts/mid-csp/Chart.yaml +++ b/csp-lmc-mid/charts/mid-csp/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 name: mid-csp description: A Helm chart for deploying the Mid_CSP.LMC devices on Kubernetes -version: 0.1.2 -appVersion: "0.7.0" +version: 0.1.3 +appVersion: "0.7.1" icon: https://www.skatelescope.org/wp-content/uploads/2016/07/09545_NEW_LOGO_2014.png dependencies: - name: tango-util diff --git a/csp-lmc-mid/charts/mid-csp/values.yaml b/csp-lmc-mid/charts/mid-csp/values.yaml index d56b102adac140a012fc7781d0da3e7898ccb3d1..b4c8dfce364c846f8a123358d3a782f3dce3dea3 100644 --- a/csp-lmc-mid/charts/mid-csp/values.yaml +++ b/csp-lmc-mid/charts/mid-csp/values.yaml @@ -37,7 +37,7 @@ midcsplmc: image: registry: nexus.engageska-portugal.pt/ska-docker image: mid-csp-lmc - tag: 0.7.0 + tag: 0.7.1 pullPolicy: IfNotPresent resources: diff --git a/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py b/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py index 6d7c0607d88ddafb47026acb6c898b648552fac8..1bfe5c72a765c96ea85cbf26a03ffb2aa492bf18 100644 --- a/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py +++ b/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py @@ -116,14 +116,14 @@ class MidCspSubarrayBase(CspSubarray): try: resources_dict = json.loads(argin) subarray_id = resources_dict['subarrayID'] - if subarray_id != self.target.SubID: + if subarray_id != int(self.target.SubID): msg = f"Mismatch in subarrayID. Received: {subarray_id} {self.target.SubID}" self.logger.error(msg) - #return (ResultCode.FAILED, msg) + return (ResultCode.FAILED, msg) receptor_list = list(map(int, resources_dict['dish']['receptorIDList'])) except (KeyError, json.JSONDecodeError) as error: msg = f"Something wrong in Json input string: {error}" - raise ValueError(msg) + return (ResultCode.FAILED, msg) return self._add_receptors(receptor_list) def _add_receptors(self, argin): diff --git a/csp-lmc-mid/csp_lmc_mid/release.py b/csp-lmc-mid/csp_lmc_mid/release.py index 5c450ad3801c5f2a7c117ae6e39927e1c1ebe755..687296cd021523c1355dd9bda4fea4e0bf1367fe 100755 --- a/csp-lmc-mid/csp_lmc_mid/release.py +++ b/csp-lmc-mid/csp_lmc_mid/release.py @@ -10,7 +10,7 @@ """Release information for Python Package""" name = """mid-csp-lmc""" -version = "0.7.0" +version = "0.7.1" version_info = version.split(".") description = """SKA MID CSP.LMC""" author = "INAF-OAA" diff --git a/csp-lmc-mid/requirements.txt b/csp-lmc-mid/requirements.txt index f8079945ab10c4683ee2269e5b07e1adb20dfd74..047ea76d4479cb85c76d785e3d1eb759c5e0db5c 100644 --- a/csp-lmc-mid/requirements.txt +++ b/csp-lmc-mid/requirements.txt @@ -2,7 +2,7 @@ numpy == 1.17.2 pytango >= 9.3.2 jsonschema >= 3.2.0 lmcbaseclasses >= 0.8.0 -csp-lmc-common >= 0.6.12 +csp-lmc-common >= 0.7.1 ska-log-transactions ska-telescope-model==0.2.0 diff --git a/csp-lmc-mid/tests/integration/MidCspMaster_test.py b/csp-lmc-mid/tests/integration/MidCspMaster_test.py index 51396a1684ec54b98b60c6d6cc7ebfd7c3f39bd0..455f5a855be0606c744879875887c246cf49fe8a 100644 --- a/csp-lmc-mid/tests/integration/MidCspMaster_test.py +++ b/csp-lmc-mid/tests/integration/MidCspMaster_test.py @@ -91,7 +91,23 @@ class TestCspMaster(TestBase): assert self.midcsp_master.state() == DevState.ON argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.Standby(argin) - prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, f"CSP Master not STANDBY") + prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, + f"CSP Master not STANDBY") + Poller(4, 0.2).check(prober_state) + + def test_issue_Standby_AFTER_On_command(self): + """ + Issue the Standby command just after the On command, without waiting + on the State value. + To solve SKB-26 bug, the power commands are now executed in + synch way. + """ + self._setup_master() + argin = ["mid_csp_cbf/sub_elt/master",] + self.midcsp_master.On(argin) + self.midcsp_master.Standby(argin) + prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, + f"CSP Master not STANDBY") Poller(4, 0.2).check(prober_state) ''' diff --git a/csp-lmc-mid/tests/integration/MidCspSubarray_test.py b/csp-lmc-mid/tests/integration/MidCspSubarray_test.py index ce9a36fb214e968bca8dfaac06b23d131334831d..5e1a2286919665242cfa582034ada8e03698433c 100755 --- a/csp-lmc-mid/tests/integration/MidCspSubarray_test.py +++ b/csp-lmc-mid/tests/integration/MidCspSubarray_test.py @@ -170,7 +170,12 @@ class TestCspSubarray(TestBase): f"Wrong CSP Subarray obsState {self.midcsp_subarray01.obsState}") Poller(5, 0.2).check(prober_subarray_obstate) - @pytest.mark.csp_k8s + def _build_resources(self, argin): + param = { + 'subarrayID': 1, + 'dish': { 'receptorIDList': list(map(str, argin))}} + return json.dumps(param) + def test_AFTER_initialization(self): """ Test for State after CSP startup. @@ -184,7 +189,6 @@ class TestCspSubarray(TestBase): prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") Poller(4, 0.2).check(prober_subarray_obsstate) - @pytest.mark.csp_k8s def test_subarray_state_AFTER_on_command_execution(self): """ @@ -200,7 +204,125 @@ class TestCspSubarray(TestBase): prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.ON, f"CSP Subarray not OFF") Poller(4, 0.2).check(prober_subarray_state) - @pytest.mark.csp_k8s + def test_OffCommand_after_RESOURCING(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-RESOURCING + """ + self._setup_subarray + json_config= self._build_resources([1,2]) + self.midcsp_subarray01.AssignResources(json_config) + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(4, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(4, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + + def test_OffCommand_after_IDLE(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-IDLE + """ + self._setup_subarray() + self._assign_receptors() + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(4, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(4, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + + def test_OffCommand_after_CONFIGURING(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-CONFIGURING + """ + self._setup_subarray() + self._configure_scan() + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(10, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(10, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + + def test_OffCommand_after_READY(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-READY + """ + self._setup_subarray() + self._configure_scan() + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.READY, f'CSP Subarray not READY') + Poller(10, 0.2).check(prober_subarray_obsstate) + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(10, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(10, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + + def test_OffCommand_after_SCANNING(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-SCANNING + """ + self._setup_subarray() + self._configure_scan() + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.READY, f'CSP Subarray not READY') + Poller(10, 0.2).check(prober_subarray_obsstate) + self.midcsp_subarray01.Scan('2') + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.SCANNING, f'CSP Subarray not SCANNING') + Poller(10, 0.2).check(prober_subarray_obsstate) + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(10, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(10, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + + def test_OffCommand_after_ABORTED(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-ABORTED + """ + self._setup_subarray() + self._assign_receptors() + self.midcsp_subarray01.Abort() + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.ABORTED, f'CSP Subarray not ABORTED') + Poller(10, 0.2).check(prober_subarray_obsstate) + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(4, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(4, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + + def test_OffCommand_after_FAULT(self): + """ + Test that the Off command send the device in OFF-EMPTY + if it is ON-FAULT + """ + self._setup_subarray() + self._assign_receptors() + self.midcsp_subarray01.Configure('{"input":"failed"}') + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.FAULT, f'CSP Subarray not FAULT') + Poller(10, 0.2).check(prober_subarray_obsstate) + self.midcsp_subarray01.Off() + prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF") + Poller(4, 0.2).check(prober_subarray_state) + prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY") + Poller(4, 0.2).check(prober_subarray_obsstate) + receptors = self.midcsp_subarray01.assignedReceptors + assert not receptors.any(), f"CSP Subarray is not empty" + def test_add_receptors_WITH_invalid_id(self): """ Test the assignment of a number of invalid receptor IDs to @@ -219,7 +341,6 @@ class TestCspSubarray(TestBase): invalid_receptor_to_assign.append(id_num) if len(invalid_receptor_to_assign) > 3: break - param = { 'subarrayID': 1, 'dish': { 'receptorIDList': list(map(str, invalid_receptor_to_assign))}}