From 40a8a72d3dfd7aa7e1ee8f2b256883e6ef690483 Mon Sep 17 00:00:00 2001
From: Jan David Mol <mol@astron.nl>
Date: Tue, 2 Nov 2021 17:25:55 +0100
Subject: [PATCH] L2SS-470: Enable initialise_hardware sequences, allow
 attributes to be read and written in STANDBY states, and fix some error
 messages.

---
 .../tangostationcontrol/clients/attribute_wrapper.py   | 10 +++++-----
 .../tangostationcontrol/devices/apsct.py               |  9 ++-------
 .../tangostationcontrol/devices/device_decorators.py   |  6 ++++--
 .../tangostationcontrol/devices/opcua_device.py        |  2 +-
 .../tangostationcontrol/devices/recv.py                |  5 -----
 5 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py
index 718ea431d..4dd071326 100644
--- a/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py
+++ b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py
@@ -1,8 +1,8 @@
 from tango.server import attribute
-from tango import AttrWriteType
+from tango import AttrWriteType, DevState
 import numpy
 
-from tangostationcontrol.devices.device_decorators import only_when_on, fault_on_error
+from tangostationcontrol.devices.device_decorators import only_in_states, fault_on_error
 import logging
 
 logger = logging.getLogger()
@@ -72,7 +72,7 @@ class attribute_wrapper(attribute):
         if access == AttrWriteType.READ_WRITE:
             """ if the attribute is of READ_WRITE type, assign the RW and write function to it"""
 
-            @only_when_on()
+            @only_in_states([DevState.STANDBY, DevState.ON], log=False)
             @fault_on_error()
             def read_RW(device):
                 # print("read_RW {}, {}x{}, {}, {}".format(me.name, me.dim_x, me.dim_y, me.attr_type, me.value))
@@ -85,7 +85,7 @@ class attribute_wrapper(attribute):
                     raise Exception("Attribute read_RW function error, attempted to read value_dict with key: `%s`, are you sure this exists?",
                                     self) from e
 
-            @only_when_on()
+            @only_in_states([DevState.STANDBY, DevState.ON], log=False)
             @fault_on_error()
             def write_RW(device, value):
                 """
@@ -102,7 +102,7 @@ class attribute_wrapper(attribute):
         else:
             """ if the attribute is of READ type, assign the read function to it"""
 
-            @only_when_on()
+            @only_in_states([DevState.STANDBY, DevState.ON], log=False)
             @fault_on_error()
             def read_R(device):
                 """
diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py
index add4e146c..90a8be0d5 100644
--- a/tangostationcontrol/tangostationcontrol/devices/apsct.py
+++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py
@@ -73,19 +73,14 @@ class APSCT(opcua_device):
     def _initialise_hardware(self):
         """ Initialise the APSCT hardware. """
 
-        # method calls don't work yet, so don't use them to allow the boot
-        # device to initialise us without errors
-        logger.error("OPC-UA methods not supported yet, not initialising APSCT hardware!")
-        return
-
         # Cycle clock
         self.CLK_off()
         self.wait_attribute("APSCTTR_translator_busy_R", False, 10)
         self.CLK_on()
         self.wait_attribute("APSCTTR_translator_busy_R", False, 10)
 
-        if not self.APSCT_PLL_200MHz_locked_R:
-            if self.APSCT_I2C_error_R:
+        if not self.proxy.APSCT_PLL_200MHz_locked_R:
+            if self.proxy.APSCT_I2C_error_R:
                 raise Exception("I2C is not working. Maybe power cycle subrack to restart CLK board and translator?")
             else:
                 raise Exception("200MHz signal is not locked. The subrack probably do not receive clock input or the CLK PCB is broken?")
diff --git a/tangostationcontrol/tangostationcontrol/devices/device_decorators.py b/tangostationcontrol/tangostationcontrol/devices/device_decorators.py
index b3f203bff..bb04cdbca 100644
--- a/tangostationcontrol/tangostationcontrol/devices/device_decorators.py
+++ b/tangostationcontrol/tangostationcontrol/devices/device_decorators.py
@@ -7,7 +7,7 @@ logger = logging.getLogger()
 
 __all__ = ["only_in_states", "only_when_on", "fault_on_error"]
 
-def only_in_states(allowed_states):
+def only_in_states(allowed_states, log=True):
     """
       Wrapper to call and return the wrapped function if the device is
       in one of the given states. Otherwise a PyTango exception is thrown.
@@ -18,7 +18,9 @@ def only_in_states(allowed_states):
             if self.get_state() in allowed_states:
                 return func(self, *args, **kwargs)
 
-            logger.warning("Illegal command: Function %s can only be called in states %s. Current state: %s" % (func.__name__, allowed_states, self.get_state()))
+            if log:
+                logger.warning("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
diff --git a/tangostationcontrol/tangostationcontrol/devices/opcua_device.py b/tangostationcontrol/tangostationcontrol/devices/opcua_device.py
index 9f8465335..d3668cfae 100644
--- a/tangostationcontrol/tangostationcontrol/devices/opcua_device.py
+++ b/tangostationcontrol/tangostationcontrol/devices/opcua_device.py
@@ -119,7 +119,7 @@ class opcua_device(lofar_device):
                 i.set_pass_func()
                 self.opcua_missing_attributes.append(",".join(self.opcua_connection.get_node_path(i.comms_annotation)))
 
-                logger.warning("error while setting the attribute {} read/write function. {}".format(i, e))
+                logger.warning(f"Error while setting the attribute {i.comms_annotation} read/write function.", exc_info=True)
 
     @log_exceptions()
     def configure_for_off(self):
diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py
index 4ac93d85a..c713690b7 100644
--- a/tangostationcontrol/tangostationcontrol/devices/recv.py
+++ b/tangostationcontrol/tangostationcontrol/devices/recv.py
@@ -151,11 +151,6 @@ class RECV(opcua_device):
     def _initialise_hardware(self):
         """ Initialise the RCU hardware. """
 
-        # method calls don't work yet, so don't use them to allow the boot
-        # device to initialise us without errors
-        logger.error("OPC-UA methods not supported yet, not initialising RCU hardware!")
-        return
-
         # Cycle RCUs
         self.RCU_off()
         self.wait_attribute("RECVTR_translator_busy_R", False, 5)
-- 
GitLab