Skip to content
Snippets Groups Projects
Commit 32b8a2cd authored by Jan David Mol's avatar Jan David Mol
Browse files

Merge branch 'master' into 'L2SS-391-boot-device'

# Conflicts:
#   devices/devices/recv.py
parents 3afd6d1d 1e3a1c21
No related branches found
No related tags found
1 merge request!144L2SS-391: Add boot device
#!/bin/bash
git submodule update --init
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
ABSOLUTE_PATH=$(realpath $(dirname ${BASH_SOURCE})) ABSOLUTE_PATH=$(realpath $(dirname ${BASH_SOURCE}))
export LOFAR20_DIR=${1:-$(realpath ${ABSOLUTE_PATH}/../..)} export LOFAR20_DIR=${1:-$(realpath ${ABSOLUTE_PATH}/../..)}
if [ ! -f "${LOFAR20_DIR}/.git/hooks/post-checkout" ]; then
alias git="cp ${LOFAR20_DIR}/bin/update_submodules.sh ${LOFAR20_DIR}/.git/hooks/post-checkout; cp ${LOFAR20_DIR}/bin/update_submodules.sh ${LOFAR20_DIR}/.git/hooks/post-merge; unalias git; git"
fi
# This needs to be modified for a development environment. # This needs to be modified for a development environment.
# In case you run multiple Docker networks on the same host in parallel, you need to specify a unique # In case you run multiple Docker networks on the same host in parallel, you need to specify a unique
# network name for each of them. # network name for each of them.
......
...@@ -37,19 +37,6 @@ __all__ = ["Docker", "main"] ...@@ -37,19 +37,6 @@ __all__ = ["Docker", "main"]
@device_logging_to_python() @device_logging_to_python()
class Docker(hardware_device): class Docker(hardware_device):
"""
**Properties:**
- Device Property
OPC_Server_Name
- Type:'DevString'
OPC_Server_Port
- Type:'DevULong'
OPC_Time_Out
- Type:'DevDouble'
"""
# ----------------- # -----------------
# Device Properties # Device Properties
# ----------------- # -----------------
...@@ -103,19 +90,6 @@ class Docker(hardware_device): ...@@ -103,19 +90,6 @@ class Docker(hardware_device):
tango_rest_R = attribute_wrapper(comms_annotation={"container": "tango-rest"}, datatype=numpy.bool_) tango_rest_R = attribute_wrapper(comms_annotation={"container": "tango-rest"}, datatype=numpy.bool_)
tango_rest_RW = attribute_wrapper(comms_annotation={"container": "tango-rest"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE) tango_rest_RW = attribute_wrapper(comms_annotation={"container": "tango-rest"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
@log_exceptions()
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 # overloaded functions
# -------- # --------
...@@ -124,9 +98,9 @@ class Docker(hardware_device): ...@@ -124,9 +98,9 @@ class Docker(hardware_device):
""" user code here. is called when the state is set to OFF """ """ user code here. is called when the state is set to OFF """
# Stop keep-alive # Stop keep-alive
try: try:
self.opcua_connection.stop() self.docker_client.stop()
except Exception as e: except Exception as e:
self.warn_stream("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e)) self.warn_stream("Exception while stopping docker client in configure_for_off function: {}. Exception ignored".format(e))
@log_exceptions() @log_exceptions()
def configure_for_initialise(self): def configure_for_initialise(self):
...@@ -135,14 +109,9 @@ class Docker(hardware_device): ...@@ -135,14 +109,9 @@ class Docker(hardware_device):
# set up the Docker client # set up the Docker client
self.docker_client = DockerClient(self.Docker_Base_URL, self.Fault, self) self.docker_client = DockerClient(self.Docker_Base_URL, self.Fault, self)
# map an access helper class # tie attributes to client
for i in self.attr_list(): for i in self.attr_list():
try:
i.set_comm_client(self.docker_client) i.set_comm_client(self.docker_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 attribute {} read/write function. {}".format(i, e))
self.docker_client.start() self.docker_client.start()
......
...@@ -59,6 +59,9 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): ...@@ -59,6 +59,9 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()). The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()).
""" """
# list of property names too be set first by set_defaults
first_default_settings = []
@classmethod @classmethod
def attr_list(cls): def attr_list(cls):
""" Return a list of all the attribute_wrapper members of this class. """ """ Return a list of all the attribute_wrapper members of this class. """
...@@ -69,6 +72,7 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): ...@@ -69,6 +72,7 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
self.value_dict = {i: i.initial_value() for i in self.attr_list()} self.value_dict = {i: i.initial_value() for i in self.attr_list()}
@log_exceptions()
def init_device(self): def init_device(self):
""" Instantiates the device in the OFF state. """ """ Instantiates the device in the OFF state. """
...@@ -77,6 +81,19 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): ...@@ -77,6 +81,19 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
self.set_state(DevState.OFF) self.set_state(DevState.OFF)
@log_exceptions()
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).
"""
logger.info("Shutting down...")
self.Off()
logger.info("Shut down. Good bye.")
# -------- # --------
# Commands # Commands
# -------- # --------
...@@ -183,18 +200,6 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): ...@@ -183,18 +200,6 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
"""Method always executed before any TANGO command is executed.""" """Method always executed before any TANGO command is executed."""
pass 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.")
@command() @command()
@only_in_states([DevState.STANDBY, DevState.ON]) @only_in_states([DevState.STANDBY, DevState.ON])
@DebugIt() @DebugIt()
...@@ -204,6 +209,11 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): ...@@ -204,6 +209,11 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
A hardware point XXX is set to the value of the object member named XXX_default, if it exists. A hardware point XXX is set to the value of the object member named XXX_default, if it exists.
XXX_default can be f.e. a constant, or a device_property. XXX_default can be f.e. a constant, or a device_property.
The points are set in the following order:
1) The python class property 'first_default_settings' is read, as an array of strings denoting property names. Each property
is set in that order.
2) Any remaining default properties are set.
""" """
# we cannot write directly to our attribute, as that would not # we cannot write directly to our attribute, as that would not
...@@ -212,11 +222,18 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): ...@@ -212,11 +222,18 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
# obtain a proxy to myself, to write values # obtain a proxy to myself, to write values
proxy = DeviceProxy(self.get_name()) proxy = DeviceProxy(self.get_name())
# for all my members # collect all attributes for which defaults are provided
for name in dir(self): attributes_with_defaults = [name for name in dir(self)
attr = getattr(self, name) # collect all attribute members
# check if it's an attribute, and there is a default value available if isinstance(getattr(self, name), Attribute)
if isinstance(attr, Attribute) and hasattr(self, f"{name}_default"): # with a default set
and hasattr(self, f"{name}_default")]
# determine the order: first do the ones mentioned in default_settings_order
attributes_to_set = self.first_default_settings + [name for name in attributes_with_defaults if name not in self.first_default_settings]
# set them all
for name in attributes_to_set:
try: try:
default_value = getattr(self, f"{name}_default") default_value = getattr(self, f"{name}_default")
......
# -*- coding: utf-8 -*-
#
# This file represents a top-level device
#
#
#
# Distributed under the terms of the APACHE license.
# See LICENSE.txt for more info.
""" Generic OPC-UA 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)
sys.path.append(parentdir)
# PyTango imports
from tango import DebugIt
from tango.server import device_property, attribute
from tango import AttrWriteType
import numpy
# Additional import
from devices.device_decorators import *
from clients.opcua_client import OPCUAConnection
from devices.hardware_device import hardware_device
from common.lofar_logging import device_logging_to_python, log_exceptions
from common.lofar_git import get_version
__all__ = ["opcua_device", "main"]
class opcua_device(hardware_device):
"""
**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
)
OPC_namespace = device_property(
dtype='DevString',
mandatory=False,
default_value="http://lofar.eu"
)
# ----------
# Attributes
# ----------
opcua_missing_attributes_R = attribute(max_dim_x=128, dtype=(str,), fget=lambda self: numpy.array(self.opcua_missing_attributes, dtype=str), doc="OPC-UA attributes that this device requested, but which are not exposed on the server. These attributes are replaced with a no-op and thus do not function as expected.")
# --------
# overloaded functions
# --------
@log_exceptions()
def configure_for_initialise(self):
""" user code here. is called when the state is set to INIT """
# set up the OPC ua client
self.opcua_connection = OPCUAConnection("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_namespace, self.OPC_Time_Out, self.Fault, self)
self.opcua_missing_attributes = []
# map an access helper class
for i in self.attr_list():
try:
if not i.comms_id or i.comms_id == OPCUAConnection:
i.set_comm_client(self.opcua_connection)
except Exception as e:
# use the pass function instead of setting read/write fails
i.set_pass_func()
self.opcua_missing_attributes.append(",".join(i.comms_annotation))
self.warn_stream("error while setting the attribute {} read/write function. {}".format(i, e))
self.opcua_connection.start()
@log_exceptions()
def configure_for_off(self):
""" user code here. is called when the state is set to OFF """
try:
# disconnect
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))
...@@ -27,51 +27,36 @@ import numpy ...@@ -27,51 +27,36 @@ import numpy
from device_decorators import * from device_decorators import *
from clients.opcua_client import OPCUAConnection
from clients.attribute_wrapper import attribute_wrapper from clients.attribute_wrapper import attribute_wrapper
from devices.hardware_device import hardware_device from devices.opcua_device import opcua_device
from common.lofar_logging import device_logging_to_python, log_exceptions from common.lofar_logging import device_logging_to_python, log_exceptions
from common.lofar_git import get_version from common.lofar_git import get_version
__all__ = ["RECV", "main"] __all__ = ["RECV", "main"]
@device_logging_to_python() @device_logging_to_python()
class RECV(hardware_device): class RECV(opcua_device):
"""
**Properties:**
- Device Property
OPC_Server_Name
- Type:'DevString'
OPC_Server_Port
- Type:'DevULong'
OPC_Time_Out
- Type:'DevDouble'
"""
# ----------------- # -----------------
# Device Properties # Device Properties
# ----------------- # -----------------
OPC_Server_Name = device_property( Ant_mask_RW_default = device_property(
dtype='DevString', dtype='DevVarBooleanArray',
mandatory=True mandatory=False,
default_value=[[True] * 3] * 32
) )
OPC_Server_Port = device_property( RCU_mask_RW_default = device_property(
dtype='DevULong', dtype='DevVarBooleanArray',
mandatory=True mandatory=False,
default_value=[True] * 32
) )
OPC_Time_Out = device_property( first_default_settings = [
dtype='DevDouble', # set the masks first, as those filter any subsequent settings
mandatory=True 'Ant_mask_RW',
) 'RCU_mask_RW'
OPC_namespace = device_property( ]
dtype='DevString',
mandatory=False
)
# ---------- # ----------
# Attributes # Attributes
...@@ -112,50 +97,9 @@ class RECV(hardware_device): ...@@ -112,50 +97,9 @@ class RECV(hardware_device):
RCU_translator_busy_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_translator_busy_R"], datatype=numpy.bool_) RCU_translator_busy_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_translator_busy_R"], datatype=numpy.bool_)
RCU_version_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_version_R"], datatype=numpy.str, dims=(32,)) RCU_version_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_version_R"], datatype=numpy.str, dims=(32,))
@log_exceptions()
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 # overloaded functions
# -------- # --------
@log_exceptions()
def configure_for_off(self):
""" 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()
def configure_for_initialise(self):
""" user code here. is called when the state is set to INIT """
# 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)
# map an access helper class
for i in self.attr_list():
try:
i.set_comm_client(self.OPCua_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 RECV attribute {} read/write function. {}".format(i, e))
self.OPCua_client.start()
# -------- # --------
# Commands # Commands
...@@ -168,7 +112,7 @@ class RECV(hardware_device): ...@@ -168,7 +112,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:RCU_off"]) self.opcua_connection.call_method(["2:PCC","2:RCU_off"])
@command() @command()
@DebugIt() @DebugIt()
...@@ -178,7 +122,7 @@ class RECV(hardware_device): ...@@ -178,7 +122,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:RCU_on"]) self.opcua_connection.call_method(["2:PCC","2:RCU_on"])
@command() @command()
@DebugIt() @DebugIt()
...@@ -188,7 +132,7 @@ class RECV(hardware_device): ...@@ -188,7 +132,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:ADC_on"]) self.opcua_connection.call_method(["2:PCC","2:ADC_on"])
@command() @command()
@DebugIt() @DebugIt()
...@@ -198,7 +142,7 @@ class RECV(hardware_device): ...@@ -198,7 +142,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:RCU_update"]) self.opcua_connection.call_method(["2:PCC","2:RCU_update"])
@command() @command()
@DebugIt() @DebugIt()
...@@ -208,7 +152,7 @@ class RECV(hardware_device): ...@@ -208,7 +152,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:CLK_off"]) self.opcua_connection.call_method(["2:PCC","2:CLK_off"])
@command() @command()
@DebugIt() @DebugIt()
...@@ -218,7 +162,7 @@ class RECV(hardware_device): ...@@ -218,7 +162,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:CLK_on"]) self.opcua_connection.call_method(["2:PCC","2:CLK_on"])
@command() @command()
@DebugIt() @DebugIt()
...@@ -228,7 +172,7 @@ class RECV(hardware_device): ...@@ -228,7 +172,7 @@ class RECV(hardware_device):
:return:None :return:None
""" """
self.OPCua_client.call_method(["2:PCC","2:CLK_PLL_setup"]) self.opcua_connection.call_method(["2:PCC","2:CLK_PLL_setup"])
def _initialise_hardware(self): def _initialise_hardware(self):
""" Initialise the RCU hardware. """ """ Initialise the RCU hardware. """
......
...@@ -24,9 +24,8 @@ from tango.server import device_property, attribute ...@@ -24,9 +24,8 @@ from tango.server import device_property, attribute
from tango import AttrWriteType from tango import AttrWriteType
# Additional import # Additional import
from clients.opcua_client import OPCUAConnection
from clients.attribute_wrapper import attribute_wrapper from clients.attribute_wrapper import attribute_wrapper
from devices.hardware_device import hardware_device from devices.opcua_device import opcua_device
from common.lofar_logging import device_logging_to_python, log_exceptions from common.lofar_logging import device_logging_to_python, log_exceptions
from common.lofar_git import get_version from common.lofar_git import get_version
...@@ -36,37 +35,15 @@ import numpy ...@@ -36,37 +35,15 @@ import numpy
__all__ = ["SDP", "main"] __all__ = ["SDP", "main"]
@device_logging_to_python() @device_logging_to_python()
class SDP(hardware_device): class SDP(opcua_device):
"""
**Properties:**
- Device Property
OPC_Server_Name
- Type:'DevString'
OPC_Server_Port
- Type:'DevULong'
OPC_Time_Out
- Type:'DevDouble'
"""
# ----------------- # -----------------
# Device Properties # Device Properties
# ----------------- # -----------------
OPC_Server_Name = device_property( TR_fpga_mask_RW_default = device_property(
dtype='DevString', dtype='DevVarBooleanArray',
mandatory=True mandatory=False,
) default_value=[True] * 16
OPC_Server_Port = device_property(
dtype='DevULong',
mandatory=True
)
OPC_Time_Out = device_property(
dtype='DevDouble',
mandatory=True
) )
FPGA_processing_enable_RW_default = device_property( FPGA_processing_enable_RW_default = device_property(
...@@ -92,6 +69,11 @@ class SDP(hardware_device): ...@@ -92,6 +69,11 @@ class SDP(hardware_device):
default_value=[[8192] * 12 * 512] * 16 default_value=[[8192] * 12 * 512] * 16
) )
first_default_settings = [
# set the masks first, as those filter any subsequent settings
'TR_fpga_mask_RW'
]
# ---------- # ----------
# Attributes # Attributes
# ---------- # ----------
...@@ -151,55 +133,9 @@ class SDP(hardware_device): ...@@ -151,55 +133,9 @@ class SDP(hardware_device):
TR_tod_R = attribute_wrapper(comms_annotation=["2:TR_tod_R"], datatype=numpy.int64, dims=(2,)) TR_tod_R = attribute_wrapper(comms_annotation=["2:TR_tod_R"], datatype=numpy.int64, dims=(2,))
TR_tod_pps_delta_R = attribute_wrapper(comms_annotation=["2:TR_tod_pps_delta_R"], datatype=numpy.double) TR_tod_pps_delta_R = attribute_wrapper(comms_annotation=["2:TR_tod_pps_delta_R"], datatype=numpy.double)
def always_executed_hook(self):
"""Method always executed before any TANGO command is executed."""
pass
@log_exceptions()
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 # overloaded functions
# -------- # --------
@log_exceptions()
def configure_for_off(self):
""" user code here. is called when the state is set to OFF """
# Stop keep-alive
try:
self.OPCua_client.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()
def configure_for_initialise(self):
""" user code here. is called when the sate is set to INIT """
"""Initialises the attributes and properties of the SDP."""
# 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)
# map an access helper class
for i in self.attr_list():
try:
i.set_comm_client(self.OPCua_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 SDP attribute {} read/write function. {}".format(i, e))
pass
self.OPCua_client.start()
# -------- # --------
# Commands # Commands
......
...@@ -57,12 +57,29 @@ class SST(Statistics): ...@@ -57,12 +57,29 @@ class SST(Statistics):
mandatory=True mandatory=True
) )
FPGA_sst_offload_enable_RW_default = device_property(
dtype='DevVarBooleanArray',
mandatory=False,
default_value=[True] * 16
)
FPGA_sst_offload_weighted_subbands_RW_default = device_property( FPGA_sst_offload_weighted_subbands_RW_default = device_property(
dtype='DevVarBooleanArray', dtype='DevVarBooleanArray',
mandatory=False, mandatory=False,
default_value=[True] * 16 default_value=[True] * 16
) )
first_default_settings = [
'FPGA_sst_offload_hdr_eth_destination_mac_RW',
'FPGA_sst_offload_hdr_ip_destination_address_RW',
'FPGA_sst_offload_hdr_udp_destination_port_RW',
'FPGA_sst_offload_weighted_subbands_RW',
# enable only after the offloading is configured correctly
'FPGA_sst_offload_enable_RW'
]
# ---------- # ----------
# Attributes # Attributes
# ---------- # ----------
......
...@@ -29,7 +29,7 @@ from clients.statistics_client import StatisticsClient ...@@ -29,7 +29,7 @@ from clients.statistics_client import StatisticsClient
from clients.opcua_client import OPCUAConnection from clients.opcua_client import OPCUAConnection
from clients.attribute_wrapper import attribute_wrapper from clients.attribute_wrapper import attribute_wrapper
from devices.hardware_device import hardware_device from devices.opcua_device import opcua_device
from common.lofar_git import get_version from common.lofar_git import get_version
from common.lofar_logging import device_logging_to_python, log_exceptions from common.lofar_logging import device_logging_to_python, log_exceptions
...@@ -41,7 +41,7 @@ import numpy ...@@ -41,7 +41,7 @@ import numpy
__all__ = ["Statistics"] __all__ = ["Statistics"]
class Statistics(hardware_device, metaclass=ABCMeta): class Statistics(opcua_device, metaclass=ABCMeta):
# In derived classes, set this to a subclass of StatisticsCollector # In derived classes, set this to a subclass of StatisticsCollector
@property @property
...@@ -53,21 +53,6 @@ class Statistics(hardware_device, metaclass=ABCMeta): ...@@ -53,21 +53,6 @@ class Statistics(hardware_device, metaclass=ABCMeta):
# Device Properties # 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
)
Statistics_Client_UDP_Port = device_property( Statistics_Client_UDP_Port = device_property(
dtype='DevUShort', dtype='DevUShort',
mandatory=True mandatory=True
...@@ -124,16 +109,15 @@ class Statistics(hardware_device, metaclass=ABCMeta): ...@@ -124,16 +109,15 @@ class Statistics(hardware_device, metaclass=ABCMeta):
except Exception as e: except Exception as e:
logger.exception("Exception while stopping statistics_client in configure_for_off. Exception ignored") logger.exception("Exception while stopping statistics_client in configure_for_off. Exception ignored")
try: super().configure_for_off()
self.OPCUA_client.stop()
except Exception as e:
logger.exception("Exception while stopping OPC UA connection in configure_for_off. Exception ignored")
@log_exceptions() @log_exceptions()
def configure_for_initialise(self): def configure_for_initialise(self):
""" user code here. is called when the sate is set to INIT """ """ user code here. is called when the sate is set to INIT """
"""Initialises the attributes and properties of the statistics device.""" """Initialises the attributes and properties of the statistics device."""
super().configure_for_initialise()
# Options for UDPReceiver # Options for UDPReceiver
udp_options = { udp_options = {
"udp_port": self.Statistics_Client_UDP_Port, "udp_port": self.Statistics_Client_UDP_Port,
...@@ -148,27 +132,12 @@ class Statistics(hardware_device, metaclass=ABCMeta): ...@@ -148,27 +132,12 @@ class Statistics(hardware_device, metaclass=ABCMeta):
self.statistics_collector = self.STATISTICS_COLLECTOR_CLASS() self.statistics_collector = self.STATISTICS_COLLECTOR_CLASS()
self.statistics_client = StatisticsClient(self.statistics_collector, udp_options, tcp_options, self.Fault, self) self.statistics_client = StatisticsClient(self.statistics_collector, udp_options, tcp_options, self.Fault, self)
self.statistics_client.start()
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) # tie attributes to client
# map an access helper class
for i in self.attr_list(): for i in self.attr_list():
try:
if i.comms_id == StatisticsClient: if i.comms_id == StatisticsClient:
i.set_comm_client(self.statistics_client) i.set_comm_client(self.statistics_client)
elif i.comms_id == OPCUAConnection:
i.set_comm_client(self.OPCUA_client)
else:
raise ValueError("Cannot set comm client for attribute {}: Unknown comms_id {}".format(i, i.comms_id))
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.statistics_client.start()
self.OPCUA_client.start()
# -------- # --------
# Commands # Commands
......
...@@ -75,6 +75,23 @@ class XST(Statistics): ...@@ -75,6 +75,23 @@ class XST(Statistics):
default_value=[[0,102,0,0,0,0,0,0]] * 16 default_value=[[0,102,0,0,0,0,0,0]] * 16
) )
FPGA_xst_offload_enable_RW_default = device_property(
dtype='DevVarBooleanArray',
mandatory=False,
default_value=[True] * 16
)
first_default_settings = [
'FPGA_xst_offload_hdr_eth_destination_mac_RW',
'FPGA_xst_offload_hdr_ip_destination_address_RW',
'FPGA_xst_offload_hdr_udp_destination_port_RW',
'FPGA_xst_subband_select_RW',
# enable only after the offloading is configured correctly
'FPGA_xst_offload_enable_RW'
]
# ---------- # ----------
# Attributes # Attributes
# ---------- # ----------
......
...@@ -23,9 +23,8 @@ from tango.server import device_property, attribute ...@@ -23,9 +23,8 @@ from tango.server import device_property, attribute
from tango import AttrWriteType from tango import AttrWriteType
# Additional import # Additional import
from clients.opcua_client import OPCUAConnection
from clients.attribute_wrapper import attribute_wrapper from clients.attribute_wrapper import attribute_wrapper
from devices.hardware_device import hardware_device from devices.opcua_device import opcua_device
from common.lofar_logging import device_logging_to_python, log_exceptions from common.lofar_logging import device_logging_to_python, log_exceptions
from common.lofar_git import get_version from common.lofar_git import get_version
...@@ -35,39 +34,11 @@ import numpy ...@@ -35,39 +34,11 @@ import numpy
__all__ = ["UNB2", "main"] __all__ = ["UNB2", "main"]
@device_logging_to_python() @device_logging_to_python()
class UNB2(hardware_device): class UNB2(opcua_device):
"""
**Properties:**
- Device Property
OPC_Server_Name
- Type:'DevString'
OPC_Server_Port
- Type:'DevULong'
OPC_Time_Out
- Type:'DevDouble'
"""
# ----------------- # -----------------
# Device Properties # 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 # Attributes
# ---------- # ----------
...@@ -167,49 +138,10 @@ class UNB2(hardware_device): ...@@ -167,49 +138,10 @@ class UNB2(hardware_device):
# QualifiedName(2: UNB2_on) # QualifiedName(2: UNB2_on)
# QualifiedName(2: UNB2_off) # QualifiedName(2: UNB2_off)
@log_exceptions()
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 # overloaded functions
# -------- # --------
@log_exceptions()
def configure_for_off(self):
""" 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()
def configure_for_initialise(self):
""" user code here. is called when the sate is set to INIT """
"""Initialises the attributes and properties of theRECV."""
# 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)
# map an access helper class
for i in self.attr_list():
try:
i.set_comm_client(self.OPCua_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 UNB2 attribute {} read/write function. {}".format(i, e))
self.OPCua_client.start()
# -------- # --------
# Commands # Commands
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment