diff --git a/pogo/CspSubElementSubarray.xmi b/pogo/CspSubElementSubarray.xmi index c6439d1827ddc7f50f5844501052da5686246514..f12f30e02e72eeea08bea282b713d566e52f83b8 100644 --- a/pogo/CspSubElementSubarray.xmi +++ b/pogo/CspSubElementSubarray.xmi @@ -282,7 +282,7 @@ <archiveEvent fire="false" libCheckCriteria="false"/> <dataReadyEvent fire="false" libCheckCriteria="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> - <properties description="The output data rate (GB/s) on the link for each scan." label="outputDataRateToSdp" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + <properties description="The output data rate (GB/s) on the link for each scan." label="outputDataRateToSdp" unit="GB/s" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> <attributes name="lastScanConfiguration" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> <dataType xsi:type="pogoDsl:StringType"/> @@ -298,7 +298,7 @@ <archiveEvent fire="false" libCheckCriteria="false"/> <dataReadyEvent fire="false" libCheckCriteria="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> - <properties description="The measured time (sec) taken to execute the command" label="configureScanMeasuredDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + <properties description="The measured time (sec) taken to execute the ConfigureScan command." label="configureScanMeasuredDuration" unit="sec" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> <attributes name="listOfDevicesCompletedTasks" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> <dataType xsi:type="pogoDsl:StringType"/> @@ -356,13 +356,29 @@ <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <properties description="The percentage progress of the command in the [0,100]." label="releaseResourcesProgress" unit="" standardUnit="" displayUnit="" format="" maxValue="100" minValue="0" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> - <attributes name="timeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <attributes name="configureScanTimeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> <dataType xsi:type="pogoDsl:BooleanType"/> <changeEvent fire="false" libCheckCriteria="false"/> <archiveEvent fire="false" libCheckCriteria="false"/> <dataReadyEvent fire="false" libCheckCriteria="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> - <properties description="Flag reporting command timeout expiration." label="timeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + <properties description="Flag reporting ConfigureScan command timeout expiration." label="configureScanTimeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="assignResourcesTimeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="Flag reporting AssignResources command timeout expiration." label="assignResourcesTimeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="releaseResourcesTimeoutExpiredFlag" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="Flag reporting ReleaseResources command timeout expiration." label="ReleaseResourcesTimeoutExpiredFlag" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> <attributes name="assignedResources" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="100" maxY="" allocReadMember="true"> <dataType xsi:type="pogoDsl:StringType"/> diff --git a/src/ska/base/csp_subelement_subarray.py b/src/ska/base/csp_subelement_subarray.py index 4cd81217ee15274e8339ef7b92085383dcd548ca..e34dc1e9099be1c90c4f49607226e8ab0cadaf18 100644 --- a/src/ska/base/csp_subelement_subarray.py +++ b/src/ska/base/csp_subelement_subarray.py @@ -72,6 +72,7 @@ class CspSubElementSubarray(SKASubarray): outputDataRateToSdp = attribute( dtype='DevFloat', label="outputDataRateToSdp", + unit="GB/s", doc="The output data rate (GB/s) on the link for each scan.", ) @@ -101,6 +102,12 @@ class CspSubElementSubarray(SKASubarray): doc="The measured time (sec) taken to execute the command", ) + configureScanTimeoutExpiredFlag = attribute( + dtype='DevBoolean', + label="configureScanTimeoutExpiredFlag", + doc="Flag reporting ConfigureScan command timeout expiration.", + ) + assignResourcesMaximumDuration = attribute( dtype='DevFloat', access=AttrWriteType.READ_WRITE, @@ -124,6 +131,13 @@ class CspSubElementSubarray(SKASubarray): doc="The percentage progress of the command in the [0,100].", ) + assignResourcesTimeoutExpiredFlag = attribute( + dtype='DevBoolean', + label="assignResourcesTimeoutExpiredFlag", + doc="Flag reporting AssignResources command timeout expiration.", + ) + + releaseResourcesMaximumDuration = attribute( dtype='DevFloat', access=AttrWriteType.READ_WRITE, @@ -147,7 +161,7 @@ class CspSubElementSubarray(SKASubarray): doc="The percentage progress of the command in the [0,100].", ) - timeoutExpiredFlag = attribute( + releaseResourcesTimeoutExpiredFlag = attribute( dtype='DevBoolean', label="timeoutExpiredFlag", doc="Flag reporting command timeout expiration.", @@ -190,7 +204,7 @@ class CspSubElementSubarray(SKASubarray): device._scan_id = 0 device._sdp_addresses = {"outputHost":[], "outputMac": [], "outputPort":[]} - device._sdp_links_active = [] + device._sdp_links_active = [False,] device._sdp_output_data_rate = 0. device._config_id = '' @@ -223,11 +237,18 @@ class CspSubElementSubarray(SKASubarray): # _timeout_expired: boolean flag to signal timeout during command execution. # To check and reset before a command execution. - # Need to implement one for each command? - device._timeout_expired = False - # configure the flag to push event from the device server - device.set_change_event('timeoutExpiredFlag', True, True) + # keys: the command name in lower case(configurescan, assignresources,..) + # values: True/False + device._timeout_expired = defaultdict(bool) + # configure the flags to push event from the device server + device.set_change_event('configureScanTimeoutExpiredFlag', True, True) + device.set_archive_event('configureScanTimeoutExpiredFlag', True, True) + device.set_change_event('assignResourcesTimeoutExpiredFlag', True, True) + device.set_archive_event('assignResourcesTimeoutExpiredFlag', True, True) + device.set_change_event('releaseResourcesTimeoutExpiredFlag', True, True) + device.set_archive_event('releaseResourcesTimeoutExpiredFlag', True, True) + message = "CspSubElementSubarray Init command completed OK" device.logger.info(message) return (ResultCode.OK, message) @@ -247,17 +268,6 @@ class CspSubElementSubarray(SKASubarray): # PROTECTED REGION ID(CspSubElementSubarray.delete_device) ENABLED START # # PROTECTED REGION END # // CspSubElementSubarray.delete_device - def _fire_timeout_expired_event(self, value): - """ - Helper method that updates the timeout_expired internal variable and push the event on the - timeoutExpiredFlag TANGO attribute. - - :param value: the flag value - :type value: boolean - """ - self._timeout_expired = value - self.push_change_event('timeoutExpiredFlag', self._timeout_expired) - # ------------------ # Attributes methods # ------------------ @@ -304,6 +314,12 @@ class CspSubElementSubarray(SKASubarray): return self._cmd_measured_duration['configurescan'] # PROTECTED REGION END # // CspSubElementSubarray.configureScanMeasuredDuration_read + def read_configureScanTimeoutExpiredFlag(self): + # PROTECTED REGION ID(CspSubElementSubarray.configureScanTimeoutExpiredFlag_read) ENABLED START # + """Return the configureScanTimeoutExpiredFlag attribute.""" + return self._timeout_expired['configurescan'] + # PROTECTED REGION END # // CspSubElementSubarray.configureScanTimeoutExpiredFlag_read + def read_listOfDevicesCompletedTasks(self): # PROTECTED REGION ID(CspSubElementSubarray.listOfDevicesCompletedTasks_read) ENABLED START # """Return the listOfDevicesCompletedTasks attribute.""" @@ -335,6 +351,12 @@ class CspSubElementSubarray(SKASubarray): return self._cmd_progress['assignresources'] # PROTECTED REGION END # // CspSubElementSubarray.assignResourcesProgress_read + def read_assignResourcesTimeoutExpiredFlag(self): + # PROTECTED REGION ID(CspSubElementSubarray.assignResourcesTimeoutExpiredFlag_read) ENABLED START # + """Return the assignResourcesTimeoutExpiredFlag attribute.""" + return self._timeout_expired['assignresources'] + # PROTECTED REGION END # // CspSubElementSubarray.assignResourcesTimeoutExpiredFlag_read + def read_releaseResourcesMaximumDuration(self): # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesMaximumDuration_read) ENABLED START # """Return the releaseResourcesMaximumDuration attribute.""" @@ -358,12 +380,12 @@ class CspSubElementSubarray(SKASubarray): """Return the releaseResourcesProgress attribute.""" return self._cmd_progress['releaseresources'] # PROTECTED REGION END # // CspSubElementSubarray.releaseResourcesProgress_read - - def read_timeoutExpiredFlag(self): - # PROTECTED REGION ID(CspSubElementSubarray.timeoutExpiredFlag_read) ENABLED START # - """Return the timeoutExpiredFlag attribute.""" - return self._timeout_expired - # PROTECTED REGION END # // CspSubElementSubarray.timeoutExpiredFlag_read + + def read_releaseResourcesTimeoutExpiredFlag(self): + # PROTECTED REGION ID(CspSubElementSubarray.releaseResourcesTimeoutExpiredFlag_read) ENABLED START # + """Return the releaseResourcesTimeoutExpiredFlag attribute.""" + return self._timeout_expired['releaseresources'] + # PROTECTED REGION END # // CspSubElementSubarray.releaseResourcesTimeoutExpiredFlag_read def read_sdpLinkActive(self): # PROTECTED REGION ID(CspSubElementSubarray.sdpLinkActive_read) ENABLED START # @@ -413,14 +435,14 @@ class CspSubElementSubarray(SKASubarray): :rtype: (ResultCode, str) """ device = self.target - result_code, msg = self.validate_configuration_data(argin) + result_code, msg = self.validate_input(argin) if result_code == ResultCode.FAILED: return (result_code, msg) # store the configuration on command success device._last_scan_configuration = argin return (ResultCode.OK, "Configure command completed OK") - def validate_configuration_data(self, argin): + def validate_input(self, argin): """ Validate the configuration parameters against allowed values, as needed. :param argin: The JSON formatted string with configuration for the device. diff --git a/tests/test_csp_subelement_subarray.py b/tests/test_csp_subelement_subarray.py index 6ef93c715897380d242c67f9282456f402cbe876..6ee89588774806c028782dfb3dbacd18d5b92af1 100644 --- a/tests/test_csp_subelement_subarray.py +++ b/tests/test_csp_subelement_subarray.py @@ -16,7 +16,6 @@ import pytest import json from tango import DevState, DevFailed -from tango.test_context import MultiDeviceTestContext # PROTECTED REGION ID(CspSubelementSubarray.test_additional_imports) ENABLED START # from ska.base import SKASubarray, CspSubElementSubarray @@ -50,6 +49,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_mocking) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_mocking + @pytest.mark.skip(reason="Not implemented") def test_properties(self, tango_context): # Test the properties # PROTECTED REGION ID(CspSubelementSubarray.test_properties) ENABLED START # @@ -166,13 +166,10 @@ class TestCspSubElementSubarray(object): def test_sdpLinkActivity(self, tango_context): """Test for sdpLinkActive """ # PROTECTED REGION ID(CspSubelementSubarray.test_sdpLinkActive) ENABLED START # - expected = tango_context.device.sdpLinkActive - if expected is not None: - n_links = len(expected) - actual = [ False for i in range(0, n_links)] - assert all([a == b for a, b in zip(actual, expected)]) - else: - assert expected is None + actual = tango_context.device.sdpLinkActive + n_links = len(actual) + expected = [ False for i in range(0, n_links)] + assert all([a == b for a, b in zip(actual, expected)]) # PROTECTED REGION END # // CspSubelementSubarray.test_sdpLinkActive # PROTECTED REGION ID(CspSubelementSubarray.test_outputDataRateToSdp_decorators) ENABLED START # @@ -263,51 +260,52 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag_decorators - def test_timeoutExpiredFlag(self, tango_context): + def test_configureScanTimeoutExpiredFlag(self, tango_context): """Test for timeoutExpiredFlag """ # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START # - assert tango_context.device.timeoutExpiredFlag == False + assert tango_context.device.configureScanTimeoutExpiredFlag == False + # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag + + # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START # + # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag_decorators + def test_assignResourcesTimeoutExpiredFlag(self, tango_context): + """Test for timeoutExpiredFlag """ + # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START # + assert tango_context.device.assignResourcesTimeoutExpiredFlag == False + # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag + + # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START # + # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag_decorators + def test_releaseResourcesTimeoutExpiredFlag(self, tango_context): + """Test for timeoutExpiredFlag """ + # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START # + assert tango_context.device.releaseResourcesTimeoutExpiredFlag == False # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan_decorators - def test_ConfigureScan(self, tango_context, tango_change_event_helper): + @pytest.mark.parametrize("command_alias", ["Configure", "ConfigureScan"]) + def test_ConfigureScan(self, tango_context, tango_change_event_helper, command_alias): """Test for ConfigureScan""" # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan) ENABLED START # tango_context.device.On() tango_context.device.AssignResources('{"example": [1,2,3]}') obs_state_callback = tango_change_event_helper.subscribe("obsState") scan_configuration = '{"id":"sbi-mvp01-20200325-00002"}' - tango_context.device.ConfigureScan(scan_configuration) + tango_context.device.command_inout(command_alias, (scan_configuration)) obs_state_callback.assert_calls([ObsState.IDLE,ObsState.CONFIGURING]) assert tango_context.device.configurationID == "sbi-mvp01-20200325-00002" assert tango_context.device.lastScanConfiguration == scan_configuration # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan - # PROTECTED REGION ID(CspSubelementSubarray.test_Configure_decorators) ENABLED START # - # PROTECTED REGION END # // CspSubelementSubarray.test_Configure_decorators - def test_Configure(self, tango_context, tango_change_event_helper): - """Test for ConfigureScan""" - # PROTECTED REGION ID(CspSubelementSubarray.test_Configure) ENABLED START # - tango_context.device.On() - tango_context.device.AssignResources('{"example": [1,2,3]}') - obs_state_callback = tango_change_event_helper.subscribe("obsState") - scan_configuration = '{"id":"sbi-mvp01-20200325-00002"}' - tango_context.device.Configure(scan_configuration) - obs_state_callback.assert_calls([ObsState.IDLE,ObsState.CONFIGURING]) - assert tango_context.device.configurationID == "sbi-mvp01-20200325-00002" - assert tango_context.device.lastScanConfiguration == scan_configuration - # PROTECTED REGION END # // CspSubelementSubarray.test_Configure - # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state_decorators def test_ConfigureScan_when_in_wrong_state(self, tango_context): """Test for ConfigureScan when the device is in wrong state""" # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state) ENABLED START # # The device in in OFF/EMPTY state, not valid to invoke ConfigureScan. - with pytest.raises(DevFailed) as df: + with pytest.raises(DevFailed, match="Error executing command ConfigureScanCommand"): tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') - assert "Error executing command ConfigureScanCommand" in str(df.value.args[0].desc) # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key_decorators) ENABLED START # @@ -338,7 +336,8 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_GoToIdle_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_GoToIdle_decorators - def test_GoToIdle(self, tango_context, tango_change_event_helper): + @pytest.mark.parametrize("command_alias", ["GoToIdle", "End"]) + def test_GoToIdle(self, tango_context, tango_change_event_helper, command_alias): """Test for GoToIdle""" # PROTECTED REGION ID(CspSubelementSubarray.test_GoToIdle) ENABLED START # tango_context.device.On() @@ -346,36 +345,8 @@ class TestCspSubElementSubarray(object): obs_state_callback = tango_change_event_helper.subscribe("obsState") tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') obs_state_callback.assert_calls([ObsState.IDLE,ObsState.CONFIGURING, ObsState.READY]) - tango_context.device.GoToIdle() - obs_state_callback.assert_call(ObsState.IDLE) - assert tango_context.device.scanID == 0 - assert tango_context.device.configurationID == '' - # PROTECTED REGION END # // CspSubelementSubarray.test_GoToIdle - - # PROTECTED REGION ID(CspSubelementSubarray.test_End_decorators) ENABLED START # - # PROTECTED REGION END # // CspSubelementSubarray.test_End_decorators - def test_End(self, tango_context, tango_change_event_helper): - """Test for End""" - # PROTECTED REGION ID(CspSubelementSubarray.test_End) ENABLED START # - tango_context.device.On() - tango_context.device.AssignResources('{"example": [1,2,3]}') - obs_state_callback = tango_change_event_helper.subscribe("obsState") - tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') - obs_state_callback.assert_calls([ObsState.IDLE,ObsState.CONFIGURING, ObsState.READY]) - tango_context.device.End() + tango_context.device.command_inout(command_alias) obs_state_callback.assert_call(ObsState.IDLE) assert tango_context.device.scanID == 0 assert tango_context.device.configurationID == '' # PROTECTED REGION END # // CspSubelementSubarray.test_GoToIdle - -def test_multiple_devices_in_same_process(): - devices_info = ( - {"class": CspSubElementSubarray, "devices": [{"name": "test/se/1"}]}, - {"class": SKASubarray, "devices": [{"name": "test/obsdevice/1"}]}, - ) - - with MultiDeviceTestContext(devices_info, process=False) as context: - proxy1 = context.get_device("test/se/1") - proxy2 = context.get_device("test/obsdevice/1") - assert proxy1.State() == DevState.OFF - assert proxy2.State() == DevState.OFF