From b67a4678615c9f9ceb261df906206d4375f87bdd Mon Sep 17 00:00:00 2001
From: Jan David Mol <mol@astron.nl>
Date: Wed, 9 Feb 2022 12:59:27 +0100
Subject: [PATCH] L2SS-613 L2SS-614: Expose HBAT properties using attributes
 instead of commands (more 'tangoic'), and avoid connecting to ltspi in the
 unit test

---
 CDB/stations/dummy_positions_ConfigDb.json    | 130 ++++++++++++++++++
 sbin/run_integration_test.sh                  |   1 +
 .../tangostationcontrol/devices/beam.py       |   8 +-
 .../tangostationcontrol/devices/recv.py       |  47 ++-----
 .../test/devices/test_recv_device.py          |  38 +----
 5 files changed, 149 insertions(+), 75 deletions(-)
 create mode 100644 CDB/stations/dummy_positions_ConfigDb.json

diff --git a/CDB/stations/dummy_positions_ConfigDb.json b/CDB/stations/dummy_positions_ConfigDb.json
new file mode 100644
index 000000000..5f998a810
--- /dev/null
+++ b/CDB/stations/dummy_positions_ConfigDb.json
@@ -0,0 +1,130 @@
+{
+    "servers": {
+        "RECV": {
+            "STAT": {
+                "RECV": {
+                    "STAT/RECV/1": {
+                        "properties": {
+                            "HBAT_reference_itrf": [
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786",
+                               "3826577.066", "461022.948", "5064892.786"
+                            ],
+                            "HBAT_antenna_itrf_offsets": [
+                               "-1.847", "-1.180", " 1.493",
+                               "-1.581", " 0.003", " 1.186",
+                               "-1.315", " 1.185", " 0.880",
+                               "-1.049", " 2.367", " 0.573",
+                               "-0.882", "-1.575", " 0.804",
+                               "-0.616", "-0.393", " 0.498",
+                               "-0.350", " 0.789", " 0.191",
+                               "-0.083", " 1.971", "-0.116",
+                               " 0.083", "-1.971", " 0.116",
+                               " 0.350", "-0.789", "-0.191",
+                               " 0.616", " 0.393", "-0.498",
+                               " 0.882", " 1.575", "-0.804",
+                               " 1.049", "-2.367", "-0.573",
+                               " 1.315", "-1.185", "-0.880",
+                               " 1.581", "-0.003", "-1.186",
+                               " 1.847", " 1.180", "-1.493"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh
index d2dbf03ec..7375bce8a 100755
--- a/sbin/run_integration_test.sh
+++ b/sbin/run_integration_test.sh
@@ -29,6 +29,7 @@ sleep 60
 # Do not remove `bash`, otherwise statement ignored by gitlab ci shell!
 bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/LOFAR_ConfigDb.json
 bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/stations/simulators_ConfigDb.json
+bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/stations/dummy_positions_ConfigDb.json
 #bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/integration_ConfigDb.json
 
 cd "$LOFAR20_DIR/docker-compose" || exit 1
diff --git a/tangostationcontrol/tangostationcontrol/devices/beam.py b/tangostationcontrol/tangostationcontrol/devices/beam.py
index b44759142..6114e3823 100644
--- a/tangostationcontrol/tangostationcontrol/devices/beam.py
+++ b/tangostationcontrol/tangostationcontrol/devices/beam.py
@@ -66,10 +66,8 @@ class Beam(lofar_device):
         self.recv_proxy = DeviceProxy("STAT/RECV/1")
 
         # Retrieve positions from RECV device
-        self.HBAT_reference_itrf = self.recv_proxy.get_hbat_reference_itrf().reshape(96,3)
-        self.HBAT_antenna_itrf = self.recv_proxy.get_hbat_antenna_itrf().reshape(96,16,3)
-        # Retrieve signal delays from RECV device
-        self.HBAT_signal_input_delays = self.recv_proxy.get_hbat_signal_input_delays().reshape(96,32)
+        self.HBAT_reference_itrf = self.recv_proxy.HBAT_reference_itrf_R
+        self.HBAT_antenna_itrf_offsets = self.recv_proxy.HBAT_antenna_itrf_offsets_R
 
     # --------
     # internal functions
@@ -89,7 +87,7 @@ class Beam(lofar_device):
             d.set_measure_time(timestamp)
 
             # calculate the delays based on the set reference position, the set time and now the set direction and antenna positions
-            delays[tile] = d.convert(pointing_direction[tile], self.HBAT_antenna_itrf[tile])    
+            delays[tile] = d.convert(pointing_direction[tile], self.HBAT_antenna_itrf_offsets + self.HBAT_reference_itrf[tile])
 
         return delays
 
diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py
index f1497362e..22f2f8483 100644
--- a/tangostationcontrol/tangostationcontrol/devices/recv.py
+++ b/tangostationcontrol/tangostationcontrol/devices/recv.py
@@ -63,16 +63,14 @@ class RECV(opcua_device):
         ],dtype=numpy.float64)
     )
     
-    HBAT_reference_itrf =  device_property(
+    HBAT_reference_itrf = device_property(
         dtype='DevVarFloatArray',
-        mandatory=False,
-        default_value = numpy.tile(numpy.array([3826577.066, 461022.948, 5064892.786]),(96,1)) # CS002LBA, in ITRF2005 timestamp 2012.5
+        mandatory=False
     )
 
-    HBAT_antenna_itrf = device_property(
+    HBAT_antenna_itrf_offsets = device_property(
         dtype='DevVarFloatArray',
-        mandatory=False,
-        default_value = numpy.tile(numpy.array([3826923.546, 460915.441, 5064643.489]),(96,16,1)) # CS001LBA, in ITRF2005 timestamp 2012.5
+        mandatory=False
     )
 
     HBAT_signal_input_delays = device_property(
@@ -149,6 +147,14 @@ class RECV(opcua_device):
     RECVTR_monitor_rate_RW       = attribute_wrapper(comms_annotation=["RECVTR_monitor_rate_RW"    ],datatype=numpy.int64  , access=AttrWriteType.READ_WRITE)
     RECVTR_translator_busy_R     = attribute_wrapper(comms_annotation=["RECVTR_translator_busy_R"  ],datatype=numpy.bool_  )
 
+    HBAT_antenna_itrf_offsets_R = attribute(access=AttrWriteType.READ,
+        dtype=((numpy.float,),), max_dim_x=3, max_dim_y=16,
+        fget=lambda self: numpy.array(self.HBAT_antenna_itrf_offsets).reshape(16,3))
+
+    HBAT_reference_itrf_R = attribute(access=AttrWriteType.READ,
+        dtype=((numpy.float,),), max_dim_x=3, max_dim_y=96,
+        fget=lambda self: numpy.array(self.HBAT_reference_itrf).reshape(96,3))
+
     # --------
     # overloaded functions
     # --------
@@ -180,37 +186,8 @@ class RECV(opcua_device):
     # --------
     # Commands
     # --------
-    @command(dtype_out=DevVarFloatArray)
-    @DebugIt()
-    @only_in_states([DevState.ON])
-    def get_hbat_bf_delay_step_delays(self):
-        """ Return the property HBAT_bf_delay_step_delays """
-        return self.HBAT_bf_delay_step_delays
-    
-    @command(dtype_out=DevVarFloatArray)
-    @DebugIt()
-    @only_in_states([DevState.ON])
-    def get_hbat_reference_itrf(self):
-        """ Return the property HBAT_reference_itrf (96x3) into a flatten array """
-        return self.HBAT_reference_itrf.flatten()
-    
-    @command(dtype_out=DevVarFloatArray)
-    @DebugIt()
-    @only_in_states([DevState.ON])
-    def get_hbat_antenna_itrf(self):
-        """ Return the property HBAT_antenna_itrf (96x16x3) into a flatten array """
-        return self.HBAT_antenna_itrf.flatten()
-    
-    @command(dtype_out=DevVarFloatArray)
-    @DebugIt()
-    @only_in_states([DevState.ON])
-    def get_hbat_signal_input_delays(self):
-        """ Return the property HBAT_signal_input_delays (96x32) into a flatten array """
-        return self.HBAT_signal_input_delays.flatten()
     
     @command(dtype_in=DevVarFloatArray, dtype_out=DevVarFloatArray)
-    @DebugIt()
-    @only_in_states([DevState.ON])
     def calculate_HBAT_bf_delay_steps(self, delays: numpy.ndarray):
         """ converts a signal path delay (in seconds) to an analog beam weight """
         
diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py
index 80571bd10..1fde8856c 100644
--- a/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py
+++ b/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py
@@ -8,7 +8,6 @@
 # See LICENSE.txt for more info.
 
 from tango.test_context import DeviceTestContext
-from tango import DeviceProxy, DevState
 
 from tangostationcontrol.devices import recv, lofar_device
 
@@ -19,7 +18,8 @@ from tangostationcontrol.test import base
 
 class TestRecvDevice(base.TestCase):
 
-    recv_properties = {'OPC_Server_Name': 'ltspi.astron.nl', 'OPC_Server_Port': 4840, 'OPC_Time_Out': 5.0}
+    # some dummy values for mandatory properties
+    recv_properties = {'OPC_Server_Name': 'example.com', 'OPC_Server_Port': 4840, 'OPC_Time_Out': 5.0}
 
     def setUp(self):
         super(TestRecvDevice, self).setUp()     
@@ -32,42 +32,10 @@ class TestRecvDevice(base.TestCase):
             proxy_patcher.start()
             self.addCleanup(proxy_patcher.stop)
     
-    def init_device(self, proxy:DeviceProxy):
-        proxy.off()
-        proxy.initialise()
-        self.assertEqual(DevState.STANDBY, proxy.state())
-        proxy.set_defaults()
-        proxy.on()
-        self.assertEqual(DevState.ON, proxy.state())
-
-    def test_get_hbat_bf_delay_step_delays(self):
-        """Verify can read delay step attribute and length matches without err"""
-        with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True, timeout=10) as proxy:
-            self.init_device(proxy)
-            self.assertEqual(32, len(proxy.get_hbat_bf_delay_step_delays()))
-
-    def test_get_hbat_reference_itrf(self):
-        """Verify can read hbat reference itrf attribute and length matches without err"""
-        with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True, timeout=10) as proxy:
-            self.init_device(proxy)
-            self.assertEqual(288, len(proxy.get_hbat_reference_itrf()))     # 96x3=288
-    
-    def test_get_hbat_antenna_itrf(self):
-        """Verify can read hbat antenna itrf attribute and length matches without err"""
-        with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True, timeout=10) as proxy:
-            self.init_device(proxy)
-            self.assertEqual(4608, len(proxy.get_hbat_antenna_itrf()))     # 96x16X3=4608
-
-    def test_get_hbat_signal_input_delays(self):
-        """Verify can read signal input delay attribute and length matches without err"""
-        with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True, timeout=10) as proxy:
-            self.init_device(proxy)
-            self.assertEqual(3072, len(proxy.get_hbat_signal_input_delays()))     # 96x32=3072
     
     def test_calculate_HBAT_bf_delay_steps(self):
         """Verify HBAT beamforming calculations are correctly executed"""
-        with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True, timeout=10) as proxy:
-            self.init_device(proxy)
+        with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True) as proxy:
             delays = numpy.random.rand(96,16).flatten()
             HBAT_bf_delay_steps = proxy.calculate_HBAT_bf_delay_steps(delays)
             self.assertEqual(3072, len(HBAT_bf_delay_steps))                             # 96x32=3072
-- 
GitLab