diff --git a/CDB/stations/testenv_cs001.json b/CDB/stations/testenv_cs001.json index 0cfb260ea9a5df7aecf8f7bf9611556586e19f46..6bf8d12a9634b50792f34d68180fe7bd6e038647 100644 --- a/CDB/stations/testenv_cs001.json +++ b/CDB/stations/testenv_cs001.json @@ -436,7 +436,7 @@ "RCU_On_Off_timeout": [ "1" ], - "RCU_DTH_On_Off_timeout": [ + "RCU_DTH_On_Off_timeout": [ "1" ] } @@ -461,7 +461,7 @@ "RCU_On_Off_timeout": [ "1" ], - "RCU_DTH_On_Off_timeout": [ + "RCU_DTH_On_Off_timeout": [ "1" ] } @@ -480,7 +480,7 @@ "RCU_On_Off_timeout": [ "1" ], - "RCU_DTH_On_Off_timeout": [ + "RCU_DTH_On_Off_timeout": [ "1" ] } @@ -501,6 +501,9 @@ ], "OPC_Time_Out": [ "5.0" + ], + "Firmware_Boot_timeout": [ + "1.0" ] } }, @@ -514,6 +517,9 @@ ], "OPC_Time_Out": [ "5.0" + ], + "Firmware_Boot_timeout": [ + "1.0" ] } }, @@ -527,6 +533,9 @@ ], "OPC_Time_Out": [ "5.0" + ], + "Firmware_Boot_timeout": [ + "1.0" ] } } diff --git a/tangostationcontrol/tangostationcontrol/common/constants.py b/tangostationcontrol/tangostationcontrol/common/constants.py index 3a0de82d0e4e3b9fc14bf0137280a85480952b1a..39fe479637af6c9ba69df7dec871abc52450f3d0 100644 --- a/tangostationcontrol/tangostationcontrol/common/constants.py +++ b/tangostationcontrol/tangostationcontrol/common/constants.py @@ -84,7 +84,7 @@ N_point_prop = 3 N_latlong = 2 # default subband we use because of its low RFI -DEFAULT_SUBBAND = 102 +DEFAULT_SUBBAND = 300 # Maximum array size to allocate for beam_device pointings, MAX_POINTINGS = N_beamlets_max diff --git a/tangostationcontrol/tangostationcontrol/devices/antennafield.py b/tangostationcontrol/tangostationcontrol/devices/antennafield.py index 6b4d732c6b22954988d3271db3ddf875dd2ee73d..4c1cb078051576c7de02b1ea0b8e32e37ae17d51 100644 --- a/tangostationcontrol/tangostationcontrol/devices/antennafield.py +++ b/tangostationcontrol/tangostationcontrol/devices/antennafield.py @@ -1083,8 +1083,12 @@ class AntennaField(LOFARDevice): # Enable controlling all antennas self.proxy.write_attribute("ANT_mask_RW", [True] * len(ANT_mask_RW)) - # Turn off power to all antennas - self.proxy.write_attribute("RCU_PWR_ANT_on_RW", [True] * len(ANT_mask_RW)) + try: + # Turn off power to all antennas + self.proxy.write_attribute("RCU_PWR_ANT_on_RW", [False] * len(ANT_mask_RW)) + finally: + # Restore original mask + self.proxy.write_attribute("ANT_mask_RW", ANT_mask_RW) # -------- # Commands diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py index 37747940d92f60700e140afcfa923861d8b4abd2..9b7023b1cb12830a5afcc3e437958f6b304d2cd2 100644 --- a/tangostationcontrol/tangostationcontrol/devices/apsct.py +++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py @@ -198,11 +198,7 @@ class APSCT(OPCUADevice): def _power_hardware_on(self): """Turns on the 200MHz clock.""" - # Cycle clock - self.APSCT_off() - self.wait_attribute( - "APSCTTR_translator_busy_R", False, self.APSCT_On_Off_timeout - ) + # Turn on 200 MHz clock self.APSCT_200MHz_on() self.wait_attribute( "APSCTTR_translator_busy_R", False, self.APSCT_On_Off_timeout @@ -242,6 +238,11 @@ class APSCT(OPCUADevice): @only_in_states(DEFAULT_COMMAND_STATES) def APSCT_off(self): """ + Turn off the clock. + + Warning: This stops the user image in SDP, making + it unresponsive. The factory image is + not affected. :return:None """ @@ -252,6 +253,7 @@ class APSCT(OPCUADevice): @only_in_states(DEFAULT_COMMAND_STATES) def APSCT_200MHz_on(self): """ + Set the clock to 200 MHz. :return:None """ diff --git a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/hierarchy_device.py b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/hierarchy_device.py index ece897ae66d229abd47be6a4ea962ff492496361..364ee39f0bc5430e181492ae00bb4e584a9a5aaa 100644 --- a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/hierarchy_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/hierarchy_device.py @@ -163,7 +163,7 @@ class AbstractHierarchyDevice: """ if not self._proxies.get(device): - self._proxies[device] = create_device_proxy(device, 30000) + self._proxies[device] = create_device_proxy(device, 60_000) return self._proxies[device] diff --git a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py index 9cff03eaf2c15883298c70f5e802b710e1d1184b..116cd4299e287d4122999282f8f2977fe85a732a 100644 --- a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py @@ -17,7 +17,6 @@ from attribute_wrapper.attribute_wrapper import AttributeWrapper from tango import ( AttrDataFormat, Attribute, - AttrWriteType, DebugIt, DeviceProxy, DevState, @@ -88,12 +87,24 @@ class LOFARDevice(Device): # ---------- version_R = attribute( - dtype=str, access=AttrWriteType.READ, fget=lambda self: version + doc="Version of this software device", dtype=str, fget=lambda self: version + ) + + uptime_R = attribute( + doc="How long this software device has been running (wall-clock time, in seconds)", + unit="s", + dtype=numpy.int64, + fget=lambda self: numpy.int64(time.time() - self._device_start_time), + ) + + access_count_R = attribute( + doc="How often this software device was accessed for commands or attributes", + dtype=numpy.int64, + fget=lambda self: numpy.int64(self._access_count), ) hardware_powered_R = attribute( dtype=bool, - access=AttrWriteType.READ, fget=lambda self: self._read_hardware_powered_R(), ) @@ -229,6 +240,15 @@ class LOFARDevice(Device): elif not mask[idx]: merge_values[idx] = current_values[idx] + def __init__(self, cl, name): + super().__init__(cl, name) + + # record how many time this device was accessed + self._access_count = 0 + + # record when this device was started + self._device_start_time = time.time() + def _init_device(self): logger.debug("[LOFARDevice] init_device") @@ -424,8 +444,10 @@ class LOFARDevice(Device): pass def always_executed_hook(self): - """Method always executed before any TANGO command is executed.""" - pass + """Method always executed before any TANGO command is executed or attribute is accessed.""" + + # increase the number of accesses + self._access_count += 1 def _read_hardware_powered_R(self): """Overloadable function called in read attribute hardware_powered_R""" @@ -519,6 +541,7 @@ class LOFARDevice(Device): self._set_defaults_for(self.TRANSLATOR_DEFAULT_SETTINGS) + @only_in_states(INITIALISED_STATES) @command() @DebugIt() @log_exceptions() @@ -529,7 +552,6 @@ class LOFARDevice(Device): self._power_hardware_on() @only_in_states(INITIALISED_STATES) - @fault_on_error() @command() @DebugIt() @log_exceptions() diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py b/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py index 85874d37d663aca9fe664d4461199ed61c909fee..866529f4851d940ef1578d60d5eaceede4015ecd 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py @@ -49,6 +49,15 @@ class SDPFirmware(OPCUADevice): dtype="DevULong", mandatory=False, default_value=CLK_200_MHZ ) + # ----- Timing values + + Firmware_Boot_timeout = device_property( + doc="Maximum amount of time to wait for FPGAs to boot.", + dtype="DevFloat", + mandatory=False, + default_value=60.0, + ) + TRANSLATOR_DEFAULT_SETTINGS = ["TR_fpga_mask_RW"] # ---------- @@ -264,16 +273,24 @@ class SDPFirmware(OPCUADevice): def _boot_to_image(self, image_nr): # FPGAs that are actually reachable and we care about - wait_for = ~( - self.read_attribute("TR_fpga_communication_error_R") - ) & self.read_attribute("TR_fpga_mask_R") + wait_for = self.read_attribute("TR_fpga_mask_R") + + # Wait for the current image to be booted (in case we connected to SDPTR before even the current + # image finished booting). + self.wait_attribute( + "TR_fpga_communication_error_R", + lambda attr: (~attr | ~wait_for).all(), + self.Firmware_Boot_timeout, + ) # Order the correct firmare to be loaded self.proxy.FPGA_boot_image_RW = [image_nr] * N_pn # Wait for the firmware to be loaded (ignoring masked out elements) self.wait_attribute( - "FPGA_boot_image_R", lambda attr: ((attr == 1) | ~wait_for).all(), 60 + "FPGA_boot_image_R", + lambda attr: ((attr == image_nr) | ~wait_for).all(), + self.Firmware_Boot_timeout, ) def _power_hardware_on(self):