diff --git a/tangostationcontrol/tangostationcontrol/clients/statistics/client.py b/tangostationcontrol/tangostationcontrol/clients/statistics/client.py
index 9ea336ad9e81df319f8596ab76d3b6080db7f567..a774e2a56fc74a0e0310ba7ce5e42484e6ad6219 100644
--- a/tangostationcontrol/tangostationcontrol/clients/statistics/client.py
+++ b/tangostationcontrol/tangostationcontrol/clients/statistics/client.py
@@ -21,12 +21,16 @@ logger = logging.getLogger()
 
 
 class StatisticsClient(AsyncCommClient):
+
+    # the maximum amount of packets unhandled packets the statistics client thread will queue
+    STATISTICS_CLIENT_QUEUE_SIZE = 1024
+
     """
       Collects statistics packets over UDP, forwards them to a StatisticsCollector,
       and provides a CommClient interface to expose points to a Device Server.
     """
 
-    def __init__(self, collector, udp_options, tcp_options, fault_func, event_loop=None, queuesize=constants.STATISTICS_CLIENT_QUEUE_SIZE):
+    def __init__(self, collector, udp_options, tcp_options, fault_func, event_loop=None, queuesize=STATISTICS_CLIENT_QUEUE_SIZE):
         """
         Create the statistics client and connect() to it and get the object node.
 
diff --git a/tangostationcontrol/tangostationcontrol/clients/udp_receiver.py b/tangostationcontrol/tangostationcontrol/clients/udp_receiver.py
index 585655172530fa7efbacc32c576f76362cb4785f..04e24366e193567f4b04c97716a77a5546bcadae 100644
--- a/tangostationcontrol/tangostationcontrol/clients/udp_receiver.py
+++ b/tangostationcontrol/tangostationcontrol/clients/udp_receiver.py
@@ -52,7 +52,7 @@ class UDPReceiver(Thread, StatisticsClientThread):
             # Number of packets we had to drop due to a full queue
             "nof_packets_dropped":   numpy.uint64(0),
             # Packets are at most 9000 bytes, the largest payload (well, MTU) of an Ethernet Jumbo frame
-            "last_packet":           numpy.zeros((constants.MAX_PACKET_SIZE,), dtype=numpy.uint8),
+            "last_packet":           numpy.zeros((constants.MAX_ETH_FRAME_SIZE,), dtype=numpy.uint8),
             # Timestamp of when the last packet was received
             "last_packet_timestamp": numpy.uint64(0),
         }
@@ -90,7 +90,7 @@ class UDPReceiver(Thread, StatisticsClientThread):
 
         while self.stream_on:
             try:
-                packet, _, _, _ = self.sock.recvmsg(constants.MAX_PACKET_SIZE)
+                packet, _, _, _ = self.sock.recvmsg(constants.MAX_ETH_FRAME_SIZE)
 
                 self.parameters["nof_packets_received"]  += numpy.uint64(1)
                 self.parameters["nof_bytes_received"]    += numpy.uint64(len(packet))
diff --git a/tangostationcontrol/tangostationcontrol/common/constants.py b/tangostationcontrol/tangostationcontrol/common/constants.py
index 6b8db920e66e9bde7700db48357b90f691169f1b..001bb089d9f9d7a7a11f2cfbea82b83e521001fd 100644
--- a/tangostationcontrol/tangostationcontrol/common/constants.py
+++ b/tangostationcontrol/tangostationcontrol/common/constants.py
@@ -1,13 +1,5 @@
 
 class constants:
-    """
-    TODO: support configurations
-
-    A good source for a good chunk of the constants can be found here: https://support.astron.nl/confluence/display/L2M/L2+STAT+Decision%3A+SC+-+SDP+OPC-UA+interface
-    """
-
-    # number of dual polarization antennas in the band.
-    N_ant = 48
 
     # number of FPGA processing nodes
     N_pn = 16
@@ -15,24 +7,20 @@ class constants:
     # number of polarisations per antenna (X and y polarisations)
     N_pol = 2
 
-    # Single polarization signal inputs ( N_ant * N_pol)
-    S_ant = 96
-
-    # number of polarisations for beamforming
-    N_pol_bf = 2
-
     # antennas per FPGA
     A_pn = 6
 
     # signal inputs per FPGA ( A_pn * N_pol )
     S_pn = A_pn * N_pol
 
-    # TODO verify whether this is the same as S_ant or not
-    # Highest number of HBA tiles we support per AntennaField
-    MAX_NUMBER_OF_HBAT = 96
+    # Highest number antennas we support
+    MAX_ANTENNA = 96
+
+    # Maximum number of antenna inputs we support (used to determine array sizes)
+    MAX_INPUTS = 192
 
     # Number of tile elements (antenna dipoles) in each HBA tile
-    N_te = 16
+    N_elements = 16
 
     # number of RCU's per subrack
     N_rcu = 32
@@ -58,10 +46,7 @@ class constants:
     # Maximum number of subbands we support
     N_subbands = 512
     # Number of points per subband (the resolution)
-    N_subband_pts = 1024
-
-    # Maximum number of antenna inputs we support (used to determine array sizes)
-    MAX_INPUTS = 192
+    N_subband_res = 1024
 
 
     # main clock frequency's are 200MHz and 160MHz
@@ -79,10 +64,6 @@ class constants:
     BST_MAX_BLOCKS = 2
 
 
-    # number of sockets the psoc has
-    PSOC_SOCKETS = 8
-
-
     # UNB2 constants
     # number of uniboards in a subrack
     N_unb = 2
@@ -93,77 +74,23 @@ class constants:
     # number of QSFP tranceivers per uniboard
     N_qsfp = 24
 
-    # the three spatial dimensions XYZ used a lot for pointing directions and ITRF coordinates.
+
+    # the three spatial dimensions XYZ used a lot for PQR and ITRF coordinates.
     N_xyz = 3
+    # amount of parameters needed for a pointing
+    N_point_prop = 3
     # number of values for latitude/longitude coordinates
-    N_coord = 2
+    N_latlong = 2
 
 
     # default subband we use because of its low RFI
     DEFAULT_SUBBAND = 102
 
     # Maximum array size to allocate for beam_device pointings,
-    MAX_POINTINGS = 1024
+    MAX_POINTINGS = N_beamlets_max
 
     # max size for a statistic packet
-    MAX_PACKET_SIZE = 9000
-
-    # Maximum number of supported simultaneous replicator clients
-    MAX_STATISTICS_CLIENTS = 128
-
-    # the maximum amount of packets unhandled packets the statistics client thread will queue
-    STATISTICS_CLIENT_QUEUE_SIZE = 1024
-
-    # maximum number of devices boot.py supports
-    MAX_BOOT_DEVICES = 128
+    MAX_ETH_FRAME_SIZE = 9000
 
     # The default polling period for polled attributes
     DEFAULT_POLLING_PERIOD = 1000
-
-
-"""
-These classes for now exist for future use
-
-class LB:
-    S_ant = 192
-    N_ant = 96
-    N_pn = 16
-    N_beamsets_sdp = 2
-    N_beamsets_ctrl = 1
-    N_beamlets_sdp = 976
-    N_beamlets_ctrl = 488
-    N_beamlets_out = 488
-
-
-class HB_Core:
-    S_ant = 96
-    N_ant = 48
-    N_pn = 8
-    N_beamsets_sdp = 2
-    N_beamsets_ctrl = 2
-    N_beamlets_sdp = 976
-    N_beamlets_ctrl = 976
-    N_beamlets_out = 976
-
-
-class HB_Remote:
-    S_ant = 96
-    N_ant = 48
-    N_pn = 8
-    N_beamsets_sdp = 2
-    N_beamsets_ctrl = 1
-    N_beamlets_sdp = 976
-    N_beamlets_ctrl = 488
-    N_beamlets_out = 488
-
-
-class HB_International:
-    S_ant = 192
-    N_ant = 96
-    N_pn = 16
-    N_beamsets_sdp = 2
-    N_beamsets_ctrl = 1
-    N_beamlets_sdp = 976
-    N_beamlets_ctrl = 488
-    N_beamlets_out = 488
-"""
diff --git a/tangostationcontrol/tangostationcontrol/devices/antennafield.py b/tangostationcontrol/tangostationcontrol/devices/antennafield.py
index 52a4ccd359867f329e3ae18ad889ce52c920c7e7..21e5d00831bda8c81fd16e839679c7f44509b3f0 100644
--- a/tangostationcontrol/tangostationcontrol/devices/antennafield.py
+++ b/tangostationcontrol/tangostationcontrol/devices/antennafield.py
@@ -91,8 +91,8 @@ class AntennaField(lofar_device):
         calculated, as well as the geohash.
     """
 
-    MAX_NUMBER_OF_HBAT =  constants.MAX_NUMBER_OF_HBAT
-    N_te = constants.N_te
+    MAX_NUMBER_OF_HBAT =  constants.MAX_ANTENNA
+    N_te = constants.N_elements
 
     # ----- Antenna names
 
@@ -292,7 +292,7 @@ class AntennaField(lofar_device):
 
     Antenna_Field_Reference_GEO_R = attribute(access=AttrWriteType.READ,
                                               doc='Absolute reference position of antenna field, in latitude/longitude (degrees)',
-                                              dtype=(numpy.float64,), max_dim_x=constants.N_coord)
+                                              dtype=(numpy.float64,), max_dim_x=constants.N_latlong)
 
     Antenna_Field_Reference_GEOHASH_R = attribute(access=AttrWriteType.READ,
                                                   doc='Absolute reference position of antenna field, as a geohash string',
@@ -309,7 +309,7 @@ class AntennaField(lofar_device):
 
     Antenna_Reference_GEO_R = attribute(access=AttrWriteType.READ,
                                         doc='Absolute reference position of each tile, in latitude/longitude (degrees)',
-                                        dtype=((numpy.float64,),), max_dim_x=constants.N_coord, max_dim_y=MAX_NUMBER_OF_HBAT)
+                                        dtype=((numpy.float64,),), max_dim_x=constants.N_latlong, max_dim_y=MAX_NUMBER_OF_HBAT)
 
     Antenna_Reference_GEOHASH_R = attribute(access=AttrWriteType.READ,
                                             doc='Absolute reference position of each tile, as geohash strings',
@@ -392,7 +392,7 @@ class AntennaField(lofar_device):
             tiles lie on the same plane in ITRF. """
 
         # the relative offsets between the elements is fixed in HBAT_base_antenna_offsets
-        base_antenna_offsets = numpy.array(self.HBAT_base_antenna_offsets).reshape(constants.N_te, constants.N_xyz)
+        base_antenna_offsets = numpy.array(self.HBAT_base_antenna_offsets).reshape(constants.N_elements, constants.N_xyz)
 
         PQR_to_ETRS_rotation_matrix = numpy.array(self.PQR_to_ETRS_rotation_matrix).reshape(constants.N_xyz, constants.N_xyz)
 
@@ -404,7 +404,7 @@ class AntennaField(lofar_device):
                 PQR_to_ETRS_rotation_matrix)
                 for angle_deg in self.HBAT_PQR_rotation_angles_deg])
 
-        return all_offsets.reshape(-1, constants.N_te * constants.N_xyz)
+        return all_offsets.reshape(-1, constants.N_elements * constants.N_xyz)
 
     def read_Antenna_Reference_ITRF_R(self):
         # provide ITRF coordinates if they were configured
@@ -521,10 +521,10 @@ class AntennaField(lofar_device):
     def calculate_HBAT_bf_delay_steps(self, delays: numpy.ndarray):
         num_tiles = self.read_nr_antennas_R()
 
-        delays = delays.reshape(num_tiles, constants.N_te)
+        delays = delays.reshape(num_tiles, constants.N_elements)
 
-        result_values = numpy.zeros((num_tiles, constants.N_te * constants.N_pol_bf), dtype=numpy.int64)
-        control_mapping = numpy.reshape(self.Control_to_RECV_mapping, (-1, constants.N_pol_bf))
+        result_values = numpy.zeros((num_tiles, constants.N_elements * constants.N_pol), dtype=numpy.int64)
+        control_mapping = numpy.reshape(self.Control_to_RECV_mapping, (-1, constants.N_pol))
 
         for recv_idx, recv_proxy in enumerate(self.recv_proxies):
             # collect all delays for this recv_proxy
@@ -538,7 +538,7 @@ class AntennaField(lofar_device):
             # convert them into delay steps
             flatten_delay_steps = numpy.array(recv_proxy.calculate_HBAT_bf_delay_steps(recv_delays.flatten()),
                                               dtype=numpy.int64)
-            delay_steps = numpy.reshape(flatten_delay_steps, (-1, constants.N_te * constants.N_pol))
+            delay_steps = numpy.reshape(flatten_delay_steps, (-1, constants.N_elements * constants.N_pol))
 
             # write back into same positions we collected them from
             result_values[recv_result_indices] = delay_steps
@@ -548,8 +548,8 @@ class AntennaField(lofar_device):
 
 class AntennaToRecvMapper(object):
 
-    _VALUE_MAP_NONE_96 = numpy.full(constants.MAX_NUMBER_OF_HBAT, None)
-    _VALUE_MAP_NONE_96_32 = numpy.full((constants.MAX_NUMBER_OF_HBAT, constants.N_rcu), None)
+    _VALUE_MAP_NONE_96 = numpy.full(constants.MAX_ANTENNA, None)
+    _VALUE_MAP_NONE_96_32 = numpy.full((constants.MAX_ANTENNA, constants.N_rcu), None)
 
     def __init__(self, control_to_recv_mapping, power_to_recv_mapping, number_of_receivers):
         number_of_antennas = len(control_to_recv_mapping)
@@ -587,13 +587,13 @@ class AntennaToRecvMapper(object):
             "RCU_band_select_RW": AntennaToRecvMapper._VALUE_MAP_NONE_96,
         }
         self._reshape_attributes_in = {
-            "HBAT_BF_delay_steps_RW": (constants.MAX_NUMBER_OF_HBAT, constants.N_rcu),
-            "RCU_PWR_ANT_on_R": (constants.MAX_NUMBER_OF_HBAT,),
-            "RCU_PWR_ANT_on_RW": (constants.MAX_NUMBER_OF_HBAT,),
-            "RCU_band_select_RW": (constants.MAX_NUMBER_OF_HBAT,),
+            "HBAT_BF_delay_steps_RW": (constants.MAX_ANTENNA, constants.N_rcu),
+            "RCU_PWR_ANT_on_R": (constants.MAX_ANTENNA,),
+            "RCU_PWR_ANT_on_RW": (constants.MAX_ANTENNA,),
+            "RCU_band_select_RW": (constants.MAX_ANTENNA,),
         }
         self._reshape_attributes_out = {
-            "HBAT_BF_delay_steps_RW": (constants.MAX_NUMBER_OF_HBAT, constants.N_rcu),
+            "HBAT_BF_delay_steps_RW": (constants.MAX_ANTENNA, constants.N_rcu),
             "RCU_PWR_ANT_on_R": (constants.N_rcu, constants.N_rcu_inp),
             "RCU_PWR_ANT_on_RW": (constants.N_rcu, constants.N_rcu_inp),
             "RCU_band_select_RW": (constants.N_rcu, constants.N_rcu_inp),
diff --git a/tangostationcontrol/tangostationcontrol/devices/beam_device.py b/tangostationcontrol/tangostationcontrol/devices/beam_device.py
index 4f64b44044ba2724aac3667c47eee33c10a5b13b..f0b66e2155965de8cf4f523e8bbca36ce749a56f 100644
--- a/tangostationcontrol/tangostationcontrol/devices/beam_device.py
+++ b/tangostationcontrol/tangostationcontrol/devices/beam_device.py
@@ -74,11 +74,11 @@ class beam_device(lofar_device):
     # will be stored as self._num_pointings.
 
     Pointing_direction_R = attribute(access=AttrWriteType.READ,
-        dtype=((str,),), max_dim_x=constants.N_xyz, max_dim_y=constants.MAX_POINTINGS,
+        dtype=((str,),), max_dim_x=constants.N_point_prop, max_dim_y=constants.MAX_POINTINGS,
         fget=lambda self: self._pointing_direction_r)
 
     Pointing_direction_RW = attribute(access=AttrWriteType.READ_WRITE,
-        dtype=((str,),), max_dim_x=constants.N_xyz, max_dim_y=constants.MAX_POINTINGS,
+        dtype=((str,),), max_dim_x=constants.N_point_prop, max_dim_y=constants.MAX_POINTINGS,
         fget=lambda self: self._pointing_direction_rw)
 
     Pointing_direction_str_R = attribute(access=AttrWriteType.READ,
@@ -230,7 +230,7 @@ class beam_device(lofar_device):
         # Initialise tracking control
         self._num_pointings            = num_pointings
         self._pointing_timestamp_r     = numpy.zeros(num_pointings, dtype=numpy.double)
-        self._pointing_direction_r     = numpy.zeros((num_pointings, constants.N_xyz), dtype="<U32")
+        self._pointing_direction_r     = numpy.zeros((num_pointings, constants.N_point_prop), dtype="<U32")
         self._pointing_direction_rw    = numpy.array([["AZELGEO","0deg","90deg"]] * num_pointings, dtype="<U32")
         self._tracking_enabled_rw      = self.Tracking_enabled_RW_default
 
diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py
index 338d88cd2e8bca397c6fdfba9c258dc85f668a2f..2f44875c6538015e9e92b3bc6d0220b36d5ecb60 100644
--- a/tangostationcontrol/tangostationcontrol/devices/boot.py
+++ b/tangostationcontrol/tangostationcontrol/devices/boot.py
@@ -53,6 +53,7 @@ class DevicesInitialiser(object):
         the start() method, and progress can be followed by inspecting the
         members progress (0-100), status (string), and is_running() (bool).
     """
+
     def __init__(self, device_names, reboot=False, initialise_hardware=True, proxy_timeout=60.0):
         self.reboot = reboot
         self.initialise_hardware = initialise_hardware
@@ -214,6 +215,10 @@ class DevicesInitialiser(object):
 
 @device_logging_to_python()
 class Boot(lofar_device):
+
+    # maximum number of devices boot.py supports
+    MAX_BOOT_DEVICES = 128
+
     # -----------------
     # Device Properties
     # -----------------
@@ -261,8 +266,8 @@ class Boot(lofar_device):
     booting_R = attribute(dtype=bool, access=AttrWriteType.READ, fget=lambda self: self.initialiser.is_running(), doc="Whether booting is in progress.")
     progress_R = attribute(dtype=numpy.int32, access=AttrWriteType.READ, fget=lambda self: numpy.int32(self.initialiser.progress), doc="Percentage of devices that was initialised")
     status_R = attribute(dtype=str, access=AttrWriteType.READ, fget=lambda self: self.initialiser.status, doc="Description of current boot activity")
-    initialised_devices_R = attribute(dtype=(str,), max_dim_x=constants.MAX_BOOT_DEVICES, access=AttrWriteType.READ, fget=lambda self: [name for name, initialised in self.initialiser.device_initialised.items() if initialised], doc="Which devices were initialised succesfully")
-    uninitialised_devices_R = attribute(dtype=(str,), max_dim_x=constants.MAX_BOOT_DEVICES, access=AttrWriteType.READ, fget=lambda self: [name for name, initialised in self.initialiser.device_initialised.items() if not initialised], doc="Which devices have not been initialised or failed to initialise")
+    initialised_devices_R = attribute(dtype=(str,), max_dim_x=MAX_BOOT_DEVICES, access=AttrWriteType.READ, fget=lambda self: [name for name, initialised in self.initialiser.device_initialised.items() if initialised], doc="Which devices were initialised succesfully")
+    uninitialised_devices_R = attribute(dtype=(str,), max_dim_x=MAX_BOOT_DEVICES, access=AttrWriteType.READ, fget=lambda self: [name for name, initialised in self.initialiser.device_initialised.items() if not initialised], doc="Which devices have not been initialised or failed to initialise")
 
     # --------
     # overloaded functions
diff --git a/tangostationcontrol/tangostationcontrol/devices/observation.py b/tangostationcontrol/tangostationcontrol/devices/observation.py
index 1d506f92f4fcffb472d57cf809ca602dffa6ec96..90b786e43f3be7b2344691d8fd9e1abb1edeecfb 100644
--- a/tangostationcontrol/tangostationcontrol/devices/observation.py
+++ b/tangostationcontrol/tangostationcontrol/devices/observation.py
@@ -47,11 +47,11 @@ class Observation(lofar_device):
                                       rel_change="1.0")
     observation_id_R = attribute(dtype=numpy.int64, access=AttrWriteType.READ)
     stop_time_R = attribute(dtype=numpy.float64, access=AttrWriteType.READ)
-    antenna_mask_R = attribute(dtype=(numpy.int64,), max_dim_x=constants.MAX_NUMBER_OF_HBAT, access=AttrWriteType.READ)
+    antenna_mask_R = attribute(dtype=(numpy.int64,), max_dim_x=constants.MAX_ANTENNA, access=AttrWriteType.READ)
     filter_R = attribute(dtype=numpy.str, access=AttrWriteType.READ)
-    saps_subband_R = attribute(dtype=((numpy.uint32,),), max_dim_x=constants.S_ant, max_dim_y=constants.N_beamlets_ctrl, access=AttrWriteType.READ)
-    saps_pointing_R = attribute(dtype=((numpy.str,),), max_dim_x=3, max_dim_y=constants.N_beamlets_ctrl, access=AttrWriteType.READ)
-    tile_beam_R = attribute(dtype=(numpy.str,), max_dim_x=3, access=AttrWriteType.READ)
+    saps_subband_R = attribute(dtype=((numpy.uint32,),), max_dim_x=constants.N_beamlets_ctrl, max_dim_y=constants.N_beamlets_ctrl, access=AttrWriteType.READ)
+    saps_pointing_R = attribute(dtype=((numpy.str,),), max_dim_x=constants.N_point_prop, max_dim_y=constants.N_beamlets_ctrl, access=AttrWriteType.READ)
+    tile_beam_R = attribute(dtype=(numpy.str,), max_dim_x=constants.N_point_prop, access=AttrWriteType.READ)
     first_beamlet_R = attribute(dtype=numpy.int64, access=AttrWriteType.READ)
 
     observation_settings_RW = attribute(dtype=str, access=AttrWriteType.READ_WRITE)
@@ -243,8 +243,8 @@ class Observation(lofar_device):
             retrieve the RCU band from filter name, returning the correct format for 
             AntennaField device
         """
-        ANT_mask_RW = [False] * constants.MAX_NUMBER_OF_HBAT
-        RCU_band_select_RW = [0] * constants.MAX_NUMBER_OF_HBAT
+        ANT_mask_RW = [False] * constants.MAX_ANTENNA
+        RCU_band_select_RW = [0] * constants.MAX_ANTENNA
         rcu_band = self.recv_proxy.get_rcu_band_from_filter(filter_name)
         for a in antenna_mask:
             ANT_mask_RW[a] = True
diff --git a/tangostationcontrol/tangostationcontrol/devices/psoc.py b/tangostationcontrol/tangostationcontrol/devices/psoc.py
index 73010d8cb9118a63ae929fd8572f5d5051c151d1..31e1393cec0c5ab09633fa8566fc8deef956b13a 100644
--- a/tangostationcontrol/tangostationcontrol/devices/psoc.py
+++ b/tangostationcontrol/tangostationcontrol/devices/psoc.py
@@ -10,7 +10,6 @@
 # Additional import
 from tangostationcontrol.common.entrypoint import entry
 from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions
-from tangostationcontrol.common.constants import constants
 
 from tango.server import device_property, command
 
@@ -33,6 +32,10 @@ __all__ = ["PSOC", "main"]
 
 @device_logging_to_python()
 class PSOC(snmp_device):
+
+    # number of sockets the psoc has
+    PSOC_SOCKETS = 8
+
     # -----------------
     # Device Properties
     # -----------------
@@ -44,7 +47,7 @@ class PSOC(snmp_device):
     # ----------
     # Attributes
     # ----------
-    sockets_state_R = attribute_wrapper(comms_annotation={"mib": "PowerNet-MIB", "name": "sPDUOutletCtl", "index": 1}, dims=(constants.PSOC_SOCKETS,), datatype=str)
+    sockets_state_R = attribute_wrapper(comms_annotation={"mib": "PowerNet-MIB", "name": "sPDUOutletCtl", "index": 1}, dims=(PSOC_SOCKETS,), datatype=str)
     master_state_R = attribute_wrapper(comms_annotation={"mib": "PowerNet-MIB", "name": "sPDUMasterState"}, datatype=str)
     current_load_R = attribute_wrapper(comms_annotation={"mib": "PowerNet-MIB", "name": "rPDULoadStatusLoad", "index": 1}, datatype=numpy.int64)
     uptime_R = attribute_wrapper(comms_annotation={"mib": "SNMPv2-MIB", "name": "sysUpTime"}, datatype=numpy.int64)
@@ -58,7 +61,7 @@ class PSOC(snmp_device):
         """ user code here. is called when the state is set to STANDBY """
 
         # make sure all sockets are named
-        if len(self.PSOC_sockets) != constants.PSOC_SOCKETS:
+        if len(self.PSOC_sockets) != self.PSOC_SOCKETS:
             raise Exception(
                 f"At least {self.PSOC_NOF_SOCKETS} names are required to be given. You can simply leave any unused sockets as empty strings")
         else:
diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py
index a08abce8656750e05e4fe7f67ba2217ca8a466ce..503daeb6a7d086f21cf740a7e2dbfb3d20c916cf 100644
--- a/tangostationcontrol/tangostationcontrol/devices/recv.py
+++ b/tangostationcontrol/tangostationcontrol/devices/recv.py
@@ -38,9 +38,8 @@ __all__ = ["RECV", "main"]
 @device_logging_to_python()
 class RECV(opcua_device):
 
-    S_ant = constants.S_ant
     N_rcu = constants.N_rcu
-    N_te = constants.N_te
+    N_te = constants.N_elements
     N_pol = constants.N_pol
     N_rcu_inp = constants.N_rcu_inp
 
@@ -63,7 +62,7 @@ class RECV(opcua_device):
     ANT_mask_RW_default = device_property(
         dtype='DevVarBooleanArray',
         mandatory=False,
-        default_value=[True] * S_ant
+        default_value=[True] * N_rcu * N_rcu_inp
     )
 
     RCU_mask_RW_default = device_property(
@@ -75,19 +74,19 @@ class RECV(opcua_device):
     RCU_attenuator_dB_RW_default = device_property(
         dtype='DevVarLong64Array',
         mandatory=False,
-        default_value=[0] * S_ant
+        default_value=[0] * N_rcu * N_rcu_inp
     )
 
     RCU_band_select_RW_default = device_property(
         dtype='DevVarLong64Array',
         mandatory=False,
-        default_value=[0] * S_ant
+        default_value=[0] * N_rcu * N_rcu_inp
     )
 
     RCU_PWR_ANT_on_RW_default = device_property(
         dtype='DevVarBooleanArray',
         mandatory=False,
-        default_value=[False] * S_ant
+        default_value=[False] * N_rcu * N_rcu_inp
         # turn power off by default in test setups, f.e. to prevent blowing up the noise sources
     )
 
@@ -146,23 +145,23 @@ class RECV(opcua_device):
     # Attributes
     # ----------
 
-    ANT_mask_RW = attribute_wrapper(comms_annotation=["ANT_mask_RW"], datatype=bool, dims=(S_ant,),
+    ANT_mask_RW = attribute_wrapper(comms_annotation=["ANT_mask_RW"], datatype=bool, dims=(N_rcu * N_rcu_inp,),
                                     access=AttrWriteType.READ_WRITE)
 
     # The HBAT beamformer delays represent 32 delays for each of the 96 inputs.
     # The 32 delays deconstruct as delays[polarisation][dipole], and each delay is the number of 'delay steps' to apply (0.5ns for HBAT1).
     HBAT_BF_delay_steps_R = attribute_wrapper(comms_annotation=["HBAT_BF_delay_steps_R"], datatype=numpy.int64,
-                                              dims=(S_ant, N_te, N_pol))
+                                              dims=(N_rcu * N_rcu_inp, N_te, N_pol))
     HBAT_BF_delay_steps_RW = attribute_wrapper(comms_annotation=["HBAT_BF_delay_steps_RW"], datatype=numpy.int64,
-                                               dims=(S_ant, N_te, N_pol), access=AttrWriteType.READ_WRITE)
-    HBAT_LED_on_R = attribute_wrapper(comms_annotation=["HBAT_LED_on_R"], datatype=bool, dims=(S_ant, N_te, N_pol))
-    HBAT_LED_on_RW = attribute_wrapper(comms_annotation=["HBAT_LED_on_RW"], datatype=bool, dims=(S_ant, N_te, N_pol),
+                                               dims=(N_rcu * N_rcu_inp, N_te, N_pol), access=AttrWriteType.READ_WRITE)
+    HBAT_LED_on_R = attribute_wrapper(comms_annotation=["HBAT_LED_on_R"], datatype=bool, dims=(N_rcu * N_rcu_inp, N_te, N_pol))
+    HBAT_LED_on_RW = attribute_wrapper(comms_annotation=["HBAT_LED_on_RW"], datatype=bool, dims=(N_rcu * N_rcu_inp, N_te, N_pol),
                                        access=AttrWriteType.READ_WRITE)
-    HBAT_PWR_LNA_on_R = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_R"], datatype=bool, dims=(S_ant, N_te, N_pol))
-    HBAT_PWR_LNA_on_RW = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_RW"], datatype=bool, dims=(S_ant, N_te, N_pol),
+    HBAT_PWR_LNA_on_R = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_R"], datatype=bool, dims=(N_rcu * N_rcu_inp, N_te, N_pol))
+    HBAT_PWR_LNA_on_RW = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_RW"], datatype=bool, dims=(N_rcu * N_rcu_inp, N_te, N_pol),
                                            access=AttrWriteType.READ_WRITE)
-    HBAT_PWR_on_R = attribute_wrapper(comms_annotation=["HBAT_PWR_on_R"], datatype=bool, dims=(S_ant, N_te, N_pol))
-    HBAT_PWR_on_RW = attribute_wrapper(comms_annotation=["HBAT_PWR_on_RW"], datatype=bool, dims=(S_ant, N_te, N_pol),
+    HBAT_PWR_on_R = attribute_wrapper(comms_annotation=["HBAT_PWR_on_R"], datatype=bool, dims=(N_rcu * N_rcu_inp, N_te, N_pol))
+    HBAT_PWR_on_RW = attribute_wrapper(comms_annotation=["HBAT_PWR_on_RW"], datatype=bool, dims=(N_rcu * N_rcu_inp, N_te, N_pol),
                                        access=AttrWriteType.READ_WRITE)
     RCU_ADC_locked_R = attribute_wrapper(comms_annotation=["RCU_ADC_locked_R"], datatype=bool, dims=(N_rcu, N_rcu_inp))
     RCU_attenuator_dB_R = attribute_wrapper(comms_annotation=["RCU_attenuator_dB_R"], datatype=numpy.int64,
@@ -217,7 +216,7 @@ class RECV(opcua_device):
             numpy.uint32)
 
     RCU_error_R = attribute(dtype=(bool,), max_dim_x=N_rcu, fisallowed="is_attribute_access_allowed")
-    ANT_error_R = attribute(dtype=(bool,), max_dim_x=S_ant, fisallowed="is_attribute_access_allowed")
+    ANT_error_R = attribute(dtype=(bool,), max_dim_x=N_rcu * N_rcu_inp, fisallowed="is_attribute_access_allowed")
 
     def read_RCU_error_R(self):
         return self.read_attribute("RCU_mask_RW") & (
@@ -230,7 +229,7 @@ class RECV(opcua_device):
             ~self.read_attribute("RCU_ADC_locked_R").flatten()
         )
 
-    RECV_IOUT_error_R = attribute(dtype=(bool,), max_dim_x=S_ant, fisallowed="is_attribute_access_allowed")
+    RECV_IOUT_error_R = attribute(dtype=(bool,), max_dim_x=N_rcu * N_rcu_inp, fisallowed="is_attribute_access_allowed")
     RECV_TEMP_error_R = attribute(dtype=(bool,), max_dim_x=N_rcu, fisallowed="is_attribute_access_allowed",
                                   polling_period=constants.DEFAULT_POLLING_PERIOD)
     RECV_VOUT_error_R = attribute(dtype=(bool,), max_dim_x=N_rcu, fisallowed="is_attribute_access_allowed")
@@ -326,7 +325,7 @@ class RECV(opcua_device):
         """ converts a signal path delay (in seconds) to an analog beam weight """
 
         # Reshape the flattened input array, into whatever how many tiles we get
-        delays = numpy.array(delays).reshape(-1, constants.N_te)
+        delays = numpy.array(delays).reshape(-1, constants.N_elements)
 
         # Calculate the beam weight array
         HBAT_bf_delay_steps = self._calculate_HBAT_bf_delay_steps(delays)
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py b/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py
index 062db14920b2e1d23317d02d25d7e76a0b0c4fb9..2db9f70dd45a9d2a11b53fe9243373851c0b117f 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py
@@ -35,7 +35,7 @@ class Beamlet(opcua_device):
     N_pol = constants.N_pol
     N_beamlets_ctrl = constants.N_beamlets_ctrl
     N_beamsets_ctrl = constants.N_beamsets_ctrl
-    N_pol_bf = constants.N_pol_bf
+    N_pol_bf = constants.N_pol
     P_sum = constants.P_sum
 
     # -----------------
@@ -165,7 +165,7 @@ class Beamlet(opcua_device):
     FPGA_bf_weights_xy_yx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_yx_R"], datatype=numpy.uint32, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn))
     FPGA_bf_weights_xy_yx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_yx_RW"], datatype=numpy.uint32, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE)
 
-    # cint16[N_pn][N_pol_bf][A_pn][N_pol][N_beamlets_ctrl]
+    # cint16[N_pn][N_pol][A_pn][N_pol][N_beamlets_ctrl]
     # Full Jones matrix of BF weights.
     FPGA_bf_weights_xx_xy_yx_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_xy_yx_yy_R"], datatype=numpy.uint32, dims=(N_pn, N_pol_bf, A_pn, N_pol, N_beamlets_ctrl))
     FPGA_bf_weights_xx_xy_yx_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_xy_yx_yy_RW"], datatype=numpy.uint32, dims=(N_pn, N_pol_bf, A_pn, N_pol, N_beamlets_ctrl), access=AttrWriteType.READ_WRITE)
@@ -320,7 +320,7 @@ class Beamlet(opcua_device):
     def _subband_frequencies(subbands: numpy.ndarray, clock: int, nyquist_zones: numpy.ndarray) -> numpy.ndarray:
         """ Obtain the frequencies of each subband, given a clock and an antenna type. """
 
-        subband_width = clock / constants.N_subband_pts
+        subband_width = clock / constants.N_subband_res
         base_subbands = nyquist_zones * constants.N_subbands
 
         # broadcast clock across frequencies
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py b/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py
index 6770f738a0a43e23919f8a73cf49f012f3827a21..b7ae61b8f7fd3d6720a4561b8c8eae1181933b98 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py
@@ -73,10 +73,10 @@ class DigitalBeam(beam_device):
         dtype=numpy.float64, fget=lambda self: self._delays.statistics["last"] or 0)
 
     input_select_RW = attribute(doc='Selection of inputs to use for forming each beamlet. Allows selecting broken antennas.',
-                                dtype=((bool,),), max_dim_x=constants.N_beamlets_ctrl, max_dim_y=constants.S_ant, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed")
+                                dtype=((bool,),), max_dim_x=constants.N_beamlets_ctrl, max_dim_y=constants.MAX_ANTENNA, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed")
 
     antenna_select_RW = attribute(doc='Selection of antennas desired to use for forming each beamlet (= a subset of input_select of the configured antennas). Unselects broken antennas.',
-                                  dtype=((bool,),), max_dim_x=constants.N_beamlets_ctrl, max_dim_y=constants.S_ant, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed")
+                                  dtype=((bool,),), max_dim_x=constants.N_beamlets_ctrl, max_dim_y=constants.MAX_ANTENNA, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed")
 
     nr_inputs_R = attribute(doc='Number of configured inputs from the associated antenna field.',
                                   dtype=numpy.uint32, fget="nr_inputs")
@@ -144,7 +144,7 @@ class DigitalBeam(beam_device):
 
         # Generate positions for all FPGA inputs.
         # Use reference position for any missing antennas so they always get a delay of 0
-        input_itrf = numpy.array([reference_itrf] * constants.S_ant)
+        input_itrf = numpy.array([reference_itrf] * constants.MAX_ANTENNA)
         for antenna_nr, (fpga_nr, input_nr) in enumerate(self.antennafield_proxy.Antenna_to_SDP_Mapping_R):
             if input_nr >= 0:
                 input_itrf[fpga_nr * constants.A_pn + input_nr] = antenna_itrf[antenna_nr]
@@ -157,7 +157,7 @@ class DigitalBeam(beam_device):
         self.relative_input_positions = input_itrf - reference_itrf
 
         # use all antennas in the mapping for all beamlets, unless specified otherwise
-        self.write_input_select_RW(numpy.zeros((constants.S_ant, constants.N_beamlets_ctrl), dtype=bool))
+        self.write_input_select_RW(numpy.zeros((constants.MAX_ANTENNA, constants.N_beamlets_ctrl), dtype=bool))
         self.write_antenna_select_RW(numpy.ones((self.nr_inputs(), constants.N_beamlets_ctrl), dtype=bool))
 
     # --------
@@ -172,7 +172,7 @@ class DigitalBeam(beam_device):
         Returns delays[antenna][beamlet]
         """
 
-        delays = numpy.zeros((constants.S_ant, constants.N_beamlets_ctrl), dtype=numpy.float64)
+        delays = numpy.zeros((constants.MAX_ANTENNA, constants.N_beamlets_ctrl), dtype=numpy.float64)
 
         d = self.delay_calculator
         d.set_measure_time(timestamp)
@@ -186,7 +186,7 @@ class DigitalBeam(beam_device):
         """ Converts an array with dimensions [antenna][beamlet] -> [fpga_nr][input_nr][pol_nr][beamlet]
             by repeating the values for both polarisations. """
 
-        assert arr.shape == (constants.S_ant, constants.N_beamlets_ctrl)
+        assert arr.shape == (constants.MAX_ANTENNA, constants.N_beamlets_ctrl)
 
         # Each antenna maps on [fpga_nr][input_nr][0] and [fpga_nr][input_nr][1], and we work
         # with [antenna][beamlet], so we have to interleave copies of the input array per beamlet
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
index 2ff880cf4e4a6a586f39a058a0dd71e878a79ff5..1e1b24f233444b1a6214344078d55a1f8ec4d682 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
@@ -69,7 +69,7 @@ class SDP(opcua_device):
         dtype='DevVarDoubleArray',
         mandatory=False,
         # Emit a signal on subband 102
-        default_value=[[constants.DEFAULT_SUBBAND * float(constants.CLK_200_MHZ) / constants.N_subband_pts] * S_pn] * N_pn
+        default_value=[[constants.DEFAULT_SUBBAND * float(constants.CLK_200_MHZ) / constants.N_subband_res] * S_pn] * N_pn
     )
 
     FPGA_wg_phase_RW_default = device_property(
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
index 117742d5fe4ac5acf6846664b556f6903f8b9c0c..4f1d62947356e90173fcdd4095a8088dcb29576d 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
@@ -40,6 +40,9 @@ class Statistics(opcua_device):
     def STATISTICS_COLLECTOR_CLASS(self):
         raise NotImplementedError
 
+    # Maximum number of supported simultaneous replicator clients
+    MAX_STATISTICS_CLIENTS = 128
+
     # -----------------
     # Device Properties
     # -----------------
@@ -64,7 +67,7 @@ class Statistics(opcua_device):
     # number of UDP packets that were dropped because we couldn't keep up with processing
     nof_packets_dropped_R   = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "udp", "parameter": "nof_packets_dropped"}, datatype=numpy.uint64)
     # last packet we processed
-    last_packet_R           = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "udp", "parameter": "last_packet"}, dims=(constants.MAX_PACKET_SIZE,), datatype=numpy.uint8)
+    last_packet_R           = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "udp", "parameter": "last_packet"}, dims=(constants.MAX_ETH_FRAME_SIZE,), datatype=numpy.uint8)
     # when last packet was received
     last_packet_timestamp_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "udp", "parameter": "last_packet_timestamp"}, datatype=numpy.uint64)
 
@@ -73,7 +76,7 @@ class Statistics(opcua_device):
     queue_collector_fill_percentage_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "queue", "parameter": "collector_fill_percentage"}, datatype=numpy.uint64)
     queue_replicator_fill_percentage_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "queue", "parameter": "replicator_fill_percentage"}, datatype=numpy.uint64)
 
-    replicator_clients_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "replicator", "parameter": "clients"}, dims=(constants.MAX_STATISTICS_CLIENTS,), datatype=str)
+    replicator_clients_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "replicator", "parameter": "clients"}, dims=(MAX_STATISTICS_CLIENTS,), datatype=str)
     replicator_nof_bytes_sent_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "replicator", "parameter": "nof_bytes_sent"}, datatype=numpy.uint64)
 
     replicator_nof_packets_sent_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "replicator", "parameter": "nof_packets_sent"}, datatype=numpy.uint64)
@@ -84,7 +87,7 @@ class Statistics(opcua_device):
     # number of invalid (non-SST) packets received
     nof_invalid_packets_R   = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "nof_invalid_packets"}, datatype=numpy.uint64)
     # last packet that could not be parsed
-    last_invalid_packet_R   = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "last_invalid_packet"}, dims=(constants.MAX_PACKET_SIZE,), datatype=numpy.uint8)
+    last_invalid_packet_R   = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "last_invalid_packet"}, dims=(constants.MAX_ETH_FRAME_SIZE,), datatype=numpy.uint8)
     # what the last exception was
     last_invalid_packet_exception_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "last_invalid_packet_exception"}, datatype=str)
 
diff --git a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py
index c175963a3533163e888119d8d7ac811b410dab37..1207eaab54560684d89dbe9e8c2726fd960b8c85 100644
--- a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py
+++ b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py
@@ -58,7 +58,7 @@ class TileBeam(beam_device):
 
         # Retrieve positions from AntennaField device
         Antenna_Reference_itrf = self.antennafield_proxy.Antenna_Reference_itrf_R
-        HBAT_antenna_itrf_offsets = self.antennafield_proxy.HBAT_antenna_itrf_offsets_R.reshape(self._nr_tiles, constants.N_te, constants.N_xyz)
+        HBAT_antenna_itrf_offsets = self.antennafield_proxy.HBAT_antenna_itrf_offsets_R.reshape(self._nr_tiles, constants.N_elements, constants.N_xyz)
 
         # a delay calculator for each tile
         self.HBAT_delay_calculators = [Delays(reference_itrf) for reference_itrf in Antenna_Reference_itrf]
@@ -77,7 +77,7 @@ class TileBeam(beam_device):
         Returns delays[tile][element]
         """
 
-        delays = numpy.zeros((self._nr_tiles, constants.N_te), dtype=numpy.float64)
+        delays = numpy.zeros((self._nr_tiles, constants.N_elements), dtype=numpy.float64)
 
         for tile in range(self._nr_tiles):
             # initialise delay calculator
@@ -107,7 +107,7 @@ class TileBeam(beam_device):
     @TimeIt()
     def _apply_weights(self, pointing_direction: numpy.array, timestamp: datetime.datetime, bf_delay_steps: numpy.array):
         # Write weights to RECV through the AntennaToRecvMapper
-        self.antennafield_proxy.HBAT_bf_delay_steps_RW = bf_delay_steps.reshape(self._nr_tiles, constants.N_te * constants.N_pol)
+        self.antennafield_proxy.HBAT_bf_delay_steps_RW = bf_delay_steps.reshape(self._nr_tiles, constants.N_elements * constants.N_pol)
 
         # Record where we now point to, now that we've updated the weights.
         # Only the entries within the mask have been updated