diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py
index 20b161e97b16f99d352340246770d5db9f99f3e3..6a3ef5ff8a609eecbc86242d745c7fcb97f61b1a 100644
--- a/tangostationcontrol/tangostationcontrol/devices/apsct.py
+++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py
@@ -79,12 +79,12 @@ class APSCT(opcua_device):
 
     def read_APSCT_error_R(self):
         return ((self.proxy.APSCTTR_I2C_error_R > 0)
-               | self.alarm_val("APSCT_PCB_ID_R")
-               | ~self.proxy.APSCT_INPUT_10MHz_good_R
-               | (~self.proxy.APSCT_INPUT_PPS_good_R & ~self.proxy.ASPCT_PPS_ignore_R)
-               | (~self.proxy.APSCT_PLL_160MHz_locked_R & ~self.proxy.APSCT_PLL_200MHz_locked_R)
-               | (self.proxy.APSCT_PLL_200MHz_locked_R & self.proxy.APSCT_PLL_200MHz_error_R)
-               | (self.proxy.APSCT_PLL_160MHz_locked_R & self.proxy.APSCT_PLL_160MHz_error_R)
+               or self.alarm_val("APSCT_PCB_ID_R")
+               or (not self.proxy.APSCT_INPUT_10MHz_good_R)
+               or (not self.proxy.APSCT_INPUT_PPS_good_R and not self.proxy.APSCT_PPS_ignore_R)
+               or (not self.proxy.APSCT_PLL_160MHz_locked_R and not self.proxy.APSCT_PLL_200MHz_locked_R)
+               or (self.proxy.APSCT_PLL_200MHz_locked_R and self.proxy.APSCT_PLL_200MHz_error_R)
+               or (self.proxy.APSCT_PLL_160MHz_locked_R and self.proxy.APSCT_PLL_160MHz_error_R)
                )
 
     APSCT_TEMP_error_R            = attribute(dtype=bool)
@@ -95,13 +95,13 @@ class APSCT(opcua_device):
 
     def read_APSCT_VOUT_error_R(self):
         return ( self.alarm_val("APSCT_PWR_PPSDIST_3V3_R")
-               | self.alarm_val("APSCT_PWR_CLKDIST1_3V3_R")
-               | self.alarm_val("APSCT_PWR_CLKDIST2_3V3_R")
-               | self.alarm_val("APSCT_PWR_CTRL_3V3_R")
-               | self.alarm_val("APSCT_PWR_INPUT_3V3_R")
-               | (self.proxy.APSCT_PWR_PLL_160MHz_on_R & self.alarm_val("APSCT_PWR_PLL_160MHz_3V3_R"))
-               | (self.proxy.APSCT_PWR_PLL_200MHz_on_R & self.alarm_val("APSCT_PWR_PLL_200MHz_3V3_R"))
-               | ~self.proxy.APSCT_PWR_on_R
+               or self.alarm_val("APSCT_PWR_CLKDIST1_3V3_R")
+               or self.alarm_val("APSCT_PWR_CLKDIST2_3V3_R")
+               or self.alarm_val("APSCT_PWR_CTRL_3V3_R")
+               or self.alarm_val("APSCT_PWR_INPUT_3V3_R")
+               or (self.proxy.APSCT_PWR_PLL_160MHz_on_R and self.alarm_val("APSCT_PWR_PLL_160MHz_3V3_R"))
+               or (self.proxy.APSCT_PWR_PLL_200MHz_on_R and self.alarm_val("APSCT_PWR_PLL_200MHz_3V3_R"))
+               or (not self.proxy.APSCT_PWR_on_R)
                )
 
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/apspu.py b/tangostationcontrol/tangostationcontrol/devices/apspu.py
index d014a0eae151d89e77c71a9f0048dfb5e01bcd6b..6be213696c16efc69ca8f20319efc03cfc0f4fe7 100644
--- a/tangostationcontrol/tangostationcontrol/devices/apspu.py
+++ b/tangostationcontrol/tangostationcontrol/devices/apspu.py
@@ -67,10 +67,10 @@ class APSPU(opcua_device):
 
     def read_APSPU_error_R(self):
         return ((self.proxy.APSPUTR_I2C_error_R > 0)
-               | self.alarm_val("APSPU_PCB_ID_R")
-               | self.alarm_val("APSPU_FAN1_RPM_R")
-               | self.alarm_val("APSPU_FAN2_RPM_R") 
-               | self.alarm_val("APSPU_FAN3_RPM_R"))
+               or self.alarm_val("APSPU_PCB_ID_R")
+               or self.alarm_val("APSPU_FAN1_RPM_R")
+               or self.alarm_val("APSPU_FAN2_RPM_R") 
+               or self.alarm_val("APSPU_FAN3_RPM_R"))
 
     APSPU_IOUT_error_R          = attribute(dtype=bool)
     APSPU_TEMP_error_R          = attribute(dtype=bool)
@@ -78,20 +78,20 @@ class APSPU(opcua_device):
 
     def read_APSPU_IOUT_error_R(self):
         return ( self.alarm_val("APSPU_LBA_IOUT_R")
-               | self.alarm_val("APSPU_RCU2A_IOUT_R")
-               | self.alarm_val("APSPU_RCU2D_IOUT_R")
+               or self.alarm_val("APSPU_RCU2A_IOUT_R")
+               or self.alarm_val("APSPU_RCU2D_IOUT_R")
                )
 
     def read_APSPU_TEMP_error_R(self):
         return ( self.alarm_val("APSPU_LBA_TEMP_R")
-               | self.alarm_val("APSPU_RCU2A_TEMP_R")
-               | self.alarm_val("APSPU_RCU2D_TEMP_R")
+               or self.alarm_val("APSPU_RCU2A_TEMP_R")
+               or self.alarm_val("APSPU_RCU2D_TEMP_R")
                )
 
     def read_APSPU_VOUT_error_R(self):
         return ( self.alarm_val("APSPU_LBA_VOUT_R")
-               | self.alarm_val("APSPU_RCU2A_VOUT_R")
-               | self.alarm_val("APSPU_RCU2D_VOUT_R")
+               or self.alarm_val("APSPU_RCU2A_VOUT_R")
+               or self.alarm_val("APSPU_RCU2D_VOUT_R")
                )
 
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/beam.py b/tangostationcontrol/tangostationcontrol/devices/beam.py
index 69f792101b10b7a83374451928315f0d25f379f3..3709bc5602dda655892b6d318e59c2eef77de716 100644
--- a/tangostationcontrol/tangostationcontrol/devices/beam.py
+++ b/tangostationcontrol/tangostationcontrol/devices/beam.py
@@ -12,7 +12,7 @@ import datetime
 from json import loads
 
 from tango.server import attribute, command, device_property
-from tango import AttrWriteType, DebugIt, DevState, DeviceProxy, DevVarStringArray, DevVarDoubleArray, DevString
+from tango import AttrWriteType, DebugIt, DevState, DeviceProxy, DevVarStringArray, DevVarDoubleArray, DevString, DevSource
 from threading import Thread, Lock, Condition
 
 # Additional import
@@ -68,10 +68,12 @@ class Beam(lofar_device):
         fget=lambda self: self._hbat_pointing_timestamp_r)
 
     HBAT_tracking_enabled_R = attribute(access=AttrWriteType.READ,
+        doc="Whether the HBAT tile beam is updated periodically",
         dtype=numpy.bool,
         fget=lambda self: self.HBAT_beam_tracker.is_alive())
 
     HBAT_tracking_enabled_RW = attribute(access=AttrWriteType.READ_WRITE,
+        doc="Whether the HBAT tile beam should be updated periodically",
         dtype=numpy.bool,
         fget=lambda self: self._hbat_tracking_enabled_rw)
 
@@ -99,6 +101,7 @@ class Beam(lofar_device):
 
         # Set a reference of RECV device
         self.recv_proxy = DeviceProxy("STAT/RECV/1")
+        self.recv_proxy.set_source(DevSource.DEV)
 
         # Retrieve positions from RECV device
         HBAT_reference_itrf = self.recv_proxy.HBAT_reference_itrf_R
@@ -121,7 +124,7 @@ class Beam(lofar_device):
         if self._hbat_tracking_enabled_rw:
             self.HBAT_beam_tracker.start()
     
-    @log_exceptions
+    @log_exceptions()
     def configure_for_off(self):
         # Stop thread object
         self.HBAT_beam_tracker.stop()
@@ -186,7 +189,7 @@ class Beam(lofar_device):
 
         # Record where we now point to, now that we've updated the weights.
         # Only the entries within the mask have been updated
-        mask = self.recv_proxy.Ant_mask_RW.flatten()
+        mask = self.recv_proxy.ANT_mask_RW.flatten()
         for rcu in range(96):
             if mask[rcu]:
                 self._hbat_pointing_direction_r[rcu]    = pointing_direction[rcu]
@@ -302,6 +305,9 @@ class BeamTracker():
         # Condition to trigger a forced update or early abort
         self.update_lock = Lock()
         self.update_condition = Condition(self.update_lock)
+
+        # Whether the pointing has to be forced updated
+        self.stale_pointing = True
     
     def start(self):
         """ Starts the Beam Tracking thread """
@@ -312,6 +318,8 @@ class BeamTracker():
         self.done = False
         self.thread = Thread(target=self._update_HBAT_pointing_direction, name=f"BeamTracker of {self.device.get_name()}")
         self.thread.start()
+
+        logger.info("BeamTracking thread started")
     
     def is_alive(self):
         """ Returns True just before the Thread run() method starts until just after the Thread run() method terminates. """
@@ -320,6 +328,10 @@ class BeamTracker():
     def force_update(self):
         """ Force the pointing to be updated. """
 
+        self.stale_pointing = True
+        self.unlock_thread()
+
+    def unlock_thread(self):
         # inform the thread to stop waiting
         with self.update_lock:
             self.update_condition.notify()
@@ -329,6 +341,8 @@ class BeamTracker():
 
         if not self.thread:
             return
+        
+        logger.info("BeamTracking thread stopping")
 
         self.done = True
         self.force_update()
@@ -340,6 +354,8 @@ class BeamTracker():
             logger.error("BeamTracking Thread did not properly terminate")
 
         self.thread = None
+        
+        logger.info("BeamTracking thread stopped")
     
     def _get_sleep_time(self):
         """ Computes the sleep time (in seconds) that needs to be waited for the next beam tracking update """  
@@ -355,16 +371,22 @@ class BeamTracker():
             return sleep_time + self.device.HBAT_beam_tracking_interval
         else:
             return sleep_time
+
+    # @fault_on_error routes errors here. we forward them to our device
+    def Fault(self, msg):
+        self.device.Fault(msg)
    
     @log_exceptions()
+    @fault_on_error()
     def _update_HBAT_pointing_direction(self):
         """ Updates the beam weights using a fixed interval of time """
 
         # Check if  flag beamtracking is true
         with self.update_lock:
             while not self.done:
-                # TODO: Occasionally this still gets called when the beam device is in OFF?
-                self.device.HBAT_set_pointing(numpy.array(self.device.proxy.HBAT_pointing_direction_RW).flatten())
+                self.stale_pointing = False
+                self.device._HBAT_set_pointing(self.device._hbat_pointing_direction_rw, datetime.datetime.now())
 
                 # sleep until the next update, or when interrupted (this releases the lock, allowing for notification)
-                self.update_condition.wait(self._get_sleep_time())
+                # note that we need wait_for as conditions can be triggered multiple times in succession
+                self.update_condition.wait_for(lambda: self.done or self.stale_pointing, self._get_sleep_time())
diff --git a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py
index bb9bf90099aa3b96bdc83011678481dca720191f..6943f86d4bde44010662cbcea45cb350ca271cea 100644
--- a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py
+++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py
@@ -430,5 +430,8 @@ class lofar_device(Device, metaclass=DeviceMeta):
             alarm_state |= value <= value.dtype.type(alarms.min_alarm)
 
         # return alarm state, with the same dimensions as the attribute
-        return alarm_state
+        if is_scalar:
+            return alarm_state.item()
+        else:
+            return alarm_state
 
diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py
index db29fe62c791a6b75744954f1f45090b7f777414..b853b60406511930ae262458564bb52eff111fe1 100644
--- a/tangostationcontrol/tangostationcontrol/devices/recv.py
+++ b/tangostationcontrol/tangostationcontrol/devices/recv.py
@@ -196,9 +196,9 @@ class RECV(opcua_device):
     RECV_VOUT_error_R          = attribute(dtype=(bool,), max_dim_x=32)
 
     def read_RECV_IOUT_error_R(self):
-        return self.proxy.ANT_mask_RW & (
+        return (self.proxy.ANT_mask_RW & (
                  self.alarm_val("RCU_PWR_ANT_IOUT_R")
-               ).any(axis=1)
+               )).any(axis=1)
 
     def read_RECV_TEMP_error_R(self):
         # Don't apply the mask here --- we always want to know if things get too hot!
@@ -210,13 +210,13 @@ class RECV(opcua_device):
         return (self.proxy.ANT_mask_RW & (
                  self.alarm_val("RCU_PWR_ANT_VIN_R")
                | self.alarm_val("RCU_PWR_ANT_VOUT_R")
-               ).any(axis=1) | (self.proxy.RCU_mask_RW & (
+               )).any(axis=1) | (self.proxy.RCU_mask_RW & (
                  self.alarm_val("RCU_PWR_1V8_R")
                | self.alarm_val("RCU_PWR_2V5_R")
                | self.alarm_val("RCU_PWR_3V3_R")
                | ~self.proxy.RCU_PWR_DIGITAL_on_R
                | ~self.proxy.RCU_PWR_good_R
-               )))
+               ))
 
     # --------
     # overloaded functions
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
index db7c1ffbcc8be04af296e14df3c0fe98e77b9da0..a483aec43eacf571a6344ee1b1823cf62af96a92 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
@@ -129,8 +129,6 @@ class SDP(opcua_device):
     FPGA_subband_weights_R = attribute_wrapper(comms_annotation=["FPGA_subband_weights_R"], datatype=numpy.uint32, dims=(12 * 512, 16))
     FPGA_subband_weights_RW = attribute_wrapper(comms_annotation=["FPGA_subband_weights_RW"], datatype=numpy.uint32, dims=(12 * 512, 16), access=AttrWriteType.READ_WRITE)
     FPGA_temp_R = attribute_wrapper(comms_annotation=["FPGA_temp_R"], datatype=numpy.float_, dims=(16,))
-    FPGA_weights_R = attribute_wrapper(comms_annotation=["FPGA_weights_R"], datatype=numpy.int16, dims=(12 * 488 * 2, 16))
-    FPGA_weights_RW = attribute_wrapper(comms_annotation=["FPGA_weights_RW"], datatype=numpy.int16, dims=(12 * 488 * 2, 16), access=AttrWriteType.READ_WRITE)
     FPGA_wg_amplitude_R = attribute_wrapper(comms_annotation=["FPGA_wg_amplitude_R"], datatype=numpy.float_, dims=(12, 16))
     FPGA_wg_amplitude_RW = attribute_wrapper(comms_annotation=["FPGA_wg_amplitude_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE)
     FPGA_wg_enable_R = attribute_wrapper(comms_annotation=["FPGA_wg_enable_R"], datatype=numpy.bool_, dims=(12, 16))
@@ -211,11 +209,12 @@ class SDP(opcua_device):
     # ----------
     FPGA_error_R                 = attribute(dtype=(bool,), max_dim_x=16)
     FPGA_processing_error_R      = attribute(dtype=(bool,), max_dim_x=16)
+    FPGA_input_error_R           = attribute(dtype=(bool,), max_dim_x=16)
 
     def read_FPGA_error_R(self):
         return self.proxy.TR_fpga_mask_RW & (
                  self.proxy.TR_fpga_communication_error_R
-               | self.proxy.FPGA_firmware_version_R != ""
+               | (self.proxy.FPGA_firmware_version_R != "")
                | (self.proxy.FPGA_jesd204b_csr_dev_syncn_R == 0).any(axis=1)
                )
 
@@ -223,8 +222,12 @@ class SDP(opcua_device):
         return self.proxy.TR_fpga_mask_RW & (
                  ~self.proxy.FPGA_processing_enable_R
                | (self.proxy.FPGA_boot_image_R == 0)
-               | self.proxy.FPGA_wg_enable_R.any(axis=1)
-               | (self.proxy.FPGA_signal_input_rms_R == 0)
+               )
+
+    def read_FPGA_input_error_R(self):
+        return self.proxy.TR_fpga_mask_RW & (
+                 self.proxy.FPGA_wg_enable_R.any(axis=1)
+               | (self.proxy.FPGA_signal_input_rms_R == 0).any(axis=1)
                )
 
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
index 0e96366bcaa2758921ef4431a82e01ac653d19ad..338c5506458f0f63bf65fd33dd34f4d3e6c4122e 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
@@ -13,7 +13,7 @@
 
 # PyTango imports
 from tango.server import device_property
-from tango import DeviceProxy
+from tango import DeviceProxy, DevSource
 
 # Additional import
 import asyncio
@@ -126,6 +126,7 @@ class Statistics(opcua_device):
 
         # proxy the SDP device in case we need the FPGA mask
         self.sdp_proxy = DeviceProxy("STAT/SDP/1")
+        self.sdp_proxy.set_source(DevSource.DEV)
 
     async def _connect_statistics(self):
         # map an access helper class
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py
index 9d4697cf2d64b3e9a03fa931b2c0e21b100322aa..8c88a3a638eafdd152e0ee39be5db3dfc8e1063f 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py
@@ -246,7 +246,7 @@ class XSTCollector(StatisticsCollector):
         xst_blocks = self.parameters["xst_blocks"]
         xst_conjugated = self.parameters["xst_conjugated"]
 
-        for subband_index in subband_indices:
+        for matrix_idx, subband_index in enumerate(subband_indices):
             for block_index in range(self.MAX_BLOCKS):
                 # convert real/imag int to complex float values. this works as real/imag come in pairs
                 block = xst_blocks[subband_index][block_index].astype(numpy.float32).view(numpy.complex64)
@@ -263,7 +263,7 @@ class XSTCollector(StatisticsCollector):
                 first_baseline = (first_baseline[0] * self.BLOCK_LENGTH, first_baseline[1] * self.BLOCK_LENGTH)
 
                 # copy block into matrix
-                matrix[subband_index][first_baseline[0]:first_baseline[0]+self.BLOCK_LENGTH, first_baseline[1]:first_baseline[1]+self.BLOCK_LENGTH] = block
+                matrix[matrix_idx][first_baseline[0]:first_baseline[0]+self.BLOCK_LENGTH, first_baseline[1]:first_baseline[1]+self.BLOCK_LENGTH] = block
 
         return matrix
 
diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py
index db9f51eb7b82d081c5b83ebe04dc998a8e5f1506..7a2609e811432a8c772a239186e16f2f442ba7a3 100644
--- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py
+++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py
@@ -61,9 +61,30 @@ class AbstractTestBases:
                 self.self.assertListEqual([], self.proxy.opcua_missing_attributes_R)
 
         def test_device_on(self):
-            """Test if we can transition to on"""
+            """Test if we can transition off -> standby -> on"""
 
             self.proxy.initialise()
             self.proxy.on()
 
             self.assertEqual(DevState.ON, self.proxy.state())
+
+        def test_device_warm_boot(self):
+            """Test if we can transition off -> on using a warm boot"""
+
+            self.proxy.warm_boot()
+
+            self.assertEqual(DevState.ON, self.proxy.state())
+
+        def test_device_read_all_attributes(self):
+            """Test if we can read all of the exposed attributes in the ON state.
+            
+               This test covers the reading logic of all attributes. """
+
+            self.proxy.initialise()
+            self.proxy.on()
+
+            for attribute_name in self.proxy.get_attribute_list():
+                try:
+                    _ = self.proxy.read_attribute(attribute_name).value
+                except Exception as e:
+                    raise AssertionError(f"Could not read attribute {attribute_name} from device {self.name}") from e
diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beam.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beam.py
index 9af017c12df46b3719c367f94a5452cdddebdbed..381678118b123793767aff753e4461b7916fe5bd 100644
--- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beam.py
+++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beam.py
@@ -12,7 +12,6 @@ import numpy
 import datetime
 import json
 
-from tango import DevState
 from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy
 
 from .base import AbstractTestBases
@@ -36,11 +35,8 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         # setup RECV
         recv_proxy = TestDeviceProxy("STAT/RECV/1")
         recv_proxy.off()
-        recv_proxy.initialise()
-        self.assertEqual(DevState.STANDBY, recv_proxy.state())
+        recv_proxy.warm_boot()
         recv_proxy.set_defaults()
-        recv_proxy.on()
-        self.assertEqual(DevState.ON, recv_proxy.state())
         return recv_proxy
     
     def test_HBAT_delays_dims(self):
@@ -48,12 +44,7 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         self.setup_recv_proxy()
 
         # setup BEAM
-        self.proxy.init()
-        self.proxy.Initialise()
-        self.assertEqual(DevState.STANDBY, self.proxy.state())
-        self.proxy.set_defaults()
-        self.proxy.on()
-        self.assertEqual(DevState.ON, self.proxy.state())
+        self.proxy.warm_boot()
 
         # verify HBAT_delays method returns the correct dimensions
         HBAT_delays = self.proxy.HBAT_delays(self.pointing_direction)
@@ -64,13 +55,8 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         recv_proxy = self.setup_recv_proxy()
 
         # setup BEAM
-        self.proxy.init()
-        self.proxy.Initialise()
-        self.assertEqual(DevState.STANDBY, self.proxy.state())
-        self.proxy.set_defaults()
+        self.proxy.warm_boot()
         self.proxy.HBAT_tracking_enabled_RW = False
-        self.proxy.on()
-        self.assertEqual(DevState.ON, self.proxy.state())
 
         # Verify attribute is present (all zeros if never used before)
         HBAT_delays_r1 = numpy.array(recv_proxy.read_attribute('HBAT_BF_delay_steps_RW').value)
@@ -90,9 +76,8 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         # setup RECV as well
         recv_proxy = self.setup_recv_proxy()
 
-        self.proxy.initialise()
+        self.proxy.warm_boot()
         self.proxy.HBAT_tracking_enabled_RW = False
-        self.proxy.on()
 
         # Point to Zenith
         self.proxy.HBAT_set_pointing(numpy.array([["AZELGEO","0deg","90deg"]] * 96).flatten())
@@ -107,9 +92,8 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         # setup RECV as well
         recv_proxy = self.setup_recv_proxy()
 
-        self.proxy.initialise()
+        self.proxy.warm_boot()
         self.proxy.HBAT_tracking_enabled_RW = False
-        self.proxy.on()
 
         # point at north on the horizon
         self.proxy.HBAT_set_pointing(["AZELGEO","0deg","0deg"] * 96)
@@ -135,9 +119,8 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         # setup RECV as well
         recv_proxy = self.setup_recv_proxy()
 
-        self.proxy.initialise()
+        self.proxy.warm_boot()
         self.proxy.HBAT_tracking_enabled_RW = False
-        self.proxy.on()
 
         # Point to LOFAR 1 ref pointing (0.929342, 0.952579, J2000)
         pointings = numpy.array([["J2000", "0.929342rad", "0.952579rad"]] * 96).flatten()
@@ -167,8 +150,7 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         # setup RECV as well
         recv_proxy = self.setup_recv_proxy()
 
-        self.proxy.initialise()
-        self.proxy.on()
+        self.proxy.warm_boot()
 
         # check if we're really tracking
         self.assertTrue(self.proxy.HBAT_tracking_enabled_R)
@@ -177,9 +159,6 @@ class TestDeviceBeam(AbstractTestBases.TestDeviceBase):
         new_pointings = [("J2000",f"{tile}deg","0deg") for tile in range(96)]
         self.proxy.HBAT_pointing_direction_RW = new_pointings
 
-        # wait for tracking thread to pick up and set. should be almost instant
-        time.sleep(0.5)
-
         # check pointing
         self.assertListEqual(new_pointings, list(self.proxy.HBAT_pointing_direction_R))
 
diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sdp.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sdp.py
index 3a075e697c473c9800257b4796f21f7b79e5e430..570d8ce6cee1bc2f1ab833c9d93acdd11cc270f7 100644
--- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sdp.py
+++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sdp.py
@@ -19,7 +19,6 @@ class TestDeviceSDP(AbstractTestBases.TestDeviceBase):
     def test_device_sdp_read_attribute(self):
         """Test if we can read an attribute obtained over OPC-UA"""
 
-        self.proxy.initialise()
-        self.proxy.on()
+        self.proxy.warm_boot()
 
         self.assertListEqual([True]*16, list(self.proxy.TR_fpga_communication_error_R))
diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py
index 60675e121364b52fb692b2f8461001bfdc78b50a..2398206083533a5fcc40051b6a80e42923a38347 100644
--- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py
+++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py
@@ -12,6 +12,7 @@ import sys
 import time
 
 from tango._tango import DevState
+from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy
 
 from .base import AbstractTestBases
 
@@ -22,14 +23,24 @@ class TestDeviceSST(AbstractTestBases.TestDeviceBase):
         """Intentionally recreate the device object in each test"""
         super().setUp("STAT/SST/1")
 
+    def test_device_read_all_attributes(self):
+        # We need to connect to SDP first to read some of our attributes
+        self.sdp_proxy = self.setup_sdp()
+
+        super().test_device_read_all_attributes()
+    
+    def setup_sdp(self):
+        # setup SDP, on which this device depends
+        sdp_proxy = TestDeviceProxy("STAT/SDP/1")
+        sdp_proxy.off()
+        sdp_proxy.warm_boot()
+        sdp_proxy.set_defaults()
+        return sdp_proxy
+
     def test_device_sst_send_udp(self):
         port_property = {"Statistics_Client_TCP_Port": "4998"}
         self.proxy.put_property(port_property)
-        self.proxy.initialise()
-
-        self.assertEqual(DevState.STANDBY, self.proxy.state())
-
-        self.proxy.on()
+        self.proxy.warm_boot()
 
         self.assertEqual(DevState.ON, self.proxy.state())
 
@@ -44,13 +55,7 @@ class TestDeviceSST(AbstractTestBases.TestDeviceBase):
     def test_device_sst_connect_tcp_receive(self):
         port_property = {"Statistics_Client_TCP_Port": "5101"}
         self.proxy.put_property(port_property)
-        self.proxy.initialise()
-
-        self.assertEqual(DevState.STANDBY, self.proxy.state())
-
-        self.proxy.on()
-
-        self.assertEqual(DevState.ON, self.proxy.state())
+        self.proxy.warm_boot()
 
         time.sleep(2)
 
diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py
new file mode 100644
index 0000000000000000000000000000000000000000..071108ee57e025c30fc423d7ce2312b66d5012a7
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py
@@ -0,0 +1,32 @@
+
+# -*- coding: utf-8 -*-
+#
+# This file is part of the LOFAR 2.0 Station Software
+#
+#
+#
+# Distributed under the terms of the APACHE license.
+# See LICENSE.txt for more info.
+from .base import AbstractTestBases
+
+from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy
+
+class TestDeviceSST(AbstractTestBases.TestDeviceBase):
+
+    def setUp(self):
+        """Intentionally recreate the device object in each test"""
+        super().setUp("STAT/XST/1")
+
+    def test_device_read_all_attributes(self):
+        # We need to connect to SDP first to read some of our attributes
+        self.sdp_proxy = self.setup_sdp()
+
+        super().test_device_read_all_attributes()
+    
+    def setup_sdp(self):
+        # setup SDP, on which this device depends
+        sdp_proxy = TestDeviceProxy("STAT/SDP/1")
+        sdp_proxy.off()
+        sdp_proxy.warm_boot()
+        sdp_proxy.set_defaults()
+        return sdp_proxy