diff --git a/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter b/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter
index 6e48f0fddf5541bc66d9f57e31297c0027ea97b7..e313399d197d266e49d6da0442ea983c6f92adad 160000
--- a/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter
+++ b/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter
@@ -1 +1 @@
-Subproject commit 6e48f0fddf5541bc66d9f57e31297c0027ea97b7
+Subproject commit e313399d197d266e49d6da0442ea983c6f92adad
diff --git a/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py
index e9239a834a248af32886df651a5f2463b4764489..b8e829ede0b5857cc5cc6c4da5d6052118cf57b7 100644
--- a/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py
+++ b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py
@@ -72,7 +72,7 @@ class attribute_wrapper(attribute):
         if access == AttrWriteType.READ_WRITE:
             """ if the attribute is of READ_WRITE type, assign the write function to it"""
 
-            @only_in_states([DevState.STANDBY, DevState.ON], log=False)
+            @only_in_states([DevState.STANDBY, DevState.ON, DevState.ALARM], log=False)
             @fault_on_error()
             def write_func_wrapper(device, value):
                 """
@@ -86,7 +86,7 @@ class attribute_wrapper(attribute):
 
         """ Assign the read function to the attribute"""
 
-        @only_in_states([DevState.STANDBY, DevState.ON], log=False)
+        @only_in_states([DevState.STANDBY, DevState.ON, DevState.ALARM], log=False)
         @fault_on_error()
         def read_func_wrapper(device):
             """
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
index c0b6f7a98894b7c7d660828231935b63c5b0f5da..3b0f59d242c7d29ac707b7e7361d2e9dce706424 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
@@ -108,8 +108,8 @@ class XST(Statistics):
     FPGA_xst_subband_select_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_subband_select_RW"], datatype=numpy.uint32, dims=(8,16), access=AttrWriteType.READ_WRITE)
     FPGA_xst_subband_select_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_subband_select_R"], datatype=numpy.uint32, dims=(8,16))
 
-     FPGA_xst_offload_nof_crosslets_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_nof_crosslets_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE)
-     FPGA_xst_offload_nof_crosslets_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_nof_crosslets_R"], datatype=numpy.uint32, dims=(16,))
+    FPGA_xst_offload_nof_crosslets_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_nof_crosslets_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE)
+    FPGA_xst_offload_nof_crosslets_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_nof_crosslets_R"], datatype=numpy.uint32, dims=(16,))
 
     # number of packets with valid payloads
     nof_valid_payloads_R    = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "nof_valid_payloads"}, dims=(XSTCollector.MAX_FPGAS,), datatype=numpy.uint64)
diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py
index 8f3e7a25046764eeedaf9fa2380b2fdbe76b0b6b..d6aada7d5c051b7140537dede572337f70dbbc14 100644
--- a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py
+++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py
@@ -7,6 +7,7 @@ from tango import DeviceProxy, AttributeProxy, DevState, DevFailed
 import time
 import json
 import pkg_resources
+from functools import wraps
 
 logger = logging.getLogger()
 
@@ -23,6 +24,19 @@ def attribute_name_from_url(attribute_name:str):
 
     return attribute_name
 
+def attribute_name_url(attribute_name:str, tango_host:str = 'databaseds:10000'):
+    """
+    For some operations Tango devices must be transformed from the form 'domain/family/name/attribute'
+    to 'tango://db:port/domain/family/name/attribute'
+    """
+    if attribute_name.startswith('tango://'):
+        return attribute_name
+
+    if len(attribute_name.split('/')) != 4:
+        raise ValueError(f"Expected attribute name of format 'domain/family/name/attribute', got {attribute_name}")
+
+    return f"tango://{tango_host}/{attribute_name}"
+
 def device_name_url(device_name:str, tango_host:str = 'databaseds:10000'):
     """
     For some operations Tango devices must be transformed from the form 'domain/family/name'
@@ -64,9 +78,9 @@ def warn_if_attribute_not_found():
     """
     def inner(func):
         @wraps(func)
-        def warn_wrapper(self, *args, **kwargs):
+        def warn_wrapper(self, attribute_name, *args, **kwargs):
             try:
-                return func(self, *args, **kwargs)
+                return func(self, attribute_name, *args, **kwargs)
             except DevFailed as e:
                 if e.args[0].reason == 'Attribute not found':
                     logger.warning(f"Attribute {attribute_name} not found!")
@@ -245,15 +259,14 @@ class Archiver():
         for a in attrs_list:
             attr_fullname = f"{device_name}/{a}".lower()
             attr_proxy = AttributeProxy(attr_fullname)
-            if attr_proxy.is_polled() is True:   # if not polled attribute is also not archived
+            if attr_proxy.is_polled() and not self.is_attribute_archived(attr_fullname):   # if not polled attribute is also not archived
                 try:
                     es = DeviceProxy(es_name or self.get_next_subscriber()) # choose an e.s. or get the first one available
-                    if es.AttributeList is None or not(self.cm.AttributeSearch(a)):
-                        polling_period = attr_proxy.get_poll_period() or self.dev_polling_time  
-                        archive_period = global_archive_period or int(attr_proxy.get_property('archive_period')['archive_period'][0]) or self.dev_archive_time                 
-                        self.add_attribute_to_archiver(attr_fullname,polling_period=polling_period,
-                            event_period=archive_period, es_name = es.name())
-                        #time.sleep(0.5)
+                    polling_period = attr_proxy.get_poll_period() or self.dev_polling_time  
+                    archive_period = global_archive_period or int(attr_proxy.get_property('archive_period')['archive_period'][0]) or self.dev_archive_time                 
+                    self.add_attribute_to_archiver(attr_fullname,polling_period=polling_period,
+                        event_period=archive_period, es_name = es.name())
+                    #time.sleep(0.5)
                 except IndexError as e:
                     logger.warning(f"Attribute {attr_fullname} will not be archived because archive event period is not defined!")
                 except Exception as e:
@@ -284,7 +297,8 @@ class Archiver():
         for a in attrs_list:
             try:
                 attr_fullname = f"{device_name}/{a}".lower()
-                self.remove_attribute_from_archiver(attr_fullname)
+                if self.is_attribute_archived(attr_fullname):
+                    self.remove_attribute_from_archiver(attr_fullname)
             except Exception as e:
                 raise Exception from e
     
@@ -331,16 +345,10 @@ class Archiver():
         """
         attribute_name = attribute_name_from_url(attribute_name)
         attributes = self.cm.AttributeSearch(attribute_name.lower())
-        if len(attributes)>1:
-            # Handle case same attribute_name r/rw 
-            if len(attributes)==2 and (attributes[0].endswith(attributes[1]+'w') or attributes[1].endswith(attributes[0]+'w')):
-                return True
-            else:
-                raise Exception(f"Multiple Attributes Matched: {attributes}")
-        elif len(attributes)==1:
-            return True
-        else:
-            return False
+
+        # search returns all matches in which attribute_name is part of the name,
+        # so check whether an exact match is included.
+        return attribute_name_url(attribute_name) in attributes
     
     def update_archiving_attribute(self, attribute_name: str, polling_period: int, event_period: int, strategy: str = 'RUN'):
         """