diff --git a/CDB/LOFAR_ConfigDb.json b/CDB/LOFAR_ConfigDb.json index a0757924b736a04db12e3e908a52c51448eec754..c37b09b85fa52b9d77300611f68e888668396951 100644 --- a/CDB/LOFAR_ConfigDb.json +++ b/CDB/LOFAR_ConfigDb.json @@ -715,8 +715,17 @@ "SST": { "LTS/SST/1": { "properties": { - "SST_Port": [ + "SST_Client_Port": [ "5001" + ], + "OPC_Server_Name": [ + "dop36.astron.nl" + ], + "OPC_Server_Port": [ + "4840" + ], + "OPC_Time_Out": [ + "5.0" ] } } diff --git a/CDB/sdp-sim-config.json b/CDB/sdp-sim-config.json index 8953c5a45e5a27d9134b1fbe9d6d77d187b3694a..75fb9998cbc210bdfee04adf41e6c854bcf13358 100644 --- a/CDB/sdp-sim-config.json +++ b/CDB/sdp-sim-config.json @@ -18,6 +18,28 @@ } } } + }, + "SST": { + "LTS": { + "SST": { + "LTS/SST/1": { + "properties": { + "SST_Client_Port": [ + "5001" + ], + "OPC_Server_Name": [ + "sdptr-sim" + ], + "OPC_Server_Port": [ + "4840" + ], + "OPC_Time_Out": [ + "5.0" + ] + } + } + } + } } } } diff --git a/CDB/thijs_ConfigDb.json b/CDB/thijs_ConfigDb.json index 6716bd3bc17828abb1135d6d78f6750dd9949329..e60ce20eacdf24bad708009c12259bdcdf8d1cbd 100644 --- a/CDB/thijs_ConfigDb.json +++ b/CDB/thijs_ConfigDb.json @@ -94,8 +94,17 @@ "SST": { "LTS/SST/1": { "properties": { - "SST_Port": [ + "SST_Client_Port": [ "5001" + ], + "OPC_Server_Name": [ + "dop36.astron.nl" + ], + "OPC_Server_Port": [ + "4840" + ], + "OPC_Time_Out": [ + "5.0" ] } } diff --git a/CDB/thomas_ConfigDb.json b/CDB/thomas_ConfigDb.json index 0ebff3734b678d3446fc5d3ecbcb955e34ecb267..33c19e162b8e15001759de58dfca22a82c2dd249 100644 --- a/CDB/thomas_ConfigDb.json +++ b/CDB/thomas_ConfigDb.json @@ -25,6 +25,19 @@ } } } + }, + "SST": { + "LTS": { + "SST": { + "LTS/SST/1": { + "properties": { + "OPC_Server_Name": [ + "okeanos" + ] + } + } + } + } } } } diff --git a/CDB/thomas_arm64_ConfigDb.json b/CDB/thomas_arm64_ConfigDb.json index 89673f8f96e2bc49ce63823a3cbaae1e299294f9..4d010b690433d631ddadc7c14babbb31ec71c6ac 100644 --- a/CDB/thomas_arm64_ConfigDb.json +++ b/CDB/thomas_arm64_ConfigDb.json @@ -25,6 +25,19 @@ } } } + }, + "SST": { + "LTS": { + "SST": { + "LTS/SST/1": { + "properties": { + "OPC_Server_Name": [ + "okeanos" + ] + } + } + } + } } } } diff --git a/devices/devices/sdp/sdp.py b/devices/devices/sdp/sdp.py index 05b4fe3162eca33318c91855fcc61281f27e9882..24e22bf1e8ae8b2f3b5d38265f79dcfb451ebcd8 100644 --- a/devices/devices/sdp/sdp.py +++ b/devices/devices/sdp/sdp.py @@ -94,16 +94,6 @@ class SDP(hardware_device): 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_station_id_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_station_id_R"], datatype=numpy.uint32, dims=(16,)) FPGA_sdp_info_station_id_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_station_id_RW"], datatype=numpy.uint32, 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_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_enable_RW"], datatype=numpy.bool_, 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_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_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_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_udp_destination_port_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, 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_selector_R = attribute_wrapper(comms_annotation=["2:FPGA_sst_offload_selector_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_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,)) diff --git a/devices/devices/sdp/sst.py b/devices/devices/sdp/sst.py index d78841939d26c058e8c1d06a2b5157b95dd06784..3961362e916e044cfa833e9929856a0c25493a85 100644 --- a/devices/devices/sdp/sst.py +++ b/devices/devices/sdp/sst.py @@ -25,6 +25,7 @@ from tango import AttrWriteType # Additional import from clients.sst_client import sst_client, SST_collector +from clients.opcua_connection import OPCUAConnection from clients.attribute_wrapper import attribute_wrapper from devices.hardware_device import hardware_device @@ -43,7 +44,32 @@ class SST(hardware_device): # Device Properties # ----------------- - SST_Port = device_property( + 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 + ) + + SST_Client_Name = device_property( + dtype='DevString', + mandatory=True + ) + + SST_Client_MAC = device_property( + dtype='DevString', + mandatory=True + ) + + SST_Client_Port = device_property( dtype='DevUShort', mandatory=True ) @@ -54,34 +80,46 @@ class SST(hardware_device): version_R = attribute(dtype = str, access = AttrWriteType.READ, fget = lambda self: get_version()) + # FPGA control points for SSTs + FPGA_sst_offload_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, 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_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_enable_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_sst_offload_hdr_eth_destination_mac_RW = attribute_wrapper(comms_id=OPCUAConnection, 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_id=OPCUAConnection, 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_id=OPCUAConnection, 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_id=OPCUAConnection, 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_id=OPCUAConnection, 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_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) + FPGA_sst_offload_selector_RW = attribute_wrapper(comms_id=OPCUAConnection, 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_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_selector_R"], datatype=numpy.bool_, dims=(16,)) + # number of UDP packets that were received - nof_packets_received_R = attribute_wrapper(comms_annotation={"type": "udp", "parameter": "nof_packets_received"}, datatype=numpy.uint64) + nof_packets_received_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "udp", "parameter": "nof_packets_received"}, datatype=numpy.uint64) # number of UDP packets that were dropped because we couldn't keep up with processing - nof_packets_dropped_R = attribute_wrapper(comms_annotation={"type": "udp", "parameter": "nof_packets_dropped"}, datatype=numpy.uint64) + nof_packets_dropped_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "udp", "parameter": "nof_packets_dropped"}, datatype=numpy.uint64) # last packet we processed - last_packet_R = attribute_wrapper(comms_annotation={"type": "udp", "parameter": "last_packet"}, dims=(9000,), datatype=numpy.uint8) + last_packet_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "udp", "parameter": "last_packet"}, dims=(9000,), datatype=numpy.uint8) # when last packet was received - last_packet_timestamp_R = attribute_wrapper(comms_annotation={"type": "udp", "parameter": "last_packet_timestamp"}, datatype=numpy.uint64) + last_packet_timestamp_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "udp", "parameter": "last_packet_timestamp"}, datatype=numpy.uint64) # number of UDP packets that were processed - nof_packets_processed_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "nof_packets"}, datatype=numpy.uint64) + nof_packets_processed_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "nof_packets"}, datatype=numpy.uint64) # queue fill percentage, as reported by the consumer - queue_fill_percentage_R = attribute_wrapper(comms_annotation={"type": "queue", "parameter": "fill_percentage"}, datatype=numpy.uint64) + queue_fill_percentage_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "queue", "parameter": "fill_percentage"}, datatype=numpy.uint64) # number of invalid (non-SST) packets received - nof_invalid_packets_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "nof_invalid_packets"}, datatype=numpy.uint64) + nof_invalid_packets_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "nof_invalid_packets"}, datatype=numpy.uint64) # last packet that could not be parsed - last_invalid_packet_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "last_invalid_packet"}, dims=(9000,), datatype=numpy.uint8) + last_invalid_packet_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "last_invalid_packet"}, dims=(9000,), datatype=numpy.uint8) # number of packets with valid payloads - nof_valid_payloads_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "nof_valid_payloads"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.uint64) + nof_valid_payloads_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "nof_valid_payloads"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.uint64) # number of packets with invalid payloads - nof_payload_errors_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "nof_payload_errors"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.uint64) + nof_payload_errors_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "nof_payload_errors"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.uint64) # latest SSTs - sst_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "sst_values"}, dims=(SST_collector.MAX_SUBBANDS, SST_collector.MAX_INPUTS), datatype=numpy.uint64) + sst_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "sst_values"}, dims=(SST_collector.MAX_SUBBANDS, SST_collector.MAX_INPUTS), datatype=numpy.uint64) # reported timestamp for each row in the latest SSTs - sst_timestamp_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "sst_timestamps"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.uint64) + sst_timestamp_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "sst_timestamps"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.uint64) # integration interval for each row in the latest SSTs - integration_interval_R = attribute_wrapper(comms_annotation={"type": "sst", "parameter": "integration_intervals"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.float32) + integration_interval_R = attribute_wrapper(comms_id=sst_client, comms_annotation={"type": "sst", "parameter": "integration_intervals"}, dims=(SST_collector.MAX_INPUTS,), datatype=numpy.float32) # -------- # overloaded functions @@ -94,17 +132,27 @@ class SST(hardware_device): except Exception as e: self.warn_stream("Exception while stopping sst_client in configure_for_off function: {}. Exception ignored".format(e)) + 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 the statistics device.""" - self.sst_client = sst_client("0.0.0.0", self.SST_Port, self.Fault, self) + self.sst_client = sst_client("0.0.0.0", self.SST_Client_Port, self.Fault, self) + + 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.sst_client) + if i.comms_id == sst_client: + i.set_comm_client(self.sst_client) + if i.comms_id == OPCUAConnection: + 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() @@ -113,6 +161,8 @@ class SST(hardware_device): self.sst_client.start() + self.OPCua_client.start() + # -------- # Commands # --------