diff --git a/deprecated/PCC/LICENSE.txt b/deprecated/PCC/LICENSE.txt deleted file mode 100644 index ae533fce6dc75595f91290511273c7ff62312f76..0000000000000000000000000000000000000000 --- a/deprecated/PCC/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2020 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, -ASTRON Netherlands Institute for Radio Astronomy - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/deprecated/PCC/MANIFEST.in b/deprecated/PCC/MANIFEST.in deleted file mode 100644 index 251eebae288846436b6dc7b6022214cda5af98af..0000000000000000000000000000000000000000 --- a/deprecated/PCC/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -recursive-include PCC *.py -recursive-include test *.py -include *.rst -include PCC.xmi -include *.txt -graft docs - -global-exclude *.pyc -global-exclude *.pyo diff --git a/deprecated/PCC/NOTICE b/deprecated/PCC/NOTICE deleted file mode 100644 index 9c7867598e17de5d69b8c26656caa8316cd0a30f..0000000000000000000000000000000000000000 --- a/deprecated/PCC/NOTICE +++ /dev/null @@ -1,8 +0,0 @@ -Citation Notice version 1.0 -This Citation Notice is part of the LOFAR software suite. -Parties that use ASTRON Software resulting in papers and/or publications are requested to -refer to the DOI(s) that correspond(s) to the version(s) of the ASTRON Software used: -<List of DOIs> -Parties that use ASTRON Software for purposes that do not result in publications (e.g. -commercial parties) are asked to inform ASTRON about their use of ASTRON Software, by -sending an email to including the DOIs mentioned above in the message. \ No newline at end of file diff --git a/deprecated/PCC/PCC/PCC.py b/deprecated/PCC/PCC/PCC.py deleted file mode 100644 index 3d4a1585c25922c5cdf86e9f416b94e470d81e8a..0000000000000000000000000000000000000000 --- a/deprecated/PCC/PCC/PCC.py +++ /dev/null @@ -1,886 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the PCC project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -""" PCC Device Server for LOFAR2.0 - -""" - -# PyTango imports -from tango import DebugIt -from tango.server import run -from tango.server import Device -from tango.server import attribute, command -from tango.server import device_property -from tango import AttrQuality, DispLevel, DevState -from tango import AttrWriteType, PipeWriteType -# Additional import -import sys -import opcua -import numpy - -from wrappers import only_in_states, only_when_on, fault_on_error -from opcua_connection import OPCUAConnection - -__all__ = ["PCC", "main"] - -class PCC(Device): - """ - - **Properties:** - - - Device Property - OPC_Server_Name - - Type:'DevString' - OPC_Server_Port - - Type:'DevULong' - OPC_Time_Out - - Type:'DevDouble' - - States are as follows: - INIT = Device is initialising. - STANDBY = Device is initialised, but pends external configuration and an explicit turning on, - ON = Device is fully configured, functional, controls the hardware, and is possibly actively running, - FAULT = Device detected an unrecoverable error, and is thus malfunctional, - OFF = Device is turned off, drops connection to the hardware, - - The following state transitions are implemented: - boot -> OFF: Triggered by tango. Device will be instantiated, - OFF -> INIT: Triggered by device. Device will initialise (connect to hardware, other devices), - INIT -> STANDBY: Triggered by device. Device is initialised, and is ready for additional configuration by the user, - STANDBY -> ON: Triggered by user. Device reports to be functional, - * -> FAULT: Triggered by device. Device has degraded to malfunctional, for example because the connection to the hardware is lost, - * -> FAULT: Triggered by user. Emulate a forced malfunction for integration testing purposes, - * -> OFF: Triggered by user. Device is turned off. Triggered by the Off() command, - FAULT -> INIT: Triggered by user. Device is reinitialised to recover from an error, - - The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()). - """ - client = 0 - name_space_index = 0 - obj = 0 - - # ----------------- - # Device Properties - # ----------------- - OPC_Server_Name = device_property( - dtype=numpy.str, - mandatory=True - ) - - OPC_Server_Port = device_property( - dtype=numpy.uint64, - mandatory=True - ) - - OPC_Time_Out = device_property( - dtype=numpy.float_, - mandatory=True - ) - - # ---------- - # Attributes - # ---------- - - RCU_state_R = attribute( - dtype = (numpy.str), - ) - - RCU_mask_RW = attribute( - dtype=(numpy.bool_,), - max_dim_x=32, - access=AttrWriteType.READ_WRITE, - ) - - Ant_mask_RW = attribute( - dtype=((numpy.bool_,),), - max_dim_x=32, max_dim_y=3, - access=AttrWriteType.READ_WRITE, - ) - - RCU_attenuator_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_attenuator_RW = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - access=AttrWriteType.READ_WRITE, - ) - - RCU_band_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_band_RW = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - access=AttrWriteType.READ_WRITE, - ) - - RCU_temperature_R = attribute( - dtype=(numpy.float_,), - max_dim_x=32, - ) - - RCU_Pwr_dig_R = attribute( - dtype=(numpy.int64,), - max_dim_x=32, - ) - - RCU_LED0_R = attribute( - dtype=(numpy.int64,), - max_dim_x=32, - ) - - RCU_LED0_RW = attribute( - dtype=(numpy.int64,), - max_dim_x=32, - access=AttrWriteType.READ_WRITE, - ) - - RCU_ADC_lock_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_ADC_SYNC_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_ADC_JESD_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_ADC_CML_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_OUT1_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_OUT2_R = attribute( - dtype=((numpy.int64,),), - max_dim_x=32, max_dim_y=3, - ) - - RCU_ID_R = attribute( - dtype=(numpy.int64,), - max_dim_x=32, - ) - - RCU_version_R = attribute( - dtype=(numpy.str,), - max_dim_x=32, - ) - - HBA_element_beamformer_delays_R = attribute( - dtype=((numpy.int64,),), - max_dim_x = 96, max_dim_y = 32, - ) - - HBA_element_beamformer_delays_RW = attribute( - dtype=((numpy.int64,),), - max_dim_x = 96, max_dim_y = 32, - access=AttrWriteType.READ_WRITE, - ) - - HBA_element_pwr_R = attribute( - dtype=((numpy.int64,),), - max_dim_x = 96, max_dim_y = 32, - ) - - HBA_element_pwr_RW = attribute( - dtype=((numpy.int64,),), - max_dim_x = 96, max_dim_y = 32, - access=AttrWriteType.READ_WRITE, - ) - - uC_ID_R = attribute( - dtype=(numpy.int64,), - max_dim_x=32, - ) - - RCU_monitor_rate_RW = attribute( - dtype=numpy.float_, - access=AttrWriteType.READ_WRITE, - ) - - # --------------- - # General methods - # --------------- - def get_pcc_node(self, node): - try: - return self.pcc_node.get_child(["{}:{}".format(self.name_space_index, node)]) - except opcua.ua.uaerrors._auto.BadNoMatch: - self.error_stream("Could not find PCC node %s", node) - - # Contract with hardware is broken --- cannot recover - raise - - def _map_attributes(self): - try: - self.name_space_index = self.client.get_namespace_index("http://lofar.eu") - except Exception as e: - self.warn_stream("Cannot determine the OPC-UA name space index. Will try and use the default = 2.") - self.name_space_index = 2 - - self.obj_node = self.client.get_objects_node() - self.pcc_node = self.obj_node.get_child(["{}:PCC".format(self.name_space_index)]) - - self.debug_stream("Mapping OPC-UA MP/CP to attributes...") - - self.attribute_mapping["RCU_state_R"] = self.get_pcc_node("RCU_state_R") - - self.attribute_mapping["RCU_mask_RW"] = self.get_pcc_node("RCU_mask_RW") - - self.attribute_mapping["Ant_mask_RW"] = self.get_pcc_node("Ant_mask_RW") - - self.attribute_mapping["RCU_attenuator_R"] = self.get_pcc_node("RCU_attenuator_R") - - self.attribute_mapping["RCU_attenuator_RW"] = self.get_pcc_node("RCU_attenuator_RW") - - self.attribute_mapping["RCU_band_R"] = self.get_pcc_node("RCU_band_R") - - self.attribute_mapping["RCU_band_RW"] = self.get_pcc_node("RCU_band_RW") - - self.attribute_mapping["RCU_temperature_R"] = self.get_pcc_node("RCU_temperature_R") - - self.attribute_mapping["RCU_Pwr_dig_R"] = self.get_pcc_node("RCU_Pwr_dig_R") - - self.attribute_mapping["RCU_LED0_R"] = self.get_pcc_node("RCU_LED0_R") - - self.attribute_mapping["RCU_LED0_RW"] = self.get_pcc_node("RCU_LED0_RW") - - self.attribute_mapping["RCU_ADC_lock_R"] = self.get_pcc_node("RCU_ADC_lock_R") - - self.attribute_mapping["RCU_ADC_SYNC_R"] = self.get_pcc_node("RCU_ADC_SYNC_R") - - self.attribute_mapping["RCU_ADC_CML_R"] = self.get_pcc_node("RCU_ADC_CML_R") - - self.attribute_mapping["RCU_ADC_JESD_R"] = self.get_pcc_node("RCU_ADC_JESD_R") - - self.attribute_mapping["RCU_OUT1_R"] = self.get_pcc_node("RCU_OUT1_R") - - self.attribute_mapping["RCU_OUT2_R"] = self.get_pcc_node("RCU_OUT2_R") - - self.attribute_mapping["RCU_ID_R"] = self.get_pcc_node("RCU_ID_R") - - self.attribute_mapping["RCU_version_R"] = self.get_pcc_node("RCU_version_R") - - self.attribute_mapping["HBA_element_beamformer_delays_R"] = self.get_pcc_node("HBA_element_beamformer_delays_R") - - self.attribute_mapping["HBA_element_beamformer_delays_RW"] = self.get_pcc_node("HBA_element_beamformer_delays_RW") - - self.attribute_mapping["HBA_element_pwr_R"] = self.get_pcc_node("HBA_element_pwr_R") - - self.attribute_mapping["HBA_element_pwr_RW"] = self.get_pcc_node("HBA_element_pwr_RW") - - self.attribute_mapping["uC_ID_R"] = self.get_pcc_node("uC_ID_R") - - self.attribute_mapping["RCU_monitor_rate_RW"] = self.get_pcc_node("RCU_monitor_rate_RW") - - self.function_mapping["RCU_off"] = self.get_pcc_node("RCU_off") - - self.function_mapping["RCU_on"] = self.get_pcc_node("RCU_on") - - self.function_mapping["ADC_on"] = self.get_pcc_node("ADC_on") - - self.function_mapping["RCU_update"] = self.get_pcc_node("RCU_update") - - self.function_mapping["CLK_off"] = self.get_pcc_node("CLK_off") - - self.function_mapping["CLK_on"] = self.get_pcc_node("CLK_on") - - self.function_mapping["CLK_PLL_setup"] = self.get_pcc_node("CLK_PLL_setup") - - - self.debug_stream("Mapping OPC-UA MP/CP to attributes done.") - - def init_device(self): - """ Instantiates the device in the OFF state. """ - - # NOTE: Will delete_device first, if necessary - Device.init_device(self) - - self.set_state(DevState.OFF) - - def initialise(self): - """Initialises the attributes and properties of the PCC.""" - - self.set_state(DevState.INIT) - - # Init the dict that contains attribute to OPC-UA MP/CP mappings. - self.attribute_mapping = {} - - # Set default values in the RW/R attributes and add them to - # the mapping. - self._RCU_state_R = "" - self.attribute_mapping["RCU_state_R"] = {} - - self._RCU_mask_RW = numpy.full(32, False) - self.attribute_mapping["RCU_mask_RW"] = {} - - self._Ant_mask_RW = numpy.full((3, 32), False) - self.attribute_mapping["Ant_mask_RW"] = {} - - self._RCU_attenuator_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_attenuator_R"] = {} - - self._RCU_attenuator_RW = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_attenuator_RW"] = {} - - self._RCU_band_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_band_R"] = {} - - self._RCU_band_RW = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_band_RW"] = {} - - self._RCU_temperature_R = numpy.full((3, 32), 0.0) - self.attribute_mapping["RCU_temperature_R"] = {} - - self._RCU_Pwr_dig_R = numpy.full(32, 0) - self.attribute_mapping["RCU_Pwr_dig_R"] = {} - - self._RCU_LED0_R = numpy.full(32, 0) - self.attribute_mapping["RCU_LED0_R"] = {} - - self._RCU_LED0_RW = numpy.full(32, 0) - self.attribute_mapping["RCU_LED0_RW"] = {} - - self._RCU_ADC_lock_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_ADC_lock_R"] = {} - - self._RCU_ADC_SYNC_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_ADC_SYNC_R"] = {} - - self._RCU_ADC_JESD_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_ADC_JESD_R"] = {} - - self._RCU_ADC_CML_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_ADC_CML_R"] = {} - - self._RCU_OUT1_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_OUT1_R"] = {} - - self._RCU_OUT2_R = numpy.full((3, 32), 0) - self.attribute_mapping["RCU_OUT2_R"] = {} - - self._RCU_ID_R = numpy.full(32, 0) - self.attribute_mapping["RCU_ID_R"] = {} - - self._RCU_version_R = numpy.full(32, "1234567890") - self.attribute_mapping["RCU_version_R"] = {} - - self._HBA_element_beamformer_delays_R = numpy.full((96, 32), 0) - self.attribute_mapping["HBA_element_beamformer_delays_R"] = {} - - self._HBA_element_beamformer_delays_RW = numpy.full((96, 32), 0) - self.attribute_mapping["HBA_element_beamformer_delays_RW"] = {} - - self._HBA_element_pwr_R = numpy.full((96, 32), 0) - self.attribute_mapping["HBA_element_pwr_R"] = {} - - self._HBA_element_pwr_RW = numpy.full((96, 32), 0) - self.attribute_mapping["HBA_element_pwr_RW"] = {} - - self._uC_ID_R = numpy.full(32, 0) - self.attribute_mapping["uC_ID_R"] = {} - - self._RCU_monitor_rate_RW = 30.0 - self.attribute_mapping["RCU_monitor_rate_RW"] = {} - - # Init the dict that contains function to OPC-UA function mappings. - self.function_mapping = {} - self.function_mapping["RCU_on"] = {} - self.function_mapping["RCU_off"] = {} - self.function_mapping["ADC_on"] = {} - self.function_mapping["RCU_update"] = {} - self.function_mapping["CLK_on"] = {} - self.function_mapping["CLK_off"] = {} - self.function_mapping["CLK_PLL_setup"] = {} - - self.client = opcua.Client("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_Time_Out) # timeout in seconds - - # Connect to OPC-UA -- will set ON state on success in case of a reconnect - self.opcua_connection = OPCUAConnection(self.client, self.Standby, self.Fault, self) - - # Explicitly connect - if not self.opcua_connection.connect(): - # hardware or infra is down -- needs fixing first - self.Fault() - return - - # Retrieve and map server attributes - try: - self._map_attributes() - except Exception as e: - self.error_stream("Could not map server interface: %s", e) - self.Fault() - return - - # Start keep-alive - self.opcua_connection.start() - - # Set the masks. - # - # Attention! - # Set the masks only after the OPCUA connection has been - # established! The setting of the masks needs to go through - # to the server. - # - # TODO - # Read default masks from config DB - self.write_RCU_mask_RW(self._RCU_mask_RW) - self.write_Ant_mask_RW(self._Ant_mask_RW) - - # Everything went ok -- go standby. - self.set_state(DevState.STANDBY) - - - def always_executed_hook(self): - """Method always executed before any TANGO command is executed.""" - pass - - def delete_device(self): - """Hook to delete resources allocated in init_device. - - This method allows for any memory or other resources allocated in the - init_device method to be released. This method is called by the device - destructor and by the device Init command (a Tango built-in). - """ - self.debug_stream("Shutting down...") - - self.Off() - self.debug_stream("Shut down. Good bye.") - - # ------------------ - # Attributes methods - # ------------------ - @only_when_on - @fault_on_error - def read_RCU_state_R(self): - """Return the RCU_state_R attribute.""" - self._RCU_state_R = self.attribute_mapping["RCU_state_R"].get_value() - return self._RCU_state_R - - @only_when_on - @fault_on_error - def read_RCU_mask_R(self): - """Return the RCU_mask_R attribute.""" - self._RCU_mask_R = numpy.array(self.attribute_mapping["RCU_mask_R"].get_value()) - return self._RCU_mask_R - - @only_when_on - @fault_on_error - def read_RCU_mask_RW(self): - """Return the RCU_mask_RW attribute.""" - return self._RCU_mask_RW - - @only_when_on - @fault_on_error - def write_RCU_mask_RW(self, value): - """Set the RCU_mask_RW attribute.""" - self.attribute_mapping["RCU_mask_RW"].set_value(value.tolist()) - self._RCU_mask_RW = value - - @only_when_on - @fault_on_error - def read_Ant_mask_R(self): - """Return the Ant_mask_R attribute.""" - value = numpy.array(self.attribute_mapping["Ant_mask_R"].get_value()) - self._Ant_mask_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._Ant_mask_R - - @only_when_on - @fault_on_error - def read_Ant_mask_RW(self): - """Return the Ant_mask_RW attribute.""" - return self._Ant_mask_RW - - @only_when_on - @fault_on_error - def write_Ant_mask_RW(self, value): - """Set the Ant_mask_RW attribute.""" - v = numpy.concatenate(value) - self.attribute_mapping["Ant_mask_RW"].set_value(v.tolist()) - self._Ant_mask_RW = value - - @only_when_on - @fault_on_error - def read_RCU_attenuator_R(self): - """Return the RCU_attenuator_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_attenuator_R"].get_value()) - self._RCU_attenuator_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_attenuator_R - - @only_when_on - @fault_on_error - def read_RCU_attenuator_RW(self): - """Return the RCU_attenuator_RW attribute.""" - return self._RCU_attenuator_RW - - @only_when_on - @fault_on_error - def write_RCU_attenuator_RW(self, value): - """Set the RCU_attenuator_RW attribute.""" - v = numpy.concatenate(value) - self.attribute_mapping["RCU_attenuator_RW"].set_value(v.tolist()) - self._RCU_attenuator_RW = value - - @only_when_on - @fault_on_error - def read_RCU_band_R(self): - """Return the RCU_band_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_band_R"].get_value()) - self._RCU_band_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_band_R - - @only_when_on - @fault_on_error - def read_RCU_band_RW(self): - """Return the RCU_band_RW attribute.""" - return self._RCU_band_RW - - @only_when_on - @fault_on_error - def write_RCU_band_RW(self, value): - """Set the RCU_band_RW attribute.""" - v = numpy.concatenate(value) - self.attribute_mapping["RCU_band_RW"].set_value(v.tolist()) - self._RCU_band_RW = value - - @only_when_on - @fault_on_error - def read_RCU_temperature_R(self): - """Return the RCU_temperature_R attribute.""" - self._RCU_temperature_R = numpy.array(self.attribute_mapping["RCU_temperature_R"].get_value()) - return self._RCU_temperature_R - - @only_when_on - @fault_on_error - def read_RCU_Pwr_dig_R(self): - """Return the RCU_Pwr_dig_R attribute.""" - self._RCU_Pwr_dig_R = numpy.array(self.attribute_mapping["RCU_Pwr_dig_R"].get_value()) - return self._RCU_Pwr_dig_R - - @only_when_on - @fault_on_error - def read_RCU_LED0_R(self): - """Return the RCU_LED0_R attribute.""" - self._RCU_LED0_R = numpy.array(self.attribute_mapping["RCU_LED0_R"].get_value()) - return self._RCU_LED0_R - - @only_when_on - @fault_on_error - def read_RCU_LED0_RW(self): - """Return the RCU_LED0_RW attribute.""" - return self._RCU_LED0_RW - - @only_when_on - @fault_on_error - def write_RCU_LED0_RW(self, value): - """Set the RCU_LED0_RW attribute.""" - self.attribute_mapping["RCU_LED0_RW"].set_value(value.tolist()) - self._RCU_LED0_RW = value - - @only_when_on - @fault_on_error - def read_RCU_ADC_lock_R(self): - """Return the RCU_ADC_lock_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_ADC_lock_R"].get_value()) - self._RCU_ADC_lock_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_ADC_lock_R - - @only_when_on - @fault_on_error - def read_RCU_ADC_SYNC_R(self): - """Return the RCU_ADC_SYNC_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_ADC_SYNC_R"].get_value()) - self._RCU_ADC_SYNC_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_ADC_SYNC_R - - @only_when_on - @fault_on_error - def read_RCU_ADC_JESD_R(self): - """Return the RCU_ADC_JESD_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_ADC_JESD_R"].get_value()) - self._RCU_ADC_JESD_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_ADC_JESD_R - - @only_when_on - @fault_on_error - def read_RCU_ADC_CML_R(self): - """Return the RCU_ADC_CML_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_ADC_CML_R"].get_value()) - self._RCU_ADC_CML_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_ADC_CML_R - - @only_when_on - @fault_on_error - def read_RCU_OUT1_R(self): - """Return the RCU_OUT1_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_OUT1_R"].get_value()) - self._RCU_OUT1_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_OUT1_R - - @only_when_on - @fault_on_error - def read_RCU_OUT2_R(self): - """Return the RCU_OUT2_R attribute.""" - value = numpy.array(self.attribute_mapping["RCU_OUT2_R"].get_value()) - self._RCU_OUT2_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._RCU_OUT2_R - - @only_when_on - @fault_on_error - def read_RCU_ID_R(self): - """Return the RCU_ID_R attribute.""" - self._RCU_ID_R = numpy.array(self.attribute_mapping["RCU_ID_R"].get_value()) - return self._RCU_ID_R - - @only_when_on - @fault_on_error - def read_RCU_version_R(self): - """Return the RCU_version_R attribute.""" - value = self.attribute_mapping["RCU_version_R"].get_value() - self._RCU_version_R = numpy.array(value) - return self._RCU_version_R - - @only_when_on - @fault_on_error - def read_HBA_element_beamformer_delays_R(self): - """Return the HBA_element_beamformer_delays_R attribute.""" - value = numpy.array(self.attribute_mapping["HBA_element_beamformer_delays_R"].get_value()) - self._HBA_element_beamformer_delays_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._HBA_element_beamformer_delays_R - - @only_when_on - @fault_on_error - def read_HBA_element_beamformer_delays_RW(self): - """Return the HBA_element_beamformer_delays_RW attribute.""" - return self._HBA_element_beamformer_delays_RW - - @only_when_on - @fault_on_error - def write_HBA_element_beamformer_delays_RW(self, value): - """Set the HBA_element_beamformer_delays_RW attribute.""" - self.attribute_mapping["HBA_element_beamformer_delays_RW"].set_value(value.flatten().tolist()) - self._HBA_element_beamformer_delays_RW = value - - @only_when_on - @fault_on_error - def read_HBA_element_pwr_R(self): - """Return the HBA_element_pwr_R attribute.""" - value = numpy.array(self.attribute_mapping["HBA_element_pwr_R"].get_value()) - self._HBA_element_pwr_R = numpy.array(numpy.split(value, indices_or_sections = 32)) - return self._HBA_element_pwr_R - - @only_when_on - @fault_on_error - def read_HBA_element_pwr_RW(self): - """Return the HBA_element_pwr_RW attribute.""" - return self._HBA_element_pwr_RW - - @only_when_on - @fault_on_error - def write_HBA_element_pwr_RW(self, value): - """Set the HBA_element_pwr_RW attribute.""" - self.attribute_mapping["HBA_element_pwr_RW"].set_value(value.flatten().tolist()) - self._HBA_element_pwr_RW = value - - @only_when_on - @fault_on_error - def read_uC_ID_R(self): - """Return the uC_ID_R attribute.""" - self._uC_ID_R = numpy.array(self.attribute_mapping["uC_ID_R"].get_value()) - return self._uC_ID_R - - @only_when_on - @fault_on_error - def read_RCU_monitor_rate_RW(self): - """Return the RCU_monitor_rate_RW attribute.""" - return self._RCU_monitor_rate_RW - - @only_when_on - @fault_on_error - def write_RCU_monitor_rate_RW(self, value): - """Set the RCU_monitor_rate_RW attribute.""" - self.attribute_mapping["RCU_monitor_rate_RW"].set_value(value) - self._RCU_monitor_rate_RW = value - - - # -------- - # Commands - # -------- - - @command() - @only_in_states([DevState.FAULT, DevState.OFF]) - @DebugIt() - def Initialise(self): - """ - Command to ask for initialisation of this device. Can only be called in FAULT or OFF state. - - :return:None - """ - - self.initialise() - - @only_in_states([DevState.INIT]) - def Standby(self): - """ - Command to ask for initialisation of this device. Can only be called in FAULT or OFF state. - - :return:None - """ - - self.set_state(DevState.STANDBY) - - @command() - @only_in_states([DevState.STANDBY]) - @DebugIt() - def On(self): - """ - Command to ask for initialisation of this device. Can only be called in FAULT or OFF state. - - :return:None - """ - - self.set_state(DevState.ON) - - @command() - @DebugIt() - def Off(self): - """ - Command to ask for shutdown of this device. - - :return:None - """ - if self.get_state() == DevState.OFF: - # Already off. Don't complain. - return - - # Turn off - self.set_state(DevState.OFF) - - # Stop keep-alive - self.opcua_connection.stop() - - # Turn off again, in case of race conditions through reconnecting - self.set_state(DevState.OFF) - - @command() - @only_in_states([DevState.ON, DevState.INIT, DevState.STANDBY]) - @DebugIt() - def Fault(self): - """ - FAULT state is used to indicate our connection with the OPC-UA server is down. - - This device will try to reconnect once, and transition to the ON state on success. - - If reconnecting fails, the user needs to call Initialise() to retry to restart this device. - - :return:None - """ - self.set_state(DevState.FAULT) - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def RCU_off(self): - """ - - :return:None - """ - self.function_mapping["RCU_off"]() - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def RCU_on(self): - """ - - :return:None - """ - self.function_mapping["RCU_on"]() - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def ADC_on(self): - """ - - :return:None - """ - self.function_mapping["ADC_on"]() - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def RCU_update(self): - """ - - :return:None - """ - self.function_mapping["RCU_update"]() - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def CLK_off(self): - """ - - :return:None - """ - self.function_mapping["CLK_off"]() - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def CLK_on(self): - """ - - :return:None - """ - self.function_mapping["CLK_on"]() - - @command() - @DebugIt() - @only_when_on - @fault_on_error - def CLK_PLL_setup(self): - """ - - :return:None - """ - self.function_mapping["CLK_PLL_setup"]() - - -# ---------- -# Run server -# ---------- -def main(args=None, **kwargs): - """Main function of the PCC module.""" - return run((PCC,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/deprecated/PCC/PCC/__init__.py b/deprecated/PCC/PCC/__init__.py deleted file mode 100644 index f46dac89c5c6fb96b76b166b6d8c2be540b19e0d..0000000000000000000000000000000000000000 --- a/deprecated/PCC/PCC/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the PCC project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -"""PCC Device Server for LOFAR2.0 - -""" - -from . import release -from .PCC import PCC, main - -__version__ = release.version -__version_info__ = release.version_info -__author__ = release.author diff --git a/deprecated/PCC/PCC/__main__.py b/deprecated/PCC/PCC/__main__.py deleted file mode 100644 index 52b1fda83b2b1f2f8d9dbae05f114527555136ce..0000000000000000000000000000000000000000 --- a/deprecated/PCC/PCC/__main__.py +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the PCC project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -from PCC import main -main() diff --git a/deprecated/PCC/PCC/opcua_connection.py b/deprecated/PCC/PCC/opcua_connection.py deleted file mode 100644 index cfcfb74ab00416b79bfc2ccc8fbf263372c9f80c..0000000000000000000000000000000000000000 --- a/deprecated/PCC/PCC/opcua_connection.py +++ /dev/null @@ -1,84 +0,0 @@ -from threading import Thread -import socket -import time - -__all__ = ["OPCUAConnection"] - -class OPCUAConnection(Thread): - """ - Connects to OPC-UA in the foreground or background, and sends HELLO - messages to keep a check on the connection. On connection failure, reconnects once. - """ - - def __init__(self, client, on_func, fault_func, streams, try_interval=2): - super().__init__(daemon=True) - - self.client = client - self.on_func = on_func - self.fault_func = fault_func - self.try_interval = try_interval - self.streams = streams - self.stopping = False - self.connected = False - - def _servername(self): - return self.client.server_url.geturl() - - def connect(self): - try: - self.streams.debug_stream("Connecting to server %s", self._servername()) - self.client.connect() - self.connected = True - self.streams.debug_stream("Connected to server. Initialising.") - return True - except socket.error as e: - self.streams.error_stream("Could not connect to server %s: %s", self._servername(), e) - return False - - def disconnect(self): - self.connected = False # always force a reconnect, regardless of a successful disconnect - - try: - self.client.disconnect() - except Exception as e: - self.streams.error_stream("Disconnect from OPC-UA server %s failed: %s", self._servername(), e) - - def run(self): - while not self.stopping: - # keep trying to connect - if not self.connected: - if self.connect(): - self.on_func() - else: - # we retry only once, to catch exotic network issues. if the infra or hardware is down, - # our device cannot help, and must be reinitialised after the infra or hardware is fixed. - self.fault_func() - return - - # keep checking if the connection is still alive - try: - while not self.stopping: - self.client.send_hello() - time.sleep(self.try_interval) - except Exception as e: - self.streams.error_stream("Lost connection to server %s: %s", self._servername(), e) - - # technically, we may not have dropped the connection, but encounter a different error. so explicitly disconnect. - self.disconnect() - - # signal that we're disconnected - self.fault_func() - - def stop(self): - """ - Stop connecting & disconnect. Can take a few seconds for the timeouts to hit. - """ - - if not self.ident: - # have not yet been started, so nothing to do - return - - self.stopping = True - self.join() - - self.disconnect() diff --git a/deprecated/PCC/PCC/release.py b/deprecated/PCC/PCC/release.py deleted file mode 100644 index 5c73788786197b9f66c7b94dfb27cb747be6776d..0000000000000000000000000000000000000000 --- a/deprecated/PCC/PCC/release.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the PCC project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -"""Release information for Python Package""" - -name = """tangods-PCC""" -version = "1.0.0" -version_info = version.split(".") -description = """""" -author = "Thomas Juerges" -author_email = "jurges at astron.nl" -license = """APACHE""" -url = """https://git.astron.nl/lofar2.0/tango.git""" -copyright = """""" diff --git a/deprecated/PCC/PCC/wrappers.py b/deprecated/PCC/PCC/wrappers.py deleted file mode 100644 index 9dbc45a68dc850b36bd30a0a5b8664d104b58e30..0000000000000000000000000000000000000000 --- a/deprecated/PCC/PCC/wrappers.py +++ /dev/null @@ -1,53 +0,0 @@ -from tango import DevState, Except -from functools import wraps -import traceback - -__all__ = ["only_in_states", "only_when_on", "fault_on_error"] - -def only_in_states(allowed_states): - """ - Wrapper to call and return the wrapped function if the device is - in one of the given states. Otherwise a PyTango exception is thrown. - """ - def wrapper(func): - @wraps(func) - def state_check_wrapper(self, *args, **kwargs): - if self.get_state() in allowed_states: - return func(self, *args, **kwargs) - - self.warn_stream("Illegal command: Function %s can only be called in states %s. Current state: %s" % (func.__name__, allowed_states, self.get_state())) - Except.throw_exception("IllegalCommand", "Function can only be called in states %s. Current state: %s" % (allowed_states, self.get_state()), func.__name__) - - return state_check_wrapper - - return wrapper - -def only_when_on(func): - """ - Wrapper to call and return the wrapped function if the device is - in the ON state. Otherwise None is returned and nothing - will be called. - """ - @wraps(func) - def when_on_wrapper(self, *args, **kwargs): - if self.get_state() == DevState.ON: - return func(self, *args, **kwargs) - - return None - - return when_on_wrapper - -def fault_on_error(func): - """ - Wrapper to catch exceptions. Sets the device in a FAULT state if any occurs. - """ - @wraps(func) - def error_wrapper(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - except Exception as e: - self.error_stream("Function failed. Trace: %s", traceback.format_exc()) - self.Fault() - return None - - return error_wrapper diff --git a/deprecated/PCC/README.rst b/deprecated/PCC/README.rst deleted file mode 100644 index 9d42e957e28bd5e452349ec56c00dab61a4def46..0000000000000000000000000000000000000000 --- a/deprecated/PCC/README.rst +++ /dev/null @@ -1,25 +0,0 @@ -## PCC Device Server for LOFAR2.0 - - -## Requirement - -- PyTango >= 8.1.6 -- devicetest (for using tests) -- sphinx (for building sphinx documentation) - -## Installation - -Run python setup.py install - -If you want to build sphinx documentation, -run python setup.py build_sphinx - -If you want to pass the tests, -run python setup.py test - -## Usage - -Now you can start your device server in any -Terminal or console by calling it : - -PCC instance_name diff --git a/deprecated/PCC/requirements.txt b/deprecated/PCC/requirements.txt deleted file mode 100644 index 3b3b3b08bb560cfbe4fed2e7c7a0241f02f0af24..0000000000000000000000000000000000000000 --- a/deprecated/PCC/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -opcua >= 0.98.9 diff --git a/deprecated/PCC/setup.py b/deprecated/PCC/setup.py deleted file mode 100644 index 0d197078aa73c4adfd461e86f94bdc5b90554629..0000000000000000000000000000000000000000 --- a/deprecated/PCC/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# This file is part of the PCC project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -import os -import sys -from setuptools import setup - -setup_dir = os.path.dirname(os.path.abspath(__file__)) - -# make sure we use latest info from local code -sys.path.insert(0, setup_dir) - -readme_filename = os.path.join(setup_dir, 'README.rst') -with open(readme_filename) as file: - long_description = file.read() - -release_filename = os.path.join(setup_dir, 'PCC', 'release.py') -exec(open(release_filename).read()) - -pack = ['PCC'] - -setup(name=name, - version=version, - description='', - packages=pack, - include_package_data=True, - test_suite="test", - entry_points={'console_scripts':['PCC = PCC:main']}, - author='Thomas Juerges', - author_email='jurges at astron.nl', - license='APACHE', - long_description=long_description, - url='https://git.astron.nl/lofar2.0/tango.git', - platforms="Unix Like" - ) diff --git a/deprecated/PCC/test/PCC_test.py b/deprecated/PCC/test/PCC_test.py deleted file mode 100644 index 37b80b7e27125b85765da7f7b29e261f32eef1f6..0000000000000000000000000000000000000000 --- a/deprecated/PCC/test/PCC_test.py +++ /dev/null @@ -1,89 +0,0 @@ -######################################################################################### -# -*- coding: utf-8 -*- -# -# This file is part of the PCC project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. -######################################################################################### -"""Contain the tests for the RCU-SCC Device Server for LOFAR2.0.""" - -# Path -import sys -import os -path = os.path.join(os.path.dirname(__file__), os.pardir) -sys.path.insert(0, os.path.abspath(path)) - -# Imports -import pytest -from mock import MagicMock - -from PyTango import DevState - -# PROTECTED REGION ID(PCC.test_additional_imports) ENABLED START # -# PROTECTED REGION END # // PCC.test_additional_imports - - -# Device test case -@pytest.mark.usefixtures("tango_context", "initialize_device") -# PROTECTED REGION ID(PCC.test_PCC_decorators) ENABLED START # -# PROTECTED REGION END # // PCC.test_PCC_decorators -class TestPCC(object): - """Test case for packet generation.""" - - properties = { - 'OPC_Server_Name': '', - 'OPC_Server_Port': '', - 'OPC_Time_Out': '', - } - - @classmethod - def mocking(cls): - """Mock external libraries.""" - # Example : Mock numpy - # cls.numpy = PCC.numpy = MagicMock() - # PROTECTED REGION ID(PCC.test_mocking) ENABLED START # - # PROTECTED REGION END # // PCC.test_mocking - - def test_properties(self, tango_context): - # Test the properties - # PROTECTED REGION ID(PCC.test_properties) ENABLED START # - # PROTECTED REGION END # // PCC.test_properties - pass - - # PROTECTED REGION ID(PCC.test_State_decorators) ENABLED START # - # PROTECTED REGION END # // PCC.test_State_decorators - def test_State(self, tango_context): - """Test for State""" - # PROTECTED REGION ID(PCC.test_State) ENABLED START # - assert tango_context.device.State() == DevState.UNKNOWN - # PROTECTED REGION END # // PCC.test_State - - # PROTECTED REGION ID(PCC.test_Status_decorators) ENABLED START # - # PROTECTED REGION END # // PCC.test_Status_decorators - def test_Status(self, tango_context): - """Test for Status""" - # PROTECTED REGION ID(PCC.test_Status) ENABLED START # - assert tango_context.device.Status() == "The device is in UNKNOWN state." - # PROTECTED REGION END # // PCC.test_Status - - - # PROTECTED REGION ID(PCC.test_time_offset_rw_decorators) ENABLED START # - # PROTECTED REGION END # // PCC.test_time_offset_rw_decorators - def test_time_offset_rw(self, tango_context): - """Test for time_offset_rw""" - # PROTECTED REGION ID(PCC.test_time_offset_rw) ENABLED START # - assert tango_context.device.time_offset_rw == 0 - # PROTECTED REGION END # // PCC.test_time_offset_rw - - # PROTECTED REGION ID(PCC.test_time_offset_r_decorators) ENABLED START # - # PROTECTED REGION END # // PCC.test_time_offset_r_decorators - def test_time_offset_r(self, tango_context): - """Test for time_offset_r""" - # PROTECTED REGION ID(PCC.test_time_offset_r) ENABLED START # - assert tango_context.device.time_offset_r == 0 - # PROTECTED REGION END # // PCC.test_time_offset_r - - diff --git a/deprecated/PCC/test/test-PCC.py b/deprecated/PCC/test/test-PCC.py deleted file mode 100644 index d151a5d31203690883b24de7916470d8acc8a653..0000000000000000000000000000000000000000 --- a/deprecated/PCC/test/test-PCC.py +++ /dev/null @@ -1,28 +0,0 @@ -#! /usr/bin/env python3 - -import opcua -from time import sleep - -port = 4840 -host = "10.87.2.8" - -client = opcua.Client("opc.tcp://{}:{}".format(host, port)) -client.connect() -obj = client.get_objects_node() -name_space_index = 2 -time_offset = obj.get_child("{}:time_offset".format(name_space_index)) -time_offset_R = time_offset.get_child("{}:time_offset_R".format(name_space_index)) -time_offset_RW = time_offset.get_child("{}:time_offset_RW".format(name_space_index)) -old_time_offset = time_offset_R.get_value() -target_time_offset = 1 -new_time_offset = old_time_offset + target_time_offset -time_offset_RW.set_value(new_time_offset) -sleep(1.0) -latest_time_offset = time_offset_R.get_value() -difference_time_offset = latest_time_offset - old_time_offset -if difference_time_offset != target_time_offset: - print("ERROR: Setting and reading back time_offset. old_time_offset = %d, new_time_offset = %d, latest_time_offset = %d, target_time_offset = %d, difference_time_offset = %d." % (old_time_offset, new_time_offset, latest_time_offset, target_time_offset, difference_time_offset)) -else: - print("SUCCESS: Setting and reading back time_offset.") -time_offset_RW.set_value(old_time_offset) -client.disconnect() diff --git a/deprecated/SDP/LICENSE.txt b/deprecated/SDP/LICENSE.txt deleted file mode 100644 index ae533fce6dc75595f91290511273c7ff62312f76..0000000000000000000000000000000000000000 --- a/deprecated/SDP/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2020 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, -ASTRON Netherlands Institute for Radio Astronomy - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/deprecated/SDP/MANIFEST.in b/deprecated/SDP/MANIFEST.in deleted file mode 100644 index d9d9aaba41c43f633c9a02635e72b4eb1b791f50..0000000000000000000000000000000000000000 --- a/deprecated/SDP/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -recursive-include RCUSCC *.py -recursive-include test *.py -include *.rst -include RCUSCC.xmi -include *.txt -graft docs - -global-exclude *.pyc -global-exclude *.pyo diff --git a/deprecated/SDP/NOTICE b/deprecated/SDP/NOTICE deleted file mode 100644 index 9c7867598e17de5d69b8c26656caa8316cd0a30f..0000000000000000000000000000000000000000 --- a/deprecated/SDP/NOTICE +++ /dev/null @@ -1,8 +0,0 @@ -Citation Notice version 1.0 -This Citation Notice is part of the LOFAR software suite. -Parties that use ASTRON Software resulting in papers and/or publications are requested to -refer to the DOI(s) that correspond(s) to the version(s) of the ASTRON Software used: -<List of DOIs> -Parties that use ASTRON Software for purposes that do not result in publications (e.g. -commercial parties) are asked to inform ASTRON about their use of ASTRON Software, by -sending an email to including the DOIs mentioned above in the message. \ No newline at end of file diff --git a/deprecated/SDP/README.rst b/deprecated/SDP/README.rst deleted file mode 100644 index aafea1e3022ae9546fd62e1a2b1474dfc1bbef6a..0000000000000000000000000000000000000000 --- a/deprecated/SDP/README.rst +++ /dev/null @@ -1,25 +0,0 @@ -## SDP Device Server for LOFAR2.0 - - -## Requirement - -- PyTango >= 8.1.6 -- devicetest (for using tests) -- sphinx (for building sphinx documentation) - -## Installation - -Run python setup.py install - -If you want to build sphinx documentation, -run python setup.py build_sphinx - -If you want to pass the tests, -run python setup.py test - -## Usage - -Now you can start your device server in any -Terminal or console by calling it : - -SDP instance_name diff --git a/deprecated/SDP/SDP/SDP.py b/deprecated/SDP/SDP/SDP.py deleted file mode 100644 index 88408be0444a98218baa6e73e2e0a43891396561..0000000000000000000000000000000000000000 --- a/deprecated/SDP/SDP/SDP.py +++ /dev/null @@ -1,492 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the SDP project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -""" SDP Device Server for LOFAR2.0 - -""" - -# PyTango imports -from tango import DebugIt -from tango.server import run -from tango.server import Device -from tango.server import attribute, command -from tango.server import device_property -from tango import AttrQuality, DispLevel, DevState -from tango import AttrWriteType, PipeWriteType -# Additional import -import sys -import opcua -import numpy - -from wrappers import only_in_states, only_when_on, fault_on_error -from opcua_connection import OPCUAConnection -from lofar_logging import device_logging_to_python, log_exceptions - -__all__ = ["SDP", "main"] - -@device_logging_to_python({"device": "SDP"}) -class SDP(Device): - """ - - **Properties:** - - - Device Property - OPC_Server_Name - - Type:numpy.str - OPC_Server_Port - - Type:'DevULong' - OPC_Time_Out - - Type:numpy.float_ - - States are as follows: - INIT = Device is initialising. - STANDBY = Device is initialised, but pends external configuration and an explicit turning on, - ON = Device is fully configured, functional, controls the hardware, and is possibly actively running, - FAULT = Device detected an unrecoverable error, and is thus malfunctional, - OFF = Device is turned off, drops connection to the hardware, - - The following state transitions are implemented: - boot -> OFF: Triggered by tango. Device will be instantiated, - OFF -> INIT: Triggered by device. Device will initialise (connect to hardware, other devices), - INIT -> STANDBY: Triggered by device. Device is initialised, and is ready for additional configuration by the user, - STANDBY -> ON: Triggered by user. Device reports to be functional, - * -> FAULT: Triggered by device. Device has degraded to malfunctional, for example because the connection to the hardware is lost, - * -> FAULT: Triggered by user. Emulate a forced malfunction for integration testing purposes, - * -> OFF: Triggered by user. Device is turned off. Triggered by the Off() command, - FAULT -> INIT: Triggered by user. Device is reinitialised to recover from an error, - - The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()). - """ - device = "SDP" - client = 0 - name_space_index = 0 - obj = 0 - - # ----------------- - # Device Properties - # ----------------- - - OPC_Server_Name = device_property( - dtype=numpy.str, - mandatory=True - ) - - OPC_Server_Port = device_property( - dtype=numpy.uint64, - mandatory=True - ) - - OPC_Time_Out = device_property( - dtype=numpy.float_, - mandatory=True - ) - - # ---------- - # Attributes - # ---------- - fpga_mask_RW = attribute( - dtype = (numpy.bool_,), - max_dim_x = 16, - access=AttrWriteType.READ_WRITE, - ) - - fpga_scrap_R = attribute( - dtype = (numpy.int32,), - max_dim_x = 2048, - ) - - fpga_scrap_RW = attribute( - dtype = (numpy.int32,), - max_dim_x = 2048, - access=AttrWriteType.READ_WRITE, - ) - - fpga_status_R = attribute( - dtype = (numpy.bool_,), - max_dim_x = 16, - ) - - fpga_temp_R = attribute( - dtype = (numpy.float_,), - max_dim_x = 16, - ) - - fpga_version_R = attribute( - dtype = (numpy.str,), - max_dim_x = 16, - ) - - fpga_weights_R = attribute( - dtype = ((numpy.int16,),), - max_dim_x = 12 * 488 * 2, max_dim_y = 16, - ) - - fpga_weights_RW = attribute( - dtype = ((numpy.int16,),), - max_dim_x = 12 * 488 * 2, max_dim_y = 16, - access=AttrWriteType.READ_WRITE, - ) - - tr_busy_R = attribute( - dtype = (numpy.bool_), - ) - - tr_reload_RW = attribute( - dtype = (numpy.bool_), - access=AttrWriteType.READ_WRITE, - ) - - tr_tod_R = attribute( - dtype = (numpy.uint64), - ) - - tr_uptime_R = attribute( - dtype = (numpy.uint64,), - ) - - - # --------------- - # General methods - # --------------- - def get_node(self, node): - try: - return self.lofar_device_node.get_child(["{}:{}".format(self.name_space_index, node)]) - except opcua.ua.uaerrors._auto.BadNoMatch: - self.error_stream("Could not find LOFAR device %s node %s", self.device, node) - - # Contract with hardware is broken --- cannot recover - raise - - def _map_attributes(self): - try: - self.name_space_index = self.client.get_namespace_index("http://lofar.eu") - except Exception as e: - self.name_space_index = 1 - self.warn_stream("Cannot determine the OPC-UA name space index. Will try and use the default = %d." % (self.name_space_index)) - - self.obj_node = self.client.get_objects_node() - # TODO - # The server does not implement the correct namespace yet. - # Instead it is directly using the Objects node. - #self.lofar_device_node = self.obj_node.get_child(["{}:SDP".format(self.name_space_index)]) - self.lofar_device_node = self.obj_node - - self.info_stream("Mapping OPC-UA MP/CP to attributes...") - - self.attribute_mapping["fpga_mask_RW"] = self.get_node("fpga_mask_RW") - self.attribute_mapping["fpga_scrap_R"] = self.get_node("fpga_scrap_R") - self.attribute_mapping["fpga_scrap_RW"] = self.get_node("fpga_scrap_RW") - self.attribute_mapping["fpga_status_R"] = self.get_node("fpga_status_R") - self.attribute_mapping["fpga_temp_R"] = self.get_node("fpga_temp_R") - self.attribute_mapping["fpga_version_R"] = self.get_node("fpga_version_R") - self.attribute_mapping["fpga_weights_R"] = self.get_node("fpga_weights_R") - self.attribute_mapping["fpga_weights_RW"] = self.get_node("fpga_weights_RW") - self.attribute_mapping["tr_busy_R"] = self.get_node("tr_busy_R") - self.attribute_mapping["tr_reload_RW"] = self.get_node("tr_reload_W") - self.attribute_mapping["tr_tod_R"] = self.get_node("tr_tod_R") - self.attribute_mapping["tr_uptime_R"] = self.get_node("tr_uptime_R") - - self.info_stream("Mapping OPC-UA MP/CP to attributes done.") - - @log_exceptions - @DebugIt() - def init_device(self): - """ Instantiates the device in the OFF state. """ - - # NOTE: Will delete_device first, if necessary - Device.init_device(self) - - self.set_state(DevState.OFF) - - @log_exceptions - def initialise(self): - """Initialises the attributes and properties of the SDP.""" - - self.set_state(DevState.INIT) - - # Init the dict that contains attribute to OPC-UA MP/CP mappings. - self.attribute_mapping = {} - - # Set default values in the RW/R attributes and add them to - # the mapping. - self._fpga_mask_RW = numpy.full(16, False) - self.attribute_mapping["fpga_mask_RW"] = {} - self._fpga_scrap_R = numpy.full(2048, False) - self.attribute_mapping["fpga_scrap_R"] = {} - self._fpga_scrap_RW = numpy.full(2048, False) - self.attribute_mapping["fpga_scrap_RW"] = {} - self._fpga_status_R = numpy.full(16, False) - self.attribute_mapping["fpga_status_R"] = {} - self._fpga_temp_R = numpy.full(16, 0.0) - self.attribute_mapping["fpga_temp_R"] = {} - self._fpga_version_R = numpy.full(16, "NO_VERSION_INFO_YET") - self.attribute_mapping["fpga_version_R"] = {} - self._fpga_weights_R = numpy.full((16, 2 * 488 * 12), 0) - self.attribute_mapping["fpga_weights_R"] = {} - self._fpga_weights_RW = numpy.full((16, 2 * 488 * 12), 0) - self.attribute_mapping["fpga_weights_RW"] = {} - self._tr_busy_R = False - self.attribute_mapping["tr_busy_R"] = {} - self._tr_reload_RW = False - self.attribute_mapping["tr_reload_RW"] = {} - self._tr_tod_R = 0 - self.attribute_mapping["tr_tod_R"] = {} - self._tr_uptime_R = 0 - self.attribute_mapping["tr_uptime_R"] = {} - - # Init the dict that contains function to OPC-UA function mappings. - self.function_mapping = {} - - self.client = opcua.Client("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_Time_Out) # timeout in seconds - - # Connect to OPC-UA -- will set ON state on success in case of a reconnect - self.opcua_connection = OPCUAConnection(self.client, self.Standby, self.Fault, self) - - # Explicitly connect - if not self.opcua_connection.connect(): - # hardware or infra is down -- needs fixing first - self.Fault() - return - - # Retrieve and map server attributes - try: - self._map_attributes() - except Exception as e: - self.error_stream("Could not map server interface: %s", e) - self.Fault() - return - - # Start keep-alive - self.opcua_connection.start() - - # Set the masks. - # - # Attention! - # Set the masks only after the OPCUA connection has been - # established! The setting of the masks needs to go through - # to the server. - # - # TODO - # Read default masks from config DB - #self.write_fpga_mask_RW(self._fpga_mask_R) - - # Everything went ok -- go standby. - self.set_state(DevState.STANDBY) - - - def always_executed_hook(self): - """Method always executed before any TANGO command is executed.""" - pass - - @DebugIt() - def delete_device(self): - """Hook to delete resources allocated in init_device. - - This method allows for any memory or other resources allocated in the - init_device method to be released. This method is called by the device - destructor and by the device Init command (a Tango built-in). - """ - self.Off() - - - # ------------------ - # Attributes methods - # ------------------ - @only_when_on - @fault_on_error - def read_fpga_mask_RW(self): - """Return the fpga_mask_RW attribute.""" - return self._fpga_mask_RW - - @only_when_on - @fault_on_error - def write_fpga_mask_RW(self, value): - """Return the fpga_mask_RW attribute.""" - self.attribute_mapping["fpga_mask_RW"].set_value(value.tolist()) - self._fpga_mask_RW = value - return - - @only_when_on - @fault_on_error - def read_fpga_scrap_R(self): - """Return the fpga_scrap_R attribute.""" - self._fpga_scrap_R = numpy.array(self.attribute_mapping["fpga_scrap_R"].get_value(), dtype = numpy.int32) - return self._fpga_scrap_R - - @only_when_on - @fault_on_error - def read_fpga_scrap_RW(self): - """Return the fpga_scrap_RW attribute.""" - return self._fpga_scrap_RW - - @only_when_on - @fault_on_error - def write_fpga_scrap_RW(self, value): - """Return the fpga_scrap_RW attribute.""" - self.attribute_mapping["fpga_scrap_RW"].set_data_value(opcua.ua.uatypes.Variant(value = value.tolist(), varianttype=opcua.ua.VariantType.Int32)) - _fpga_scrap_RW = value - - @only_when_on - @fault_on_error - def read_fpga_status_R(self): - """Return the fpga_status_R attribute.""" - self._fpga_status_R = numpy.array(self.attribute_mapping["fpga_status_R"].get_value()) - return self._fpga_status_R - - @only_when_on - @fault_on_error - def read_fpga_temp_R(self): - """Return the fpga_temp_R attribute.""" - self._fpga_temp_R = numpy.array(self.attribute_mapping["fpga_temp_R"].get_value()) - return self._fpga_temp_R - - @only_when_on - @fault_on_error - def read_fpga_version_R(self): - """Return the fpga_version_R attribute.""" - self._fpga_version_R = numpy.array(self.attribute_mapping["fpga_version_R"].get_value()) - return self._fpga_version_R - - @only_when_on - @fault_on_error - def read_fpga_weights_R(self): - """Return the fpga_weights_R attribute.""" - value = numpy.array(numpy.split(numpy.array(self.attribute_mapping["fpga_weights_R"].get_value(), dtype = numpy.int16), indices_or_sections = 16)) - self._fpga_weights_R = value - return self._fpga_weights_R - - @only_when_on - @fault_on_error - def read_fpga_weights_RW(self): - """Return the fpga_weights_RW attribute.""" - return self._fpga_weights_RW - - @only_when_on - @fault_on_error - def write_fpga_weights_RW(self, value): - """Return the fpga_weights_RW attribute.""" - self.attribute_mapping["fpga_weights_RW"].set_data_value(opcua.ua.uatypes.Variant(value = value.flatten().tolist(), varianttype=opcua.ua.VariantType.Int16)) - self._fpga_weights_RW = value - - @only_when_on - @fault_on_error - def read_tr_busy_R(self): - """Return the tr_busy_R attribute.""" - self._tr_busy_R = self.attribute_mapping["tr_busy_R"].get_value() - return self._tr_busy_R - - @only_when_on - @fault_on_error - def read_tr_reload_RW(self): - """Return the tr_reload_RW attribute.""" - self._tr_reload_RW = self.attribute_mapping["tr_reload_RW"].get_value() - return self._tr_reload_RW - - @only_when_on - @fault_on_error - def write_tr_reload_RW(self, value): - """Return the tr_reload_RW attribute.""" - self.attribute_mapping["tr_reload_RW"].set_value(value) - self._tr_reload_RW = value - - @only_when_on - @fault_on_error - def read_tr_tod_R(self): - """Return the _tr_tod_R attribute.""" - self._tr_tod_R = self.attribute_mapping["tr_tod_R"].get_value() - return self._tr_tod_R - - @only_when_on - @fault_on_error - def read_tr_uptime_R(self): - """Return the _tr_uptime_R attribute.""" - self._tr_uptime_R = self.attribute_mapping["tr_uptime_R"].get_value() - return self._tr_uptime_R - - - # -------- - # Commands - # -------- - @command() - @only_in_states([DevState.FAULT, DevState.OFF]) - @DebugIt() - def Initialise(self): - """ - Command to ask for initialisation of this device. Can only be called in FAULT or OFF state. - - :return:None - """ - self.initialise() - - @only_in_states([DevState.INIT]) - def Standby(self): - """ - Command to ask for initialisation of this device. Can only be called in FAULT or OFF state. - - :return:None - """ - self.set_state(DevState.STANDBY) - - @command() - @only_in_states([DevState.STANDBY]) - @DebugIt() - def On(self): - """ - Command to ask for initialisation of this device. Can only be called in FAULT or OFF state. - - :return:None - """ - self.set_state(DevState.ON) - - @command() - @DebugIt() - def Off(self): - """ - Command to ask for shutdown of this device. - - :return:None - """ - if self.get_state() == DevState.OFF: - # Already off. Don't complain. - return - - # Turn off - self.set_state(DevState.OFF) - - # Stop keep-alive - self.opcua_connection.stop() - - # Turn off again, in case of race conditions through reconnecting - self.set_state(DevState.OFF) - - @command() - @only_in_states([DevState.ON, DevState.INIT, DevState.STANDBY]) - @DebugIt() - def Fault(self): - """ - FAULT state is used to indicate our connection with the OPC-UA server is down. - - This device will try to reconnect once, and transition to the ON state on success. - - If reconnecting fails, the user needs to call Initialise() to retry to restart this device. - - :return:None - """ - self.set_state(DevState.FAULT) - -# ---------- -# Run server -# ---------- -def main(args=None, **kwargs): - """Main function of the SDP module.""" - return run((SDP,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/deprecated/SDP/SDP/__init__.py b/deprecated/SDP/SDP/__init__.py deleted file mode 100644 index cf68b03729a1a4d562556c9765b9e7389fd49b18..0000000000000000000000000000000000000000 --- a/deprecated/SDP/SDP/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the SDP project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -"""SDP Device Server for LOFAR2.0 - -""" - -from . import release -from .SDP import SDP, main - -__version__ = release.version -__version_info__ = release.version_info -__author__ = release.author diff --git a/deprecated/SDP/SDP/__main__.py b/deprecated/SDP/SDP/__main__.py deleted file mode 100644 index 5ef0710c551b94138cfbe4b1c762af830dae9a62..0000000000000000000000000000000000000000 --- a/deprecated/SDP/SDP/__main__.py +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the SDP project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -from SDP import main -main() diff --git a/deprecated/SDP/SDP/opcua_connection.py b/deprecated/SDP/SDP/opcua_connection.py deleted file mode 100644 index cfcfb74ab00416b79bfc2ccc8fbf263372c9f80c..0000000000000000000000000000000000000000 --- a/deprecated/SDP/SDP/opcua_connection.py +++ /dev/null @@ -1,84 +0,0 @@ -from threading import Thread -import socket -import time - -__all__ = ["OPCUAConnection"] - -class OPCUAConnection(Thread): - """ - Connects to OPC-UA in the foreground or background, and sends HELLO - messages to keep a check on the connection. On connection failure, reconnects once. - """ - - def __init__(self, client, on_func, fault_func, streams, try_interval=2): - super().__init__(daemon=True) - - self.client = client - self.on_func = on_func - self.fault_func = fault_func - self.try_interval = try_interval - self.streams = streams - self.stopping = False - self.connected = False - - def _servername(self): - return self.client.server_url.geturl() - - def connect(self): - try: - self.streams.debug_stream("Connecting to server %s", self._servername()) - self.client.connect() - self.connected = True - self.streams.debug_stream("Connected to server. Initialising.") - return True - except socket.error as e: - self.streams.error_stream("Could not connect to server %s: %s", self._servername(), e) - return False - - def disconnect(self): - self.connected = False # always force a reconnect, regardless of a successful disconnect - - try: - self.client.disconnect() - except Exception as e: - self.streams.error_stream("Disconnect from OPC-UA server %s failed: %s", self._servername(), e) - - def run(self): - while not self.stopping: - # keep trying to connect - if not self.connected: - if self.connect(): - self.on_func() - else: - # we retry only once, to catch exotic network issues. if the infra or hardware is down, - # our device cannot help, and must be reinitialised after the infra or hardware is fixed. - self.fault_func() - return - - # keep checking if the connection is still alive - try: - while not self.stopping: - self.client.send_hello() - time.sleep(self.try_interval) - except Exception as e: - self.streams.error_stream("Lost connection to server %s: %s", self._servername(), e) - - # technically, we may not have dropped the connection, but encounter a different error. so explicitly disconnect. - self.disconnect() - - # signal that we're disconnected - self.fault_func() - - def stop(self): - """ - Stop connecting & disconnect. Can take a few seconds for the timeouts to hit. - """ - - if not self.ident: - # have not yet been started, so nothing to do - return - - self.stopping = True - self.join() - - self.disconnect() diff --git a/deprecated/SDP/SDP/release.py b/deprecated/SDP/SDP/release.py deleted file mode 100644 index 74a9dd436a73d6acd8d9c7918c63dfc95b49ca09..0000000000000000000000000000000000000000 --- a/deprecated/SDP/SDP/release.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the SDP project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -"""Release information for Python Package""" - -name = """tangods-sdp""" -version = "1.0.0" -version_info = version.split(".") -description = """""" -author = "Thomas Juerges" -author_email = "jurges at astron.nl" -license = """APACHE""" -url = """https://git.astron.nl/lofar2.0/tango.git""" -copyright = """""" diff --git a/deprecated/SDP/SDP/wrappers.py b/deprecated/SDP/SDP/wrappers.py deleted file mode 100644 index 9dbc45a68dc850b36bd30a0a5b8664d104b58e30..0000000000000000000000000000000000000000 --- a/deprecated/SDP/SDP/wrappers.py +++ /dev/null @@ -1,53 +0,0 @@ -from tango import DevState, Except -from functools import wraps -import traceback - -__all__ = ["only_in_states", "only_when_on", "fault_on_error"] - -def only_in_states(allowed_states): - """ - Wrapper to call and return the wrapped function if the device is - in one of the given states. Otherwise a PyTango exception is thrown. - """ - def wrapper(func): - @wraps(func) - def state_check_wrapper(self, *args, **kwargs): - if self.get_state() in allowed_states: - return func(self, *args, **kwargs) - - self.warn_stream("Illegal command: Function %s can only be called in states %s. Current state: %s" % (func.__name__, allowed_states, self.get_state())) - Except.throw_exception("IllegalCommand", "Function can only be called in states %s. Current state: %s" % (allowed_states, self.get_state()), func.__name__) - - return state_check_wrapper - - return wrapper - -def only_when_on(func): - """ - Wrapper to call and return the wrapped function if the device is - in the ON state. Otherwise None is returned and nothing - will be called. - """ - @wraps(func) - def when_on_wrapper(self, *args, **kwargs): - if self.get_state() == DevState.ON: - return func(self, *args, **kwargs) - - return None - - return when_on_wrapper - -def fault_on_error(func): - """ - Wrapper to catch exceptions. Sets the device in a FAULT state if any occurs. - """ - @wraps(func) - def error_wrapper(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - except Exception as e: - self.error_stream("Function failed. Trace: %s", traceback.format_exc()) - self.Fault() - return None - - return error_wrapper diff --git a/deprecated/SDP/requirements.txt b/deprecated/SDP/requirements.txt deleted file mode 100644 index a0195dd42b98b0f3194e55e91cded17608ed6ee3..0000000000000000000000000000000000000000 --- a/deprecated/SDP/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -opcua >= 0.98.9 -numpy diff --git a/deprecated/SDP/setup.py b/deprecated/SDP/setup.py deleted file mode 100644 index 8def2ec90e9cf446fc680fe7740f2c18aaa19975..0000000000000000000000000000000000000000 --- a/deprecated/SDP/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# This file is part of the SDP project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -import os -import sys -from setuptools import setup - -setup_dir = os.path.dirname(os.path.abspath(__file__)) - -# make sure we use latest info from local code -sys.path.insert(0, setup_dir) - -readme_filename = os.path.join(setup_dir, 'README.rst') -with open(readme_filename) as file: - long_description = file.read() - -release_filename = os.path.join(setup_dir, 'SDP', 'release.py') -exec(open(release_filename).read()) - -pack = ['SDP'] - -setup(name=name, - version=version, - description='', - packages=pack, - include_package_data=True, - test_suite="test", - entry_points={'console_scripts':['SDP = SDP:main']}, - author='Thomas Juerges', - author_email='jurges at astron.nl', - license='APACHE', - long_description=long_description, - url='https://git.astron.nl/lofar2.0/tango.git', - platforms="Unix Like" - ) diff --git a/devices/clients/sst_client.py b/devices/clients/sst_client.py index 4a1bc5376ef3a2bb458bb0f7fd905aa7963d8f49..4aa4e3c68bb9e2b49e815feb605e8e7b7c2adce3 100644 --- a/devices/clients/sst_client.py +++ b/devices/clients/sst_client.py @@ -7,7 +7,7 @@ import socket import time from clients.comms_client import CommClient -from devices.sdp_statistics.statistics_packet import SSTPacket +from devices.sdp.statistics_packet import SSTPacket logger = logging.getLogger() diff --git a/deprecated/PCC/test/__init__.py b/devices/devices/sdp/__init__.py similarity index 100% rename from deprecated/PCC/test/__init__.py rename to devices/devices/sdp/__init__.py diff --git a/devices/SST.py b/devices/devices/sdp/sst.py similarity index 95% rename from devices/SST.py rename to devices/devices/sdp/sst.py index e9ee22d1187eb580c58ad397b33c687c28e409a0..5d614323bc7b807797ae3547366ae0efed779d2c 100644 --- a/devices/SST.py +++ b/devices/devices/sdp/sst.py @@ -11,6 +11,13 @@ """ +# TODO(Corne): Remove sys.path.append hack once packaging is in place! +import os, sys +currentdir = os.path.dirname(os.path.realpath(__file__)) +parentdir = os.path.dirname(currentdir) +parentdir = os.path.dirname(parentdir) +sys.path.append(parentdir) + # PyTango imports from tango.server import run from tango.server import device_property, attribute diff --git a/devices/devices/sdp_statistics/statistics_packet.py b/devices/devices/sdp/statistics_packet.py similarity index 100% rename from devices/devices/sdp_statistics/statistics_packet.py rename to devices/devices/sdp/statistics_packet.py diff --git a/devices/devices/sdp_statistics/__init__.py b/devices/devices/sdp_statistics/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/devices/devices/sdp_statistics/sst.py b/devices/devices/sdp_statistics/sst.py deleted file mode 100644 index 5ea315fd9808fe1fd7dcc456b64d17e858977a1c..0000000000000000000000000000000000000000 --- a/devices/devices/sdp_statistics/sst.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the Statistics project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -""" Statistics Device Server for LOFAR2.0 - -""" - -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - -# PyTango imports -from tango.server import run -from tango.server import device_property -# Additional import - -from clients.sst_client import sst_client - -from clients.attribute_wrapper import attribute_wrapper -from devices.hardware_device import hardware_device - -from common.lofar_logging import device_logging_to_python, log_exceptions - -import numpy - -__all__ = ["SST", "main"] - -@device_logging_to_python({"device": "SST"}) -class SST(hardware_device): - - # ----------------- - # Device Properties - # ----------------- - - SST_Port = device_property( - dtype='DevUShort', - mandatory=True - ) - - # ---------- - # Attributes - # ---------- - # -------- - - # SST client annotation consists of a dict that contains the parameter name that needs to be read. - # Example: comms_annotation={"parameter": "this_value_R"} - packet_count_R = attribute_wrapper(comms_annotation={"parameter": "packet_count_R"}, datatype=numpy.int64) - last_packet_timestamp_R = attribute_wrapper(comms_annotation={"parameter": "last_packet_timestamp_R"}, datatype=numpy.int64) - queue_percentage_used_R = attribute_wrapper(comms_annotation={"parameter": "queue_percentage_used_R"}, datatype=numpy.double) - - # -------- - # overloaded functions - def configure_for_off(self): - """ user code here. is called when the state is set to OFF """ - - # Stop keep-alive - try: - self.sst_client.stop() - except Exception as e: - self.warn_stream("Exception while stopping sst_client in configure_for_off function: {}. Exception ignored".format(e)) - - @log_exceptions() - def configure_for_initialise(self): - """ user code here. is called when the sate is set to INIT """ - """Initialises the attributes and properties of the statistics device.""" - - self.sst_client = sst_client("0.0.0.0", self.SST_Port, self.Fault, self) - - # map an access helper class - for i in self.attr_list(): - try: - i.set_comm_client(self.sst_client) - except Exception as e: - # use the pass function instead of setting read/write fails - i.set_pass_func() - self.warn_stream("error while setting the sst attribute {} read/write function. {}. using pass function instead".format(i, e)) - pass - - self.sst_client.start() - - # -------- - # Commands - # -------- - -# ---------- -# Run server -# ---------- -def main(args=None, **kwargs): - """Main function of the Statistics Device module.""" - - from common.lofar_logging import configure_logger - import logging - configure_logger(logging.getLogger()) - - return run((SST,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/docker-compose/device-sst.yml b/docker-compose/device-sst.yml index c42496700eaf96347825a93c5050dc90744c1888..992980bcaafd8de43e85c56d134f9736944e2eac 100644 --- a/docker-compose/device-sst.yml +++ b/docker-compose/device-sst.yml @@ -26,7 +26,7 @@ services: - control - data ports: - - 5001:5001/udp + - 5001:5001/udp volumes: - ${TANGO_LOFAR_CONTAINER_MOUNT} environment: @@ -37,5 +37,5 @@ services: - --timeout=30 - --strict - -- - - python3 -u ${TANGO_LOFAR_CONTAINER_DIR}/devices/devices/sst.py LTS -v + - python3 -u ${TANGO_LOFAR_CONTAINER_DIR}/devices/devices/sdp/sst.py LTS -v restart: on-failure