Skip to content
Snippets Groups Projects
SDP.py 8.9 KiB
Newer Older
# -*- 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.server import run
from tango.server import device_property, attribute
Taya Snijder's avatar
Taya Snijder committed
from tango import AttrWriteType
# Additional import

from clients.opcua_connection import OPCUAConnection
from util.attribute_wrapper import attribute_wrapper
from util.hardware_device import hardware_device
from util.lofar_logging import device_logging_to_python, log_exceptions
from util.lofar_git import get_version
Taya Snijder's avatar
Taya Snijder committed
import numpy

__all__ = ["SDP", "main"]

@device_logging_to_python({"device": "SDP"})
class SDP(hardware_device):
Thomas Juerges's avatar
Thomas Juerges committed
    """

    **Properties:**

    - Device Property
        OPC_Server_Name
            - Type:'DevString'
        OPC_Server_Port
            - Type:'DevULong'
        OPC_Time_Out
            - Type:'DevDouble'
    """

    # -----------------
    # Device Properties
    # -----------------

    OPC_Server_Name = device_property(
        dtype='DevString',
        mandatory=True
    )

    OPC_Server_Port = device_property(
        dtype='DevULong',
        mandatory=True
    )

    OPC_Time_Out = device_property(
        dtype='DevDouble',
        mandatory=True
    )

    # ----------
    # Attributes
    # ----------
    version_R = attribute(dtype=str, access=AttrWriteType.READ, fget=lambda self: get_version())
    # SDP will switch from FPGA_mask_RW to TR_FPGA_mask_RW, offer both for now as its a critical flag
    TR_FPGA_mask_RW = attribute_wrapper(comms_annotation=["2:TR_FPGA_mask_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_mask_RW = attribute_wrapper(comms_annotation=["2:FPGA_mask_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_scrap_R = attribute_wrapper(comms_annotation=["2:FPGA_scrap_R"], datatype=numpy.int32, dims=(2048,))
    FPGA_scrap_RW = attribute_wrapper(comms_annotation=["2:FPGA_scrap_RW"], datatype=numpy.int32, dims=(2048,), access=AttrWriteType.READ_WRITE)
    FPGA_status_R = attribute_wrapper(comms_annotation=["2:FPGA_status_R"], datatype=numpy.bool_, dims=(16,))
    FPGA_temp_R = attribute_wrapper(comms_annotation=["2:FPGA_temp_R"], datatype=numpy.float_, dims=(16,))
    FPGA_version_R = attribute_wrapper(comms_annotation=["2:FPGA_version_R"], datatype=numpy.str_, dims=(16,))
    FPGA_weights_R = attribute_wrapper(comms_annotation=["2:FPGA_weights_R"], datatype=numpy.int16, dims=(16, 12 * 488 * 2))
    FPGA_weights_RW = attribute_wrapper(comms_annotation=["2:FPGA_weights_RW"], datatype=numpy.int16, dims=(16, 12 * 488 * 2), access=AttrWriteType.READ_WRITE)
    FPGA_processing_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_processing_enable_R = attribute_wrapper(comms_annotation=["2:FPGA_processing_enable_R"], datatype=numpy.bool_, dims=(16,))
    FPGA_sst_offload_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sst_offload_enable_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_enable_R"], datatype=numpy.bool_, dims=(16,))
    FPGA_sst_offload_selector_RW = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_selector_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sst_offload_selector_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_selector_R"], datatype=numpy.bool_, dims=(16,))
    FPGA_sst_offload_hdr_eth_destination_mac_RW = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_eth_destination_mac_RW"], datatype=numpy.str_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sst_offload_hdr_eth_destination_mac_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_eth_destination_mac_R"], datatype=numpy.str_, dims=(16,))
    FPGA_sst_offload_hdr_ip_destination_address_RW = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_ip_destination_address_RW"], datatype=numpy.str_, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sst_offload_hdr_ip_destination_address_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_ip_destination_address_R"], datatype=numpy.str_, dims=(16,))
    FPGA_sst_offload_hdr_udp_destination_port_RW = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sst_offload_hdr_udp_destination_port_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,))
    FPGA_sdp_info_station_id_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_station_id_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sdp_info_station_id_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_station_id_R"], datatype=numpy.uint16, dims=(16,))
    FPGA_sdp_info_observation_id_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_observation_id_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sdp_info_observation_id_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_observation_id_R"], datatype=numpy.uint32, dims=(16,))
    FPGA_sdp_info_nyquist_sampling_zone_index_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_nyquist_sampling_zone_index_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE)
    FPGA_sdp_info_nyquist_sampling_zone_index_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_nyquist_sampling_zone_index_R"], datatype=numpy.uint16, dims=(16,))
    FPGA_sdp_info_subband_calibrated_flag_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_subband_calibrated_flag_R"], datatype=numpy.uint16, dims=(16,)) 
    FPGA_sdp_info_beamlet_scale_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_beamlet_scale_R"], datatype=numpy.uint16, dims=(16,)) 

    TR_busy_R = attribute_wrapper(comms_annotation=["2:TR_busy_R"], datatype=numpy.bool_)
    TR_reload_RW = attribute_wrapper(comms_annotation=["2:TR_reload_RW"], datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
    TR_tod_R = attribute_wrapper(comms_annotation=["2:TR_tod_R"], datatype=numpy.uint64)
    TR_uptime_R = attribute_wrapper(comms_annotation=["2:TR_uptime_R"], datatype=numpy.uint64)

    FPGA_firmware_version_R = attribute_wrapper(comms_annotation=["2:FPGA_firmware_version_R"], datatype=numpy.str_, dims=(16,))
    FPGA_hardware_version_R = attribute_wrapper(comms_annotation=["2:FPGA_hardware_version_R"], datatype=numpy.str_, dims=(16,))
    TR_software_version_R = attribute_wrapper(comms_annotation=["2:TR_software_version_R"], datatype=numpy.str_)
Thomas Juerges's avatar
Thomas Juerges committed

    def always_executed_hook(self):
        """Method always executed before any TANGO command is executed."""
        pass

    @log_exceptions()
Thomas Juerges's avatar
Thomas Juerges committed
    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.")

    # --------
    # overloaded functions
    # --------
    @log_exceptions()
Taya Snijder's avatar
Taya Snijder committed
    def configure_for_off(self):
Thomas Juerges's avatar
Thomas Juerges committed
        """ user code here. is called when the state is set to OFF """

        # Stop keep-alive
        try:
            self.opcua_connection.stop()
        except Exception as e:
            self.warn_stream("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e))
    @log_exceptions()
Taya Snijder's avatar
Taya Snijder committed
    def configure_for_initialise(self):
Thomas Juerges's avatar
Thomas Juerges committed
        """ user code here. is called when the sate is set to INIT """
        """Initialises the attributes and properties of the SDP."""
Thomas Juerges's avatar
Thomas Juerges committed

        # set up the OPC ua client
        self.OPCua_client = OPCUAConnection("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), "http://lofar.eu", self.OPC_Time_Out, self.Fault, self)
Thomas Juerges's avatar
Thomas Juerges committed

        # map an access helper class
        for i in self.attr_list():
Taya Snijder's avatar
Taya Snijder committed
            try:
                i.set_comm_client(self.OPCua_client)
                # use the pass function instead of setting read/write fails
                self.warn_stream("error while setting the SDP attribute {} read/write function. {}".format(i, e))
Thomas Juerges's avatar
Thomas Juerges committed

        self.OPCua_client.start()

    # --------
    # Commands
    # --------

# ----------
# Run server
# ----------
def main(args=None, **kwargs):
Thomas Juerges's avatar
Thomas Juerges committed
    """Main function of the SDP module."""

    from util.lofar_logging import configure_logger
    import logging
    configure_logger(logging.getLogger())

Thomas Juerges's avatar
Thomas Juerges committed
    return run((SDP,), args=args, **kwargs)


if __name__ == '__main__':
Thomas Juerges's avatar
Thomas Juerges committed
    main()