diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..929b6bb4f5a33f37a97181698c5a0626021018f0
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+* text eol=lf
+
+*.py text
+*.json text
+*.sh text
+
+*.png binary
+*.h5 binary
+*.jpg binary
+*.bin binary
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ca3a617c1b052564c46e2a5e426fe9a1e86787d6..0371a7f7f806a9a6e9ac5c22d8c5562c6880a4eb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -33,7 +33,6 @@ bandit:
     - tox -e bandit
 shellcheck:
   stage: static-analysis
-  allow_failure: true
   before_script:
     - sudo apt-get update
     - sudo apt-get install -y shellcheck
@@ -44,11 +43,9 @@ unit_test:
   before_script:
     - sudo apt-get update
     - sudo apt-get install -y git
-    - pip3 install -r devices/test-requirements.txt
-    - pip3 install -r docker-compose/itango/lofar-requirements.txt
   script:
     - cd devices
-    - tox -e py37
+    - tox --recreate -e py37
 integration_test:
   stage: integration-tests
   allow_failure: true
diff --git a/CDB/LOFAR_ConfigDb.json b/CDB/LOFAR_ConfigDb.json
index c7fc852c35cb9fcff76b24ab0e10664e17489156..e903a459ef687aa8ee11164c58cc0c22c43c1347 100644
--- a/CDB/LOFAR_ConfigDb.json
+++ b/CDB/LOFAR_ConfigDb.json
@@ -1,977 +1,869 @@
-{
-    "servers": {
-        "docker_device": {
-            "LTS": {
-                "Docker": {
-                    "LTS/Docker/1": {}
-                }
-            }
-        },
-        "Femto": {
-            "CS999": {
-                "Femto": {
-                    "opc-ua/test-femto/1": {}
-                }
-            }
-        },
-        "observation_control": {
-            "LTS": {
-                "ObservationControl": {
-                    "LTS/ObservationControl/1": {}
-                }
-            }
-        },
-        "RECV": {
-            "LTS": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "attribute_properties": {
-                            "Ant_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_Enable_PWR_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_I2C_STATUS_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "CLK_PLL_error_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_PLL_locked_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_monitor_rate_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "CLK_translator_busy_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "HBA_element_LNA_pwr_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_LNA_pwr_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_beamformer_delays_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_beamformer_delays_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_led_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_led_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_pwr_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_pwr_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_ADC_lock_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_I2C_STATUS_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_ID_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_LED0_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_LED0_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_LED1_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_LED1_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_Pwr_dig_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_attenuator_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_attenuator_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_band_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_band_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_monitor_rate_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ],
-                                "rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ]
-                            },
-                            "RCU_temperature_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ],
-                                "rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ]
-                            },
-                            "RCU_translator_busy_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_version_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "State": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "event_period": [
-                                    "0"
-                                ]
-                            },
-                            "Status": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "event_period": [
-                                    "0"
-                                ]
-                            }
-                        },
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "ltspi.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ],
-                            "polled_attr": [
-                                "state",
-                                "1000",
-                                "status",
-                                "1000",
-                                "ant_mask_rw",
-                                "1000",
-                                "rcu_adc_lock_r",
-                                "1000",
-                                "rcu_attenuator_r",
-                                "1000",
-                                "rcu_attenuator_rw",
-                                "1000",
-                                "rcu_band_r",
-                                "1000",
-                                "rcu_band_rw",
-                                "1000",
-                                "rcu_id_r",
-                                "1000",
-                                "rcu_led0_r",
-                                "1000",
-                                "rcu_led0_rw",
-                                "1000",
-                                "rcu_mask_rw",
-                                "1000",
-                                "rcu_monitor_rate_rw",
-                                "1000",
-                                "rcu_pwr_dig_r",
-                                "1000",
-                                "rcu_temperature_r",
-                                "1000",
-                                "rcu_version_r",
-                                "1000",
-                                "hba_element_beamformer_delays_r",
-                                "1000",
-                                "hba_element_beamformer_delays_rw",
-                                "1000",
-                                "hba_element_led_r",
-                                "1000",
-                                "hba_element_led_rw",
-                                "1000",
-                                "hba_element_pwr_r",
-                                "1000",
-                                "hba_element_pwr_rw",
-                                "1000",
-                                "clk_enable_pwr_r",
-                                "1000",
-                                "clk_i2c_status_r",
-                                "1000",
-                                "clk_monitor_rate_rw",
-                                "1000",
-                                "clk_pll_error_r",
-                                "1000",
-                                "clk_pll_locked_r",
-                                "1000",
-                                "clk_translator_busy_r",
-                                "1000",
-                                "hba_element_lna_pwr_r",
-                                "1000",
-                                "hba_element_lna_pwr_rw",
-                                "1000",
-                                "rcu_i2c_status_r",
-                                "1000",
-                                "rcu_led1_r",
-                                "1000",
-                                "rcu_led1_rw",
-                                "1000",
-                                "rcu_translator_busy_r",
-                                "1000"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "random_data": {
-            "LTS": {
-                "Random_Data": {
-                    "LTS/random_data/1": {
-                        "properties": {
-                            "polled_attr": [
-                                "rnd1",
-                                "1000",
-                                "rnd2",
-                                "1000",
-                                "rnd3",
-                                "1000",
-                                "rnd4",
-                                "1000",
-                                "rnd5",
-                                "1000",
-                                "rnd6",
-                                "1000",
-                                "rnd7",
-                                "1000",
-                                "rnd8",
-                                "1000",
-                                "rnd9",
-                                "1000",
-                                "rnd10",
-                                "1000",
-                                "rnd11",
-                                "1000",
-                                "rnd12",
-                                "1000",
-                                "rnd13",
-                                "1000",
-                                "rnd14",
-                                "1000",
-                                "rnd15",
-                                "1000",
-                                "rnd16",
-                                "1000",
-                                "rnd17",
-                                "1000",
-                                "rnd18",
-                                "1000",
-                                "rnd19",
-                                "1000",
-                                "rnd20",
-                                "1000",
-                                "rnd21",
-                                "1000",
-                                "state",
-                                "1000",
-                                "status",
-                                "1000"
-                            ]
-                        }
-                    },
-                    "LTS/random_data/2": {
-                        "properties": {
-                            "polled_attr": [
-                                "rnd1",
-                                "100",
-                                "rnd2",
-                                "100",
-                                "rnd3",
-                                "100",
-                                "rnd4",
-                                "100",
-                                "rnd5",
-                                "100",
-                                "rnd6",
-                                "100",
-                                "rnd7",
-                                "100",
-                                "rnd8",
-                                "100",
-                                "rnd9",
-                                "100",
-                                "rnd10",
-                                "100",
-                                "rnd11",
-                                "100",
-                                "rnd12",
-                                "100",
-                                "rnd13",
-                                "100",
-                                "rnd14",
-                                "100",
-                                "rnd15",
-                                "100",
-                                "rnd16",
-                                "100",
-                                "rnd17",
-                                "100",
-                                "rnd18",
-                                "100",
-                                "rnd19",
-                                "100",
-                                "rnd20",
-                                "100"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "LTS": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "attribute_properties": {
-                            "SDP_mask_RW": {
-                                "event_period": [
-                                    "60000"
-                                ]
-                            },
-                            "State": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "Status": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_scrap_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_scrap_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_status_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_temp_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_version_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_weights_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_weights_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "tr_busy_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "tr_reload_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "tr_tod_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "tr_uptime_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-3600",
-                                    "3600"
-                                ],
-                                "rel_change": [
-                                    "-10",
-                                    "10"
-                                ]
-                            }
-                        },
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ],
-                            "FPGA_sdp_info_station_id_RW_default": [
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901",
-                                "901"
-                            ],
-                            "polled_attr": [
-                                "fpga_temp_r",
-                                "1000",
-                                "state",
-                                "1000",
-                                "status",
-                                "1000",
-                                "fpga_mask_rw",
-                                "1000",
-                                "fpga_scrap_r",
-                                "1000",
-                                "fpga_scrap_rw",
-                                "1000",
-                                "fpga_status_r",
-                                "1000",
-                                "fpga_version_r",
-                                "1000",
-                                "fpga_weights_r",
-                                "1000",
-                                "fpga_weights_rw",
-                                "1000",
-                                "tr_busy_r",
-                                "1000",
-                                "tr_reload_rw",
-                                "1000",
-                                "tr_tod_r",
-                                "1000",
-                                "tr_uptime_r",
-                                "1000"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SST": {
-            "LTS": {
-                "SST": {
-                    "LTS/SST/1": {
-                        "properties": {
-                            "Statistics_Client_UDP_Port": [
-                                "5001"
-                            ],
-                            "Statistics_Client_TCP_Port": [
-                                "5101"
-                            ],
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ],
-                            "FPGA_sst_offload_hdr_eth_destination_mac_RW_default": [
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd"
-                            ],
-                            "FPGA_sst_offload_hdr_ip_destination_address_RW_default": [
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250"
-                            ],
-                            "FPGA_sst_offload_hdr_udp_destination_port_RW_default": [
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001",
-                                "5001"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "XST": {
-            "LTS": {
-                "XST": {
-                    "LTS/XST/1": {
-                        "properties": {
-                            "Statistics_Client_UDP_Port": [
-                                "5002"
-                            ],
-                            "Statistics_Client_TCP_Port": [
-                                "5102"
-                            ],
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ],
-                            "FPGA_xst_offload_hdr_eth_destination_mac_RW_default": [
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd",
-                                "6c:2b:59:97:be:dd"
-                            ],
-                            "FPGA_xst_offload_hdr_ip_destination_address_RW_default": [
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250",
-                                "10.99.250.250"
-                            ],
-                            "FPGA_xst_offload_hdr_udp_destination_port_RW_default": [
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002",
-                                "5002"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "UNB2": {
-            "LTS": {
-                "UNB2": {
-                    "LTS/UNB2/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "despi.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "StatsCrosslet": {
-            "CS997": {
-                "StatsCrosslet": {
-                    "opc-ua/test-crossletstats/1": {
-                        "attribute_properties": {
-                            "visibilities_imag": {
-                                "archive_rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ],
-                                "rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ]
-                            },
-                            "visibilities_real": {
-                                "archive_rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ],
-                                "rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ]
-                            }
-                        },
-                        "properties": {
-                            "polled_attr": [
-                                "integration_time",
-                                "0",
-                                "pause_time",
-                                "0",
-                                "rcu_modes",
-                                "0",
-                                "state",
-                                "0",
-                                "status",
-                                "0",
-                                "subband",
-                                "0",
-                                "time_stamp",
-                                "0",
-                                "visibilities_imag",
-                                "0",
-                                "visibilities_real",
-                                "0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "docker_device": {
+            "LTS": {
+                "Docker": {
+                    "LTS/Docker/1": {}
+                }
+            }
+        },
+        "Femto": {
+            "CS999": {
+                "Femto": {
+                    "opc-ua/test-femto/1": {}
+                }
+            }
+        },
+        "observation_control": {
+            "LTS": {
+                "ObservationControl": {
+                    "LTS/ObservationControl/1": {}
+                }
+            }
+        },
+        "boot": {
+            "LTS": {
+                "Boot": {
+                    "LTS/Boot/1": {}
+                }
+            }
+        },
+        "APSCT": {
+            "LTS": {
+                "APSCT": {
+                    "LTS/APSCT/1": {
+                        "properties": {
+                        }
+                    }
+                }
+            }
+        },
+        "APSPU": {
+            "LTS": {
+                "APSPU": {
+                    "LTS/APSPU/1": {
+                        "properties": {
+                        }
+                    }
+                }
+            }
+        },
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "attribute_properties": {
+                            "Ant_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_Enable_PWR_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_I2C_STATUS_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "CLK_PLL_error_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_PLL_locked_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_monitor_rate_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "CLK_translator_busy_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "HBA_element_LNA_pwr_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_LNA_pwr_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_beamformer_delays_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_beamformer_delays_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_led_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_led_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_pwr_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_pwr_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_ADC_lock_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_I2C_STATUS_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_ID_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_LED0_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_LED0_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_LED1_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_LED1_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_Pwr_dig_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_attenuator_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_attenuator_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_band_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_band_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_monitor_rate_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ],
+                                "rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ]
+                            },
+                            "RCU_temperature_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ],
+                                "rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ]
+                            },
+                            "RCU_translator_busy_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_version_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "State": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "event_period": [
+                                    "0"
+                                ]
+                            },
+                            "Status": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "event_period": [
+                                    "0"
+                                ]
+                            }
+                        },
+                        "properties": {
+                            "polled_attr": [
+                                "state",
+                                "1000",
+                                "status",
+                                "1000",
+                                "ant_mask_rw",
+                                "1000",
+                                "rcu_adc_lock_r",
+                                "1000",
+                                "rcu_attenuator_r",
+                                "1000",
+                                "rcu_attenuator_rw",
+                                "1000",
+                                "rcu_band_r",
+                                "1000",
+                                "rcu_band_rw",
+                                "1000",
+                                "rcu_id_r",
+                                "1000",
+                                "rcu_led0_r",
+                                "1000",
+                                "rcu_led0_rw",
+                                "1000",
+                                "rcu_mask_rw",
+                                "1000",
+                                "rcu_monitor_rate_rw",
+                                "1000",
+                                "rcu_pwr_dig_r",
+                                "1000",
+                                "rcu_temperature_r",
+                                "1000",
+                                "rcu_version_r",
+                                "1000",
+                                "hba_element_beamformer_delays_r",
+                                "1000",
+                                "hba_element_beamformer_delays_rw",
+                                "1000",
+                                "hba_element_led_r",
+                                "1000",
+                                "hba_element_led_rw",
+                                "1000",
+                                "hba_element_pwr_r",
+                                "1000",
+                                "hba_element_pwr_rw",
+                                "1000",
+                                "clk_enable_pwr_r",
+                                "1000",
+                                "clk_i2c_status_r",
+                                "1000",
+                                "clk_monitor_rate_rw",
+                                "1000",
+                                "clk_pll_error_r",
+                                "1000",
+                                "clk_pll_locked_r",
+                                "1000",
+                                "clk_translator_busy_r",
+                                "1000",
+                                "hba_element_lna_pwr_r",
+                                "1000",
+                                "hba_element_lna_pwr_rw",
+                                "1000",
+                                "rcu_i2c_status_r",
+                                "1000",
+                                "rcu_led1_r",
+                                "1000",
+                                "rcu_led1_rw",
+                                "1000",
+                                "rcu_translator_busy_r",
+                                "1000"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "random_data": {
+            "LTS": {
+                "Random_Data": {
+                    "LTS/random_data/1": {
+                        "properties": {
+                            "polled_attr": [
+                                "rnd1",
+                                "1000",
+                                "rnd2",
+                                "1000",
+                                "rnd3",
+                                "1000",
+                                "rnd4",
+                                "1000",
+                                "rnd5",
+                                "1000",
+                                "rnd6",
+                                "1000",
+                                "rnd7",
+                                "1000",
+                                "rnd8",
+                                "1000",
+                                "rnd9",
+                                "1000",
+                                "rnd10",
+                                "1000",
+                                "rnd11",
+                                "1000",
+                                "rnd12",
+                                "1000",
+                                "rnd13",
+                                "1000",
+                                "rnd14",
+                                "1000",
+                                "rnd15",
+                                "1000",
+                                "rnd16",
+                                "1000",
+                                "rnd17",
+                                "1000",
+                                "rnd18",
+                                "1000",
+                                "rnd19",
+                                "1000",
+                                "rnd20",
+                                "1000",
+                                "rnd21",
+                                "1000",
+                                "state",
+                                "1000",
+                                "status",
+                                "1000"
+                            ]
+                        }
+                    },
+                    "LTS/random_data/2": {
+                        "properties": {
+                            "polled_attr": [
+                                "rnd1",
+                                "100",
+                                "rnd2",
+                                "100",
+                                "rnd3",
+                                "100",
+                                "rnd4",
+                                "100",
+                                "rnd5",
+                                "100",
+                                "rnd6",
+                                "100",
+                                "rnd7",
+                                "100",
+                                "rnd8",
+                                "100",
+                                "rnd9",
+                                "100",
+                                "rnd10",
+                                "100",
+                                "rnd11",
+                                "100",
+                                "rnd12",
+                                "100",
+                                "rnd13",
+                                "100",
+                                "rnd14",
+                                "100",
+                                "rnd15",
+                                "100",
+                                "rnd16",
+                                "100",
+                                "rnd17",
+                                "100",
+                                "rnd18",
+                                "100",
+                                "rnd19",
+                                "100",
+                                "rnd20",
+                                "100"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "attribute_properties": {
+                            "SDP_mask_RW": {
+                                "event_period": [
+                                    "60000"
+                                ]
+                            },
+                            "State": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "Status": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_scrap_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_scrap_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_status_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_temp_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_version_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_weights_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_weights_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "tr_busy_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "tr_reload_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "tr_tod_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "tr_uptime_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-3600",
+                                    "3600"
+                                ],
+                                "rel_change": [
+                                    "-10",
+                                    "10"
+                                ]
+                            }
+                        },
+                        "properties": {
+                            "polled_attr": [
+                                "fpga_temp_r",
+                                "1000",
+                                "state",
+                                "1000",
+                                "status",
+                                "1000",
+                                "fpga_mask_rw",
+                                "1000",
+                                "fpga_scrap_r",
+                                "1000",
+                                "fpga_scrap_rw",
+                                "1000",
+                                "fpga_status_r",
+                                "1000",
+                                "fpga_version_r",
+                                "1000",
+                                "fpga_weights_r",
+                                "1000",
+                                "fpga_weights_rw",
+                                "1000",
+                                "tr_busy_r",
+                                "1000",
+                                "tr_reload_rw",
+                                "1000",
+                                "tr_tod_r",
+                                "1000",
+                                "tr_uptime_r",
+                                "1000"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "Statistics_Client_UDP_Port": [
+                                "5001"
+                            ],
+                            "Statistics_Client_TCP_Port": [
+                                "5101"
+                            ],
+                            "FPGA_sst_offload_hdr_udp_destination_port_RW_default": [
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001"
+                            ]
+                       }
+                    }
+                }
+            }
+        },
+        "XST": {
+            "LTS": {
+                "XST": {
+                    "LTS/XST/1": {
+                        "properties": {
+                            "Statistics_Client_UDP_Port": [
+                                "5002"
+                            ],
+                            "Statistics_Client_TCP_Port": [
+                                "5102"
+                            ],
+                            "FPGA_xst_offload_hdr_udp_destination_port_RW_default": [
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "UNB2": {
+            "LTS": {
+                "UNB2": {
+                    "LTS/UNB2/1": {
+                        "properties": {
+                        }
+                    }
+                }
+            }
+        },
+        "StatsCrosslet": {
+            "CS997": {
+                "StatsCrosslet": {
+                    "opc-ua/test-crossletstats/1": {
+                        "attribute_properties": {
+                            "visibilities_imag": {
+                                "archive_rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ],
+                                "rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ]
+                            },
+                            "visibilities_real": {
+                                "archive_rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ],
+                                "rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ]
+                            }
+                        },
+                        "properties": {
+                            "polled_attr": [
+                                "integration_time",
+                                "0",
+                                "pause_time",
+                                "0",
+                                "rcu_modes",
+                                "0",
+                                "state",
+                                "0",
+                                "status",
+                                "0",
+                                "subband",
+                                "0",
+                                "time_stamp",
+                                "0",
+                                "visibilities_imag",
+                                "0",
+                                "visibilities_real",
+                                "0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/MAXIV-ConfigDb.json b/CDB/MAXIV-ConfigDb.json
index 5c4c63a977632948cb6351169902d4654fe376ae..2087ec3feb67a7ed362fd415a9ab4c654d6741f6 100644
--- a/CDB/MAXIV-ConfigDb.json
+++ b/CDB/MAXIV-ConfigDb.json
@@ -1,24 +1,24 @@
-{
-    "servers": {
-        "Femto": {
-        "TangoRestServer": {
-            "tango-rest": {
-                "TangoRestServer": {
-                    "tango-rest/rest/0": {
-                        "properties": {
-                            "TANGO_DB": [
-                                "tango://databaseds:10000/sys/database/2"
-                            ],
-                            "TOMCAT_AUTH_METHOD": [
-                                "plain"
-                            ],
-                            "TOMCAT_PORT": [
-                                "8080"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "Femto": {
+        "TangoRestServer": {
+            "tango-rest": {
+                "TangoRestServer": {
+                    "tango-rest/rest/0": {
+                        "properties": {
+                            "TANGO_DB": [
+                                "tango://databaseds:10000/sys/database/2"
+                            ],
+                            "TOMCAT_AUTH_METHOD": [
+                                "plain"
+                            ],
+                            "TOMCAT_PORT": [
+                                "8080"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/default_ConfigDb.json b/CDB/default_ConfigDb.json
index 52e0cb91f9c04a2a6fd732ae859c5c619a5e8c7b..a33ece273af53c2a3934b49b4d1d09b539ae0dc8 100644
--- a/CDB/default_ConfigDb.json
+++ b/CDB/default_ConfigDb.json
@@ -1,80 +1,80 @@
-{
-    "servers": {
-        "DataBaseds": {
-            "2": {
-                "DataBase": {
-                    "sys/database/2": {}
-                }
-            }
-        }, 
-        "TangoAccessControl": {
-            "1": {
-                "TangoAccessControl": {
-                    "sys/access_control/1": {}
-                }
-            }
-        }, 
-        "TangoRestServer": {
-            "rest": {
-                "TangoRestServer": {
-                    "sys/rest/0": {}
-                }
-            }
-        }, 
-        "TangoTest": {
-            "test": {
-                "TangoTest": {
-                    "sys/tg_test/1": {}
-                }
-            }
-        }, 
-        "hdbppcm-srv": {
-            "01": {
-                "HdbConfigurationManager": {
-                    "archiving/hdbpp/confmanager01": {
-                        "properties": {
-                            "ArchiverList": [
-                                "archiving/hdbpp/eventsubscriber01"
-                            ], 
-                            "LibConfiguration": [
-                                "host=archiver-maria-db", 
-                                "libname=libhdb++mysql.so.6", 
-                                "dbname=hdbpp", 
-                                "port=3306", 
-                                "user=tango", 
-                                "password=tango"
-                            ], 
-                            "MaxSearchSize": [
-                                "1000"
-                            ]
-                        }
-                    }
-                }
-            }
-        }, 
-        "hdbppes-srv": {
-            "01": {
-                "HdbEventSubscriber": {
-                    "archiving/hdbpp/eventsubscriber01": {
-                        "properties": {
-                            "CheckPeriodicTimeoutDelay": [
-                                "5"
-                            ], 
-                            "LibConfiguration": [
-                                "host=archiver-maria-db", 
-                                "libname=libhdb++mysql.so.6", 
-                                "dbname=hdbpp", 
-                                "port=3306", 
-                                "user=tango", 
-                                "password=tango"
-                            ], 
-                            "PollingThreadPeriod": [
-                                "3"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "DataBaseds": {
+            "2": {
+                "DataBase": {
+                    "sys/database/2": {}
+                }
+            }
+        }, 
+        "TangoAccessControl": {
+            "1": {
+                "TangoAccessControl": {
+                    "sys/access_control/1": {}
+                }
+            }
+        }, 
+        "TangoRestServer": {
+            "rest": {
+                "TangoRestServer": {
+                    "sys/rest/0": {}
+                }
+            }
+        }, 
+        "TangoTest": {
+            "test": {
+                "TangoTest": {
+                    "sys/tg_test/1": {}
+                }
+            }
+        }, 
+        "hdbppcm-srv": {
+            "01": {
+                "HdbConfigurationManager": {
+                    "archiving/hdbpp/confmanager01": {
+                        "properties": {
+                            "ArchiverList": [
+                                "archiving/hdbpp/eventsubscriber01"
+                            ], 
+                            "LibConfiguration": [
+                                "host=archiver-maria-db", 
+                                "libname=libhdb++mysql.so.6", 
+                                "dbname=hdbpp", 
+                                "port=3306", 
+                                "user=tango", 
+                                "password=tango"
+                            ], 
+                            "MaxSearchSize": [
+                                "1000"
+                            ]
+                        }
+                    }
+                }
+            }
+        }, 
+        "hdbppes-srv": {
+            "01": {
+                "HdbEventSubscriber": {
+                    "archiving/hdbpp/eventsubscriber01": {
+                        "properties": {
+                            "CheckPeriodicTimeoutDelay": [
+                                "5"
+                            ], 
+                            "LibConfiguration": [
+                                "host=archiver-maria-db", 
+                                "libname=libhdb++mysql.so.6", 
+                                "dbname=hdbpp", 
+                                "port=3306", 
+                                "user=tango", 
+                                "password=tango"
+                            ], 
+                            "PollingThreadPeriod": [
+                                "3"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/integration_ConfigDb.json b/CDB/integration_ConfigDb.json
index 46e7b25bc23440689d8ac41a5c50a37f50b63baa..aa67083d5c849d9fb653726f71387d71057923a1 100644
--- a/CDB/integration_ConfigDb.json
+++ b/CDB/integration_ConfigDb.json
@@ -1,5 +1,43 @@
 {
     "servers": {
+        "APSCT": {
+            "LTS": {
+                "APSCT": {
+                    "LTS/APSCT/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "apsct-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4843"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "APSPU": {
+            "LTS": {
+                "APSPU": {
+                    "LTS/APSPU/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "apspu-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4843"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
         "RECV": {
             "LTS": {
                 "RECV": {
@@ -9,7 +47,7 @@
                                 "recv-sim"
                             ],
                             "OPC_Server_Port": [
-                                "4843"
+                                "4840"
                             ],
                             "OPC_Time_Out": [
                                 "5.0"
@@ -253,7 +291,7 @@
                                 "unb2-sim"
                             ],
                             "OPC_Server_Port": [
-                                "4844"
+                                "4841"
                             ],
                             "OPC_Time_Out": [
                                 "5.0"
diff --git a/CDB/jasper_ConfigDb.json b/CDB/jasper_ConfigDb.json
index b8ce969d8a47e9b5ebba6402f29a84579c88bebd..8455c1859e4a122f38b95be929c81a3af164aede 100644
--- a/CDB/jasper_ConfigDb.json
+++ b/CDB/jasper_ConfigDb.json
@@ -1,816 +1,816 @@
-{
-    "servers": {
-        "Femto": {
-            "CS999": {
-                "Femto": {
-                    "opc-ua/test-femto/1": {}
-                }
-            }
-        },
-        "observation_control": {
-            "LTS": {
-                "ObservationControl": {
-                    "LTS/ObservationControl/1": {}
-                }
-            }
-        },
-        "RECV": {
-            "LTS": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "attribute_properties": {
-                            "Ant_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_Enable_PWR_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_I2C_STATUS_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "CLK_PLL_error_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_PLL_locked_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "CLK_monitor_rate_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "CLK_translator_busy_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "HBA_element_LNA_pwr_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_LNA_pwr_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_beamformer_delays_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_beamformer_delays_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_led_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_led_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_pwr_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "HBA_element_pwr_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_ADC_lock_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_I2C_STATUS_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_ID_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_LED0_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_LED0_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_LED1_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_LED1_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_Pwr_dig_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_attenuator_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_attenuator_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_band_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_band_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "RCU_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_monitor_rate_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ],
-                                "rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ]
-                            },
-                            "RCU_temperature_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ],
-                                "rel_change": [
-                                    "-1.0",
-                                    "1.0"
-                                ]
-                            },
-                            "RCU_translator_busy_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "RCU_version_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "State": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "event_period": [
-                                    "0"
-                                ]
-                            },
-                            "Status": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "event_period": [
-                                    "0"
-                                ]
-                            }
-                        },
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "ltspi.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ],
-                            "polled_attr": [
-                                "state",
-                                "1000",
-                                "status",
-                                "1000",
-                                "ant_mask_rw",
-                                "1000",
-                                "rcu_adc_lock_r",
-                                "1000",
-                                "rcu_attenuator_r",
-                                "1000",
-                                "rcu_attenuator_rw",
-                                "1000",
-                                "rcu_band_r",
-                                "1000",
-                                "rcu_band_rw",
-                                "1000",
-                                "rcu_id_r",
-                                "1000",
-                                "rcu_led0_r",
-                                "1000",
-                                "rcu_led0_rw",
-                                "1000",
-                                "rcu_mask_rw",
-                                "1000",
-                                "rcu_monitor_rate_rw",
-                                "1000",
-                                "rcu_pwr_dig_r",
-                                "1000",
-                                "rcu_temperature_r",
-                                "1000",
-                                "rcu_version_r",
-                                "1000",
-                                "hba_element_beamformer_delays_r",
-                                "1000",
-                                "hba_element_beamformer_delays_rw",
-                                "1000",
-                                "hba_element_led_r",
-                                "1000",
-                                "hba_element_led_rw",
-                                "1000",
-                                "hba_element_pwr_r",
-                                "1000",
-                                "hba_element_pwr_rw",
-                                "1000",
-                                "clk_enable_pwr_r",
-                                "1000",
-                                "clk_i2c_status_r",
-                                "1000",
-                                "clk_monitor_rate_rw",
-                                "1000",
-                                "clk_pll_error_r",
-                                "1000",
-                                "clk_pll_locked_r",
-                                "1000",
-                                "clk_translator_busy_r",
-                                "1000",
-                                "hba_element_lna_pwr_r",
-                                "1000",
-                                "hba_element_lna_pwr_rw",
-                                "1000",
-                                "rcu_i2c_status_r",
-                                "1000",
-                                "rcu_led1_r",
-                                "1000",
-                                "rcu_led1_rw",
-                                "1000",
-                                "rcu_translator_busy_r",
-                                "1000"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "random_data": {
-            "LTS": {
-                "Random_Data": {
-                    "LTS/random_data/1": {
-                        "properties": {
-                            "polled_attr": [
-                                "rnd1",
-                                "1000",
-                                "rnd2",
-                                "1000",
-                                "rnd3",
-                                "1000",
-                                "rnd4",
-                                "1000",
-                                "rnd5",
-                                "1000",
-                                "rnd6",
-                                "1000",
-                                "rnd7",
-                                "1000",
-                                "rnd8",
-                                "1000",
-                                "rnd9",
-                                "1000",
-                                "rnd10",
-                                "1000",
-                                "rnd11",
-                                "1000",
-                                "rnd12",
-                                "1000",
-                                "rnd13",
-                                "1000",
-                                "rnd14",
-                                "1000",
-                                "rnd15",
-                                "1000",
-                                "rnd16",
-                                "1000",
-                                "rnd17",
-                                "1000",
-                                "rnd18",
-                                "1000",
-                                "rnd19",
-                                "1000",
-                                "rnd20",
-                                "1000",
-                                "rnd21",
-                                "1000",
-                                "state",
-                                "1000",
-                                "status",
-                                "1000"
-                            ]
-                        }
-                    },
-                    "LTS/random_data/2": {
-                        "properties": {
-                            "polled_attr": [
-                                "rnd1",
-                                "100",
-                                "rnd2",
-                                "100",
-                                "rnd3",
-                                "100",
-                                "rnd4",
-                                "100",
-                                "rnd5",
-                                "100",
-                                "rnd6",
-                                "100",
-                                "rnd7",
-                                "100",
-                                "rnd8",
-                                "100",
-                                "rnd9",
-                                "100",
-                                "rnd10",
-                                "100",
-                                "rnd11",
-                                "100",
-                                "rnd12",
-                                "100",
-                                "rnd13",
-                                "100",
-                                "rnd14",
-                                "100",
-                                "rnd15",
-                                "100",
-                                "rnd16",
-                                "100",
-                                "rnd17",
-                                "100",
-                                "rnd18",
-                                "100",
-                                "rnd19",
-                                "100",
-                                "rnd20",
-                                "100"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "LTS": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "attribute_properties": {
-                            "SDP_mask_RW": {
-                                "event_period": [
-                                    "60000"
-                                ]
-                            },
-                            "State": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "Status": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_scrap_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_scrap_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_status_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_temp_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_version_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "fpga_weights_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "fpga_weights_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "tr_busy_R": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "tr_reload_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            },
-                            "tr_tod_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-1",
-                                    "1"
-                                ],
-                                "rel_change": [
-                                    "-1",
-                                    "1"
-                                ]
-                            },
-                            "tr_uptime_R": {
-                                "archive_period": [
-                                    "600000"
-                                ],
-                                "archive_rel_change": [
-                                    "-3600",
-                                    "3600"
-                                ],
-                                "rel_change": [
-                                    "-10",
-                                    "10"
-                                ]
-                            }
-                        },
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ],
-                            "polled_attr": [
-                                "fpga_temp_r",
-                                "1000",
-                                "state",
-                                "1000",
-                                "status",
-                                "1000",
-                                "fpga_mask_rw",
-                                "1000",
-                                "fpga_scrap_r",
-                                "1000",
-                                "fpga_scrap_rw",
-                                "1000",
-                                "fpga_status_r",
-                                "1000",
-                                "fpga_version_r",
-                                "1000",
-                                "fpga_weights_r",
-                                "1000",
-                                "fpga_weights_rw",
-                                "1000",
-                                "tr_busy_r",
-                                "1000",
-                                "tr_reload_rw",
-                                "1000",
-                                "tr_tod_r",
-                                "1000",
-                                "tr_uptime_r",
-                                "1000"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SST": {
-            "LTS": {
-                "SST": {
-                    "LTS/SST/1": {
-                        "properties": {
-                            "Statistics_Client_Port": [
-                                "5001"
-                            ],
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "UNB2": {
-            "LTS": {
-                "UNB2": {
-                    "LTS/UNB2/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "despi.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "StatsCrosslet": {
-            "CS997": {
-                "StatsCrosslet": {
-                    "opc-ua/test-crossletstats/1": {
-                        "attribute_properties": {
-                            "visibilities_imag": {
-                                "archive_rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ],
-                                "rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ]
-                            },
-                            "visibilities_real": {
-                                "archive_rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ],
-                                "rel_change": [
-                                    "-0.1",
-                                    "0.1"
-                                ]
-                            }
-                        },
-                        "properties": {
-                            "polled_attr": [
-                                "integration_time",
-                                "0",
-                                "pause_time",
-                                "0",
-                                "rcu_modes",
-                                "0",
-                                "state",
-                                "0",
-                                "status",
-                                "0",
-                                "subband",
-                                "0",
-                                "time_stamp",
-                                "0",
-                                "visibilities_imag",
-                                "0",
-                                "visibilities_real",
-                                "0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "Femto": {
+            "CS999": {
+                "Femto": {
+                    "opc-ua/test-femto/1": {}
+                }
+            }
+        },
+        "observation_control": {
+            "LTS": {
+                "ObservationControl": {
+                    "LTS/ObservationControl/1": {}
+                }
+            }
+        },
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "attribute_properties": {
+                            "Ant_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_Enable_PWR_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_I2C_STATUS_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "CLK_PLL_error_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_PLL_locked_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "CLK_monitor_rate_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "CLK_translator_busy_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "HBA_element_LNA_pwr_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_LNA_pwr_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_beamformer_delays_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_beamformer_delays_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_led_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_led_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_pwr_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "HBA_element_pwr_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_ADC_lock_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_I2C_STATUS_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_ID_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_LED0_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_LED0_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_LED1_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_LED1_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_Pwr_dig_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_attenuator_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_attenuator_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_band_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_band_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "RCU_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_monitor_rate_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ],
+                                "rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ]
+                            },
+                            "RCU_temperature_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ],
+                                "rel_change": [
+                                    "-1.0",
+                                    "1.0"
+                                ]
+                            },
+                            "RCU_translator_busy_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "RCU_version_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "State": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "event_period": [
+                                    "0"
+                                ]
+                            },
+                            "Status": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "event_period": [
+                                    "0"
+                                ]
+                            }
+                        },
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "polled_attr": [
+                                "state",
+                                "1000",
+                                "status",
+                                "1000",
+                                "ant_mask_rw",
+                                "1000",
+                                "rcu_adc_lock_r",
+                                "1000",
+                                "rcu_attenuator_r",
+                                "1000",
+                                "rcu_attenuator_rw",
+                                "1000",
+                                "rcu_band_r",
+                                "1000",
+                                "rcu_band_rw",
+                                "1000",
+                                "rcu_id_r",
+                                "1000",
+                                "rcu_led0_r",
+                                "1000",
+                                "rcu_led0_rw",
+                                "1000",
+                                "rcu_mask_rw",
+                                "1000",
+                                "rcu_monitor_rate_rw",
+                                "1000",
+                                "rcu_pwr_dig_r",
+                                "1000",
+                                "rcu_temperature_r",
+                                "1000",
+                                "rcu_version_r",
+                                "1000",
+                                "hba_element_beamformer_delays_r",
+                                "1000",
+                                "hba_element_beamformer_delays_rw",
+                                "1000",
+                                "hba_element_led_r",
+                                "1000",
+                                "hba_element_led_rw",
+                                "1000",
+                                "hba_element_pwr_r",
+                                "1000",
+                                "hba_element_pwr_rw",
+                                "1000",
+                                "clk_enable_pwr_r",
+                                "1000",
+                                "clk_i2c_status_r",
+                                "1000",
+                                "clk_monitor_rate_rw",
+                                "1000",
+                                "clk_pll_error_r",
+                                "1000",
+                                "clk_pll_locked_r",
+                                "1000",
+                                "clk_translator_busy_r",
+                                "1000",
+                                "hba_element_lna_pwr_r",
+                                "1000",
+                                "hba_element_lna_pwr_rw",
+                                "1000",
+                                "rcu_i2c_status_r",
+                                "1000",
+                                "rcu_led1_r",
+                                "1000",
+                                "rcu_led1_rw",
+                                "1000",
+                                "rcu_translator_busy_r",
+                                "1000"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "random_data": {
+            "LTS": {
+                "Random_Data": {
+                    "LTS/random_data/1": {
+                        "properties": {
+                            "polled_attr": [
+                                "rnd1",
+                                "1000",
+                                "rnd2",
+                                "1000",
+                                "rnd3",
+                                "1000",
+                                "rnd4",
+                                "1000",
+                                "rnd5",
+                                "1000",
+                                "rnd6",
+                                "1000",
+                                "rnd7",
+                                "1000",
+                                "rnd8",
+                                "1000",
+                                "rnd9",
+                                "1000",
+                                "rnd10",
+                                "1000",
+                                "rnd11",
+                                "1000",
+                                "rnd12",
+                                "1000",
+                                "rnd13",
+                                "1000",
+                                "rnd14",
+                                "1000",
+                                "rnd15",
+                                "1000",
+                                "rnd16",
+                                "1000",
+                                "rnd17",
+                                "1000",
+                                "rnd18",
+                                "1000",
+                                "rnd19",
+                                "1000",
+                                "rnd20",
+                                "1000",
+                                "rnd21",
+                                "1000",
+                                "state",
+                                "1000",
+                                "status",
+                                "1000"
+                            ]
+                        }
+                    },
+                    "LTS/random_data/2": {
+                        "properties": {
+                            "polled_attr": [
+                                "rnd1",
+                                "100",
+                                "rnd2",
+                                "100",
+                                "rnd3",
+                                "100",
+                                "rnd4",
+                                "100",
+                                "rnd5",
+                                "100",
+                                "rnd6",
+                                "100",
+                                "rnd7",
+                                "100",
+                                "rnd8",
+                                "100",
+                                "rnd9",
+                                "100",
+                                "rnd10",
+                                "100",
+                                "rnd11",
+                                "100",
+                                "rnd12",
+                                "100",
+                                "rnd13",
+                                "100",
+                                "rnd14",
+                                "100",
+                                "rnd15",
+                                "100",
+                                "rnd16",
+                                "100",
+                                "rnd17",
+                                "100",
+                                "rnd18",
+                                "100",
+                                "rnd19",
+                                "100",
+                                "rnd20",
+                                "100"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "attribute_properties": {
+                            "SDP_mask_RW": {
+                                "event_period": [
+                                    "60000"
+                                ]
+                            },
+                            "State": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "Status": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_scrap_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_scrap_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_status_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_temp_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_version_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "fpga_weights_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "fpga_weights_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "tr_busy_R": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "tr_reload_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            },
+                            "tr_tod_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-1",
+                                    "1"
+                                ],
+                                "rel_change": [
+                                    "-1",
+                                    "1"
+                                ]
+                            },
+                            "tr_uptime_R": {
+                                "archive_period": [
+                                    "600000"
+                                ],
+                                "archive_rel_change": [
+                                    "-3600",
+                                    "3600"
+                                ],
+                                "rel_change": [
+                                    "-10",
+                                    "10"
+                                ]
+                            }
+                        },
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "polled_attr": [
+                                "fpga_temp_r",
+                                "1000",
+                                "state",
+                                "1000",
+                                "status",
+                                "1000",
+                                "fpga_mask_rw",
+                                "1000",
+                                "fpga_scrap_r",
+                                "1000",
+                                "fpga_scrap_rw",
+                                "1000",
+                                "fpga_status_r",
+                                "1000",
+                                "fpga_version_r",
+                                "1000",
+                                "fpga_weights_r",
+                                "1000",
+                                "fpga_weights_rw",
+                                "1000",
+                                "tr_busy_r",
+                                "1000",
+                                "tr_reload_rw",
+                                "1000",
+                                "tr_tod_r",
+                                "1000",
+                                "tr_uptime_r",
+                                "1000"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "Statistics_Client_Port": [
+                                "5001"
+                            ],
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "UNB2": {
+            "LTS": {
+                "UNB2": {
+                    "LTS/UNB2/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "despi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "StatsCrosslet": {
+            "CS997": {
+                "StatsCrosslet": {
+                    "opc-ua/test-crossletstats/1": {
+                        "attribute_properties": {
+                            "visibilities_imag": {
+                                "archive_rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ],
+                                "rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ]
+                            },
+                            "visibilities_real": {
+                                "archive_rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ],
+                                "rel_change": [
+                                    "-0.1",
+                                    "0.1"
+                                ]
+                            }
+                        },
+                        "properties": {
+                            "polled_attr": [
+                                "integration_time",
+                                "0",
+                                "pause_time",
+                                "0",
+                                "rcu_modes",
+                                "0",
+                                "state",
+                                "0",
+                                "status",
+                                "0",
+                                "subband",
+                                "0",
+                                "time_stamp",
+                                "0",
+                                "visibilities_imag",
+                                "0",
+                                "visibilities_real",
+                                "0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/recv-sim-config.json b/CDB/recv-sim-config.json
deleted file mode 100644
index e9585345e783b54e8bd21bd6e46f90692b8ee095..0000000000000000000000000000000000000000
--- a/CDB/recv-sim-config.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "servers": {
-        "RECV": {
-            "LTS": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "recv-sim"
-                            ],
-                            "OPC_Server_Port": [
-                                "4843"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/CDB/sdp-sim-config.json b/CDB/sdp-sim-config.json
deleted file mode 100644
index f733a85a6c570ccdc25646d894bace08c78e9acf..0000000000000000000000000000000000000000
--- a/CDB/sdp-sim-config.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-    "servers": {
-        "SDP": {
-            "LTS": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "sdptr-sim"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SST": {
-            "LTS": {
-                "SST": {
-                    "LTS/SST/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "sdptr-sim"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "XST": {
-            "LTS": {
-                "XST": {
-                    "LTS/XST/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "sdptr-sim"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/CDB/stations/DTS_ConfigDb.json b/CDB/stations/DTS_ConfigDb.json
new file mode 100644
index 0000000000000000000000000000000000000000..685a3d62da82e40aa05ea409c20f2475e3472ea5
--- /dev/null
+++ b/CDB/stations/DTS_ConfigDb.json
@@ -0,0 +1,227 @@
+{
+    "servers": {
+        "APSCT": {
+            "LTS": {
+                "APSCT": {
+                    "LTS/APSCT/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "DESPi3.nfra.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4843"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "APSPU": {
+            "LTS": {
+                "APSPU": {
+                    "LTS/APSPU/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "DESPi3.nfra.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "DESPi3.nfra.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_sdp_info_station_id_RW_default": [
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902",
+                                "902"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_sst_offload_hdr_eth_destination_mac_RW_default": [
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1"
+                            ],
+                            "FPGA_sst_offload_hdr_ip_destination_address_RW_default": [
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "XST": {
+            "LTS": {
+                "XST": {
+                    "LTS/XST/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_xst_offload_hdr_eth_destination_mac_RW_default": [
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1",
+                                "0c:c4:7a:c0:30:f1"
+                            ],
+                            "FPGA_xst_offload_hdr_ip_destination_address_RW_default": [
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1",
+                                "10.99.0.1"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "UNB2": {
+            "LTS": {
+                "UNB2": {
+                    "LTS/UNB2/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "DESPi3.nfra.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4841"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/stations/LTS_ConfigDb.json b/CDB/stations/LTS_ConfigDb.json
new file mode 100644
index 0000000000000000000000000000000000000000..672ff0210a9bad8ed6c48db2f648393b8cee0069
--- /dev/null
+++ b/CDB/stations/LTS_ConfigDb.json
@@ -0,0 +1,287 @@
+{
+    "servers": {
+        "APSCT": {
+            "LTS": {
+                "APSCT": {
+                    "LTS/APSCT/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "OPC_Node_Path_prefix": [
+                                "PCC"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "APSPU": {
+            "LTS": {
+                "APSPU": {
+                    "LTS/APSPU/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "OPC_Node_Path_prefix": [
+                                "PCC"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Node_Path_prefix": [
+                                "PCC"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_sdp_info_station_id_RW_default": [
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901",
+                                "901"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "Statistics_Client_UDP_Port": [
+                                "5001"
+                            ],
+                            "Statistics_Client_TCP_Port": [
+                                "5101"
+                            ],
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_sst_offload_hdr_eth_destination_mac_RW_default": [
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd"
+                            ],
+                            "FPGA_sst_offload_hdr_ip_destination_address_RW_default": [
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250"
+                            ],
+                            "FPGA_sst_offload_hdr_udp_destination_port_RW_default": [
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001",
+                                "5001"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "XST": {
+            "LTS": {
+                "XST": {
+                    "LTS/XST/1": {
+                        "properties": {
+                            "Statistics_Client_UDP_Port": [
+                                "5002"
+                            ],
+                            "Statistics_Client_TCP_Port": [
+                                "5102"
+                            ],
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_xst_offload_hdr_eth_destination_mac_RW_default": [
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd",
+                                "6c:2b:59:97:be:dd"
+                            ],
+                            "FPGA_xst_offload_hdr_ip_destination_address_RW_default": [
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250",
+                                "10.99.250.250"
+                            ],
+                            "FPGA_xst_offload_hdr_udp_destination_port_RW_default": [
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002",
+                                "5002"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "UNB2": {
+            "LTS": {
+                "UNB2": {
+                    "LTS/UNB2/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "despi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Node_Path_prefix": [
+                                "PCC"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/stations/simulators_configDb.json b/CDB/stations/simulators_configDb.json
new file mode 100644
index 0000000000000000000000000000000000000000..7d246bdd6cbc80b7f0cc3e21110265fdc4bbd81a
--- /dev/null
+++ b/CDB/stations/simulators_configDb.json
@@ -0,0 +1,209 @@
+{
+    "servers": {
+        "APSCT": {
+            "LTS": {
+                "APSCT": {
+                    "LTS/APSCT/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "apsct-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4843"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "APSPU": {
+            "LTS": {
+                "APSPU": {
+                    "LTS/APSPU/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "apspu-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4843"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "recv-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "sdptr-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "sdptr-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_sst_offload_hdr_eth_destination_mac_RW_default": [
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB"
+                            ],
+                            "FPGA_sst_offload_hdr_ip_destination_address_RW_default": [
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "XST": {
+            "LTS": {
+                "XST": {
+                    "LTS/XST/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "sdptr-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ],
+                            "FPGA_xst_offload_hdr_eth_destination_mac_RW_default": [
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB",
+                                "01:23:45:67:89:AB"
+                            ],
+                            "FPGA_xst_offload_hdr_ip_destination_address_RW_default": [
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1",
+                                "127.0.0.1"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "UNB2": {
+            "LTS": {
+                "UNB2": {
+                    "LTS/UNB2/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "unb2-sim"
+                            ],
+                            "OPC_Server_Port": [
+                                "4841"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/test_ConfigDb.json b/CDB/test_ConfigDb.json
index b73683f9f1df2b8af3f0f712e9f601bbb292ce50..7030e2d97166b244c3d3c682d4a975386510ecbc 100644
--- a/CDB/test_ConfigDb.json
+++ b/CDB/test_ConfigDb.json
@@ -1,75 +1,75 @@
-{
-    "servers": {
-        "RECV": {
-            "1": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "ltspi.astron.nl"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "1": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "APSCTL": {
-            "1": {
-                "APSCTL": {
-                    "LTS/APSCTL/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "ltspi.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4844"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "test_device": {
-            "1": {
-                "test_device": {
-                    "LTS/test_device/1": {
-                         "attribute_properties": {
-                            "Ant_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            }
-						},
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "RECV": {
+            "1": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "1": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "APSCTL": {
+            "1": {
+                "APSCTL": {
+                    "LTS/APSCTL/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4844"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "test_device": {
+            "1": {
+                "test_device": {
+                    "LTS/test_device/1": {
+                         "attribute_properties": {
+                            "Ant_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            }
+						},
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/thijs_ConfigDb.json b/CDB/thijs_ConfigDb.json
index 95fa70578a94531454684fdc5ee5bb6df7e8e3a7..5cd6813622bc642a8e2fd4ce1001158da3977dae 100644
--- a/CDB/thijs_ConfigDb.json
+++ b/CDB/thijs_ConfigDb.json
@@ -1,137 +1,137 @@
-{
-    "servers": {
-        "RECV": {
-            "1": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "1": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "example_device": {
-            "1": {
-                "example_device": {
-                    "LTS/example_device/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "ini_device": {
-            "1": {
-                "ini_device": {
-                    "LTS/ini_device/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ],
-                            "OPC_Server_Port": [
-                                "4844"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "APSCTL": {
-            "1": {
-                "APSCTL": {
-                    "LTS/APSCTL/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "ltspi.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4844"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SST": {
-            "1": {
-                "SST": {
-                    "LTS/SST/1": {
-                        "properties": {
-                            "Statistics_Client_UDP_Port": [
-                                "5001"
-                            ],
-                            "Statistics_Client_TCP_Port": [
-                                "5101"
-                            ],
-                            "OPC_Server_Name": [
-                                "dop36.astron.nl"
-                            ],
-                            "OPC_Server_Port": [
-                                "4840"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SNMP": {
-            "1": {
-                "SNMP": {
-                    "LTS/SNMP/1": {
-                        "properties": {
-                            "SNMP_community": [
-                                "public"
-                            ],
-                            "SNMP_host": [
-                                "192.168.178.17"
-                            ],
-                            "SNMP_timeout": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "RECV": {
+            "1": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "1": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "example_device": {
+            "1": {
+                "example_device": {
+                    "LTS/example_device/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "ini_device": {
+            "1": {
+                "ini_device": {
+                    "LTS/ini_device/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ],
+                            "OPC_Server_Port": [
+                                "4844"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "APSCTL": {
+            "1": {
+                "APSCTL": {
+                    "LTS/APSCTL/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "ltspi.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4844"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "1": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "Statistics_Client_UDP_Port": [
+                                "5001"
+                            ],
+                            "Statistics_Client_TCP_Port": [
+                                "5101"
+                            ],
+                            "OPC_Server_Name": [
+                                "dop36.astron.nl"
+                            ],
+                            "OPC_Server_Port": [
+                                "4840"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SNMP": {
+            "1": {
+                "SNMP": {
+                    "LTS/SNMP/1": {
+                        "properties": {
+                            "SNMP_community": [
+                                "public"
+                            ],
+                            "SNMP_host": [
+                                "192.168.178.17"
+                            ],
+                            "SNMP_timeout": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/thomas_ConfigDb.json b/CDB/thomas_ConfigDb.json
index 93256085f0acbb13bd111e414c548ae8724d6eaa..c1d50d969298798a95755fd340c9061f08762310 100644
--- a/CDB/thomas_ConfigDb.json
+++ b/CDB/thomas_ConfigDb.json
@@ -1,43 +1,43 @@
-{
-    "servers": {
-        "RECV": {
-            "LTS": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "okeanos"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "LTS": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "okeanos"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SST": {
-            "LTS": {
-                "SST": {
-                    "LTS/SST/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "okeanos"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "okeanos"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "okeanos"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "okeanos"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/thomas_arm64_ConfigDb.json b/CDB/thomas_arm64_ConfigDb.json
index 298794f42247cee40ea88fc507e587f16e695adc..0bf870680b8ff66ae6f46851b01870f4dd4f6ee8 100644
--- a/CDB/thomas_arm64_ConfigDb.json
+++ b/CDB/thomas_arm64_ConfigDb.json
@@ -1,43 +1,43 @@
-{
-    "servers": {
-        "RECV": {
-            "LTS": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "arm2"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "LTS": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "okeanos"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SST": {
-            "LTS": {
-                "SST": {
-                    "LTS/SST/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "okeanos"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "RECV": {
+            "LTS": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "arm2"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "LTS": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "okeanos"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SST": {
+            "LTS": {
+                "SST": {
+                    "LTS/SST/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "okeanos"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/CDB/unb2-sim-config.json b/CDB/unb2-sim-config.json
deleted file mode 100644
index a98fa27492e3835867b214cfd2789caf949de460..0000000000000000000000000000000000000000
--- a/CDB/unb2-sim-config.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "servers": {
-        "UNB2": {
-            "LTS": {
-                "UNB2": {
-                    "LTS/UNB2/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "unb2-sim"
-                            ],
-                            "OPC_Server_Port": [
-                                "4844"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/CDB/windows_ConfigDb.json b/CDB/windows_ConfigDb.json
index ac8b7ef7f50b35f8f245ceaea5b5d525d7fd755e..d00826eddf16687cc0329f68f8ae86b0543d7a82 100644
--- a/CDB/windows_ConfigDb.json
+++ b/CDB/windows_ConfigDb.json
@@ -1,108 +1,108 @@
-{
-    "servers": {
-        "RECV": {
-            "1": {
-                "RECV": {
-                    "LTS/RECV/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SDP": {
-            "1": {
-                "SDP": {
-                    "LTS/SDP/1": {
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-		"ini_device": {
-            "1": {
-                "ini_device": {
-                    "LTS/ini_device/1": {
-                         "attribute_properties": {
-                            "Ant_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            }
-						},
-                        "properties": {
-                            "SNMP_community": [
-                                "public"
-                            ],
-                            "SNMP_host": [
-                                "172.22.176.1"
-                            ],
-                            "SNMP_timeout": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "SNMP": {
-            "1": {
-                "SNMP": {
-                    "LTS/SNMP/1": {
-                         "attribute_properties": {
-                            "Ant_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            }
-						},
-                        "properties": {
-                            "SNMP_community": [
-                                "public"
-                            ],
-                            "SNMP_host": [
-                                "172.22.176.1"
-                            ],
-                            "SNMP_timeout": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-		"test_device": {
-            "1": {
-                "test_device": {
-                    "LTS/test_device/1": {
-                         "attribute_properties": {
-                            "Ant_mask_RW": {
-                                "archive_period": [
-                                    "600000"
-                                ]
-                            }
-						},
-                        "properties": {
-                            "OPC_Server_Name": [
-                                "host.docker.internal"
-                            ],
-                            "OPC_Server_Port": [
-                                "4842"
-                            ],
-                            "OPC_Time_Out": [
-                                "5.0"
-                            ]
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
+{
+    "servers": {
+        "RECV": {
+            "1": {
+                "RECV": {
+                    "LTS/RECV/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SDP": {
+            "1": {
+                "SDP": {
+                    "LTS/SDP/1": {
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+		"ini_device": {
+            "1": {
+                "ini_device": {
+                    "LTS/ini_device/1": {
+                         "attribute_properties": {
+                            "Ant_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            }
+						},
+                        "properties": {
+                            "SNMP_community": [
+                                "public"
+                            ],
+                            "SNMP_host": [
+                                "172.22.176.1"
+                            ],
+                            "SNMP_timeout": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "SNMP": {
+            "1": {
+                "SNMP": {
+                    "LTS/SNMP/1": {
+                         "attribute_properties": {
+                            "Ant_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            }
+						},
+                        "properties": {
+                            "SNMP_community": [
+                                "public"
+                            ],
+                            "SNMP_host": [
+                                "172.22.176.1"
+                            ],
+                            "SNMP_timeout": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+		"test_device": {
+            "1": {
+                "test_device": {
+                    "LTS/test_device/1": {
+                         "attribute_properties": {
+                            "Ant_mask_RW": {
+                                "archive_period": [
+                                    "600000"
+                                ]
+                            }
+						},
+                        "properties": {
+                            "OPC_Server_Name": [
+                                "host.docker.internal"
+                            ],
+                            "OPC_Server_Port": [
+                                "4842"
+                            ],
+                            "OPC_Time_Out": [
+                                "5.0"
+                            ]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/README.md b/README.md
index 192b3edb7713088120b672065296575c255adfa6..3f9bb0b2ba94b26e76a850d713a2dd048e218b9e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,49 @@
 # Tango Station Control
 
 Station Control software related to Tango devices.
+
+# Installation
+
+## Prerequisites
+
+After checking out this repo, be sure to also check out the submodules:
+
+```
+git submodule init
+git submodule update
+```
+
+You will also need:
+
+* docker
+* docker-compose
+* make
+* bash
+
+## Bootstrap
+
+The bootstrap procedure is needed only once. First we build all docker containers, and load the initial configuration. This may take a while:
+
+```
+cd docker-compose
+make bootstrap
+```
+
+If you lack access to LOFAR station hardware, configure the devices to use their simulators instead:
+
+```
+for sim in ../CDB/*-sim-config.json; do
+  ../sbin/update_ConfigDb.sh ../CDB${sim}-config.json
+done
+```
+
+Now we can start all containers, and make sure everything is up:
+
+```
+make start
+make status
+```
+
+If not, you can inspect why with `docker logs <container>`. The containers will automatically be restarted on reboot or failure. Stop them explicitly to bring them down (`make stop <container>`).
+
+Most notably, you will have web interfaces available at http://localhost:8888 (Jupyter Notebook), and http://localhost:3000 (Grafana).
diff --git a/bin/start-DS.sh b/bin/start-DS.sh
index a9c9765d52db4fecd744117ef64938f20288511d..83a6eec6dd30f2e496fa03ffc6f7351d8e9a664d 100755
--- a/bin/start-DS.sh
+++ b/bin/start-DS.sh
@@ -1,7 +1,8 @@
+#!/bin/bash
 function help()
 {
     why="${1}"
-    echo -e "*** Cannot start the Python device server.\n${why}\n\n* The Python file for the device server must be the 1st parameter that is provided.\n* The instance of this device server must be the 2nd parameter that is provided."
+    echo -e "*** Cannot start the Python device server.\\n${why}\\n\\n* The Python file for the device server must be the 1st parameter that is provided.\\n* The instance of this device server must be the 2nd parameter that is provided."
     exit -1
 }
 
@@ -29,14 +30,14 @@ esac
 # ATTENTION
 # This is assuming that the device server's Python file exists
 # on the Docker's host in the user's ${HOME} directory.
-runThis=$(basename ${deviceServer})
+runThis=$(basename "${deviceServer}")
 runThis=${runThis//.sh/.py}
-if [ -f ${runThis} ]; then
+if [ -f "${runThis}" ]; then
     myDir=${PWD}
 else
-    myDir=${PWD}/$(dirname ${deviceServer})
+    myDir=${PWD}/$(dirname "${deviceServer}")
 fi
 deviceServerPath=${myDir/${HOME}/\/hosthome}
 
 # Tango log lines start with a UNIX timestamp. Replace them with the UTC time.
-docker exec -it itango python3 ${deviceServerPath}/${runThis} ${instance} ${@} | perl -ne 'use Time::Piece; s/^([0-9]+)/gmtime($1)->strftime("%F %T")/e; print;'
+docker exec -it itango python3 "${deviceServerPath}/${runThis}" "${instance}" "${@}" | perl -ne 'use Time::Piece; s/^([0-9]+)/gmtime($1)->strftime("%F %T")/e; print;'
diff --git a/bin/start-jive.sh b/bin/start-jive.sh
index fcbb9f8b5e95a4bbbfb6b2895c30d4d2a1914340..38e04ce1837f2351a46f0f5f3c55936825cf5d7b 100755
--- a/bin/start-jive.sh
+++ b/bin/start-jive.sh
@@ -1,9 +1,10 @@
+#!/bin/bash
 OS=$(uname)
 
 case ${OS} in
     Linux)
         display=""
-        XTRA_OPTIONS="-u $(id -u ${USER}):$(id -g ${USER}) -v /etc/passwd:/etc/passwd:ro -v /etc/groups:/etc/groups:ro"
+        XTRA_OPTIONS="-u $(id -u "${USER}"):$(id -g "${USER}") -v /etc/passwd:/etc/passwd:ro -v /etc/groups:/etc/groups:ro"
 
         ;;
     Darwin)
@@ -28,10 +29,10 @@ else
 fi
 
 #docker run --rm -it --network host ${OPTIONS} nexus.engageska-portugal.pt/ska-docker/tango-java:latest ${command} ${@}
-container_name=artefact.skatelescope.org/ska-tango-images/tango-java:9.3.3.2
-container=$(docker ps | egrep ${container_name} | cut -d' ' -f1)
-if [ ! -z ${container} ]; then
-    docker exec -it ${container} ${command} ${@}
+container_name=artefact.skao.int/ska-tango-images-tango-java:9.3.4
+container=$(docker ps | grep -E ${container_name} | cut -d' ' -f1)
+if [ ! -z "${container}" ]; then
+    docker exec -it "${container}" ${command} "${@}"
 else
     echo "Container \"${container_name}\" is not running."
 fi
diff --git a/bootstrap/etc/requirements.txt b/bootstrap/etc/requirements.txt
index d7d6026bc20c52b6255dc0563d0780dc63c7f3aa..5502737a6308c9939be7a2fa4981707f965918ac 100644
--- a/bootstrap/etc/requirements.txt
+++ b/bootstrap/etc/requirements.txt
@@ -5,5 +5,5 @@ numpy
 opcua-client
 pyqtgraph
 PyQt5
-opcua >= 0.98.13
+asyncua
 dataclasses
diff --git a/devices/LICENSE.txt b/devices/LICENSE.txt
index 8a0eaeb196094a651006f51fd99c0c05cb16ccd6..c9978b8eee263aebfdd8d0a016e447940682ba8b 100644
--- a/devices/LICENSE.txt
+++ b/devices/LICENSE.txt
@@ -1,201 +1,201 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright 2021 ASTRON Netherlands Institute for Radio Astronomy
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright 2021 ASTRON Netherlands Institute for Radio Astronomy
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/devices/clients/attribute_wrapper.py b/devices/clients/attribute_wrapper.py
index 4cb389824750cb9d01fc836e8d65caf3656d59a4..e55a662142cb89f62775fb7ac2189c063593df37 100644
--- a/devices/clients/attribute_wrapper.py
+++ b/devices/clients/attribute_wrapper.py
@@ -154,8 +154,15 @@ class attribute_wrapper(attribute):
         try:
             self.read_function, self.write_function = client.setup_attribute(self.comms_annotation, self)
         except Exception as e:
+            raise Exception("Exception while setting %s attribute with annotation: '%s'", client.__class__.__name__, self.comms_annotation) from e
 
-            logger.error("Exception while setting {} attribute with annotation: '{}' {}".format(client.__class__.__name__, self.comms_annotation, e))
+    async def async_set_comm_client(self, client):
+        """
+          Asynchronous version of set_comm_client.
+        """
+        try:
+            self.read_function, self.write_function = await client.setup_attribute(self.comms_annotation, self)
+        except Exception as e:
             raise Exception("Exception while setting %s attribute with annotation: '%s'", client.__class__.__name__, self.comms_annotation) from e
 
     def set_pass_func(self):
diff --git a/devices/clients/comms_client.py b/devices/clients/comms_client.py
index b204dfb6567ef41e589734fe4ff0f3f87dbd2de5..31dfc99ce4092d8f1025bfe3b10fc8a9c561ebe8 100644
--- a/devices/clients/comms_client.py
+++ b/devices/clients/comms_client.py
@@ -1,9 +1,51 @@
 from threading import Thread
 import time
+import asyncio
+from abc import ABC, abstractmethod
 
-class CommClient(Thread):
+import logging
+logger = logging.getLogger()
+
+class AbstractCommClient(ABC):
+    @abstractmethod
+    def start(self):
+        """ Start communication with the client. """
+
+    @abstractmethod
+    def stop(self):
+        """ Stop communication with the client. """
+
+    def ping(self):
+        """ Check whether the connection is still alive.
+        
+            Clients that override this method must raise an Exception if the
+            connection died. """
+        pass
+
+    @abstractmethod
+    def setup_attribute(self, annotation, attribute):
+        """
+        This function returns a (read_function, write_function) tuple for the provided attribute with the provided annotation.
+
+        The setup-attribute has access to the comms_annotation provided to the attribute wrapper to pass along to the comms client
+        as well as a reference to the attribute itself.
+
+        The read_function must return a single value, representing the current value of the attribute.
+        
+        The write_function must take a single value, write it, and return None.
+
+        Examples:
+        - File system:  get_mapping returns functions that read/write a fixed
+        number of bytes at a fixed location in a file. (SEEK)
+        - OPC-UA:  traverse the OPC-UA tree until the node is found.
+        Then return the read/write functions for that node which automatically
+        convert values between Python and OPC-UA.
+        """
+
+class CommClient(AbstractCommClient, Thread):
     """
-    The ProtocolHandler class is the generic interface class between the tango attribute_wrapper and the outside world
+    Abstracts communication with a client, for instance, over the network, by handling connect(), disconnect(), and ping()
+    primitives.
     """
 
     def __init__(self, fault_func, streams, try_interval=2):
@@ -63,7 +105,11 @@ class CommClient(Thread):
                 time.sleep(self.try_interval)
 
     def ping(self):
-        return
+        """ Check whether the connection is still alive.
+        
+            Clients that override this method must raise an Exception if the
+            connection died. """
+        pass
 
     def stop(self):
         """
@@ -79,47 +125,144 @@ class CommClient(Thread):
 
         self.disconnect()
 
-    def setup_attribute(self, annotation, attribute):
-        """
-        This function is responsible for providing the attribute_wrapper with a read/write function
-        How this is done is implementation specific.
-        The setup-attribute has access to the comms_annotation provided to the attribute wrapper to pass along to the comms client
-        as well as a reference to the attribute itself.
+class AsyncCommClient(object):
+    """
+    Abstracts communication with a client, for instance, over the network, by handling connect(), disconnect(), and ping()
+    primitives.
 
-        It should do this by first calling: _setup_annotation and setup_value_conversion to get all data necceacry to configure the read/write functions.
-        It should then return the read and write functions to the attribute.
+    asyncio version of the CommClient. Also does not reconnect if the connection is lost.
+    """
 
-        MANDATORY:
-        annotation_outputs = _setup_annotation(annotation)
-        attribute_outputs = _setup_annotation(attribute)
-        (note: outputs are up to the user)
+    def __init__(self, fault_func=lambda: None, event_loop=None):
+        """
+          Create an Asynchronous communication client.
 
-        REQUIRED: provide read and write functions to return, there are no restrictions on how these should be provided,
-        except that the read function takes a single input value and the write function returns a single value
+          fault_func: Function to call to put the device to FAULT if an error is detected.
+          event_loop: Aysncio event loop to use. If None, a new event loop is created and
+                      run in a separate thread. Only share event loops if any of the functions
+                      executed doesn't stall, as asyncio used a cooperative multitasking model.
 
-        MANDATORY:
-        return read_function, write_function
+                      If the executed functions can stall (for a bit), use a dedicated loop to avoid
+                      interfering with other users of the event loop.
 
-        Examples:
-        - File system:  get_mapping returns functions that read/write a fixed
-        number of bytes at a fixed location in a file. (SEEK)
-        - OPC-UA:  traverse the OPC-UA tree until the node is found.
-        Then return the read/write functions for that node which automatically
-        convert values between Python and OPC-UA.
+                      All coroutines need to be executed in this loop, which wil also be stored
+                      as the `event_loop` member of this object.
         """
-        raise NotImplementedError("the setup_attribute must be implemented and provide return a valid read/write function for the attribute")
+        self.fault_func = fault_func
+        self.running = False
+
+        if event_loop is None:
+            # Run a dedicated event loop for communications
+            #
+            # All co-routines need to be called through this event loop,
+            # for example using asyncio.run_coroutine_threadsafe(coroutine, event_loop).
+
+            def run_loop(loop: asyncio.AbstractEventLoop) -> None:
+                asyncio.set_event_loop(loop)
+                loop.run_forever()
+
+            self.event_loop = asyncio.new_event_loop()
+            self.event_loop_thread = Thread(target=run_loop, args=(self.event_loop,), name=f"AsyncCommClient {self.name()} event loop", daemon=True)
+            self.event_loop_thread.start()
+        else:
+            self.event_loop = event_loop
+            self.event_loop_thread = None
 
-    def _setup_annotation(self, annotation):
+    def __del__(self):
+        if self.event_loop_thread is not None:
+            # signal our event loop thread to stop
+            self.event_loop.call_soon_threadsafe(self.event_loop.stop)
+
+            # reap our event loop thread once it is done processing tasks
+            self.event_loop_thread.join()
+
+    def name(self):
+        """ The name of this CommClient, for use in logs. """
+        return self.__class__.__name__
+
+    @abstractmethod
+    async def connect(self):
         """
-        This function is responsible for handling the annotation data provided by the attribute to configure the read/write function the client must provide.
-        This function should be called by setup_attribute
+        Function used to connect to the client, and any
+        post init.
         """
-        raise NotImplementedError("the _setup_annotation must be implemented, content and outputs are up to the user")
 
-    def setup_value_conversion(self, attribute):
+    @abstractmethod
+    async def disconnect(self):
         """
-        this function is responsible for setting up the value conversion between the client and the attribute.
-        This function should be called by setup_attribute
+        Function used to disconnect from the client.
         """
-        raise NotImplementedError("the setup_value_conversion must be implemented, content and outputs are up to the user")
 
+    async def watch_connection(self):
+        """ Notice when the connection goes down. """
+
+        try:
+            logger.info(f"[AsyncCommClient {self.name()}] Start watching")
+
+            while self.running:
+                # ping will throw in case of connection issues
+                try:
+                    await self.ping()
+                except Exception as e:
+                    logger.exception(f"[AsyncCommClient {self.name()}] Ping failed: connection considered lost")
+
+                    # connection error, go to fault
+                    self.fault_func()
+
+                    # disconnect will cancel us
+                    await self.disconnect()
+
+                    # always have a backup plan
+                    return
+
+                # don't spin, sleep for a while
+                await asyncio.sleep(2)
+        except asyncio.CancelledError as e:
+            pass
+        except Exception as e:
+            # log immediately, or the exception will only be printed once this task is awaited
+            logger.exception(f"[AsyncCommClient {self.name()}] Exception raised while watching")
+
+            raise
+        finally:
+            logger.info(f"[AsyncCommClient {self.name()}] Stop watching")
+
+    async def ping(self):
+        return
+
+    async def start(self):
+        if self.running:
+            # already running
+            return
+
+        await self.connect()
+        self.running = True
+
+        # watch connection
+        self.watch_connection_task = asyncio.create_task(self.watch_connection())
+
+    async def stop(self):
+        if not self.running:
+            # already stopped
+            return
+
+        self.running = False
+
+        # cancel & reap watcher
+        self.watch_connection_task.cancel()
+        try:
+            await self.watch_connection_task
+        except asyncio.CancelledError as e:
+            pass
+        except Exception as e:
+            logger.exception(f"[AsyncCommClient {self.name()}] Watcher thread raised exception")
+
+            # the task stopped eithr way, so no need to bother our caller with this
+
+        await self.disconnect()
+
+    def sync_stop(self):
+        """ Synchronous version of stop(). """
+
+        future = asyncio.run_coroutine_threadsafe(self.stop(), self.event_loop)
+        return future.result()
diff --git a/devices/clients/docker_client.py b/devices/clients/docker_client.py
index c5b0e8b81f69e7f83ae381468b6bcd738f9ec296..a7b487b66656f727b9bd794fcadf9fbe9c50e7fb 100644
--- a/devices/clients/docker_client.py
+++ b/devices/clients/docker_client.py
@@ -1,63 +1,44 @@
 import logging
 import docker
 
-from .comms_client import CommClient
+from .comms_client import AsyncCommClient
 
 logger = logging.getLogger()
 
-class DockerClient(CommClient):
+class DockerClient(AsyncCommClient):
     """
       Controls & queries running docker containers.
     """
 
-    def start(self):
-        super().start()
-
-    def __init__(self, base_url, fault_func, streams):
-        super().__init__(fault_func, streams)
+    def __init__(self, base_url, fault_func, event_loop=None):
+        super().__init__(fault_func, event_loop)
 
         self.base_url = base_url
 
-    def connect(self):
-        """
-        Function used to connect to the client.
-        """
-        if not self.connected:
-            self.client = docker.DockerClient(self.base_url)
+    async def connect(self):
+        self.client = docker.DockerClient(self.base_url)
 
-        return super().connect()
+    async def ping(self):
+        # Raises if the server is unresponsive
+        self.client.ping()
 
-    def ping(self):
-        return True
-
-    def disconnect(self):
+    async def disconnect(self):
         self.client = None
 
-        return super().disconnect()
-
-    def setup_value_conversion(self, attribute):
-        """
-        gives the client access to the attribute_wrapper object in order to access all data it could potentially need.
-        the OPC ua read/write functions require the dimensionality and the type to be known
-        """
-        return
-
-    def setup_attribute(self, annotation, attribute):
+    async def setup_attribute(self, annotation, attribute):
         """
         MANDATORY function: is used by the attribute wrapper to get read/write functions. must return the read and write functions
         """
 
         container_name = annotation["container"]
 
-        # get all the necessary data to set up the read/write functions from the attribute_wrapper
-        self.setup_value_conversion(attribute)
-
         def read_function():
             try:
                 container = self.client.containers.get(container_name)
             except docker.errors.NotFound:
                 return False
 
+            # expected values: running, restarting, paused, exited, created
             return container.status == 'running'
 
         def write_function(value):
diff --git a/devices/clients/opcua_client.py b/devices/clients/opcua_client.py
index 345b848bed36f3e3e691f5ae5d0b7ac2cf1b046e..bf68edd19318648f1c8313f349a63671000382c7 100644
--- a/devices/clients/opcua_client.py
+++ b/devices/clients/opcua_client.py
@@ -1,120 +1,98 @@
 from threading import Thread
 import socket
 import numpy
-import opcua
-from opcua import Client
+import asyncua
+import asyncio
+from asyncua import Client
 
-from clients.comms_client import CommClient
+from clients.comms_client import AsyncCommClient
 
-__all__ = ["OPCUAConnection"]
+import logging
+logger = logging.getLogger()
+
+__all__ = ["OPCUAConnection", "event_loop"]
 
 numpy_to_OPCua_dict = {
-    numpy.bool_: opcua.ua.VariantType.Boolean,
-    numpy.int8: opcua.ua.VariantType.SByte,
-    numpy.uint8: opcua.ua.VariantType.Byte,
-    numpy.int16: opcua.ua.VariantType.Int16,
-    numpy.uint16: opcua.ua.VariantType.UInt16,
-    numpy.int32: opcua.ua.VariantType.Int32,
-    numpy.uint32: opcua.ua.VariantType.UInt32,
-    numpy.int64: opcua.ua.VariantType.Int64,
-    numpy.uint64: opcua.ua.VariantType.UInt64,
-    numpy.float32: opcua.ua.VariantType.Float,
-    numpy.double: opcua.ua.VariantType.Double,
-    numpy.float64: opcua.ua.VariantType.Double,
-    numpy.str: opcua.ua.VariantType.String
+    numpy.bool_: asyncua.ua.VariantType.Boolean,
+    numpy.int8: asyncua.ua.VariantType.SByte,
+    numpy.uint8: asyncua.ua.VariantType.Byte,
+    numpy.int16: asyncua.ua.VariantType.Int16,
+    numpy.uint16: asyncua.ua.VariantType.UInt16,
+    numpy.int32: asyncua.ua.VariantType.Int32,
+    numpy.uint32: asyncua.ua.VariantType.UInt32,
+    numpy.int64: asyncua.ua.VariantType.Int64,
+    numpy.uint64: asyncua.ua.VariantType.UInt64,
+    numpy.float32: asyncua.ua.VariantType.Float,
+    numpy.double: asyncua.ua.VariantType.Double,
+    numpy.float64: asyncua.ua.VariantType.Double,
+    numpy.str: asyncua.ua.VariantType.String
 }
 
-# <class 'numpy.bool_'>
-
-class OPCUAConnection(CommClient):
+class OPCUAConnection(AsyncCommClient):
     """
       Connects to OPC-UA in the foreground or background, and sends HELLO
       messages to keep a check on the connection. On connection failure, reconnects once.
     """
 
-    def start(self):
-        super().start()
-
-    def __init__(self, address, namespace, timeout, fault_func, streams, try_interval=2):
+    def __init__(self, address, namespace, timeout, fault_func, event_loop=None):
         """
         Create the OPC ua client and connect() to it and get the object node
         """
-        super().__init__(fault_func, streams, try_interval)
 
-        self.client = Client(address, timeout)
+        self.client = Client(address, int(timeout))
+        self.namespace = namespace
 
-        # Explicitly connect
-        self.connect()
+        # prefix path to all nodes with this. this allows the user to switch trees more easily.
+        self.node_path_prefix = []
 
-        # determine namespace used
-        if type(namespace) is str:
-            self.name_space_index = self.client.get_namespace_index(namespace)
-        elif type(namespace) is int:
-            self.name_space_index = namespace
-        else:
-            raise TypeError(f"namespace must be of type str or int, but is of type {type(namespace).__name__}")
-
-        self.obj = self.client.get_objects_node()
-        self.check_nodes()
+        super().__init__(fault_func, event_loop)
 
     def _servername(self):
         return self.client.server_url.geturl()
 
-    def connect(self):
+    async def connect(self):
         """
         Try to connect to the client
         """
 
-        try:
-            self.streams.debug_stream("Connecting to server %s", self._servername())
-            self.client.connect()
-            self.streams.debug_stream("Connected to %s. Initialising.", self._servername())
-        except socket.error as e:
-            self.streams.error_stream("Could not connect to server %s: %s", self._servername(), e)
-            raise Exception("Could not connect to server %s", self._servername()) from e
+        logger.debug(f"Connecting to server {self._servername()}")
 
-        super().connect()
+        try:
+            await self.client.connect()
+        except (socket.error, IOError, OSError) as e:
+            raise IOError(f"Could not connect to OPC-UA server {self._servername()}") from e
 
-    def check_nodes(self):
-        """
-        function purely for debugging/development only. Simply lists all top level nodes and the nodes below that
-        """
+        logger.debug(f"Connected to OPC-UA server {self._servername()}")
 
-        for i in self.obj.get_children():
-            print(i.get_browse_name())
-            for j in i.get_children():
-                try:
-                    print(j.get_browse_name(), j.get_data_type_as_variant_type(), j.get_value())
-                except:
-                    print(j.get_browse_name())
-                finally:
-                    pass
+        # determine namespace used
+        if type(self.namespace) is str:
+            self.name_space_index = await self.client.get_namespace_index(self.namespace)
+        elif type(self.namespace) is int:
+            self.name_space_index = self.namespace
+        else:
+            raise TypeError(f"namespace must be of type str or int, but is of type {type(self.namespace).__name__}")
 
+        self.obj = self.client.get_objects_node()
 
-    def disconnect(self):
+    async def disconnect(self):
         """
         disconnect from the client
         """
-        self.connected = False  # always force a reconnect, regardless of a successful disconnect
 
-        try:
-            self.client.disconnect()
-        except Exception as e:
-            self.streams.error_stream("Disconnect from OPC-UA server %s failed: %s", self._servername(), e)
+        await self.client.disconnect()
 
-    def ping(self):
+    async def ping(self):
         """
         ping the client to make sure the connection with the client is still functional.
         """
         try:
-            #self.client.send_hello() # <-- this crashes when communicating with open62541 v1.2.2+
-            pass
+            await self.client.send_hello()
         except Exception as e:
-            raise Exception("Lost connection to server %s: %s", self._servername(), e)
+            raise IOError("Lost connection to server %s: %s", self._servername(), e)
 
-    def _setup_annotation(self, annotation):
+    def get_node_path(self, annotation):
         """
-        This class's Implementation of the get_mapping function. returns the read and write functions
+        Return the path of a node as it will be looked up on the server.
         """
 
         if isinstance(annotation, dict):
@@ -128,40 +106,31 @@ class OPCUAConnection(CommClient):
         else:
             raise Exception("OPC-ua mapping requires either a list of the path or dict with the path. Was given %s type containing: %s", type(annotation), annotation)
 
+
+        # add path prefix
+        path = self.node_path_prefix + path
+
         # prepend namespace index for each element if none is given
         path = [name if ':' in name else f'{self.name_space_index}:{name}' for name in path]
 
+        return path
+
+
+    async def setup_attribute(self, annotation, attribute):
+        # process the annotation
+        path = self.get_node_path(annotation)
+
         try:
-            node = self.obj.get_child(path)
+            node = await self.obj.get_child(path)
         except Exception as e:
-            self.streams.error_stream("Could not get node: %s on server %s: %s", path, self._servername(), e)
+            logger.exception("Could not get node: %s on server %s", path, self._servername())
             raise Exception("Could not get node: %s on server %s", path, self._servername()) from e
 
-        return node
-
-    def setup_value_conversion(self, attribute):
-        """
-        gives the client access to the attribute_wrapper object in order to access all data it could potentially need.
-        the OPC ua read/write functions require the dimensionality and the type to be known
-        """
-
+        # get all the necessary data to set up the read/write functions from the attribute_wrapper
         dim_x = attribute.dim_x
         dim_y = attribute.dim_y
         ua_type = numpy_to_OPCua_dict[attribute.numpy_type]	 # convert the numpy type to a corresponding UA type
 
-        return dim_x, dim_y, ua_type
-
-    def setup_attribute(self, annotation, attribute):
-        """
-        MANDATORY function: is used by the attribute wrapper to get read/write functions. must return the read and write functions
-        """
-
-        # process the annotation
-        node = self._setup_annotation(annotation)
-
-        # get all the necessary data to set up the read/write functions from the attribute_wrapper
-        dim_x, dim_y, ua_type = self.setup_value_conversion(attribute)
-
         # configure and return the read/write functions
         prot_attr = ProtocolAttribute(node, dim_x, dim_y, ua_type)
 
@@ -171,8 +140,27 @@ class OPCUAConnection(CommClient):
             self.streams.debug_stream("connected OPC ua node {} of type {} to attribute with dimensions: {} x {} ".format(str(node_name)[:len(node_name)-1], str(ua_type)[len("VariantType."):], dim_x, dim_y))
         except:
             pass
+
+        # Tango will call these from a separate polling thread.
+        def read_function():
+            return asyncio.run_coroutine_threadsafe(prot_attr.read_function(), self.event_loop).result()
+
+        def write_function(value):
+            asyncio.run_coroutine_threadsafe(prot_attr.write_function(value), self.event_loop).result()
+
         # return the read/write functions
-        return prot_attr.read_function, prot_attr.write_function
+        return read_function, write_function
+
+
+    async def call_method(self, method_path, *args):
+        node = await self.obj.get_child(method_path[:-1])
+        return await node.call_method(method_path[-1], *args)
+
+
+    def call_method(self, method_path, *args):
+        method_path = self.get_node_path(method_path)
+
+        raise NotImplementedError
 
 
 class ProtocolAttribute:
@@ -186,27 +174,31 @@ class ProtocolAttribute:
         self.dim_x = dim_x
         self.ua_type = ua_type
 
-    def read_function(self):
+    async def read_function(self):
         """
         Read_R function
         """
-        value = self.node.get_value()
 
-        if self.dim_y + self.dim_x == 1:
-            # scalar
-            return value
-        elif self.dim_y != 0:
-            # 2D array
-            value = numpy.array(numpy.split(numpy.array(value), indices_or_sections=self.dim_y))
-        else:
-            # 1D array
-            value = numpy.array(value)
+        value = await self.node.get_value()
 
-        return value
+        try:
+            if self.dim_y + self.dim_x == 1:
+                # scalar
+                return value
+            elif self.dim_y != 0:
+                # 2D array
+                value = numpy.array(numpy.split(numpy.array(value), indices_or_sections=self.dim_y))
+            else:
+                # 1D array
+                value = numpy.array(value)
 
+            return value
+        except Exception as e:
+            # Log "value" that gave us this issue
+            raise ValueError(f"Failed to parse atribute value retrieved from OPC-UA: {value}") from e
 
 
-    def write_function(self, value):
+    async def write_function(self, value):
         """
         write_RW function
         """
@@ -219,8 +211,8 @@ class ProtocolAttribute:
             value = value.tolist() if type(value) == numpy.ndarray else value
 
         try:
-            self.node.set_data_value(opcua.ua.uatypes.Variant(value=value, varianttype=self.ua_type))
-        except (TypeError, opcua.ua.uaerrors.BadTypeMismatch) as e:
+            await self.node.set_data_value(asyncua.ua.uatypes.Variant(Value=value, VariantType=self.ua_type))
+        except (TypeError, asyncua.ua.uaerrors.BadTypeMismatch) as e:
             # A type conversion went wrong or there is a type mismatch.
             #
             # This is either the conversion us -> opcua in our client, or client -> server.
@@ -244,10 +236,10 @@ class ProtocolAttribute:
                     dim_x=self.dim_x,
                     dim_y=self.dim_y)
 
-            actual_server_type = "{dtype} {dimensions}".format(
-                dtype=self.node.get_data_type_as_variant_type(),
-                dimensions=(self.node.get_array_dimensions() or "???"))
+            actual_server_type = "{dtype} x {dimensions}".format(
+                dtype=await self.node.read_data_type_as_variant_type(),
+                dimensions=(await self.node.read_array_dimensions()) or "(dimensions unknown)")
 
-            attribute_name = self.node.get_display_name().to_string()
+            attribute_name = (await self.node.read_display_name()).to_string()
 
             raise TypeError(f"Cannot write value to OPC-UA attribute '{attribute_name}': tried to convert data type {our_type} to expected server type {expected_server_type}, server reports type {actual_server_type}") from e
diff --git a/devices/clients/statistics_client.py b/devices/clients/statistics_client.py
index a63d03a3a26a939362e2fed685d086a2b1101552..3fd470fbf0319e45242abbc3a79362584628f844 100644
--- a/devices/clients/statistics_client.py
+++ b/devices/clients/statistics_client.py
@@ -2,7 +2,7 @@ from queue import Queue
 import logging
 import numpy
 
-from .comms_client import CommClient
+from .comms_client import AsyncCommClient
 from .tcp_replicator import TCPReplicator
 from .udp_receiver import UDPReceiver
 
@@ -11,16 +11,13 @@ from devices.sdp.statistics_collector import StatisticsConsumer
 logger = logging.getLogger()
 
 
-class StatisticsClient(CommClient):
+class StatisticsClient(AsyncCommClient):
     """
       Collects statistics packets over UDP, forwards them to a StatisticsCollector,
       and provides a CommClient interface to expose points to a Device Server.
     """
 
-    def start(self):
-        super().start()
-
-    def __init__(self, collector, udp_options, tcp_options, fault_func, streams, try_interval=2, queuesize=1024):
+    def __init__(self, collector, udp_options, tcp_options, fault_func, event_loop=None, queuesize=1024):
         """
         Create the statistics client and connect() to it and get the object node.
 
@@ -34,10 +31,7 @@ class StatisticsClient(CommClient):
         self.queuesize = queuesize
         self.collector = collector
 
-        super().__init__(fault_func, streams, try_interval)
-
-        # Explicitly connect
-        self.connect()
+        super().__init__(fault_func, event_loop)
 
     @staticmethod
     def _queue_fill_percentage(queue: Queue):
@@ -47,7 +41,7 @@ class StatisticsClient(CommClient):
             # some platforms don't have qsize(), nothing we can do here
             return 0
 
-    def connect(self):
+    async def connect(self):
         """
         Function used to connect to the client.
         """
@@ -55,11 +49,11 @@ class StatisticsClient(CommClient):
 
         self.tcp = TCPReplicator(self.tcp_options, self.queuesize)
         self.statistics = StatisticsConsumer(self.collector_queue, self.collector)
-        self.udp = UDPReceiver([self.collector_queue, self.tcp], self.udp_options)
 
-        super().connect()
+        self.udp = UDPReceiver([self.collector_queue, self.tcp],
+                               self.udp_options)
 
-    def ping(self):
+    async def ping(self):
         if not self.statistics.is_alive():
             raise Exception("Statistics processing thread died unexpectedly")
 
@@ -69,7 +63,7 @@ class StatisticsClient(CommClient):
         if not self.tcp.is_alive():
             raise Exception("TCPReplicator thread died unexpectedly")
 
-    def disconnect(self):
+    async def disconnect(self):
         # explicit disconnect, instead of waiting for the GC to kick in after "del" below
         try:
             self.statistics.disconnect()
@@ -93,25 +87,13 @@ class StatisticsClient(CommClient):
         del self.statistics
         del self.collector_queue
 
-        return super().disconnect()
-
-    def setup_value_conversion(self, attribute):
-        """
-        gives the client access to the attribute_wrapper object in order to access all data it could potentially need.
-        the OPC ua read/write functions require the dimensionality and the type to be known
-        """
-        return
-
-    def setup_attribute(self, annotation, attribute):
+    async def setup_attribute(self, annotation, attribute):
         """
         MANDATORY function: is used by the attribute wrapper to get read/write functions. must return the read and write functions
         """
 
         parameter = annotation["parameter"]
 
-        # get all the necessary data to set up the read/write functions from the attribute_wrapper
-        self.setup_value_conversion(attribute)
-
         # redirect to right object. this works as long as the parameter names are unique among them.
         if annotation["type"] == "statistics":
             def read_function():
diff --git a/devices/common/lofar_logging.py b/devices/common/lofar_logging.py
index e571ebb1f92c87f7963a2c8c8f623ed79346f068..826e484e6e2bd321c343b814ccb734472e8bf73c 100644
--- a/devices/common/lofar_logging.py
+++ b/devices/common/lofar_logging.py
@@ -30,7 +30,13 @@ class TangoLoggingHandler(logging.Handler):
         stream = self.level_to_device_stream[record.levelno]
 
         # send the log message to Tango
-        stream(record.tango_device, record.msg, *record.args)
+        try:
+            record_msg = record.msg % record.args
+            stream(record.tango_device, record.msg, *record.args)
+        except TypeError:
+            # Tango's logger barfs on mal-formed log lines, f.e. if msg % args is not possible
+            record_msg = f"{record.msg} {record.args}".replace("%","%%")
+            stream(record.tango_device, record_msg)
 
         self.flush()
 
@@ -88,6 +94,9 @@ class LogAnnotator(logging.Formatter):
         # annotate record with currently executing Tango device, if any
         record.tango_device = self.get_current_tango_device()
 
+        # construct an identifier we can add for other devices as well
+        record.lofar_id = f"tango - {record.tango_device}"
+
         # annotate record with the current software version
         record.software_version = get_version()
 
@@ -112,7 +121,10 @@ def configure_logger(logger: logging.Logger=None, log_extra=None, debug=False):
     logger.setLevel(logging.DEBUG)
 
     # remove spam from the OPC-UA client connection
-    logging.getLogger("opcua").setLevel(logging.WARN)
+    logging.getLogger("asyncua").setLevel(logging.WARN)
+
+    # don't spam errors for git, as we use it in our log handler, which would result in an infinite loop
+    logging.getLogger("git").setLevel(logging.ERROR)
 
     # for now, also log to stderr
     # Set up logging in a way that it can be understood by a human reader, be
diff --git a/devices/devices/apsct.py b/devices/devices/apsct.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8b0cb0ad8843fc44fd6c3e298d3a6cfd15d6f5f
--- /dev/null
+++ b/devices/devices/apsct.py
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of the RECV project
+#
+#
+#
+# Distributed under the terms of the APACHE license.
+# See LICENSE.txt for more info.
+
+""" APSCT Device Server for LOFAR2.0
+
+"""
+
+# TODO(Corne): Remove sys.path.append hack once packaging is in place!
+import os, sys
+currentdir = os.path.dirname(os.path.realpath(__file__))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+
+# PyTango imports
+from tango import DebugIt
+from tango.server import run, command
+from tango.server import device_property, attribute
+from tango import AttrWriteType
+import numpy
+# Additional import
+
+from device_decorators import *
+
+from clients.attribute_wrapper import attribute_wrapper
+from devices.opcua_device import opcua_device
+from common.lofar_logging import device_logging_to_python, log_exceptions
+
+import logging
+logger = logging.getLogger()
+
+__all__ = ["APSCT", "main"]
+
+@device_logging_to_python()
+class APSCT(opcua_device):
+    # -----------------
+    # Device Properties
+    # -----------------
+
+    # ----------
+    # Attributes
+    # ----------
+
+    APSCTTR_translator_busy_R    = attribute_wrapper(comms_annotation=["APSCTTR_translator_busy_R" ],datatype=numpy.bool_  )
+    APSCT_I2C_error_R            = attribute_wrapper(comms_annotation=["APSCT_I2C_error_R"         ],datatype=numpy.int64  )
+    APSCT_ID_R                   = attribute_wrapper(comms_annotation=["APSCT_ID_R"                ],datatype=numpy.int64  )
+    APSCT_INPUT_10MHz_good_R     = attribute_wrapper(comms_annotation=["APSCT_INPUT_10MHz_good_R"  ],datatype=numpy.bool_  )
+    APSCT_INPUT_PPS_good_R       = attribute_wrapper(comms_annotation=["APSCT_INPUT_PPS_good_R"    ],datatype=numpy.bool_  )
+    APSCT_PLL_160MHz_error_R     = attribute_wrapper(comms_annotation=["APSCT_PLL_160MHz_error_R"  ],datatype=numpy.bool_  )
+    APSCT_PLL_160MHz_locked_R    = attribute_wrapper(comms_annotation=["APSCT_PLL_160MHz_locked_R" ],datatype=numpy.bool_  )
+    APSCT_PLL_200MHz_error_R     = attribute_wrapper(comms_annotation=["APSCT_PLL_200MHz_error_R"  ],datatype=numpy.bool_  )
+    APSCT_PLL_200MHz_locked_R    = attribute_wrapper(comms_annotation=["APSCT_PLL_200MHz_locked_R" ],datatype=numpy.bool_  )
+    APSCT_PPS_ignore_R           = attribute_wrapper(comms_annotation=["APSCT_PPS_ignore_R"        ],datatype=numpy.bool_  )
+    APSCT_PPS_ignore_RW          = attribute_wrapper(comms_annotation=["APSCT_PPS_ignore_RW"       ],datatype=numpy.bool_  , access=AttrWriteType.READ_WRITE)
+    APSCT_PWR_CLKDIST1_3V3_R     = attribute_wrapper(comms_annotation=["APSCT_PWR_CLKDIST1_3V3_R"  ],datatype=numpy.float64)
+    APSCT_PWR_CLKDIST2_3V3_R     = attribute_wrapper(comms_annotation=["APSCT_PWR_CLKDIST2_3V3_R"  ],datatype=numpy.float64)
+    APSCT_PWR_CTRL_3V3_R         = attribute_wrapper(comms_annotation=["APSCT_PWR_CTRL_3V3_R"      ],datatype=numpy.float64)
+    APSCT_PWR_INPUT_3V3_R        = attribute_wrapper(comms_annotation=["APSCT_PWR_INPUT_3V3_R"     ],datatype=numpy.float64)
+    APSCT_PWR_on_R               = attribute_wrapper(comms_annotation=["APSCT_PWR_on_R"            ],datatype=numpy.bool_  )
+    APSCT_PWR_PLL_160MHz_3V3_R   = attribute_wrapper(comms_annotation=["APSCT_PWR_PLL_160MHz_3V3_R"],datatype=numpy.float64)
+    APSCT_PWR_PLL_160MHz_on_R    = attribute_wrapper(comms_annotation=["APSCT_PWR_PLL_160MHz_on_R" ],datatype=numpy.bool_  )
+    APSCT_PWR_PLL_200MHz_3V3_R   = attribute_wrapper(comms_annotation=["APSCT_PWR_PLL_200MHz_3V3_R"],datatype=numpy.float64)
+    APSCT_PWR_PLL_200MHz_on_R    = attribute_wrapper(comms_annotation=["APSCT_PWR_PLL_200MHz_on_R" ],datatype=numpy.bool_  )
+    APSCT_PWR_PPSDIST_3V3_R      = attribute_wrapper(comms_annotation=["APSCT_PWR_PPSDIST_3V3_R"   ],datatype=numpy.float64)
+    APSCT_temperature_R          = attribute_wrapper(comms_annotation=["APSCT_temperature_R"       ],datatype=numpy.float64)
+    APSCT_version_R              = attribute_wrapper(comms_annotation=["APSCT_version_R"           ],datatype=numpy.str    )
+
+    # --------
+    # overloaded functions
+    # --------
+
+    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:
+                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?")
+
+    # --------
+    # Commands
+    # --------
+
+    @command()
+    @DebugIt()
+    @only_when_on()
+    def CLK_off(self):
+        """
+
+        :return:None
+        """
+        self.opcua_connection.call_method(["CLK_off"])
+
+    @command()
+    @DebugIt()
+    @only_when_on()
+    def CLK_on(self):
+        """
+
+        :return:None
+        """
+        self.opcua_connection.call_method(["CLK_on"])
+
+    @command()
+    @DebugIt()
+    @only_when_on()
+    def CLK_PLL_setup(self):
+        """
+
+        :return:None
+        """
+        self.opcua_connection.call_method(["CLK_PLL_setup"])
+
+# ----------
+# Run server
+# ----------
+def main(args=None, **kwargs):
+    """Main function of the APSCT module."""
+
+    from common.lofar_logging import configure_logger
+    configure_logger()
+
+    return run((APSCT,), args=args, **kwargs)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/devices/devices/apspu.py b/devices/devices/apspu.py
new file mode 100644
index 0000000000000000000000000000000000000000..cec9e56364a7c78d8938d0fb9241a840d1e0f95e
--- /dev/null
+++ b/devices/devices/apspu.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of the RECV project
+#
+#
+#
+# Distributed under the terms of the APACHE license.
+# See LICENSE.txt for more info.
+
+""" APSPU Device Server for LOFAR2.0
+
+"""
+
+# TODO(Corne): Remove sys.path.append hack once packaging is in place!
+import os, sys
+currentdir = os.path.dirname(os.path.realpath(__file__))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+
+# PyTango imports
+from tango import DebugIt
+from tango.server import run, command
+from tango.server import device_property, attribute
+from tango import AttrWriteType
+import numpy
+# Additional import
+
+from device_decorators import *
+
+from clients.attribute_wrapper import attribute_wrapper
+from devices.opcua_device import opcua_device
+from common.lofar_logging import device_logging_to_python, log_exceptions
+
+__all__ = ["APSPU", "main"]
+
+@device_logging_to_python()
+class APSPU(opcua_device):
+    # -----------------
+    # Device Properties
+    # -----------------
+
+    # ----------
+    # Attributes
+    # ----------
+
+    APSPUTR_translator_busy_R    = attribute_wrapper(comms_annotation=["APSPUTR_translator_busy_R" ],datatype=numpy.bool_  )
+    APSPU_FAN1_RMS_R             = attribute_wrapper(comms_annotation=["APSPU_FAN1_RMS_R"          ],datatype=numpy.float64)
+    APSPU_FAN2_RMS_R             = attribute_wrapper(comms_annotation=["APSPU_FAN2_RMS_R"          ],datatype=numpy.float64)
+    APSPU_FAN3_RMS_R             = attribute_wrapper(comms_annotation=["APSPU_FAN3_RMS_R"          ],datatype=numpy.float64)
+    APSPU_I2C_error_R            = attribute_wrapper(comms_annotation=["APSPU_I2C_error_R"         ],datatype=numpy.int64  )
+    APSPU_ID_R                   = attribute_wrapper(comms_annotation=["APSPU_ID_R"                ],datatype=numpy.int64  )
+    APSPU_LBA_IOUT_R             = attribute_wrapper(comms_annotation=["APSPU_LBA_IOUT_R"          ],datatype=numpy.float64)
+    APSPU_LBA_TEMP_R             = attribute_wrapper(comms_annotation=["APSPU_LBA_TEMP_R"          ],datatype=numpy.float64)
+    APSPU_LBA_VOUT_R             = attribute_wrapper(comms_annotation=["APSPU_LBA_VOUT_R"          ],datatype=numpy.float64)
+    APSPU_RCU2A_IOUT_R           = attribute_wrapper(comms_annotation=["APSPU_RCU2A_IOUT_R"        ],datatype=numpy.float64)
+    APSPU_RCU2A_TEMP_R           = attribute_wrapper(comms_annotation=["APSPU_RCU2A_TEMP_R"        ],datatype=numpy.float64)
+    APSPU_RCU2A_VOUT_R           = attribute_wrapper(comms_annotation=["APSPU_RCU2A_VOUT_R"        ],datatype=numpy.float64)
+    APSPU_RCU2D_IOUT_R           = attribute_wrapper(comms_annotation=["APSPU_RCU2D_IOUT_R"        ],datatype=numpy.float64)
+    APSPU_RCU2D_TEMP_R           = attribute_wrapper(comms_annotation=["APSPU_RCU2D_TEMP_R"        ],datatype=numpy.float64)
+    APSPU_RCU2D_VOUT_R           = attribute_wrapper(comms_annotation=["APSPU_RCU2D_VOUT_R"        ],datatype=numpy.float64)
+    APSPU_version_R              = attribute_wrapper(comms_annotation=["APSPU_version_R"           ],datatype=numpy.str    )
+
+    # --------
+    # overloaded functions
+    # --------
+
+
+    # --------
+    # Commands
+    # --------
+
+# ----------
+# Run server
+# ----------
+def main(args=None, **kwargs):
+    """Main function of the APSPU module."""
+
+    from common.lofar_logging import configure_logger
+    configure_logger()
+
+    return run((APSPU,), args=args, **kwargs)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/devices/devices/boot.py b/devices/devices/boot.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d9540aa52ffa1f177b3cd615110676f73466343
--- /dev/null
+++ b/devices/devices/boot.py
@@ -0,0 +1,307 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of the RECV project
+#
+#
+#
+# Distributed under the terms of the APACHE license.
+# See LICENSE.txt for more info.
+
+""" Boot Device Server for LOFAR2.0
+
+Boots the rest of the station software.
+
+"""
+
+# TODO(Corne): Remove sys.path.append hack once packaging is in place!
+import os, sys
+currentdir = os.path.dirname(os.path.realpath(__file__))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+
+# PyTango imports
+from tango import DebugIt
+from tango.server import run, command
+from tango.server import device_property, attribute
+from tango import AttrWriteType, DeviceProxy, DevState
+# Additional import
+import numpy
+
+from device_decorators import *
+
+from clients.attribute_wrapper import attribute_wrapper
+from devices.hardware_device import hardware_device
+from common.lofar_logging import device_logging_to_python, log_exceptions
+from common.lofar_git import get_version
+
+import logging
+logger = logging.getLogger()
+
+from threading import Thread
+
+__all__ = ["Boot", "main"]
+
+
+class InitialisationException(Exception):
+    pass
+
+class DevicesInitialiser(Thread):
+    """
+        Initialise devices on this station.
+
+        Devices which are unreachable are assumed to be brought down explicitly,
+        and are ignored (unless ignore_unavailable_devices == False).
+
+        Initialisation happens in a separate thread. It is started by calling
+        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, ignore_unavailable_devices=True, proxy_timeout=10.0):
+        self.ignore_unavailable_devices = ignore_unavailable_devices
+
+        self.device_names = device_names
+        self.proxy_timeout = proxy_timeout
+
+        # setup initial state
+        self.progress = 0
+        self.set_status("Initialisation not started yet")
+
+        super().__init__()
+
+    def run(self):
+        self.set_status("Starting initialisation")
+
+        try:
+            # Since Python3.7+, the insertion order equals the iteration order, which is what we depend on
+            # to process the devices in the same order as in device_names.
+            self.devices = {}
+            for name in self.device_names:
+                self.set_status(f"Obtaining a DeviceProxy to {name}")
+                self.devices[name] = DeviceProxy(name)
+
+            # set the timeout for all proxies
+            self.set_status("Configuring DeviceProxies")
+            for device in self.devices.values():
+                device.set_timeout_millis(int(self.proxy_timeout * 1000))
+
+            self.set_status("Initialisation started")
+            self.initialise_devices()
+
+            self.set_status("Initialisation completed")
+        except Exception as e:
+            logger.exception("Failed to initialise station")
+
+            # add the exception to the status
+            self.set_status(f"ERROR: {self.status} [{e.__class__.__name__}: {str(e)}]")
+
+            # we keep the status stuck at the last thing it tried
+
+    def is_running(self):
+        return self.is_alive()
+
+
+    def stop(self):
+        if not self.is_alive():
+            return
+
+        # Just wait for the current initialisation to finish. It's a finite process.
+        self.join()
+
+    def set_status(self, status):
+        self.status = status
+
+        logger.info(status)
+
+    def initialise_devices(self):
+        """
+        Initialise or re-initialise all devices on the station.
+
+        :return:None
+        """
+
+        # reset initialisation parameters
+        self.progress = 0
+
+        # restart devices in order
+        for num_restarted_devices, device in enumerate(self.devices.keys(), 1):
+            if self.is_available(device) or not self.ignore_unavailable_devices:
+                self.start_device(device)
+
+            self.progress = 100.0 * num_restarted_devices / len(self.devices)
+
+        # make sure we always finish at 100% in case of success
+        self.progress = 100
+
+    def is_available(self, device_name: str):
+        """ Return whether the device 'device_name' is actually available on this server. """
+
+        proxy = self.devices[device_name]
+        try:
+            proxy.state()
+        except Exception as e:
+            return False
+
+        return True
+
+    def stop_device(self, device_name: str):
+        """ Stop device 'device_name'. """
+
+        proxy = self.devices[device_name]
+
+        if proxy.state() == DevState.OFF:
+            # already off
+            return
+
+        self.set_status(f"[stopping {device_name}] Stopping device.")
+
+        proxy.Off()
+        if proxy.state() != DevState.OFF:
+            raise InitialisationException(f"Could not turn off device {device_name}. Please look at its logs.")
+
+        self.set_status(f"[stopping {device_name}] Stopped device.")
+
+    def start_device(self, device_name: str):
+        """ Run the startup sequence for device 'device_name'. """
+
+        proxy = self.devices[device_name]
+
+        # go to a well-defined state, which may be needed if the user calls
+        # this function explicitly.
+        self.stop_device(device_name)
+
+        # setup connections to hardware
+        self.set_status(f"[restarting {device_name}] Initialising device.")
+        proxy.Initialise()
+        if proxy.state() != DevState.STANDBY:
+            raise InitialisationException(f"Could not initialise device {device_name}. Please look at its logs.")
+
+        # configure the device
+        self.set_status(f"[restarting {device_name}] Setting defaults.")
+        proxy.set_defaults()
+
+        self.set_status(f"[restarting {device_name}] Initialising hardware.")
+        proxy.initialise_hardware()
+
+        # mark as ready for service
+        self.set_status(f"[restarting {device_name}] Turning on device.")
+        proxy.On()
+        if proxy.state() != DevState.ON:
+            raise InitialisationException(f"Could not turn on device {device_name}. Please look at its logs.")
+
+        self.set_status(f"[restarting {device_name}] Succesfully started.")
+
+@device_logging_to_python()
+class Boot(hardware_device):
+    # -----------------
+    # Device Properties
+    # -----------------
+
+    DeviceProxy_Time_Out = device_property(
+        dtype='DevDouble',
+        mandatory=False,
+        default_value=10.0,
+    )
+
+    # Which devices to initialise, and in which order
+    Device_Names = device_property(
+        dtype='DevVarStringArray',
+        mandatory=False,
+        default_value=["LTS/Docker/1", # Docker controls the device containers, so it goes before anything else
+                       "LTS/APSPU/1",  # APS Power Units control other hardware we want to initialise
+                       "LTS/APSCT/1",
+                       "LTS/RECV/1",   # RCUs are input for SDP, so initialise them first
+                       "LTS/UNB2/1",   # Uniboards host SDP, so initialise them first
+                       "LTS/SDP/1",    # SDP controls the mask for SST/XST/BST, so initialise it first
+                       "LTS/SST/1",
+                       "LTS/XST/1",
+                      ],
+    )
+
+    # By default, we assume any device is not available
+    # because its docker container was not started, which
+    # is an explicit and thus intentional action.
+    # We ignore such devices when initialising the station.
+    Ignore_Unavailable_Devices = device_property(
+        dtype='DevBoolean',
+        mandatory=False,
+        default_value=True,
+    )
+
+    # ----------
+    # Attributes
+    # ----------
+    initialising_station_R = attribute(dtype=numpy.bool_, access=AttrWriteType.READ, fget=lambda self: self.initialiser.is_running())
+    initialisation_progress_R = attribute(dtype=numpy.int, access=AttrWriteType.READ, fget=lambda self: numpy.int(self.initialiser.progress))
+    initialisation_status_R = attribute(dtype=str, access=AttrWriteType.READ, fget=lambda self: self.initialiser.status)
+
+    @log_exceptions()
+    def delete_device(self):
+        """Hook to delete resources allocated in init_device.
+
+        This method allows for any memory or other resources allocated in the
+        init_device method to be released.  This method is called by the device
+        destructor and by the device Init command (a Tango built-in).
+        """
+        self.debug_stream("Shutting down...")
+
+        self.Off()
+        self.debug_stream("Shut down.  Good bye.")
+
+    # --------
+    # overloaded functions
+    # --------
+    @log_exceptions()
+    def configure_for_off(self):
+        """ user code here. is called when the state is set to OFF """
+        try:
+            self.initialiser.stop()
+        except Exception as e:
+            self.warn_stream("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e))
+
+    @log_exceptions()
+    def configure_for_initialise(self):
+        # create an initialiser object so we can query it even before starting the (first) initialisation
+        self.initialiser = DevicesInitialiser(self.Device_Names, self.Ignore_Unavailable_Devices, self.DeviceProxy_Time_Out)
+
+    @command()
+    @DebugIt()
+    @only_in_states([DevState.ON])
+    @fault_on_error()
+    @log_exceptions()
+    def initialise_station(self):
+        """
+        Initialise or re-initialise all devices on the station.
+
+        This command will take a while to execute, so should be called asynchronously.
+
+        :return:None
+        """
+
+        if self.initialiser.is_running():
+            # already initialising
+            return
+
+        # join any previous attempt, if any
+        try:
+            self.initialiser.join()
+        except RuntimeError:
+            pass
+
+        # start new initialisation attempt
+        self.initialiser = DevicesInitialiser(self.Device_Names, self.Ignore_Unavailable_Devices, self.DeviceProxy_Time_Out)
+        self.initialiser.start()
+
+# ----------
+# Run server
+# ----------
+def main(args=None, **kwargs):
+    """Main function of the RECV module."""
+
+    from common.lofar_logging import configure_logger
+    configure_logger()
+
+    return run((Boot,), args=args, **kwargs)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/devices/devices/docker_device.py b/devices/devices/docker_device.py
index 2acf7aeecf04755b71337d42f6a64946ef7cd54a..f8a83dd41f9a81a217dcab9a2dc54201ecff1025 100644
--- a/devices/devices/docker_device.py
+++ b/devices/devices/docker_device.py
@@ -23,6 +23,7 @@ from tango.server import run, command
 from tango.server import device_property, attribute
 from tango import AttrWriteType
 import numpy
+import asyncio
 # Additional import
 
 from device_decorators import *
@@ -53,6 +54,10 @@ class Docker(hardware_device):
     archiver_maria_db_RW = attribute_wrapper(comms_annotation={"container": "archiver-maria-db"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
     databaseds_R = attribute_wrapper(comms_annotation={"container": "databaseds"}, datatype=numpy.bool_)
     databaseds_RW = attribute_wrapper(comms_annotation={"container": "databaseds"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
+    device_apsct_R = attribute_wrapper(comms_annotation={"container": "device-apsct"}, datatype=numpy.bool_)
+    device_apsct_RW = attribute_wrapper(comms_annotation={"container": "device-apsct"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
+    device_apspu_R = attribute_wrapper(comms_annotation={"container": "device-apspu"}, datatype=numpy.bool_)
+    device_apspu_RW = attribute_wrapper(comms_annotation={"container": "device-apspu"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
     device_recv_R = attribute_wrapper(comms_annotation={"container": "device-recv"}, datatype=numpy.bool_)
     device_recv_RW = attribute_wrapper(comms_annotation={"container": "device-recv"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
     device_sdp_R = attribute_wrapper(comms_annotation={"container": "device-sdp"}, datatype=numpy.bool_)
@@ -96,7 +101,7 @@ class Docker(hardware_device):
         """ user code here. is called when the state is set to OFF """
         # Stop keep-alive
         try:
-            self.docker_client.stop()
+            self.docker_client.sync_stop()
         except Exception as e:
             self.warn_stream("Exception while stopping docker client in configure_for_off function: {}. Exception ignored".format(e))
 
@@ -105,13 +110,18 @@ class Docker(hardware_device):
         """ user code here. is called when the state is set to INIT """
 
         # set up the Docker client
-        self.docker_client = DockerClient(self.Docker_Base_URL, self.Fault, self)
+        self.docker_client = DockerClient(self.Docker_Base_URL, self.Fault)
 
+        # schedule the docker initialisation, and wait for it to finish
+        future = asyncio.run_coroutine_threadsafe(self._connect_docker(), self.docker_client.event_loop)
+        _ = future.result()
+
+    async def _connect_docker(self):
         # tie attributes to client
         for i in self.attr_list():
-            i.set_comm_client(self.docker_client)
+            await i.async_set_comm_client(self.docker_client)
 
-        self.docker_client.start()
+        await self.docker_client.start()
 
     # --------
     # Commands
diff --git a/devices/devices/hardware_device.py b/devices/devices/hardware_device.py
index a25b863ebc8255fa05c02a5f420f23f309ebf0fb..7c7e6663cff7a68f8b0340d59f076bb946ea9ec5 100644
--- a/devices/devices/hardware_device.py
+++ b/devices/devices/hardware_device.py
@@ -11,7 +11,7 @@
 
 """
 
-from abc import ABCMeta, abstractmethod
+from abc import abstractmethod
 
 # PyTango imports
 from tango.server import Device, command, DeviceMeta, attribute
@@ -23,15 +23,14 @@ from common.lofar_logging import log_exceptions
 from common.lofar_git import get_version
 from devices.abstract_device import AbstractDeviceMetas
 from devices.device_decorators import only_in_states, fault_on_error
-
-import logging
+import time
+import math
 
 __all__ = ["hardware_device"]
 
+import logging
 logger = logging.getLogger()
 
-
-#@log_exceptions()
 class hardware_device(Device, metaclass=AbstractDeviceMetas):
     """
 
@@ -57,6 +56,10 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
         The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()).
     """
 
+    # ----------
+    # Attributes
+    # ----------
+
     version_R = attribute(dtype=str, access=AttrWriteType.READ, fget=lambda self: get_version())
 
     # list of property names too be set first by set_defaults
@@ -244,3 +247,36 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas):
                 # log which attribute we're addressing
                 raise Exception(f"Cannot assign default to attribute {name}") from e
 
+    @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON])
+    @fault_on_error()
+    @command()
+    def initialise_hardware(self):
+        """ Initialise the hardware after configuring it. """
+
+        # This is just the command version of _initialise_hardware().
+        self._initialise_hardware()
+
+    def _initialise_hardware(self):
+        """ Override this method to initialise any hardware after configuring it. """
+        pass
+
+    def wait_attribute(self, attr_name, value, timeout=10, pollperiod=0.2):
+        """ Wait until the given attribute obtains the given value.
+
+            Raises an Exception if it has not after the timeout.
+
+            timeout:     time until an Exception is raised, in seconds.
+            pollperiod:  how often to check the attribute, in seconds.
+        """
+
+        attr = getattr(self, attr_name)
+
+        # Poll every half a second
+        for _ in range(math.ceil(timeout/pollperiod)):
+            if attr != value:
+                return
+
+            time.sleep(pollperiod)
+
+        raise Exception(f"{attr} != {value} after f{timeout} seconds still.")
+
diff --git a/devices/devices/opcua_device.py b/devices/devices/opcua_device.py
index 698df95705b0dce00cb869ed880a29f97d472cb1..fd49b90f122868a0741ebe91ba69d71a434143d6 100644
--- a/devices/devices/opcua_device.py
+++ b/devices/devices/opcua_device.py
@@ -22,6 +22,7 @@ from tango import DebugIt
 from tango.server import device_property, attribute
 from tango import AttrWriteType
 import numpy
+import asyncio
 # Additional import
 
 from devices.device_decorators import *
@@ -71,6 +72,13 @@ class opcua_device(hardware_device):
         default_value="http://lofar.eu"
     )
 
+    # Add these elements to the OPC-UA node path.
+    OPC_Node_Path_Prefix = device_property(
+        dtype='DevVarStringArray',
+        mandatory=False,
+        default_value=[]
+    )
+
     # ----------
     # Attributes
     # ----------
@@ -86,29 +94,36 @@ class opcua_device(hardware_device):
         """ user code here. is called when the state is set to INIT """
 
         # set up the OPC ua client
-        self.opcua_connection = OPCUAConnection("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_namespace, self.OPC_Time_Out, self.Fault, self)
+        self.opcua_connection = OPCUAConnection("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_namespace, self.OPC_Time_Out, self.Fault)
+        self.opcua_connection.node_path_prefix = self.OPC_Node_Path_Prefix
+
         self.opcua_missing_attributes = []
 
+        # schedule the opc-ua initialisation, and wait for it to finish
+        future = asyncio.run_coroutine_threadsafe(self._connect_opcua(), self.opcua_connection.event_loop)
+        _ = future.result()
+
+    async def _connect_opcua(self):
+        # connect
+        await self.opcua_connection.start()
+
         # map an access helper class
         for i in self.attr_list():
             try:
                 if not i.comms_id or i.comms_id == OPCUAConnection:
-                    i.set_comm_client(self.opcua_connection)
+                    await i.async_set_comm_client(self.opcua_connection)
             except Exception as e:
                 # use the pass function instead of setting read/write fails
                 i.set_pass_func()
-                self.opcua_missing_attributes.append(",".join(i.comms_annotation))
+                self.opcua_missing_attributes.append(",".join(self.opcua_connection.get_node_path(i.comms_annotation)))
 
                 self.warn_stream("error while setting the attribute {} read/write function. {}".format(i, e))
 
-        self.opcua_connection.start()
-
     @log_exceptions()
     def configure_for_off(self):
         """ user code here. is called when the state is set to OFF """
         try:
             # disconnect
-            self.opcua_connection.stop()
+            self.opcua_connection.sync_stop()
         except Exception as e:
             self.warn_stream("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e))
-
diff --git a/devices/devices/recv.py b/devices/devices/recv.py
index a078f601c7d1962f4a11367e7ca9745ec590d5f2..d180e955a56ee583a7a2fbc1a732d933c27acced 100644
--- a/devices/devices/recv.py
+++ b/devices/devices/recv.py
@@ -31,6 +31,9 @@ from clients.attribute_wrapper import attribute_wrapper
 from devices.opcua_device import opcua_device
 from common.lofar_logging import device_logging_to_python, log_exceptions
 
+import logging
+logger = logging.getLogger()
+
 __all__ = ["RECV", "main"]
 
 @device_logging_to_python()
@@ -39,7 +42,7 @@ class RECV(opcua_device):
     # Device Properties
     # -----------------
 
-    Ant_mask_RW_default = device_property(
+    ANT_mask_RW_default = device_property(
         dtype='DevVarBooleanArray',
         mandatory=False,
         default_value=[[True] * 3] * 32
@@ -53,62 +56,58 @@ class RECV(opcua_device):
 
     first_default_settings = [
         # set the masks first, as those filter any subsequent settings
-        'Ant_mask_RW',
+        'ANT_mask_RW',
         'RCU_mask_RW'
     ]
 
     # ----------
     # Attributes
     # ----------
-    Ant_mask_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:Ant_mask_RW"], datatype=numpy.bool_, dims=(3, 32), access=AttrWriteType.READ_WRITE)
-    CLK_Enable_PWR_R = attribute_wrapper(comms_annotation=["2:PCC", "2:CLK_Enable_PWR_R"], datatype=numpy.bool_)
-    CLK_I2C_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:CLK_I2C_STATUS_R"], datatype=numpy.int64)
-    CLK_PLL_error_R = attribute_wrapper(comms_annotation=["2:PCC", "2:CLK_PLL_error_R"], datatype=numpy.bool_)
-    CLK_PLL_locked_R = attribute_wrapper(comms_annotation=["2:PCC", "2:CLK_PLL_locked_R"], datatype=numpy.bool_)
-    CLK_monitor_rate_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:CLK_monitor_rate_RW"], datatype=numpy.int64, access=AttrWriteType.READ_WRITE)
-    CLK_translator_busy_R = attribute_wrapper(comms_annotation=["2:PCC", "2:CLK_translator_busy_R"], datatype=numpy.bool_)
-    HBA_element_beamformer_delays_R = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_beamformer_delays_R"], datatype=numpy.int64, dims=(32, 96))
-    HBA_element_beamformer_delays_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_beamformer_delays_RW"], datatype=numpy.int64, dims=(32, 96), access=AttrWriteType.READ_WRITE)
-    HBA_element_led_R = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_led_R"], datatype=numpy.int64, dims=(32, 96))
-    HBA_element_led_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_led_RW"], datatype=numpy.int64, dims=(32, 96), access=AttrWriteType.READ_WRITE)
-    HBA_element_LNA_pwr_R = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_LNA_pwr_R"], datatype=numpy.int64, dims=(32, 96))
-    HBA_element_LNA_pwr_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_LNA_pwr_RW"], datatype=numpy.int64, dims=(32, 96), access=AttrWriteType.READ_WRITE)
-    HBA_element_pwr_R = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_pwr_R"], datatype=numpy.int64, dims=(32, 96))
-    HBA_element_pwr_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:HBA_element_pwr_RW"], datatype=numpy.int64, dims=(32, 96), access=AttrWriteType.READ_WRITE)
-    RCU_ADC_lock_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_ADC_lock_R"], datatype=numpy.int64, dims=(3, 32))
-    RCU_attenuator_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_attenuator_R"], datatype=numpy.int64, dims=(3, 32))
-    RCU_attenuator_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_attenuator_RW"], datatype=numpy.int64, dims=(3, 32),  access=AttrWriteType.READ_WRITE)
-    RCU_band_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_band_R"], datatype=numpy.int64, dims=(3, 32))
-    RCU_band_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_band_RW"], datatype=numpy.int64, dims=(3, 32), access=AttrWriteType.READ_WRITE)
-    RCU_I2C_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_I2C_STATUS_R"], datatype=numpy.int64, dims=(32,))
-    RCU_ID_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_ID_R"], datatype=numpy.int64, dims=(32,))
-    RCU_LED0_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_LED0_R"], datatype=numpy.bool_, dims=(32,))
-    RCU_LED0_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_LED0_RW"], datatype=numpy.bool_, dims=(32,), access=AttrWriteType.READ_WRITE)
-    RCU_LED1_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_LED1_R"], datatype=numpy.bool_, dims=(32,))
-    RCU_LED1_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_LED1_RW"], datatype=numpy.bool_, dims=(32,), access=AttrWriteType.READ_WRITE)
-    RCU_mask_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_mask_RW"], datatype=numpy.bool_, dims=(32,), access=AttrWriteType.READ_WRITE)
-    RCU_monitor_rate_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_monitor_rate_RW"], datatype=numpy.int64, access=AttrWriteType.READ_WRITE)
-    RCU_Pwr_dig_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_Pwr_dig_R"], datatype=numpy.bool_, dims=(32,))
-    RCU_temperature_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_temperature_R"], datatype=numpy.float64, dims=(32,))
-    RCU_translator_busy_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_translator_busy_R"], datatype=numpy.bool_)
-    RCU_version_R = attribute_wrapper(comms_annotation=["2:PCC", "2:RCU_version_R"], datatype=numpy.str, dims=(32,))
+    Ant_status_R = attribute(dtype=str, max_dim_x=3, max_dim_y=32)
+
+    ANT_mask_RW                  = attribute_wrapper(comms_annotation=["ANT_mask_RW"               ],datatype=numpy.bool_  , dims=(3,32), access=AttrWriteType.READ_WRITE)
+    HBAT_beamformer_delays_R     = attribute_wrapper(comms_annotation=["HBAT_beamformer_delays_R"  ],datatype=numpy.int64  , dims=(32,96))
+    HBAT_beamformer_delays_RW    = attribute_wrapper(comms_annotation=["HBAT_beamformer_delays_RW" ],datatype=numpy.int64  , dims=(32,96), access=AttrWriteType.READ_WRITE)
+    HBAT_LED_on_R                = attribute_wrapper(comms_annotation=["HBAT_LED_on_R"             ],datatype=numpy.bool_  , dims=(32,96))
+    HBAT_LED_on_RW               = attribute_wrapper(comms_annotation=["HBAT_LED_on_RW"            ],datatype=numpy.bool_  , dims=(32,96), access=AttrWriteType.READ_WRITE)
+    HBAT_PWR_LNA_on_R            = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_R"         ],datatype=numpy.bool_  , dims=(32,96))
+    HBAT_PWR_LNA_on_RW           = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_RW"        ],datatype=numpy.bool_  , dims=(32,96), access=AttrWriteType.READ_WRITE)
+    HBAT_PWR_on_R                = attribute_wrapper(comms_annotation=["HBAT_PWR_on_R"             ],datatype=numpy.bool_  , dims=(32,96))
+    HBAT_PWR_on_RW               = attribute_wrapper(comms_annotation=["HBAT_PWR_on_RW"            ],datatype=numpy.bool_  , dims=(32,96), access=AttrWriteType.READ_WRITE)
+    RCU_ADC_locked_R             = attribute_wrapper(comms_annotation=["RCU_ADC_locked_R"          ],datatype=numpy.bool_  , dims=(3,32))
+    RCU_attenuator_dB_R          = attribute_wrapper(comms_annotation=["RCU_attenuator_dB_R"       ],datatype=numpy.int64  , dims=(3,32))
+    RCU_attenuator_dB_RW         = attribute_wrapper(comms_annotation=["RCU_attenuator_dB_RW"      ],datatype=numpy.int64  , dims=(3,32), access=AttrWriteType.READ_WRITE)
+    RCU_band_select_R            = attribute_wrapper(comms_annotation=["RCU_band_select_R"         ],datatype=numpy.int64  , dims=(3,32))
+    RCU_band_select_RW           = attribute_wrapper(comms_annotation=["RCU_band_select_RW"        ],datatype=numpy.int64  , dims=(3,32), access=AttrWriteType.READ_WRITE)
+    RCU_DTH_freq_R               = attribute_wrapper(comms_annotation=["RCU_DTH_freq_R"            ],datatype=numpy.int64  , dims=(3,32))
+    RCU_DTH_freq_RW              = attribute_wrapper(comms_annotation=["RCU_DTH_freq_RW"           ],datatype=numpy.int64  , dims=(3,32), access=AttrWriteType.READ_WRITE)
+    RCU_DTH_on_R                 = attribute_wrapper(comms_annotation=["RCU_DTH_on_R"              ],datatype=numpy.bool_  , dims=(3,32))
+    RCU_DTH_shutdown_R           = attribute_wrapper(comms_annotation=["RCU_DTH_shutdown_R"        ],datatype=numpy.bool_  , dims=(3,32))
+    RCU_I2C_error_R              = attribute_wrapper(comms_annotation=["RCU_I2C_error_R"           ],datatype=numpy.int64  , dims=(32,))
+    RCU_ID_R                     = attribute_wrapper(comms_annotation=["RCU_ID_R"                  ],datatype=numpy.int64  , dims=(32,))
+    RCU_LED_green_off_R          = attribute_wrapper(comms_annotation=["RCU_LED_green_off_R"       ],datatype=numpy.bool_  , dims=(32,))
+    RCU_LED_green_off_RW         = attribute_wrapper(comms_annotation=["RCU_LED_green_off_RW"      ],datatype=numpy.bool_  , dims=(32,), access=AttrWriteType.READ_WRITE)
+    RCU_LED_red_off_R            = attribute_wrapper(comms_annotation=["RCU_LED_red_off_R"         ],datatype=numpy.bool_  , dims=(32,))
+    RCU_LED_red_off_RW           = attribute_wrapper(comms_annotation=["RCU_LED_red_off_RW"        ],datatype=numpy.bool_  , dims=(32,), access=AttrWriteType.READ_WRITE)
+    RCU_mask_RW                  = attribute_wrapper(comms_annotation=["RCU_mask_RW"               ],datatype=numpy.bool_  , dims=(32,), access=AttrWriteType.READ_WRITE)
+    RCU_PWR_1V8_R                = attribute_wrapper(comms_annotation=["RCU_PWR_1V8_R"             ],datatype=numpy.float64, dims=(32,))
+    RCU_PWR_2V5_R                = attribute_wrapper(comms_annotation=["RCU_PWR_2V5_R"             ],datatype=numpy.float64, dims=(32,))
+    RCU_PWR_3V3_R                = attribute_wrapper(comms_annotation=["RCU_PWR_3V3_R"             ],datatype=numpy.float64, dims=(32,))
+    RCU_PWR_ANALOG_on_R          = attribute_wrapper(comms_annotation=["RCU_PWR_ANALOG_on_R"       ],datatype=numpy.bool_  , dims=(32,))
+    RCU_PWR_ANT_IOUT_R           = attribute_wrapper(comms_annotation=["RCU_PWR_ANT_IOUT_R"        ],datatype=numpy.float64, dims=(3,32))
+    RCU_PWR_ANT_on_R             = attribute_wrapper(comms_annotation=["RCU_PWR_ANT_on_R"          ],datatype=numpy.bool_  , dims=(3,32))
+    RCU_PWR_ANT_on_RW            = attribute_wrapper(comms_annotation=["RCU_PWR_ANT_on_RW"         ],datatype=numpy.bool_  , dims=(3,32), access=AttrWriteType.READ_WRITE)
+    RCU_PWR_ANT_VIN_R            = attribute_wrapper(comms_annotation=["RCU_PWR_ANT_VIN_R"         ],datatype=numpy.float64, dims=(3,32))
+    RCU_PWR_ANT_VOUT_R           = attribute_wrapper(comms_annotation=["RCU_PWR_ANT_VOUT_R"        ],datatype=numpy.float64, dims=(3,32))
+    RCU_PWR_DIGITAL_on_R         = attribute_wrapper(comms_annotation=["RCU_PWR_DIGITAL_on_R"      ],datatype=numpy.bool_  , dims=(32,))
+    RCU_PWR_good_R               = attribute_wrapper(comms_annotation=["RCU_PWR_good_R"            ],datatype=numpy.bool_  , dims=(32,))
+    RCU_temperature_R            = attribute_wrapper(comms_annotation=["RCU_temperature_R"         ],datatype=numpy.float64, dims=(32,))
+    RCU_version_R                = attribute_wrapper(comms_annotation=["RCU_version_R"             ],datatype=numpy.str    , dims=(32,))
+    RECVTR_translator_busy_R     = attribute_wrapper(comms_annotation=["RECVTR_translator_busy_R"  ],datatype=numpy.bool_  )
 
     # --------
     # overloaded functions
     # --------
-    @log_exceptions()
-    def configure_for_initialise(self):
-        """ user code here. is called when the state is set to INIT """
-
-        # Init the dict that contains function to OPC-UA function mappings.
-        self.function_mapping = {}
-        self.function_mapping["RCU_on"] = {}
-        self.function_mapping["RCU_off"] = {}
-        self.function_mapping["CLK_on"] = {}
-        self.function_mapping["CLK_off"] = {}
-
-        super().configure_for_initialise()
-
 
     # --------
     # Commands
@@ -116,80 +115,119 @@ class RECV(opcua_device):
     @command()
     @DebugIt()
     @only_when_on()
-    @fault_on_error()
     def RCU_off(self):
         """
 
         :return:None
         """
-        self.function_mapping["RCU_off"]()
+        self.opcua_connection.call_method(["RCU_off"])
 
     @command()
     @DebugIt()
     @only_when_on()
-    @fault_on_error()
     def RCU_on(self):
         """
 
         :return:None
         """
-        self.function_mapping["RCU_on"]()
+        self.opcua_connection.call_method(["RCU_on"])
 
     @command()
     @DebugIt()
     @only_when_on()
-    @fault_on_error()
     def ADC_on(self):
         """
 
         :return:None
         """
-        self.function_mapping["ADC_on"]()
+        self.opcua_connection.call_method(["ADC_on"])
 
     @command()
     @DebugIt()
     @only_when_on()
-    @fault_on_error()
     def RCU_update(self):
         """
 
         :return:None
         """
-        self.function_mapping["RCU_update"]()
+        self.opcua_connection.call_method(["RCU_update"])
 
-    @command()
-    @DebugIt()
-    @only_when_on()
-    @fault_on_error()
-    def CLK_off(self):
-        """
+    def _initialise_hardware(self):
+        """ Initialise the RCU hardware. """
 
-        :return:None
-        """
-        self.function_mapping["CLK_off"]()
+        # 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
 
-    @command()
-    @DebugIt()
-    @only_when_on()
-    @fault_on_error()
-    def CLK_on(self):
-        """
+        # Cycle RCUs
+        self.RCU_off()
+        self.wait_attribute("RECVTR_translator_busy_R", False, 5)
+        self.RCU_on()
+        self.wait_attribute("RECVTR_translator_busy_R", False, 5)
 
-        :return:None
-        """
-        self.function_mapping["CLK_on"]()
+    def read_RCU_status_R(self):
+        """ Returns a set of strings denoting the status of each RCU.
 
-    @command()
-    @DebugIt()
-    @only_when_on()
-    @fault_on_error()
-    def CLK_PLL_setup(self):
-        """
+            An empty string means no problems were detected. A non-empty
+            string means the RCU seems unusable.
 
-        :return:None
-        """
-        self.function_mapping["CLK_PLL_setup"]()
+            This function can be used as input to modify the RCU_mask_RW. """
+
+        rcu_mask = self.RCU_mask_RW
+        i2c_errors = self.RCU_I2C_STATUS_R
+
+        nr_rcus = len(rcu_mask)
+        rcu_status = [""] * nr_rcus
+
+        # construct status of each RCU
+        for rcu in range(nr_rcus):
+            status = []
+
+            if not i2c_status[rcu]:
+                status.append("[I2C error]")
+
+            rcu_status[rcu] = " ".join(status)
+
+        return rcu_status
+
+    def read_Ant_status_R(self):
+        """ Returns a set of strings denoting the status of each antenna.
+
+            An empty string means no problems were detected. A non-empty
+            string means the antenna seems unusable.
+
+            This function can be used as input to modify the Ant_mask_RW. """
+
+        ant_mask = self.Ant_mask_RW
+        rcu_mask = self.RCU_mask_RW
+        adc_lock = self.RCU_ADC_lock_R
+        i2c_errors = self.RCU_I2C_STATUS_R
+
+        nr_rcus = len(ant_mask)
+        nr_ants_per_rcu = len(ant_mask[0])
+
+        # Collect status, join them into a single string per antenna later 
+        ant_status = [""] * nr_ants
+
+
+        for rcu in range(nr_rcus):
+            for ant in range(nr_ants_per_rcu):
+                status = []
+
+                if i2c_status[rcu] != 0:
+                    status.append("[I2C error]")
+
+                if not rcu_mask[rcu]:
+                    status.append("[RCU masked out]")
+
+                if not adc_lock[rcu][ant]:
+                    status.append("[ADC lock error]")
+
+                ant_status[rcu][ant] = " ".join(status)
 
+        return ant_status
+ 
 
 # ----------
 # Run server
diff --git a/devices/devices/sdp/sdp.py b/devices/devices/sdp/sdp.py
index 1575aaa6b74c373fd952820365d6790450491d36..6cdfe9a2b2788f1b3466bbdb38a4ca5c83e9780f 100644
--- a/devices/devices/sdp/sdp.py
+++ b/devices/devices/sdp/sdp.py
@@ -80,7 +80,8 @@ class SDP(opcua_device):
     
     FPGA_sdp_info_station_id_RW_default = device_property(
         dtype='DevVarULongArray',
-        mandatory=True
+        mandatory=False,
+        default_value=[0] * 16
     )
 
     FPGA_subband_weights_RW_default = device_property(
@@ -115,8 +116,6 @@ class SDP(opcua_device):
     FPGA_processing_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
     FPGA_scrap_R = attribute_wrapper(comms_annotation=["2:FPGA_scrap_R"], datatype=numpy.int32, dims=(8192,))
     FPGA_scrap_RW = attribute_wrapper(comms_annotation=["2:FPGA_scrap_RW"], datatype=numpy.int32, dims=(8192,), access=AttrWriteType.READ_WRITE)
-    FPGA_signal_input_mean_R = attribute_wrapper(comms_annotation=["2:FPGA_signal_input_mean_R"], datatype=numpy.double, dims=(12, 16))
-    FPGA_signal_input_rms_R = attribute_wrapper(comms_annotation=["2:FPGA_signal_input_rms_R"], datatype=numpy.double, dims=(12, 16))
     FPGA_sdp_info_antenna_band_index_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_antenna_band_index_R"], datatype=numpy.uint32, dims=(16,))
     FPGA_sdp_info_block_period_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_block_period_R"], datatype=numpy.uint32, dims=(16,))
     FPGA_sdp_info_f_adc_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_f_adc_R"], datatype=numpy.uint32, dims=(16,))
@@ -151,6 +150,24 @@ class SDP(opcua_device):
     TR_tod_R = attribute_wrapper(comms_annotation=["2:TR_tod_R"], datatype=numpy.int64, dims=(2,))
     TR_tod_pps_delta_R = attribute_wrapper(comms_annotation=["2:TR_tod_pps_delta_R"], datatype=numpy.double)
 
+    S_pn = 12 # Number of ADC signal inputs per Processing Node (PN) FPGA.
+    N_pn = 16 # Number of FPGAs per antenna band that is controlled via the SC - SDP interface.
+
+    # OPC-UA MP only points for AIT
+    FPGA_signal_input_mean_R = attribute_wrapper(comms_annotation=["2:FPGA_signal_input_mean_R"], datatype=numpy.double , dims=(S_pn, N_pn))
+    FPGA_signal_input_rms_R = attribute_wrapper(comms_annotation=["2:FPGA_signal_input_rms_R"], datatype=numpy.double, dims=(S_pn, N_pn))
+
+    FPGA_jesd204b_csr_rbd_count_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_csr_rbd_count_R"], datatype=numpy.uint32, dims=(S_pn, N_pn))
+    FPGA_jesd204b_csr_dev_syncn_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_csr_dev_syncn_R"], datatype=numpy.uint32, dims=(S_pn, N_pn))
+    FPGA_jesd204b_rx_err0_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_rx_err0_R"], datatype=numpy.uint32, dims=(S_pn, N_pn))
+    FPGA_jesd204b_rx_err1_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_rx_err1_R"], datatype=numpy.uint32, dims=(S_pn, N_pn))
+
+    FPGA_bsn_monitor_input_bsn_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_bsn_R"], datatype=numpy.int64, dims=(N_pn,))
+    FPGA_bsn_monitor_input_nof_packets_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_nof_packets_R"], datatype=numpy.int32, dims=(N_pn,))
+    FPGA_bsn_monitor_input_nof_valid_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_nof_valid_R"], datatype=numpy.int32, dims=(N_pn,))
+    FPGA_bsn_monitor_input_nof_err_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_nof_err_R"], datatype=numpy.int32, dims=(N_pn,))
+
+
     # --------
     # overloaded functions
     # --------
diff --git a/devices/devices/sdp/sst.py b/devices/devices/sdp/sst.py
index fe1b353b17737d56f5566da9cc7913e16ff828a6..277714ab0b7ada6882a5ec1086690b3c29fb2382 100644
--- a/devices/devices/sdp/sst.py
+++ b/devices/devices/sdp/sst.py
@@ -25,8 +25,8 @@ from tango import AttrWriteType
 # Additional import
 
 from clients.attribute_wrapper import attribute_wrapper
-from clients.opcua_client import OPCUAConnection
 from clients.statistics_client import StatisticsClient
+from clients.opcua_client import OPCUAConnection
 from devices.sdp.statistics import Statistics
 from devices.sdp.statistics_collector import SSTCollector
 
diff --git a/devices/devices/sdp/statistics.py b/devices/devices/sdp/statistics.py
index 63f1cb0a7b1d2763fc51fa79abfa6317684bfd38..af1cf0201fd4dc244b8495730660b7c84398a518 100644
--- a/devices/devices/sdp/statistics.py
+++ b/devices/devices/sdp/statistics.py
@@ -24,9 +24,9 @@ from abc import ABCMeta, abstractmethod
 from tango.server import device_property, attribute
 from tango import AttrWriteType
 # Additional import
+import asyncio
 
 from clients.statistics_client import StatisticsClient
-from clients.opcua_client import OPCUAConnection
 from clients.attribute_wrapper import attribute_wrapper
 
 from devices.opcua_device import opcua_device
@@ -100,9 +100,8 @@ class Statistics(opcua_device, metaclass=ABCMeta):
     def configure_for_off(self):
         """ user code here. is called when the state is set to OFF """
 
-        # Stop keep-alive
         try:
-            self.statistics_client.stop()
+            self.statistics_client.sync_stop()
         except Exception as e:
             logger.exception("Exception while stopping statistics_client in configure_for_off. Exception ignored")
 
@@ -128,13 +127,24 @@ class Statistics(opcua_device, metaclass=ABCMeta):
         }
 
         self.statistics_collector = self.STATISTICS_COLLECTOR_CLASS()
-        self.statistics_client = StatisticsClient(self.statistics_collector, udp_options, tcp_options, self.Fault, self)
-        self.statistics_client.start()
+        self.statistics_client = StatisticsClient(self.statistics_collector, udp_options, tcp_options, self.Fault, self.opcua_connection.event_loop) # can share event loop
 
-        # tie attributes to client
+        # schedule the opc-ua initialisation, and wait for it to finish
+        future = asyncio.run_coroutine_threadsafe(self._connect_statistics(), self.statistics_client.event_loop)
+        _ = future.result()
+
+    async def _connect_statistics(self):
+        # map an access helper class
         for i in self.attr_list():
-            if i.comms_id == StatisticsClient:
-                i.set_comm_client(self.statistics_client)
+            try:
+                if i.comms_id == StatisticsClient:
+                    await i.async_set_comm_client(self.statistics_client)
+            except Exception as e:
+                # use the pass function instead of setting read/write fails
+                i.set_pass_func()
+                self.warn_stream("error while setting the sst attribute {} read/write function. {}. using pass function instead".format(i, e))
+
+        await self.statistics_client.start()
 
     # --------
     # Commands
diff --git a/devices/devices/sdp/xst.py b/devices/devices/sdp/xst.py
index 7ecc937b9baa198b9aa3d8015204ff910d23f83b..c9883303b80425f0c142181994d43e477ec5431c 100644
--- a/devices/devices/sdp/xst.py
+++ b/devices/devices/sdp/xst.py
@@ -25,12 +25,9 @@ from tango import AttrWriteType
 # Additional import
 
 from clients.attribute_wrapper import attribute_wrapper
-from clients.opcua_client import OPCUAConnection
 from clients.statistics_client import StatisticsClient
+from clients.opcua_client import OPCUAConnection
 
-from devices.hardware_device import hardware_device
-
-from common.lofar_git import get_version
 from common.lofar_logging import device_logging_to_python, log_exceptions
 
 from devices.sdp.statistics import Statistics
diff --git a/devices/devices/unb2.py b/devices/devices/unb2.py
index e2f781a24e5e59c52591f0826e36000a38687aa1..bad1b1a324c9c838960d07cdfeb804b2789bbac6 100644
--- a/devices/devices/unb2.py
+++ b/devices/devices/unb2.py
@@ -38,6 +38,12 @@ class UNB2(opcua_device):
     # Device Properties
     # -----------------
 
+    UNB2_mask_RW_default = device_property(
+        dtype='DevVarBooleanArray',
+        mandatory=False,
+        default_value=[True] * 2
+    )
+
     # ----------
     # Attributes
     # ----------
@@ -47,94 +53,70 @@ class UNB2(opcua_device):
     N_ddr = 2
     N_qsfp = 6
 
-    ### All CP/MP are in order of appearance in the ICD
-    ### Central CP per Uniboard
-
-    ### Some points are not working yet on the UNB2 or under discussion
-    #XXX means Not working yet, but they are working on it
-    ##XXX Means Under discussion
-
-    # Special case for the on off switch: instead of UNB2_Power_ON_OFF_R we use UNB2_POL_FPGA_CORE_VOUT_R as the MP
-    UNB2_Power_ON_OFF_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Power_ON_OFF_RW"], datatype=numpy.bool_, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
-    UNB2_Front_Panel_LED_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Front_Panel_LED_RW"], datatype=numpy.uint8, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
-    UNB2_Front_Panel_LED_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Front_Panel_LED_R"], datatype=numpy.uint8, dims=(N_unb,))
-    UNB2_mask_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_mask_RW"], datatype=numpy.bool_, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
-    # Not yet deployed
-    #UNB2_mask_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_mask_R"], datatype=numpy.bool_, dims=(N_unb,))
-
-    ### Central MP per Uniboard
-    # These three are only available in UNB2c
-    UNB2_I2C_bus_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_STATUS_R"], datatype=numpy.bool_, dims=(N_unb,))
-    ##UNB2_I2C_bus_STATUS_R will probably be renamed to UNB2_I2C_bus_OK_R
-    ##UNB2_I2C_bus_OK_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_OK_R"], datatype=numpy.bool_, dims=(N_unb,))
-    #UNB2_EEPROM_Serial_Number_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_EEPROM_Serial_Number_R"], datatype=numpy.str, dims=(N_unb,))
-    UNB2_EEPROM_Unique_ID_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_EEPROM_Unique_ID_R"], datatype=numpy.uint32, dims=(N_unb,))
-    UNB2_DC_DC_48V_12V_VIN_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_VIN_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_DC_DC_48V_12V_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_DC_DC_48V_12V_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_DC_DC_48V_12V_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_QSFP_N01_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N01_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_QSFP_N01_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N01_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_QSFP_N01_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N01_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_QSFP_N23_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N23_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_QSFP_N23_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N23_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_QSFP_N23_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N23_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_SWITCH_1V2_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_1V2_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_SWITCH_1V2_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_1V2_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_SWITCH_1V2_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_1V2_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_SWITCH_PHY_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_PHY_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_SWITCH_PHY_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_PHY_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_SWITCH_PHY_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_PHY_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_CLOCK_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_CLOCK_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_CLOCK_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_CLOCK_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
-    UNB2_POL_CLOCK_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_CLOCK_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
-
-    ### Local MP per FPGA
-    UNB2_FPGA_DDR4_SLOT_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_DDR4_SLOT_TEMP_R"], datatype=numpy.double, dims=((N_fpga * N_ddr), N_unb))
-    #UNB2_FPGA_DDR4_SLOT_PART_NUMBER_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_DDR4_SLOT_PART_NUMBER_R"], datatype=numpy.str, dims=(N_fpga * N_ddr), N_unb))
-    #UNB2_FPGA_QSFP_CAGE_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_0_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_1_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_1_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_2_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_2_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_3_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_3_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_4_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_4_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_5_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_5_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_0_LOS_R"], datatype=numpy.uint8, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_1_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_1_LOS_R"], datatype=numpy.uint8, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_2_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_2_LOS_R"], datatype=numpy.uint8, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_3_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_3_LOS_R"], datatype=numpy.uint8, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_4_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_4_LOS_R"], datatype=numpy.uint8, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_QSFP_CAGE_5_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_5_LOS_R"], datatype=numpy.uint8, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_POL_CORE_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_FPGA_CORE_VOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_CORE_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_CORE_IOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_CORE_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_CORE_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_ERAM_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_ERAM_VOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_ERAM_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_ERAM_IOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_ERAM_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_ERAM_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_RXGXB_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_RXGXB_VOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_RXGXB_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_RXGXB_IOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_RXGXB_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_RXGXB_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_TXGXB_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_TXGXB_VOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_TXGXB_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_TXGXB_IOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    #UNB2_FPGA_POL_TXGXB_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_FPGA_TXGXB_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_HGXB_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_HGXB_VOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_HGXB_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_HGXB_IOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_HGXB_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_HGXB_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_PGM_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_PGM_VOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_PGM_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_PGM_IOUT_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-    UNB2_FPGA_POL_PGM_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_PGM_TEMP_R"], datatype=numpy.double, dims=(N_fpga, N_unb))
-
-
-  ##UNB2_I2C_bus_QSFP_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_QSFP_STATUS_R"], datatype=numpy.int64, dims=((N_unb * N_fpga), N_qsfp))
-  ##UNB2_I2C_bus_DDR4_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_DDR4_STATUS_R"], datatype=numpy.int64, dims=(N_ddr, N_fpga))
-  ##UNB2_I2C_bus_FPGA_PS_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_FPGA_PS_STATUS_R"], datatype=numpy.int64, dims=(N_unb * N_fpga,))
-  ##UNB2_I2C_bus_PS_STATUS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_PS_STATUS_R"], datatype=numpy.double, dims=(N_unb,))
-  ##UNB2_translator_busy_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_translator_busy_R"], datatype=numpy.bool_)
-  ##UNB2_monitor_rate_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_monitor_rate_RW"], datatype=numpy.double, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
-
-
-
-    # QualifiedName(2: UNB2_on)
-    # QualifiedName(2: UNB2_off)
+    UNB2_mask_RW_default = device_property(
+        dtype='DevVarBooleanArray',
+        mandatory=False,
+        default_value=[True] * 2
+    )
+
+    first_default_settings = [
+        # set the masks first, as those filter any subsequent settings
+        'UNB2_mask_RW'
+    ]
+
+    UNB2TR_translator_busy_R     = attribute_wrapper(comms_annotation=["UNB2TR_translator_busy_R"  ],datatype=numpy.bool_  )
+    UNB2_DC_DC_48V_12V_IOUT_R    = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_IOUT_R" ],datatype=numpy.float64, dims=(2,))
+    UNB2_DC_DC_48V_12V_TEMP_R    = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_TEMP_R" ],datatype=numpy.float64, dims=(2,))
+    UNB2_DC_DC_48V_12V_VIN_R     = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_VIN_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_DC_DC_48V_12V_VOUT_R    = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_VOUT_R" ],datatype=numpy.float64, dims=(2,))
+    UNB2_EEPROM_Serial_Number_R  = attribute_wrapper(comms_annotation=["UNB2_EEPROM_Serial_Number_R"],datatype=numpy.str    , dims=(2,))
+    UNB2_EEPROM_Unique_ID_R      = attribute_wrapper(comms_annotation=["UNB2_EEPROM_Unique_ID_R"   ],datatype=numpy.int64  , dims=(2,))
+    UNB2_FPGA_DDR4_SLOT_TEMP_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_DDR4_SLOT_TEMP_R"],datatype=numpy.float64, dims=(16,))
+    UNB2_FPGA_POL_CORE_IOUT_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_IOUT_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_CORE_TEMP_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_TEMP_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_CORE_VOUT_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_VOUT_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_ERAM_IOUT_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_IOUT_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_ERAM_TEMP_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_TEMP_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_ERAM_VOUT_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_VOUT_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_HGXB_IOUT_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_IOUT_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_HGXB_TEMP_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_TEMP_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_HGXB_VOUT_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_VOUT_R" ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_PGM_IOUT_R     = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_IOUT_R"  ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_PGM_TEMP_R     = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_TEMP_R"  ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_PGM_VOUT_R     = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_VOUT_R"  ],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_RXGXB_IOUT_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_IOUT_R"],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_RXGXB_TEMP_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_TEMP_R"],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_RXGXB_VOUT_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_VOUT_R"],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_TXGXB_IOUT_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_IOUT_R"],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_TXGXB_TEMP_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_TEMP_R"],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_POL_TXGXB_VOUT_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_VOUT_R"],datatype=numpy.float64, dims=(8,))
+    UNB2_FPGA_QSFP_CAGE_LOS_R    = attribute_wrapper(comms_annotation=["UNB2_FPGA_QSFP_CAGE_LOS_R" ],datatype=numpy.int64  , dims=(48,))
+    UNB2_FPGA_QSFP_CAGE_TEMP_R   = attribute_wrapper(comms_annotation=["UNB2_FPGA_QSFP_CAGE_TEMP_R"],datatype=numpy.float64, dims=(48,))
+    UNB2_Front_Panel_LED_R       = attribute_wrapper(comms_annotation=["UNB2_Front_Panel_LED_R"    ],datatype=numpy.int64  , dims=(2,))
+    UNB2_Front_Panel_LED_RW      = attribute_wrapper(comms_annotation=["UNB2_Front_Panel_LED_RW"   ],datatype=numpy.int64  , dims=(2,), access=AttrWriteType.READ_WRITE)
+    UNB2_I2C_bus_DDR4_error_R    = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_DDR4_error_R" ],datatype=numpy.int64  , dims=(8,))
+    UNB2_I2C_bus_error_R         = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_error_R"      ],datatype=numpy.int64  , dims=(2,))
+    UNB2_I2C_bus_FPGA_PS_error_R = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_FPGA_PS_error_R"],datatype=numpy.int64  , dims=(8,))
+    UNB2_I2C_bus_PS_error_R      = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_PS_error_R"   ],datatype=numpy.int64  , dims=(2,))
+    UNB2_I2C_bus_QSFP_error_R    = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_QSFP_error_R" ],datatype=numpy.int64  , dims=(48,))
+    UNB2_mask_RW                 = attribute_wrapper(comms_annotation=["UNB2_mask_RW"              ],datatype=numpy.bool_  , dims=(2,), access=AttrWriteType.READ_WRITE)
+    UNB2_POL_CLOCK_IOUT_R        = attribute_wrapper(comms_annotation=["UNB2_POL_CLOCK_IOUT_R"     ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_CLOCK_TEMP_R        = attribute_wrapper(comms_annotation=["UNB2_POL_CLOCK_TEMP_R"     ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_CLOCK_VOUT_R        = attribute_wrapper(comms_annotation=["UNB2_POL_CLOCK_VOUT_R"     ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_QSFP_N01_IOUT_R     = attribute_wrapper(comms_annotation=["UNB2_POL_QSFP_N01_IOUT_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_QSFP_N01_TEMP_R     = attribute_wrapper(comms_annotation=["UNB2_POL_QSFP_N01_TEMP_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_QSFP_N01_VOUT_R     = attribute_wrapper(comms_annotation=["UNB2_POL_QSFP_N01_VOUT_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_QSFP_N23_IOUT_R     = attribute_wrapper(comms_annotation=["UNB2_POL_QSFP_N23_IOUT_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_QSFP_N23_TEMP_R     = attribute_wrapper(comms_annotation=["UNB2_POL_QSFP_N23_TEMP_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_QSFP_N23_VOUT_R     = attribute_wrapper(comms_annotation=["UNB2_POL_QSFP_N23_VOUT_R"  ],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_SWITCH_1V2_IOUT_R   = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_1V2_IOUT_R"],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_SWITCH_1V2_TEMP_R   = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_1V2_TEMP_R"],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_SWITCH_1V2_VOUT_R   = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_1V2_VOUT_R"],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_SWITCH_PHY_IOUT_R   = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_PHY_IOUT_R"],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_SWITCH_PHY_TEMP_R   = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_PHY_TEMP_R"],datatype=numpy.float64, dims=(2,))
+    UNB2_POL_SWITCH_PHY_VOUT_R   = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_PHY_VOUT_R"],datatype=numpy.float64, dims=(2,))
+    UNB2_PWR_off_R               = attribute_wrapper(comms_annotation=["UNB2_PWR_off_R"            ],datatype=numpy.bool_  , dims=(2,))
+    UNB2_PWR_off_RW              = attribute_wrapper(comms_annotation=["UNB2_PWR_off_RW"           ],datatype=numpy.bool_  , dims=(2,), access=AttrWriteType.READ_WRITE)
 
     # --------
     # overloaded functions
diff --git a/devices/integration_test/base.py b/devices/integration_test/base.py
index 085cbc540dba035969685c3a0fbfbef8c6c7e394..241f0ecd409fd16484d81e31f1e1f83dc1b9d81b 100644
--- a/devices/integration_test/base.py
+++ b/devices/integration_test/base.py
@@ -10,6 +10,7 @@
 from common.lofar_logging import configure_logger
 
 import unittest
+import asynctest
 import testscenarios
 
 """Setup logging for integration tests"""
@@ -28,3 +29,9 @@ class IntegrationTestCase(BaseIntegrationTestCase):
 
     def setUp(self):
         super().setUp()
+
+class IntegrationAsyncTestCase(testscenarios.WithScenarios, asynctest.TestCase):
+    """Integration test case base class for all asyncio unit tests."""
+
+    def setUp(self):
+        super().setUp()
diff --git a/devices/integration_test/client/test_sdptr_sim.py b/devices/integration_test/client/test_sdptr_sim.py
index 3ba48e7d761c7ef366c8690e2d114c773de7311d..ab9288b727e515c19b07c99d1fe8a233d7032055 100644
--- a/devices/integration_test/client/test_sdptr_sim.py
+++ b/devices/integration_test/client/test_sdptr_sim.py
@@ -7,26 +7,26 @@
 # Distributed under the terms of the APACHE license.
 # See LICENSE.txt for more info.
 
-from opcua import Client
+from asyncua import Client
 
 from integration_test import base
 
 
-class TestSDPTRSim(base.IntegrationTestCase):
+class TestSDPTRSim(base.IntegrationAsyncTestCase):
 
     def setUp(self):
         super(TestSDPTRSim, self).setUp()
 
-    def test_opcua_connection(self):
+    async def test_opcua_connection(self):
         """Check if we can connect to sdptr-sim"""
 
         client = Client("opc.tcp://sdptr-sim:4840")
         root_node = None
 
         try:
-            client.connect()
+            await client.connect()
             root_node = client.get_root_node()
         finally:
-            client.disconnect()
+            await client.disconnect()
 
         self.assertNotEqual(None, root_node)
diff --git a/devices/integration_test/client/test_unb2_sim.py b/devices/integration_test/client/test_unb2_sim.py
index 227e031e3651fdc1c0523e103b072762271b647a..d934c06fb6dfb40dad1c8b54dc00a00715deedc8 100644
--- a/devices/integration_test/client/test_unb2_sim.py
+++ b/devices/integration_test/client/test_unb2_sim.py
@@ -7,27 +7,27 @@
 # Distributed under the terms of the APACHE license.
 # See LICENSE.txt for more info.
 
-from opcua import Client
+from asyncua import Client
 
 from integration_test import base
 
 
-class TestUNB2Sim(base.IntegrationTestCase):
+class TestUNB2Sim(base.IntegrationAsyncTestCase):
 
     def setUp(self):
         super(TestUNB2Sim, self).setUp()
 
-    def test_opcua_connection(self):
+    async def test_opcua_connection(self):
         """Check if we can connect to unb2-sim"""
 
-        client = Client("opc.tcp://unb2-sim:4844")
+        client = Client("opc.tcp://unb2-sim:4841")
         root_node = None
 
-        client.connect()
+        await client.connect()
 
         try:
             root_node = client.get_root_node()
         finally:
-            client.disconnect()
+            await client.disconnect()
 
         self.assertNotEqual(None, root_node)
diff --git a/devices/integration_test/devices/test_device_sdp.py b/devices/integration_test/devices/test_device_sdp.py
index cfd656748054cb21e0e3bb2110ce60072d9fb28a..5f064128f858e0bd2c44768a4f13057e5dc20266 100644
--- a/devices/integration_test/devices/test_device_sdp.py
+++ b/devices/integration_test/devices/test_device_sdp.py
@@ -57,3 +57,14 @@ class TestDeviceSDP(base.IntegrationTestCase):
         d.on()
 
         self.assertEqual(DevState.ON, d.state())
+
+    def test_device_sdp_read_attribute(self):
+        """Test if we can read an attribute obtained over OPC-UA"""
+
+        d = DeviceProxy("LTS/SDP/1")
+
+        d.initialise()
+
+        d.on()
+
+        self.assertListEqual([True]*16, list(d.TR_fpga_communication_error_R))
diff --git a/devices/integration_test/devices/test_device_unb2.py b/devices/integration_test/devices/test_device_unb2.py
index 97f31ab6ee162f8183db963e92f4f03b9ee7f617..d796e586cd5165b0e3fb7cd09c1c3acf5cdd747c 100644
--- a/devices/integration_test/devices/test_device_unb2.py
+++ b/devices/integration_test/devices/test_device_unb2.py
@@ -1,59 +1,59 @@
-# -*- 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.
-
-import time
-
-from tango import DeviceProxy
-from tango._tango import DevState
-
-from integration_test import base
-
-
-class TestDeviceUNB2(base.IntegrationTestCase):
-
-    def setUp(self):
-        """Intentionally recreate the device object in each test"""
-        super(TestDeviceUNB2, self).setUp()
-
-    def tearDown(self):
-        """Turn device Off in teardown to prevent blocking tests"""
-        d = DeviceProxy("LTS/UNB2/1")
-
-        try:
-            d.Off()
-        except Exception as e:
-            """Failing to turn Off devices should not raise errors here"""
-            print(f"Failed to turn device off in teardown {e}")
-
-    def test_device_proxy_unb2(self):
-        """Test if we can successfully create a DeviceProxy and fetch state"""
-
-        d = DeviceProxy("LTS/UNB2/1")
-
-        self.assertEqual(DevState.OFF, d.state())
-
-    def test_device_unb2_initialize(self):
-        """Test if we can transition to standby"""
-
-        d = DeviceProxy("LTS/UNB2/1")
-
-        d.initialise()
-
-        self.assertEqual(DevState.STANDBY, d.state())
-
-    def test_device_unb2_on(self):
-        """Test if we can transition to on"""
-
-        d = DeviceProxy("LTS/UNB2/1")
-
-        d.initialise()
-
-        d.on()
-
-        self.assertEqual(DevState.ON, d.state())
+# -*- 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.
+
+import time
+
+from tango import DeviceProxy
+from tango._tango import DevState
+
+from integration_test import base
+
+
+class TestDeviceUNB2(base.IntegrationTestCase):
+
+    def setUp(self):
+        """Intentionally recreate the device object in each test"""
+        super(TestDeviceUNB2, self).setUp()
+
+    def tearDown(self):
+        """Turn device Off in teardown to prevent blocking tests"""
+        d = DeviceProxy("LTS/UNB2/1")
+
+        try:
+            d.Off()
+        except Exception as e:
+            """Failing to turn Off devices should not raise errors here"""
+            print(f"Failed to turn device off in teardown {e}")
+
+    def test_device_proxy_unb2(self):
+        """Test if we can successfully create a DeviceProxy and fetch state"""
+
+        d = DeviceProxy("LTS/UNB2/1")
+
+        self.assertEqual(DevState.OFF, d.state())
+
+    def test_device_unb2_initialize(self):
+        """Test if we can transition to standby"""
+
+        d = DeviceProxy("LTS/UNB2/1")
+
+        d.initialise()
+
+        self.assertEqual(DevState.STANDBY, d.state())
+
+    def test_device_unb2_on(self):
+        """Test if we can transition to on"""
+
+        d = DeviceProxy("LTS/UNB2/1")
+
+        d.initialise()
+
+        d.on()
+
+        self.assertEqual(DevState.ON, d.state())
diff --git a/devices/statistics_writer/receiver.py b/devices/statistics_writer/receiver.py
index 919357764a2196cb7955e4ec77f2487b81d24d59..92d0d6d34bfc69f8f89f306c86b906c68956e47b 100644
--- a/devices/statistics_writer/receiver.py
+++ b/devices/statistics_writer/receiver.py
@@ -54,6 +54,15 @@ class tcp_receiver(receiver):
 
         super().__init__(fd=self.sock.fileno())
 
+    def reconnect(self):
+        self.fd = None
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.sock.connect((self.host, self.port))
+        self.fd = self.sock.fileno()
+        return True
+
+
+
 class file_receiver(receiver):
     def __init__(self, filename):
         self.filename = filename
diff --git a/devices/statistics_writer/statistics_writer.py b/devices/statistics_writer/statistics_writer.py
index 594e261c6d1e00e0ea7882c595449813c305c8ce..8bf8fa64fbba9626f60abec0bb6cacb7e7288c51 100644
--- a/devices/statistics_writer/statistics_writer.py
+++ b/devices/statistics_writer/statistics_writer.py
@@ -2,23 +2,28 @@ import argparse
 from receiver import tcp_receiver, file_receiver
 from hdf5_writer import hdf5_writer
 
+import time
+from datetime import datetime
+
 import sys
 import signal
 
 import logging
-logging.basicConfig(level=logging.INFO)
+logging.basicConfig(level=logging.INFO, format = '%(asctime)s:%(levelname)s: %(message)s')
 logger = logging.getLogger("statistics_writer")
 
+
 parser = argparse.ArgumentParser(description='Converts a stream of statistics packets into HDF5 files.')
-parser.add_argument('-a', '--host', type=str, help='the host to connect to')
-parser.add_argument('-p', '--port', type=int, default=0, help='the port to connect to, or 0 to use default port for the selected mode (default: %(default)s)')
-parser.add_argument('-f', '--file', type=str, help='the file to read from')
+parser.add_argument('-a', '--host', type=str, help='The host to connect to.')
+parser.add_argument('-p', '--port', type=int, default=0, help='The port to connect to, or 0 to use default port for the selected mode. (default: %(default)s)')
+parser.add_argument('-f', '--file', type=str, help='The file to read from. (will ignore --host and --port)')
 
-parser.add_argument('-m', '--mode', type=str, choices=['SST', 'XST', 'BST'], default='SST', help='sets the statistics type to be decoded options (default: %(default)s)')
-parser.add_argument('-i', '--interval', type=float, default=3600, nargs="?", help='The time between creating new files in seconds (default: %(default)s)')
-parser.add_argument('-o', '--output_dir', type=str, default=".", nargs="?", help='specifies the folder to write all the files (default: %(default)s)')
-parser.add_argument('-v', '--debug', dest='debug', action='store_true', default=False, help='increase log output')
-parser.add_argument('-d', '--decimation', type=int, default=1, help='Configure the writer to only store one every n samples. Saves storage space')
+parser.add_argument('-m', '--mode', type=str, choices=['SST', 'XST', 'BST'], default='SST', help='Sets the statistics type to be decoded options. (default: %(default)s)')
+parser.add_argument('-i', '--interval', type=float, default=3600, nargs="?", help='The time between creating new files in seconds. (default: %(default)s)')
+parser.add_argument('-o', '--output_dir', type=str, default=".", nargs="?", help='Specifies the folder to write all the files. (default: %(default)s)')
+parser.add_argument('-d', '--decimation', type=int, default=1, help='Configure the writer to only store one every n samples. Saves storage space.')
+parser.add_argument('-v', '--debug', dest='debug', action='store_true', default=False, help='Increase log output.')
+parser.add_argument('-r', '--reconnect', dest='reconnect', action='store_true', default=False, help='Set the writer to keep trying to reconnect whenever connection is lost. (default: %(default)s)')
 
 
 if __name__ == "__main__":
@@ -31,8 +36,9 @@ if __name__ == "__main__":
     output_dir = args.output_dir
     interval = args.interval
     mode = args.mode
-    debug = args.debug
     decimation = args.decimation
+    debug = args.debug
+    reconnect = args.reconnect
 
     if decimation < 1:
         raise ValueError("Please use an integer --Decimation value 1 or higher to only store one every n statistics' ")
@@ -60,13 +66,27 @@ if __name__ == "__main__":
     # start looping
     try:
         while True:
-            packet = receiver.get_packet()
-            writer.next_packet(packet)
+            try:
+                packet = receiver.get_packet()
+                writer.next_packet(packet)
+            except EOFError:
+                if reconnect and not filename:
+                    logger.warning("Connection lost, attempting to reconnect")
+                    while True:
+                        try:
+                            receiver.reconnect()
+                        except Exception as e:
+                            logger.warning(f"Could not reconnect: {e.__class__.__name__}: {e}")
+                            time.sleep(10)
+                        else:
+                            break
+                    logger.warning("Reconnected! Resuming operations")
+                else:
+                    logger.info("End of input.")
+                    raise SystemExit
+
     except KeyboardInterrupt:
         # user abort, don't complain
         logger.warning("Received keyboard interrupt. Stopping.")
-    except EOFError:
-        # done processing all input, don't complain
-        logger.info("End of input.")
     finally:
         writer.close_writer()
diff --git a/devices/statistics_writer/test/test_server.py b/devices/statistics_writer/test/test_server.py
index eec9ec3eed992b03ee809ca37de012bad43bd213..74101b93de2e83824c70e4630e8560ae24b28fa8 100644
--- a/devices/statistics_writer/test/test_server.py
+++ b/devices/statistics_writer/test/test_server.py
@@ -45,6 +45,9 @@ while True:
                     time.sleep(INTERVAL)
                     conn.sendall(data)
 
+    except KeyboardInterrupt:
+        logger.info("Received keyboard interrupt. Stopping.")
+        exit()
     except Exception as e:
         logger.warning(f"Exception occurred: {e}")
 
diff --git a/devices/test-requirements.txt b/devices/test-requirements.txt
index 20ed449cd8f17f9110ebe1b70774916abe8c00cb..1cd8ccb799fd1dc8b3b25db9051cb12d42d63bb3 100644
--- a/devices/test-requirements.txt
+++ b/devices/test-requirements.txt
@@ -2,6 +2,7 @@
 # order of appearance. Changing the order has an impact on the overall
 # integration process, which may cause wedges in the gate later.
 
+asynctest>=0.13.0 # Apache-2.0
 bandit>=1.6.0 # Apache-2.0
 coverage>=5.2.0 # Apache-2.0
 doc8>=0.8.0 # Apache-2.0
diff --git a/devices/test/base.py b/devices/test/base.py
index aecaaebc3b57909c49e0425d755f52f5028e0ded..1c2eff09be8e6a4034a476173944c8ec2a1fe61c 100644
--- a/devices/test/base.py
+++ b/devices/test/base.py
@@ -11,6 +11,7 @@ from common.lofar_logging import configure_logger
 
 import unittest
 import testscenarios
+import asynctest
 
 """Setup logging for unit tests"""
 configure_logger(debug=True)
@@ -28,3 +29,10 @@ class TestCase(BaseTestCase):
 
     def setUp(self):
         super().setUp()
+
+
+class AsyncTestCase(testscenarios.WithScenarios, asynctest.TestCase):
+    """Test case base class for all asyncio unit tests."""
+
+    def setUp(self):
+        super().setUp()
diff --git a/devices/test/clients/test_attr_wrapper.py b/devices/test/clients/test_attr_wrapper.py
index 453e19c19d67b56eb339462cc1da7e0e8414451b..8711d989a67730667c10aed91de7c9929c500fcb 100644
--- a/devices/test/clients/test_attr_wrapper.py
+++ b/devices/test/clients/test_attr_wrapper.py
@@ -18,6 +18,8 @@ from devices.hardware_device import *
 from tango.test_context import DeviceTestContext
 from test import base
 
+import asyncio
+
 scalar_dims = (1,)
 spectrum_dims = (4,)
 image_dims = (3,2)
@@ -31,7 +33,7 @@ def dev_init(device):
     device.set_state(DevState.INIT)
     device.test_client = test_client(device.Fault, device)
     for i in device.attr_list():
-        i.set_comm_client(device.test_client)
+        asyncio.run(i.async_set_comm_client(device.test_client))
     device.test_client.start()
 
 
@@ -361,6 +363,9 @@ class TestAttributeTypes(base.TestCase):
 
     def read_RW_test(self, dev, dtype, test_type):
         '''Test device'''
+        expected = None
+        val = None
+
         try:
             with DeviceTestContext(dev, process=True) as proxy:
 
diff --git a/devices/test/clients/test_client.py b/devices/test/clients/test_client.py
index d09f418282a67756f2aad1be6a2a21bff60ae12f..7e002c3ad28a531b0ba16f12a22e782d4ba3bb01 100644
--- a/devices/test/clients/test_client.py
+++ b/devices/test/clients/test_client.py
@@ -87,7 +87,7 @@ class test_client(CommClient):
         self.streams.debug_stream("created and bound example_client read/write functions to attribute_wrapper object")
         return read_function, write_function
 
-    def setup_attribute(self, annotation=None, attribute=None):
+    async def setup_attribute(self, annotation=None, attribute=None):
         """
         MANDATORY function: is used by the attribute wrapper to get read/write functions.
         must return the read and write functions
diff --git a/devices/test/clients/test_opcua_client.py b/devices/test/clients/test_opcua_client.py
index df9296c417857683955aa73ee3cbc0b7985ade76..bc13dc5e1d1d04c800e35f113825015b38779cd9 100644
--- a/devices/test/clients/test_opcua_client.py
+++ b/devices/test/clients/test_opcua_client.py
@@ -2,13 +2,15 @@ import numpy
 from clients.opcua_client import OPCUAConnection
 from clients import opcua_client
 
-import opcua
+import asyncua
 import io
+import asyncio
 
 from unittest import mock
 import unittest
 
 from test import base
+import asynctest
 
 
 class attr_props:
@@ -37,36 +39,39 @@ image_shape = (2, 3)
 dimension_tests = [scalar_shape, spectrum_shape, image_shape]
 
 
-class TestOPCua(base.TestCase):
-    @mock.patch.object(OPCUAConnection, "check_nodes")
-    @mock.patch.object(OPCUAConnection, "connect")
-    @mock.patch.object(opcua_client, "Client")
-    def test_opcua_connection(self, m_opc_client, m_connect, m_check):
+class TestOPCua(base.AsyncTestCase):
+    @asynctest.patch.object(OPCUAConnection, "ping")
+    @asynctest.patch.object(opcua_client, "Client")
+    async def test_opcua_connection(self, m_opc_client, m_ping):
         """
         This tests verifies whether the correct connection steps happen. It checks whether we can init an OPCUAConnection object
         Whether we can set the namespace, and the OPCua client.
         """
 
-        m_get_namespace = mock.Mock()
-        m_get_namespace.get_namespace_index.return_value = 42
-        m_opc_client.return_value = m_get_namespace
+        m_opc_client_members = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.get_namespace_index = asynctest.asynctest.CoroutineMock(return_value=42)
+        m_opc_client_members.connect = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.disconnect = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.send_hello = asynctest.asynctest.CoroutineMock()
+        m_opc_client.return_value = m_opc_client_members
 
-        test_client = OPCUAConnection("opc.tcp://localhost:4874/freeopcua/server/", "http://lofar.eu", 5, mock.Mock(), mock.Mock())
+        test_client = OPCUAConnection("opc.tcp://localhost:4874/freeopcua/server/", "http://lofar.eu", 5, mock.Mock(), self.loop)
+        try:
+            await test_client.start()
 
-        """Verify that construction of OPCUAConnection calls self.connect"""
-        m_connect.assert_called_once()  # the connect function in the opcua client
-        m_check.assert_called_once()  # debug function that prints out all nodes
-        m_opc_client.assert_called_once()  # makes sure the actual freeOPCua client object is created only once
+            m_opc_client.assert_called_once()  # makes sure the actual freeOPCua client object is created only once
 
-        m_get_namespace.get_namespace_index.assert_called_once_with("http://lofar.eu")
-        self.assertEqual(42, test_client.name_space_index)
+            # this also implies test_client.connect() is called
+            m_opc_client_members.get_namespace_index.assert_called_once_with("http://lofar.eu")
+            self.assertEqual(42, test_client.name_space_index)
+        finally:
+            await test_client.stop()
 
 
-    @mock.patch.object(OPCUAConnection, "check_nodes")
-    @mock.patch.object(OPCUAConnection, "connect")
-    @mock.patch.object(opcua_client, "Client")
-    @mock.patch.object(opcua_client, 'ProtocolAttribute')
-    def test_opcua_attr_setup(self, m_protocol_attr, m_opc_client, m_connect, m_check):
+    @asynctest.patch.object(OPCUAConnection, "ping")
+    @asynctest.patch.object(opcua_client, "Client")
+    @asynctest.patch.object(opcua_client, 'ProtocolAttribute')
+    async def test_opcua_attr_setup(self, m_protocol_attr, m_opc_client, m_ping):
         """
         This tests covers the correct creation of read/write functions.
         In normal circumstances called by he attribute wrapper.
@@ -75,6 +80,16 @@ class TestOPCua(base.TestCase):
         Test succeeds if there are no errors.
         """
 
+        m_opc_client_members = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.get_namespace_index = asynctest.asynctest.CoroutineMock(return_value=2)
+        m_opc_client_members.connect = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.disconnect = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.send_hello = asynctest.asynctest.CoroutineMock()
+        m_objects_node = asynctest.Mock()
+        m_objects_node.get_child = asynctest.asynctest.CoroutineMock()
+        m_opc_client_members.get_objects_node = asynctest.Mock(return_value=m_objects_node)
+        m_opc_client.return_value = m_opc_client_members
+
         for i in attr_test_types:
             class mock_attr:
                 def __init__(self, dtype, x, y):
@@ -96,13 +111,15 @@ class TestOPCua(base.TestCase):
                 # pretend like there is a running OPCua server with a node that has this name
                 m_annotation = ["2:PCC", f"2:testNode_{str(i.numpy_type)}_{str(dim_x)}_{str(dim_y)}"]
 
-                test = OPCUAConnection("opc.tcp://localhost:4874/freeopcua/server/", "http://lofar.eu", 5, mock.Mock(), mock.Mock())
-                test.setup_attribute(m_annotation, m_attribute)
+                test_client = OPCUAConnection("opc.tcp://localhost:4874/freeopcua/server/", "http://lofar.eu", 5, mock.Mock(), self.loop)
+                try:
+                    await test_client.start()
+                    await test_client.setup_attribute(m_annotation, m_attribute)
+                finally:
+                    await test_client.stop()
 
                 # success if there are no errors.
 
-
-
     def test_protocol_attr(self):
         """
         This tests finding an OPCua node and returning a valid object with read/write functions.
@@ -136,7 +153,7 @@ class TestOPCua(base.TestCase):
                 self.assertTrue(hasattr(test, "write_function"), f"No write function found")
                 self.assertTrue(hasattr(test, "read_function"), f"No read function found")
 
-    def test_read(self):
+    async def test_read(self):
         """
         This tests the read functions.
         """
@@ -146,17 +163,17 @@ class TestOPCua(base.TestCase):
                 def get_test_value():
                     return numpy.zeros(j, i.numpy_type)
 
-                def get_flat_value():
+                async def get_flat_value():
                     return get_test_value().flatten()
 
-                m_node = mock.Mock()
+                m_node = asynctest.asynctest.CoroutineMock()
 
                 if len(j) == 1:
                     test = opcua_client.ProtocolAttribute(m_node, j[0], 0, opcua_client.numpy_to_OPCua_dict[i.numpy_type])
                 else:
                     test = opcua_client.ProtocolAttribute(m_node, j[1], j[0], opcua_client.numpy_to_OPCua_dict[i.numpy_type])
                 m_node.get_value = get_flat_value
-                val = test.read_function()
+                val = await test.read_function()
 
                 comp = val == get_test_value()
                 self.assertTrue(comp.all(), "Read value unequal to expected value: \n\t{} \n\t{}".format(val, get_test_value()))
@@ -175,15 +192,15 @@ class TestOPCua(base.TestCase):
               default_value = 42.25
 
             # apply our mapping
-            v = opcua.ua.uatypes.Variant(value=numpy_type(default_value), varianttype=opcua_type)
+            v = asyncua.ua.uatypes.Variant(Value=numpy_type(default_value), VariantType=opcua_type)
 
             try:
                 # try to convert it to binary to force opcua to parse the value as the type
-                binary = opcua.ua.ua_binary.variant_to_binary(v)
+                binary = asyncua.ua.ua_binary.variant_to_binary(v)
 
                 # reinterpret the resulting binary to obtain what opcua made of our value
                 binary_stream = io.BytesIO(binary)
-                reparsed_v = opcua.ua.ua_binary.variant_from_binary(binary_stream)
+                reparsed_v = asyncua.ua.ua_binary.variant_from_binary(binary_stream)
             except Exception as e:
                 raise Exception(f"Conversion {numpy_type} -> {opcua_type} failed.") from e
 
@@ -192,11 +209,11 @@ class TestOPCua(base.TestCase):
 
             # does the OPC-UA type have the same datasize (and thus, precision?)
             if numpy_type not in [str, numpy.str]:
-                self.assertEqual(numpy_type().itemsize, getattr(opcua.ua.ua_binary.Primitives, opcua_type.name).size, msg=f"Conversion {numpy_type} -> {opcua_type} failed: precision mismatch")
+                self.assertEqual(numpy_type().itemsize, getattr(asyncua.ua.ua_binary.Primitives, opcua_type.name).size, msg=f"Conversion {numpy_type} -> {opcua_type} failed: precision mismatch")
 
 
 
-    def test_write(self):
+    async def test_write(self):
         """
         Test the writing of values by instantiating a ProtocolAttribute attribute, and calling the write function.
         but the opcua function that writes to the server has been changed to the compare_values function.
@@ -215,9 +232,9 @@ class TestOPCua(base.TestCase):
 
                 # get opcua Varianttype array of the test value
                 def get_mock_value(value):
-                    return opcua.ua.uatypes.Variant(value=value, varianttype=opcua_client.numpy_to_OPCua_dict[i.numpy_type])
+                    return asyncua.ua.uatypes.Variant(Value=value, VariantType=opcua_client.numpy_to_OPCua_dict[i.numpy_type])
 
-                m_node = mock.Mock()
+                m_node = asynctest.asynctest.CoroutineMock()
 
                 # create the protocolattribute
                 if len(j) == 1:
@@ -225,14 +242,12 @@ class TestOPCua(base.TestCase):
                 else:
                     test = opcua_client.ProtocolAttribute(m_node, j[1], j[0], opcua_client.numpy_to_OPCua_dict[i.numpy_type])
 
-                test.node.get_data_value = mock.Mock()
-
                 # comparison function that replaces `set_data_value` inside the attributes write function
-                def compare_values(val):
-                    # test values
+                async def compare_values(val):
+                    # test valuest
                     val = val.tolist() if type(val) == numpy.ndarray else val
                     if j != dimension_tests[0]:
-                        comp = val._value == get_mock_value(get_test_value().flatten())._value
+                        comp = val.Value == get_mock_value(get_test_value().flatten()).Value
                         self.assertTrue(comp.all(),
                                         "Array attempting to write unequal to expected array: \n\t got: {} \n\texpected: {}".format(val,get_mock_value(get_test_value())))
                     else:
@@ -243,4 +258,4 @@ class TestOPCua(base.TestCase):
                 m_node.set_data_value = compare_values
 
                 # call the write function with the test values
-                test.write_function(get_test_value())
+                await test.write_function(get_test_value())
diff --git a/devices/test/common/test_lofar_logging.py b/devices/test/common/test_lofar_logging.py
index 534b2650c8d432ef7c7dae9e32448b01cc5913f3..98222563f33167e62db9385090e1738aa29b6b24 100644
--- a/devices/test/common/test_lofar_logging.py
+++ b/devices/test/common/test_lofar_logging.py
@@ -75,7 +75,7 @@ class TestLofarLogging(base.TestCase):
 
         # create a Tango Device that logs something
         class MyDevice(Device):
-            def __init__(self):
+            def init_device(self):
                 self.log_deeper_in_stack()
 
             def log_deeper_in_stack(self):
@@ -83,7 +83,7 @@ class TestLofarLogging(base.TestCase):
 
         with mock.patch.object(device_server.DeviceImpl, '__info_stream') as m_info_stream:
             # logs in the constructor already
-            mydevice = MyDevice()
+            mydevice = MyDevice(None, "MyDeviceName")
 
             self.assertEqual(mydevice, self.memory_handler.records[0].tango_device, msg="configure_logging did not detect active Tango device")
             self.assertEqual(1, m_info_stream.call_count, msg="configure_logger did not send logs to active Tango device")
diff --git a/devices/toolkit/lts_cold_start.py b/devices/toolkit/lts_cold_start.py
deleted file mode 100644
index 47d3243e2064dc39fba8127e33da842acba19416..0000000000000000000000000000000000000000
--- a/devices/toolkit/lts_cold_start.py
+++ /dev/null
@@ -1,228 +0,0 @@
-#! /usr/bin/env python3
-import logging
-from time import sleep
-
-# TODO(Corne): Remove sys.path.append hack once packaging is in place!
-import os, sys
-currentdir = os.path.dirname(os.path.realpath(__file__))
-parentdir = os.path.dirname(currentdir)
-sys.path.append(parentdir)
-
-from toolkit.startup import startup
-from toolkit.lofar2_config import configure_logging
-
-
-def start_device(device: str):
-    '''
-    Start a Tango device with the help of the startup function.
-    The device will not be forced to got through
-    OFF/INIT/STANDBY/ON but it is assumed that the device is in OFF
-    state.  If the device is not in OFF state, then an exception
-    will be raised.
-    '''
-    dev = startup(device = device, force_restart = False)
-    state = device.state()
-    if state is not tango._tango.DevState.ON:
-        raise Exception("Device \"{}\" is unexpectedly in \"{}\" state but it is expected to be in \"{}\" state.  Please check the reason for the unexpected device state.  Aborting the start-up procedure.".format(device, state, tango._tango.DevState.ON))
-    return device
-
-
-def lts_cold_start():
-    '''
-    What is this?
-    This is the LTS (LOFAR Test - and I forgot what S stands for) cold start
-    procedure cast into source code.  The procedure can be found there:
-    https://support.astron.nl/confluence/display/L2M/LTS+startup+procedure
-
-    Paulus wrote already a script that - illegally ;) - makes direct use of the
-    OPC-UA servers to accomplish the same thing that we are doing here.
-    Paulus' script can be found there:
-    https://git.astron.nl/lofar2.0/pypcc/-/blob/master/scripts/Startup.py
-    Thanks, Paulus!  You made it very easy for me to cobble together this
-    script.
-
-    For obvious reasons is our script much better though.  :)
-    First, it is bigger.  And bigger is always better.
-    Then it is better documented but that does not count in the HW world.
-    But it also raises exceptions with error messages that make an attempt to
-    help the user reading them and shuts down the respective Tango device(s) if
-    something goes south.
-    And that is where we try to do it really right:  there is no reason to be
-    excessively verbatim when things work like they are expected to work.  But
-    tell the user when something goes wrong, give an indication of what could
-    have gone wrong and where to look for the problem.
-
-    Again, Paulus' script contains already very good indications where problems
-    might lie and made my job very easy.
-
-    No parameters, parameters are for wimps.  :)
-    '''
-    # Define the LOFAR2.0 specific log format
-    configure_logging()
-
-    # Get a reference to the RECV device, do not
-    # force a restart of the already running Tango
-    # device.
-    recv = startup("LTS/RECV/1")
-
-    # Getting CLK, RCU & RCU ADCs into proper shape for use by real people.
-    #
-    # The start-up needs to happen in this sequence due to HW dependencies
-    # that can introduce issues which are then becoming very complicated to
-    # handle in SW.  Therefore to keep it as simple as possible, let's stick
-    # to the rule recommended by Paulus:
-    # 1 CLK
-    # 2 RCU
-    # 3 RCU ADCs
-    #
-    #
-    # First take the CLK board through the motions.
-    # 1.1 Switch off CLK
-    # 1.2 Wait for CLK_translator_busy_R == True, throw an exception in timeout
-    # 1.3 Switch on CLK
-    # 1.4 Wait for CLK_translator_busy_R == True, throw an exception in timeout
-    # 1.5 Check if CLK_PLL_locked_R == True
-    # 1.6 Done
-    #
-    #
-    # Steps 1.1 & 1.2
-    recv.CLK_off()
-    # 2021-04-30, Thomas
-    # This should be refactored into a function.
-    timeout = 10.0
-    while recv.CLK_translator_busy_R is True:
-        logging.debug("Waiting on \"CLK_translator_busy_R\" to become \"True\"...")
-        timeout = timeout - 1.0
-        if timeout < 1.0:
-            # Switching the RECV clock off should never take longer than
-            # 10 seconds.  Here we ran into a timeout.
-            # Clean up and raise an exception.
-            recv.off()
-            raise Exception("After calling \"CLK_off\" a timeout occured while waiting for \"CLK_translator_busy_R\" to become \"True\".  Please investigate the reason why the RECV translator never set \"CLK_translator_busy_R\" to \"True\".  Aborting start-up procedure.")
-        sleep(1.0)
-
-    # Steps 1.3 & 1.4
-    recv.CLK_on()
-    # Per Paulus this should never take longer than 2 seconds.
-    # 2021-04-30, Thomas
-    # This should be refactored into a function.
-    timeout = 2.0
-    while recv.CLK_translator_busy_R is True:
-        logging.debug("After calling \"CLK_on()\"  Waiting on \"CLK_translator_busy_R\" to become \"True\"...")
-        timeout = timeout - 1.0
-        if timeout < 1.0:
-            # Switching theRECV clock on should never take longer than
-            # a couple of seconds.  Here we ran into a timeout.
-            # Clean up and raise an exception.
-            recv.off()
-            raise Exception("After calling \"CLK_on\" a timeout occured while waiting for \"CLK_translator_busy_R\" to become \"True\".  Please investigate the reason why the RECV translator never set \"CLK_translator_busy_R\" to \"True\".  Aborting start-up procedure.")
-        sleep(1.0)
-
-    # 1.5 Check if CLK_PLL_locked_R == True
-    # 2021-04-30, Thomas
-    # This should be refactored into a function.
-    clk_locked = recv.CLK_PLL_locked_R
-    if clk_locked is True:
-       logging.info("CLK signal is locked.")
-    else:
-        # CLK signal is not locked
-        clk_i2c_status = recv.CLK_I2C_STATUS_R
-        exception_text = "CLK I2C is not working.  Please investigate!  Maybe power cycle subrack to restart CLK board and translator.  Aborting start-up procedure."
-        if i2c_status <= 0:
-            exception_text = "CLK signal is not locked.  Please investigate!  The subrack probably do not receive clock input or the CLK PCB is broken.  Aborting start-up procedure."
-        recv.off()
-        raise Exception(exception_text)
-    # Step 1.6
-    # Done.
-
-    # 2 RCUs
-    # If we reach this point in the start-up procedure, then the CLK board setup
-    # is done.  We can proceed with the RCUs.
-    #
-    # Now take the RCUs through the motions.
-    # 2.1 Set RCU mask to all available RCUs
-    # 2.2 Switch off all RCUs
-    # 2.3 Wait for RCU_translator_busy_R = True, throw an exception in timeout
-    # 2.4 Switch on RCUs
-    # 2.5 Wait for RCU_translator_busy_R = True, throw an exception in timeout
-    # 2.6 Done
-    #
-    #
-    # Step 2.1
-    # We have only 8 RCUs in LTS.
-    recv.RCU_mask_RW = [True, ] * 8
-    # Steps 2.2 & 2.3
-    recv.RCU_off()
-    # 2021-04-30, Thomas
-    # This should be refactored into a function.
-    timeout = 10.0
-    while recv.RCU_translator_busy_R is True:
-        logging.debug("Waiting on \"RCU_translator_busy_R\" to become \"True\"...")
-        timeout = timeout - 1.0
-        if timeout < 1.0:
-            # Switching the RCUs off should never take longer than
-            # 10 seconds.  Here we ran into a timeout.
-            # Clean up and raise an exception.
-            recv.off()
-            raise Exception("After calling \"RCU_off\" a timeout occured while waiting for \"RCU_translator_busy_R\" to become \"True\".  Please investigate the reason why the RECV translator never set \"RCU_translator_busy_R\" to \"True\".  Aborting start-up procedure.")
-        sleep(1.0)
-
-    # Steps 2.4 & 2.5
-    # We leave the RCU mask as it is because it got already set for the
-    # RCU_off() call.
-    recv.RCU_on()
-    # Per Paulus this should never take longer than 5 seconds.
-    # 2021-04-30, Thomas
-    # This should be refactored into a function.
-    timeout = 5.0
-    while recv.RCU_translator_busy_R is True:
-        logging.debug("After calling \"RCU_on()\"  Waiting on \"RCU_translator_busy_R\" to become \"True\"...")
-        timeout = timeout - 1.0
-        if timeout < 1.0:
-            # Switching the RCUs on should never take longer than
-            # a couple of seconds.  Here we ran into a timeout.
-            # Clean up and raise an exception.
-            recv.off()
-            raise Exception("After calling \"RCU_on\" a timeout occured while waiting for \"RCU_translator_busy_R\" to become \"True\".  Please investigate the reason why the RECV translator never set \"RCU_translator_busy_R\" to \"True\".  Aborting start-up procedure.")
-        sleep(1.0)
-    # Step 2.6
-    # Done.
-
-    # 3 ADCs
-    # If we get here, we only got to check if the ADCs are locked, too.
-    # 3.1 Check RCUs' I2C status
-    # 3.2 Check RCU_ADC_lock_R == [True, ] for RCUs that have a good I2C status
-    # 3.3 Done
-    #
-    #
-    # Steps 3.1 & 3.2
-    rcu_mask = recv.RCU_mask_RW
-    adc_locked = numpy.array(recv.RCU_ADC_lock_R)
-    for rcu, i2c_status in enumerate(recv.RCU_I2C_STATUS_R):
-        if i2c_status == 0:
-            rcu_mask[rcu] = True
-            logging.info("RCU #{} is available.".format(rcu))
-            for adc, adc_is_locked in enumerate(adc_locked[rcu]):
-                if adc_is_locked < 1:
-                    logging.warning("RCU#{}, ADC#{} is unlocked.  Please investigate!  Will continue with normal operation.".format(rcu, adc))
-        else:
-            # The RCU's I2C bus is not working.
-            rcu_mask[rcu] = False
-            logging.error("RCU #{}'s I2C is not working.  Please investigate!  Disabling RCU #{} to avoid damage.".format(rcu, rcu))
-    recv.RCU_mask_RW = rcu_mask
-    # Step 3.3
-    # Done
-
-    # Start-up APSCTL, i.e. Uniboard2s.
-    aps = startup("APSCTL/SDP/1")
-    logging.warning("Cannot start-up APSCTL because it requires manual actions.")
-
-    # Start up SDP, i.e. configure the firmware in the Unibards
-    sdp = startup("LTS/SDP/1")
-    logging.warning("Cannot start-up SDP because it requires manual actions.")
-
-    logging.info("LTS has been successfully started and configured.")
-
-
-if __name__ == '__main__':
-    lts_cold_start()
diff --git a/devices/toolkit/startup.py b/devices/toolkit/startup.py
deleted file mode 100644
index 66a8d2c496fc7e86d0d13086336e900fc1a1bfaf..0000000000000000000000000000000000000000
--- a/devices/toolkit/startup.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#! /usr/bin/env python3
-import tango
-import logging
-
-logger = logging.getLogger()
-
-def startup(device: str, force_restart: bool) -> tango.DeviceProxy:
-    '''
-    Start a LOFAR Tango device:
-    recv = startup(device = 'LTS/RECV/1', force_restart = False)
-    '''
-    proxy = tango.DeviceProxy(device)
-    state = proxy.state()
-
-    # go to OFF, but only if force_restart is True
-    if force_restart is True:
-        logger.warning(f"Forcing device {device} restart.")
-        proxy.off()
-        state = proxy.state()
-        if state is not tango._tango.DevState.OFF:
-            logger.error(f"Device {device} cannot perform off although restart has been enforced, state = {state}.  Please investigate.")
-            return proxy
-
-    if state is not tango._tango.DevState.OFF:
-        logger.error(f"Device {device} is not in OFF state, cannot start it.  state = {state}")
-        return proxy
-
-    # Initialise device
-    logger.info(f"Device {device} is in OFF, performing initialisation.")
-    proxy.initialise()
-    state = proxy.state()
-    if state is not tango._tango.DevState.STANDBY:
-        logger.error(f"Device {device} cannot perform initialise, state = {state}.  Please investigate.")
-        return proxy
-
-    # Set default values
-    logger.info(f"Device {device} is in STANDBY, setting default values.")
-    proxy.set_defaults()
-
-    # Turn on device
-    logger.info(f"Device {device} is in STANDBY, performing on.")
-    proxy.on()
-    state = proxy.state()
-    if state is not tango._tango.DevState.ON:
-        logger.error(f"Device {device} cannot perform on, state = {state}.  Please investigate.")
-    else:
-        logger.info(f"Device {device} has successfully reached ON state.")
-
-    return proxy
diff --git a/docker-compose/Makefile b/docker-compose/Makefile
index 8e660436fb7ab61d86f704a00c5a386fcc25c401..649e63518d5f1276a2f1fb696d90a2b79fef0f24 100644
--- a/docker-compose/Makefile
+++ b/docker-compose/Makefile
@@ -138,7 +138,7 @@ build-nocache: ## rebuild images from scratch
 	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) build --no-cache --progress=plain $(SERVICE)
 
 up: minimal  ## start the base TANGO system and prepare all services
-	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) up --no-start
+	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) up --no-start --no-recreate
 
 down:  ## stop all services and tear down the system
 	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) down
@@ -154,6 +154,13 @@ ifneq ($(NETWORK_MODE),host)
 endif
 	$(DOCKER_COMPOSE_ARGS) docker-compose -f tango.yml -f networks.yml up -d
 
+bootstrap: pull build # first start, initialise from scratch
+	$(MAKE) start elk-configure-host # configure host kernel for elk container
+	$(MAKE) start dsconfig # boot up containers to load configurations
+	sleep 5 # wait for dsconfig container to come up
+	../sbin/update_ConfigDb.sh ../CDB/LOFAR_ConfigDb.json # load default configuration
+	../sbin/update_ConfigDb.sh ../CDB/stations/simulators_ConfigDb.json # by default, use simulators
+
 start: up ## start a service (usage: make start <servicename>)
 	if [ $(UNAME_S) = Linux ]; then touch ~/.Xauthority; chmod a+r ~/.Xauthority; fi
 	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) start $(SERVICE)
diff --git a/docker-compose/apsct-sim.yml b/docker-compose/apsct-sim.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d30f5a026f734bb72ee91c7bf533df677f37ca88
--- /dev/null
+++ b/docker-compose/apsct-sim.yml
@@ -0,0 +1,17 @@
+#
+# Docker compose file that launches an APSCT simulator
+#
+# Defines:
+#   - apsct-sim
+#
+version: '2'
+
+services:
+  apsct-sim:
+    build:
+        context: pypcc-sim-base
+    container_name: ${CONTAINER_NAME_PREFIX}apsct-sim
+    networks:
+      - control
+    entrypoint: python3 pypcc2.py --simulator --port 4843 --config APSCTTR
+    restart: on-failure
diff --git a/docker-compose/apspu-sim.yml b/docker-compose/apspu-sim.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d3fc5fa04f6ce0d6ddfe4c8f87887ab7500720e3
--- /dev/null
+++ b/docker-compose/apspu-sim.yml
@@ -0,0 +1,17 @@
+#
+# Docker compose file that launches an APSPU simulator
+#
+# Defines:
+#   - apspu-sim
+#
+version: '2'
+
+services:
+  apspu-sim:
+    build:
+        context: pypcc-sim-base
+    container_name: ${CONTAINER_NAME_PREFIX}apspu-sim
+    networks:
+      - control
+    entrypoint: python3 pypcc2.py --simulator --port 4842 --config APSPUTR
+    restart: on-failure
diff --git a/docker-compose/archiver.yml b/docker-compose/archiver.yml
index 8a357d371e89377a1bfa2ce89e341ba708526fef..84dded354d22c97eeccd51ea97d8ff41b909f01e 100644
--- a/docker-compose/archiver.yml
+++ b/docker-compose/archiver.yml
@@ -73,5 +73,5 @@ services:
       - ..:/opt/lofar/tango:rw
       - ${HOME}:/hosthome
       - ../docker/tango/tango-archiver:/tango-archiver
-    restart: on-failure
+    restart: unless-stopped
 
diff --git a/docker-compose/device-apsct.yml b/docker-compose/device-apsct.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f17919a227a12b9846ba7a272254faaaee4d496a
--- /dev/null
+++ b/docker-compose/device-apsct.yml
@@ -0,0 +1,42 @@
+#
+# Docker compose file that launches an interactive iTango session.
+#
+# Connect to the interactive session with 'docker attach itango'.
+# Disconnect with the Docker deattach sequence: <CTRL>+<P> <CTRL>+<Q>
+#
+# Defines:
+#   - itango: iTango interactive session
+#
+# Requires:
+#   - lofar-device-base.yml
+#
+version: '2'
+
+services:
+  device-apsct:
+    image: device-apsct
+    # build explicitly, as docker-compose does not understand a local image
+    # being shared among services.
+    build:
+        context: lofar-device-base
+        args:
+            SOURCE_IMAGE: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-itango:${TANGO_ITANGO_VERSION}
+    container_name: ${CONTAINER_NAME_PREFIX}device-apsct
+    networks:
+      - control
+    ports:
+      - "5709:5709" # unique port for this DS
+    volumes:
+        - ..:/opt/lofar/tango:rw
+    environment:
+      - TANGO_HOST=${TANGO_HOST}
+    entrypoint:
+      - /usr/local/bin/wait-for-it.sh
+      - ${TANGO_HOST}
+      - --timeout=30
+      - --strict
+      - --
+      # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
+      # can't know about our Docker port forwarding
+      - python3 -u /opt/lofar/tango/devices/devices/apsct.py LTS -v -ORBendPoint giop:tcp:0:5709 -ORBendPointPublish giop:tcp:${HOSTNAME}:5709
+    restart: on-failure
diff --git a/docker-compose/device-apspu.yml b/docker-compose/device-apspu.yml
new file mode 100644
index 0000000000000000000000000000000000000000..30da5a6c2aba5daef2452f906693c41e7fece330
--- /dev/null
+++ b/docker-compose/device-apspu.yml
@@ -0,0 +1,42 @@
+#
+# Docker compose file that launches an interactive iTango session.
+#
+# Connect to the interactive session with 'docker attach itango'.
+# Disconnect with the Docker deattach sequence: <CTRL>+<P> <CTRL>+<Q>
+#
+# Defines:
+#   - itango: iTango interactive session
+#
+# Requires:
+#   - lofar-device-base.yml
+#
+version: '2'
+
+services:
+  device-apspu:
+    image: device-apspu
+    # build explicitly, as docker-compose does not understand a local image
+    # being shared among services.
+    build:
+        context: lofar-device-base
+        args:
+            SOURCE_IMAGE: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-itango:${TANGO_ITANGO_VERSION}
+    container_name: ${CONTAINER_NAME_PREFIX}device-apspu
+    networks:
+      - control
+    ports:
+      - "5710:5710" # unique port for this DS
+    volumes:
+        - ..:/opt/lofar/tango:rw
+    environment:
+      - TANGO_HOST=${TANGO_HOST}
+    entrypoint:
+      - /usr/local/bin/wait-for-it.sh
+      - ${TANGO_HOST}
+      - --timeout=30
+      - --strict
+      - --
+      # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
+      # can't know about our Docker port forwarding
+      - python3 -u /opt/lofar/tango/devices/devices/apspu.py LTS -v -ORBendPoint giop:tcp:0:5710 -ORBendPointPublish giop:tcp:${HOSTNAME}:5710
+    restart: on-failure
diff --git a/docker-compose/device-boot.yml b/docker-compose/device-boot.yml
new file mode 100644
index 0000000000000000000000000000000000000000..58a9aa7df81eab368464f4ca69ddab54129b7ace
--- /dev/null
+++ b/docker-compose/device-boot.yml
@@ -0,0 +1,41 @@
+#
+# Docker compose file that launches a LOFAR2.0 station's
+# ObservationControl device. It also runs the dynamically
+# created Observation devices.
+#
+# Defines:
+#   - device-observation_control: LOFAR2.0 station ObvservationControl
+#
+# Requires:
+#   - lofar-device-base.yml
+#
+version: '2'
+
+services:
+  device-boot:
+    image: device-boot
+    # build explicitly, as docker-compose does not understand a local image
+    # being shared among services.
+    build:
+        context: lofar-device-base
+        args:
+            SOURCE_IMAGE: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-itango:${TANGO_ITANGO_VERSION}
+    container_name: ${CONTAINER_NAME_PREFIX}device-boot
+    networks:
+      - control
+    ports:
+      - "5708:5708" # unique port for this DS
+    volumes:
+      - ..:/opt/lofar/tango:rw
+    environment:
+      - TANGO_HOST=${TANGO_HOST}
+    entrypoint:
+      - /usr/local/bin/wait-for-it.sh
+      - ${TANGO_HOST}
+      - --timeout=30
+      - --strict
+      - --
+      # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
+      # can't know about our Docker port forwarding
+      - python3 -u /opt/lofar/tango/devices/devices/boot.py LTS -v -ORBendPoint giop:tcp:0:5708 -ORBendPointPublish giop:tcp:${HOSTNAME}:5708
+    restart: unless-stopped
diff --git a/docker-compose/device-docker.yml b/docker-compose/device-docker.yml
index 5386ead921b386741e62febeab399f3007a79281..d9e1e1e35233177ab271db395773538ed8c74ffa 100644
--- a/docker-compose/device-docker.yml
+++ b/docker-compose/device-docker.yml
@@ -41,4 +41,4 @@ services:
       # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
       # can't know about our Docker port forwarding
       - python3 -u /opt/lofar/tango/devices/devices/docker_device.py LTS -v -ORBendPoint giop:tcp:0:5705 -ORBendPointPublish giop:tcp:${HOSTNAME}:5705
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/device-observation_control.yml b/docker-compose/device-observation_control.yml
index 011fe0a94112df557670a218518b6492520f4480..827a558a10167d29f3e0bd3402f3f84debcd3c23 100644
--- a/docker-compose/device-observation_control.yml
+++ b/docker-compose/device-observation_control.yml
@@ -38,4 +38,4 @@ services:
       # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
       # can't know about our Docker port forwarding
       - python3 -u /opt/lofar/tango/devices/devices/observation_control.py LTS -v -ORBendPoint giop:tcp:0:5703 -ORBendPointPublish giop:tcp:${HOSTNAME}:5703
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/device-recv.yml b/docker-compose/device-recv.yml
index fdf8a535b002d629b29ee48b49b9ee91d8e925d7..f3bc3eea12b51b44cacbeb790d0666ced24ae169 100644
--- a/docker-compose/device-recv.yml
+++ b/docker-compose/device-recv.yml
@@ -39,4 +39,4 @@ services:
       # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
       # can't know about our Docker port forwarding
       - python3 -u /opt/lofar/tango/devices/devices/recv.py LTS -v -ORBendPoint giop:tcp:0:5707 -ORBendPointPublish giop:tcp:${HOSTNAME}:5707
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/device-sdp.yml b/docker-compose/device-sdp.yml
index cdd8d137d6f249ef91e500dd4b9bb32734b23c90..8fefa3f355eda485ea757f0859924e317b9245ee 100644
--- a/docker-compose/device-sdp.yml
+++ b/docker-compose/device-sdp.yml
@@ -39,4 +39,4 @@ services:
       # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
       # can't know about our Docker port forwarding
       - python3 -u /opt/lofar/tango/devices/devices/sdp/sdp.py LTS -v -ORBendPoint giop:tcp:0:5701 -ORBendPointPublish giop:tcp:${HOSTNAME}:5701
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/device-sst.yml b/docker-compose/device-sst.yml
index a9547f53830a564eeba6c9123c753c0062d1da30..7d922a61badf6575d15c6f0a0489a6fac3683367 100644
--- a/docker-compose/device-sst.yml
+++ b/docker-compose/device-sst.yml
@@ -42,4 +42,4 @@ services:
       # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
       # can't know about our Docker port forwarding
       - python3 -u /opt/lofar/tango/devices/devices/sdp/sst.py LTS -v -ORBendPoint giop:tcp:0:5702 -ORBendPointPublish giop:tcp:${HOSTNAME}:5702
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/device-unb2.yml b/docker-compose/device-unb2.yml
index 67c443121cf02bc9c1652978b1dd67a5ebf3a80b..6844ee2b6994c11fb53469535925284be42410c0 100644
--- a/docker-compose/device-unb2.yml
+++ b/docker-compose/device-unb2.yml
@@ -1,42 +1,42 @@
-#
-# Docker compose file that launches an interactive iTango session.
-#
-# Connect to the interactive session with 'docker attach itango'.
-# Disconnect with the Docker deattach sequence: <CTRL>+<P> <CTRL>+<Q>
-#
-# Defines:
-#   - itango: iTango interactive session
-#
-# Requires:
-#   - lofar-device-base.yml
-#
-version: '2'
-
-services:
-  device-unb2:
-    image: device-unb2
-    # build explicitly, as docker-compose does not understand a local image
-    # being shared among services.
-    build:
-        context: lofar-device-base
-        args:
-            SOURCE_IMAGE: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-itango:${TANGO_ITANGO_VERSION}
-    container_name: ${CONTAINER_NAME_PREFIX}device-unb2
-    networks:
-      - control
-    ports:
-      - "5704:5704" # unique port for this DS
-    volumes:
-        - ..:/opt/lofar/tango:rw
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    entrypoint:
-      - /usr/local/bin/wait-for-it.sh
-      - ${TANGO_HOST}
-      - --timeout=30
-      - --strict
-      - --
-      # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
-      # can't know about our Docker port forwarding
-      - python3 -u /opt/lofar/tango/devices/devices/unb2.py LTS -v -ORBendPoint giop:tcp:0:5704 -ORBendPointPublish giop:tcp:${HOSTNAME}:5704
-    restart: on-failure
+#
+# Docker compose file that launches an interactive iTango session.
+#
+# Connect to the interactive session with 'docker attach itango'.
+# Disconnect with the Docker deattach sequence: <CTRL>+<P> <CTRL>+<Q>
+#
+# Defines:
+#   - itango: iTango interactive session
+#
+# Requires:
+#   - lofar-device-base.yml
+#
+version: '2'
+
+services:
+  device-unb2:
+    image: device-unb2
+    # build explicitly, as docker-compose does not understand a local image
+    # being shared among services.
+    build:
+        context: lofar-device-base
+        args:
+            SOURCE_IMAGE: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-itango:${TANGO_ITANGO_VERSION}
+    container_name: ${CONTAINER_NAME_PREFIX}device-unb2
+    networks:
+      - control
+    ports:
+      - "5704:5704" # unique port for this DS
+    volumes:
+        - ..:/opt/lofar/tango:rw
+    environment:
+      - TANGO_HOST=${TANGO_HOST}
+    entrypoint:
+      - /usr/local/bin/wait-for-it.sh
+      - ${TANGO_HOST}
+      - --timeout=30
+      - --strict
+      - --
+      # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
+      # can't know about our Docker port forwarding
+      - python3 -u /opt/lofar/tango/devices/devices/unb2.py LTS -v -ORBendPoint giop:tcp:0:5704 -ORBendPointPublish giop:tcp:${HOSTNAME}:5704
+    restart: unless-stopped
diff --git a/docker-compose/device-xst.yml b/docker-compose/device-xst.yml
index 1f75009dc6042b83aff706e34a811c1023f532b0..c634e5d83fc7b28f2b8438ae59dffb7157a03f54 100644
--- a/docker-compose/device-xst.yml
+++ b/docker-compose/device-xst.yml
@@ -42,4 +42,4 @@ services:
       # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
       # can't know about our Docker port forwarding
       - python3 -u /opt/lofar/tango/devices/devices/sdp/xst.py LTS -v -ORBendPoint giop:tcp:0:5706 -ORBendPointPublish giop:tcp:${HOSTNAME}:5706
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/grafana/dashboards/home.json b/docker-compose/grafana/dashboards/home.json
index 51ed27cc87098fa85f7563d813c6807eb18a7b3d..6d4641a656c20b40ceaa8a18d2b02da47b0b55ba 100644
--- a/docker-compose/grafana/dashboards/home.json
+++ b/docker-compose/grafana/dashboards/home.json
@@ -19,10 +19,12 @@
     ]
   },
   "editable": true,
+  "fiscalYearStartMonth": 0,
   "gnetId": null,
   "graphTooltip": 0,
-  "id": 3,
+  "id": 6,
   "links": [],
+  "liveNow": false,
   "panels": [
     {
       "collapsed": false,
@@ -47,6 +49,8 @@
             "mode": "thresholds"
           },
           "mappings": [],
+          "max": 100,
+          "min": 0,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -76,6 +80,7 @@
       },
       "id": 43,
       "options": {
+        "orientation": "auto",
         "reduceOptions": {
           "calcs": [
             "lastNotNull"
@@ -87,7 +92,7 @@
         "showThresholdMarkers": false,
         "text": {}
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -176,10 +181,13 @@
           "fields": "",
           "values": false
         },
-        "text": {},
+        "text": {
+          "titleSize": 20,
+          "valueSize": 20
+        },
         "textMode": "value_and_name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -191,6 +199,15 @@
         }
       ],
       "title": "Device States",
+      "transformations": [
+        {
+          "id": "renameByRegex",
+          "options": {
+            "regex": ".*/(.*)/1",
+            "renamePattern": "$1"
+          }
+        }
+      ],
       "type": "stat"
     },
     {
@@ -247,7 +264,7 @@
       },
       "gridPos": {
         "h": 9,
-        "w": 12,
+        "w": 10,
         "x": 10,
         "y": 1
       },
@@ -267,7 +284,7 @@
           "alias": "",
           "bucketAggs": [
             {
-              "field": "extra.tango_device.keyword",
+              "field": "extra.lofar_id.keyword",
               "id": "2",
               "settings": {
                 "min_doc_count": "0",
@@ -300,8 +317,71 @@
         }
       ],
       "title": "Errors",
+      "transformations": [
+        {
+          "id": "renameByRegex",
+          "options": {
+            "regex": "\\(.*/.*/1\\)",
+            "renamePattern": ""
+          }
+        }
+      ],
       "type": "timeseries"
     },
+    {
+      "datasource": null,
+      "description": "Links to other dashboards",
+      "gridPos": {
+        "h": 9,
+        "w": 4,
+        "x": 20,
+        "y": 1
+      },
+      "id": 47,
+      "options": {
+        "folderId": 0,
+        "maxItems": 10,
+        "query": "",
+        "showHeadings": false,
+        "showRecentlyViewed": false,
+        "showSearch": true,
+        "showStarred": false,
+        "tags": []
+      },
+      "pluginVersion": "8.2.1",
+      "targets": [
+        {
+          "format": "time_series",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": false,
+          "rawSql": "SELECT\n  data_time AS \"time\",\n  att_conf_id\nFROM att_scalar_devboolean_rw\nWHERE\n  $__timeFilter(data_time)\nORDER BY data_time",
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "att_conf_id"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "table": "att_scalar_devboolean_rw",
+          "timeColumn": "data_time",
+          "timeColumnType": "timestamp",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "Dashboards",
+      "type": "dashlist"
+    },
     {
       "datasource": "Prometheus",
       "description": "",
@@ -341,7 +421,7 @@
       "options": {
         "showHeader": false
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -358,6 +438,10 @@
           "id": "labelsToFields",
           "options": {}
         },
+        {
+          "id": "merge",
+          "options": {}
+        },
         {
           "id": "organize",
           "options": {
@@ -414,95 +498,6 @@
       "title": "RECV",
       "type": "row"
     },
-    {
-      "datasource": "Prometheus",
-      "description": "",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "auto",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "mappings": [],
-          "min": 0,
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 80
-              }
-            ]
-          },
-          "unit": "celsius"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 0,
-        "y": 11
-      },
-      "id": 22,
-      "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
-        },
-        "tooltip": {
-          "mode": "single"
-        }
-      },
-      "pluginVersion": "8.1.2",
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/recv/1\",name=\"RCU_temperature_R\"} - 273.15",
-          "format": "time_series",
-          "hide": false,
-          "instant": false,
-          "interval": "",
-          "legendFormat": "{{x}}",
-          "refId": "A"
-        }
-      ],
-      "title": "RCU temperatures",
-      "transformations": [],
-      "type": "timeseries"
-    },
     {
       "datasource": "Prometheus",
       "fieldConfig": {
@@ -534,7 +529,7 @@
       "gridPos": {
         "h": 8,
         "w": 6,
-        "x": 5,
+        "x": 0,
         "y": 11
       },
       "id": 21,
@@ -553,7 +548,7 @@
         "text": {},
         "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -597,726 +592,40 @@
       "gridPos": {
         "h": 8,
         "w": 6,
-        "x": 11,
+        "x": 6,
         "y": 11
       },
       "id": 25,
-      "options": {
-        "colorMode": "background",
-        "graphMode": "area",
-        "justifyMode": "auto",
-        "orientation": "auto",
-        "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
-          "fields": "",
-          "values": false
-        },
-        "text": {},
-        "textMode": "name"
-      },
-      "pluginVersion": "8.1.2",
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "(2 - device_attribute{device=\"lts/recv/1\",name=\"RCU_I2C_STATUS_R\"}) * on(x) device_attribute{device=\"lts/recv/1\",name=\"RCU_mask_RW\"}",
-          "interval": "",
-          "legendFormat": "{{y}}",
-          "refId": "A"
-        }
-      ],
-      "title": "RCU I2C status",
-      "type": "stat"
-    },
-    {
-      "datasource": "Prometheus",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "thresholds"
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 1
-              }
-            ]
-          }
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 5,
-        "w": 3,
-        "x": 17,
-        "y": 11
-      },
-      "id": 24,
-      "options": {
-        "colorMode": "background",
-        "graphMode": "none",
-        "justifyMode": "auto",
-        "orientation": "auto",
-        "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
-          "fields": "",
-          "values": false
-        },
-        "text": {},
-        "textMode": "name"
-      },
-      "pluginVersion": "8.1.2",
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "1-device_attribute{device=\"lts/recv/1\",name=\"CLK_Enable_PWR_R\"}",
-          "interval": "",
-          "legendFormat": "Power",
-          "refId": "A"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/recv/1\",name=\"CLK_I2C_STATUS_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "I2C",
-          "refId": "B"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/recv/1\",name=\"CLK_PLL_error_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "PLL",
-          "refId": "C"
-        },
-        {
-          "exemplar": true,
-          "expr": "1-device_attribute{device=\"lts/recv/1\",name=\"CLK_PLL_locked_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "PLL Lock",
-          "refId": "D"
-        }
-      ],
-      "title": "Clock",
-      "type": "stat"
-    },
-    {
-      "collapsed": false,
-      "datasource": null,
-      "gridPos": {
-        "h": 1,
-        "w": 24,
-        "x": 0,
-        "y": 19
-      },
-      "id": 46,
-      "panels": [],
-      "title": "Uniboard 2",
-      "type": "row"
-    },
-    {
-      "datasource": "Prometheus",
-      "description": "Temperature sensors of each node on each board",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic",
-            "seriesBy": "max"
-          },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "line"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 85
-              }
-            ]
-          },
-          "unit": "celsius"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 0,
-        "y": 20
-      },
-      "id": 48,
-      "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
-        },
-        "tooltip": {
-          "mode": "single"
-        }
-      },
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_CORE_TEMP_R\"}",
-          "interval": "",
-          "legendFormat": "Core board {{x}} node {{y}}",
-          "refId": "A"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "ERAM board {{x}} node {{y}}",
-          "refId": "B"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "TrRx board {{x}} node {{y}}",
-          "refId": "C"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_HXGB_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "TrHx board {{x}} node {{y}}",
-          "refId": "D"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_PGM_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "IO board {{x}} node {{y}}",
-          "refId": "E"
-        },
-        {
-          "hide": false,
-          "refId": "F"
-        }
-      ],
-      "title": "Uniboard2 Node Temperatures",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "Prometheus",
-      "description": "Temperature sensors of the power supply on each board",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic",
-            "seriesBy": "max"
-          },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "line"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 85
-              }
-            ]
-          },
-          "unit": "celsius"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 5,
-        "y": 20
-      },
-      "id": 50,
-      "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
-        },
-        "tooltip": {
-          "mode": "single"
-        }
-      },
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N01_TEMP_R\"}",
-          "interval": "",
-          "legendFormat": "QSFP N01 board {{x}} ",
-          "refId": "A"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N23_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "QSFP N23 board {{x}}",
-          "refId": "B"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "Switch 1v2 board {{x}}",
-          "refId": "C"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "Switch PHY board {{x}}",
-          "refId": "D"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_CLOCK_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "Clock PWR board {{x}}",
-          "refId": "E"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_DC_DC_48V_12V_TEMP_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "DC-DC board {{x}}",
-          "refId": "F"
-        }
-      ],
-      "title": "Uniboard2 Power Supply Temperatures",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "Prometheus",
-      "description": "Voltage sensors of each node on each board",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "axisSoftMax": 2,
-            "axisSoftMin": 0,
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "line"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 85
-              }
-            ]
-          },
-          "unit": "volt"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 10,
-        "y": 20
-      },
-      "id": 49,
-      "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
-        },
-        "tooltip": {
-          "mode": "single"
-        }
-      },
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_CORE_VOUT_R\"}",
-          "interval": "",
-          "legendFormat": "Core board {{x}} node {{y}}",
-          "refId": "A"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "ERAM board {{x}} node {{y}}",
-          "refId": "B"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "TrRx board {{x}} node {{y}}",
-          "refId": "C"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_HXGB_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "TrHx board {{x}} node {{y}}",
-          "refId": "D"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_PGM_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "IO board {{x}} node {{y}}",
-          "refId": "E"
-        }
-      ],
-      "title": "Uniboard2 Voltages",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "Prometheus",
-      "description": "Voltage sensors of the power supply on each board",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic",
-            "seriesBy": "max"
-          },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "axisSoftMin": 0,
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "line"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 85
-              }
-            ]
-          },
-          "unit": "volt"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 15,
-        "y": 20
-      },
-      "id": 51,
-      "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
-        },
-        "tooltip": {
-          "mode": "single"
-        }
-      },
-      "targets": [
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N01_VOUT_R\"}",
-          "interval": "",
-          "legendFormat": "QSFP N01 board {{x}} ",
-          "refId": "A"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N23_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "QSFP N23 board {{x}}",
-          "refId": "B"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "Switch 1v2 board {{x}}",
-          "refId": "C"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "Switch PHY board {{x}}",
-          "refId": "D"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_CLOCK_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "Clock PWR board {{x}}",
-          "refId": "E"
-        },
-        {
-          "exemplar": true,
-          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_DC_DC_48V_12V_VOUT_R\"}",
-          "hide": false,
-          "interval": "",
-          "legendFormat": "DC-DC board {{x}}",
-          "refId": "F"
-        }
-      ],
-      "title": "Uniboard2 Power Supply Voltages",
-      "type": "timeseries"
-    },
-    {
-      "collapsed": false,
-      "datasource": null,
-      "gridPos": {
-        "h": 1,
-        "w": 24,
-        "x": 0,
-        "y": 28
-      },
-      "id": 19,
-      "panels": [],
-      "title": "SDP",
-      "type": "row"
-    },
-    {
-      "datasource": "Prometheus",
-      "description": "",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "auto",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green",
-                "value": null
-              },
-              {
-                "color": "red",
-                "value": 80
-              }
-            ]
-          },
-          "unit": "celsius"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 0,
-        "y": 29
-      },
-      "id": 5,
-      "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
+      "options": {
+        "colorMode": "background",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
         },
-        "tooltip": {
-          "mode": "single"
-        }
+        "text": {},
+        "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
-          "expr": "device_attribute{device=\"lts/sdp/1\",name=\"FPGA_temp_R\"}",
-          "format": "time_series",
-          "hide": false,
-          "instant": false,
+          "expr": "(2 - device_attribute{device=\"lts/recv/1\",name=\"RCU_I2C_STATUS_R\"}) * on(x) device_attribute{device=\"lts/recv/1\",name=\"RCU_mask_RW\"}",
           "interval": "",
-          "legendFormat": "{{x}}",
+          "legendFormat": "{{y}}",
           "refId": "A"
         }
       ],
-      "title": "FPGA temperatures",
-      "transformations": [],
-      "type": "timeseries"
+      "title": "RCU I2C status",
+      "type": "stat"
     },
     {
       "datasource": "Prometheus",
-      "description": "",
       "fieldConfig": {
         "defaults": {
           "color": {
@@ -1326,17 +635,13 @@
           "thresholds": {
             "mode": "absolute",
             "steps": [
-              {
-                "color": "transparent",
-                "value": null
-              },
               {
                 "color": "green",
-                "value": 50
+                "value": null
               },
               {
                 "color": "red",
-                "value": 100
+                "value": 1
               }
             ]
           }
@@ -1344,15 +649,15 @@
         "overrides": []
       },
       "gridPos": {
-        "h": 8,
-        "w": 5,
-        "x": 5,
-        "y": 29
+        "h": 5,
+        "w": 3,
+        "x": 12,
+        "y": 11
       },
-      "id": 11,
+      "id": 24,
       "options": {
         "colorMode": "background",
-        "graphMode": "area",
+        "graphMode": "none",
         "justifyMode": "auto",
         "orientation": "auto",
         "reduceOptions": {
@@ -1365,23 +670,57 @@
         "text": {},
         "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
-          "expr": "(50+50*device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_communication_error_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}",
-          "format": "time_series",
-          "hide": false,
-          "instant": false,
+          "expr": "1-device_attribute{device=\"lts/apsct/1\",name=\"APSCT_PWR_on_R\"}",
           "interval": "",
-          "legendFormat": "{{x}}",
+          "legendFormat": "Power",
           "refId": "A"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/apsct/1\",name=\"APSCT_I2C_error_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "I2C",
+          "refId": "B"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/apsct/1\",name=\"APSCT_PLL_200MHz_error_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "PLL",
+          "refId": "C"
+        },
+        {
+          "exemplar": true,
+          "expr": "1-device_attribute{device=\"lts/apsct/1\",name=\"APSCT_PLL_200MHz_locked_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "PLL Lock",
+          "refId": "D"
         }
       ],
-      "title": "FPGA communication",
-      "transformations": [],
+      "title": "Clock",
       "type": "stat"
     },
+    {
+      "collapsed": false,
+      "datasource": null,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 19
+      },
+      "id": 19,
+      "panels": [],
+      "title": "SDP",
+      "type": "row"
+    },
     {
       "datasource": "Prometheus",
       "description": "",
@@ -1414,10 +753,10 @@
       "gridPos": {
         "h": 8,
         "w": 5,
-        "x": 10,
-        "y": 29
+        "x": 0,
+        "y": 20
       },
-      "id": 9,
+      "id": 11,
       "options": {
         "colorMode": "background",
         "graphMode": "area",
@@ -1433,11 +772,11 @@
         "text": {},
         "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
-          "expr": "(100-50*device_attribute{device=\"lts/sdp/1\",name=\"FPGA_processing_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}",
+          "expr": "(50+50*device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_communication_error_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}",
           "format": "time_series",
           "hide": false,
           "instant": false,
@@ -1446,91 +785,66 @@
           "refId": "A"
         }
       ],
-      "title": "FPGA processing enabled",
+      "title": "FPGA communication",
       "transformations": [],
       "type": "stat"
     },
     {
       "datasource": "Prometheus",
-      "description": "Measured difference between PTP and PPS",
+      "description": "",
       "fieldConfig": {
         "defaults": {
           "color": {
             "mode": "thresholds"
           },
-          "custom": {
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "auto",
-            "spanNulls": 60000,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "decimals": 2,
           "mappings": [],
           "thresholds": {
             "mode": "absolute",
             "steps": [
               {
-                "color": "red",
+                "color": "transparent",
                 "value": null
               },
               {
                 "color": "green",
-                "value": 0.001
+                "value": 50
               },
               {
                 "color": "red",
-                "value": 0.1
+                "value": 100
               }
             ]
-          },
-          "unit": "s"
+          }
         },
         "overrides": []
       },
       "gridPos": {
         "h": 8,
         "w": 5,
-        "x": 15,
-        "y": 29
+        "x": 5,
+        "y": 20
       },
-      "id": 13,
+      "id": 9,
       "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "hidden",
-          "placement": "bottom"
+        "colorMode": "background",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
         },
-        "tooltip": {
-          "mode": "single"
-        }
+        "text": {},
+        "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
-          "expr": "device_attribute{device=\"lts/sdp/1\",name=\"TR_tod_pps_delta_R\"}",
+          "expr": "(100-50*device_attribute{device=\"lts/sdp/1\",name=\"FPGA_processing_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}",
           "format": "time_series",
           "hide": false,
           "instant": false,
@@ -1539,9 +853,9 @@
           "refId": "A"
         }
       ],
-      "title": "FPGA Clock offset",
+      "title": "FPGA processing enabled",
       "transformations": [],
-      "type": "timeseries"
+      "type": "stat"
     },
     {
       "datasource": "Prometheus",
@@ -1581,8 +895,8 @@
       "gridPos": {
         "h": 4,
         "w": 3,
-        "x": 20,
-        "y": 29
+        "x": 10,
+        "y": 20
       },
       "id": 12,
       "options": {
@@ -1600,7 +914,7 @@
         "text": {},
         "textMode": "value"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -1624,7 +938,7 @@
         "h": 1,
         "w": 24,
         "x": 0,
-        "y": 37
+        "y": 28
       },
       "id": 27,
       "panels": [],
@@ -1664,7 +978,7 @@
         "h": 8,
         "w": 5,
         "x": 0,
-        "y": 38
+        "y": 29
       },
       "id": 28,
       "options": {
@@ -1682,7 +996,7 @@
         "text": {},
         "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -1762,7 +1076,7 @@
         "h": 8,
         "w": 5,
         "x": 5,
-        "y": 38
+        "y": 29
       },
       "id": 29,
       "options": {
@@ -1871,7 +1185,7 @@
         "h": 8,
         "w": 5,
         "x": 10,
-        "y": 38
+        "y": 29
       },
       "id": 30,
       "options": {
@@ -1964,7 +1278,7 @@
         "h": 8,
         "w": 5,
         "x": 15,
-        "y": 38
+        "y": 29
       },
       "id": 33,
       "options": {
@@ -2059,7 +1373,7 @@
         "h": 8,
         "w": 3,
         "x": 20,
-        "y": 38
+        "y": 29
       },
       "id": 34,
       "options": {
@@ -2096,7 +1410,7 @@
         "h": 1,
         "w": 24,
         "x": 0,
-        "y": 46
+        "y": 37
       },
       "id": 36,
       "panels": [],
@@ -2136,7 +1450,7 @@
         "h": 8,
         "w": 5,
         "x": 0,
-        "y": 47
+        "y": 38
       },
       "id": 37,
       "options": {
@@ -2154,7 +1468,7 @@
         "text": {},
         "textMode": "name"
       },
-      "pluginVersion": "8.1.2",
+      "pluginVersion": "8.2.1",
       "targets": [
         {
           "exemplar": true,
@@ -2234,7 +1548,7 @@
         "h": 8,
         "w": 5,
         "x": 5,
-        "y": 47
+        "y": 38
       },
       "id": 38,
       "options": {
@@ -2343,7 +1657,7 @@
         "h": 8,
         "w": 5,
         "x": 10,
-        "y": 47
+        "y": 38
       },
       "id": 39,
       "options": {
@@ -2436,7 +1750,7 @@
         "h": 8,
         "w": 5,
         "x": 15,
-        "y": 47
+        "y": 38
       },
       "id": 40,
       "options": {
@@ -2531,7 +1845,7 @@
         "h": 8,
         "w": 3,
         "x": 20,
-        "y": 47
+        "y": 38
       },
       "id": 41,
       "options": {
@@ -2560,10 +1874,78 @@
       "title": "XST Replicator load",
       "transformations": [],
       "type": "timeseries"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "transparent",
+                "value": null
+              },
+              {
+                "color": "green",
+                "value": 50
+              },
+              {
+                "color": "red",
+                "value": 100
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 0,
+        "y": 46
+      },
+      "id": 45,
+      "options": {
+        "colorMode": "background",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "text": {},
+        "textMode": "name"
+      },
+      "pluginVersion": "8.2.1",
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "(100-50*device_attribute{device=\"lts/xst/1\",name=\"FPGA_xst_processing_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "legendFormat": "{{x}}",
+          "refId": "A"
+        }
+      ],
+      "title": "XST processing enabled",
+      "transformations": [],
+      "type": "stat"
     }
   ],
   "refresh": false,
-  "schemaVersion": 30,
+  "schemaVersion": 31,
   "style": "dark",
   "tags": [],
   "templating": {
@@ -2575,7 +1957,7 @@
   },
   "timepicker": {},
   "timezone": "",
-  "title": "LOFAR2.0 Station",
-  "uid": "6f7Pv8Vnz",
-  "version": 1
+  "title": "Home",
+  "uid": "nC8N_kO7k",
+  "version": 5
 }
diff --git a/docker-compose/grafana/dashboards/sensors.json b/docker-compose/grafana/dashboards/sensors.json
new file mode 100644
index 0000000000000000000000000000000000000000..95e39f60d024ea355119a24d72cbd9bdd9c178fe
--- /dev/null
+++ b/docker-compose/grafana/dashboards/sensors.json
@@ -0,0 +1,927 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "fiscalYearStartMonth": 0,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "id": 4,
+  "links": [],
+  "liveNow": false,
+  "panels": [
+    {
+      "datasource": null,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 16,
+      "title": "Temperatures",
+      "type": "row"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "celsius"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 0,
+        "y": 1
+      },
+      "id": 2,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.1.2",
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/recv/1\",name=\"RCU_temperature_R\"} - 273.15",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "legendFormat": "{{x}}",
+          "refId": "A"
+        }
+      ],
+      "title": "RCU temperatures",
+      "transformations": [],
+      "type": "timeseries"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Temperature sensors of each node on each board",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic",
+            "seriesBy": "max"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "line"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "celsius"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 5,
+        "y": 1
+      },
+      "id": 4,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_CORE_TEMP_R\"}",
+          "interval": "",
+          "legendFormat": "Core board {{x}} node {{y}}",
+          "refId": "A"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "ERAM board {{x}} node {{y}}",
+          "refId": "B"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "TrRx board {{x}} node {{y}}",
+          "refId": "C"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_TXGB_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "TrHx board {{x}} node {{y}}",
+          "refId": "D"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_PGM_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "IO board {{x}} node {{y}}",
+          "refId": "E"
+        },
+        {
+          "hide": false,
+          "refId": "F"
+        }
+      ],
+      "title": "Uniboard2 Node Temperatures",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Temperature sensors of the power supply on each board",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic",
+            "seriesBy": "max"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "line"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "celsius"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 10,
+        "y": 1
+      },
+      "id": 8,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N01_TEMP_R\"}",
+          "interval": "",
+          "legendFormat": "QSFP N01 board {{x}} ",
+          "refId": "A"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N23_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "QSFP N23 board {{x}}",
+          "refId": "B"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Switch 1v2 board {{x}}",
+          "refId": "C"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Switch PHY board {{x}}",
+          "refId": "D"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_CLOCK_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Clock PWR board {{x}}",
+          "refId": "E"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_DC_DC_48V_12V_TEMP_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "DC-DC board {{x}}",
+          "refId": "F"
+        }
+      ],
+      "title": "Uniboard2 Power Supply Temperatures",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "celsius"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 15,
+        "y": 1
+      },
+      "id": 6,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.1.2",
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/sdp/1\",name=\"FPGA_temp_R\"}",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "legendFormat": "{{x}}",
+          "refId": "A"
+        }
+      ],
+      "title": "FPGA temperatures",
+      "transformations": [],
+      "type": "timeseries"
+    },
+    {
+      "collapsed": true,
+      "datasource": null,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 9
+      },
+      "id": 18,
+      "panels": [],
+      "title": "Voltages",
+      "type": "row"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Voltage sensors of the power supplies of the APS",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic",
+            "seriesBy": "max"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "axisSoftMax": 10,
+            "axisSoftMin": 0,
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "line"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "volt"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 0,
+        "y": 10
+      },
+      "id": 21,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/apspu/1\",name=~\"APSPU_.*_VOUT_R\"}",
+          "interval": "",
+          "legendFormat": "{{name}} {{x}} ",
+          "refId": "A"
+        }
+      ],
+      "title": "APSPU Voltages",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Voltage sensors of each node on each board",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "axisSoftMax": 2,
+            "axisSoftMin": 0,
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "line"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "volt"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 5,
+        "y": 10
+      },
+      "id": 10,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_CORE_VOUT_R\"}",
+          "interval": "",
+          "legendFormat": "Core board {{x}} node {{y}}",
+          "refId": "A"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "ERAM board {{x}} node {{y}}",
+          "refId": "B"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "TrRx board {{x}} node {{y}}",
+          "refId": "C"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_TXGB_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "TrHx board {{x}} node {{y}}",
+          "refId": "D"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_PGM_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "IO board {{x}} node {{y}}",
+          "refId": "E"
+        }
+      ],
+      "title": "Uniboard2 Voltages",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Voltage sensors of the power supply on each board",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic",
+            "seriesBy": "max"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "axisSoftMin": 0,
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "line"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "volt"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 10,
+        "y": 10
+      },
+      "id": 12,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N01_VOUT_R\"}",
+          "interval": "",
+          "legendFormat": "QSFP N01 board {{x}} ",
+          "refId": "A"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N23_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "QSFP N23 board {{x}}",
+          "refId": "B"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Switch 1v2 board {{x}}",
+          "refId": "C"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Switch PHY board {{x}}",
+          "refId": "D"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_CLOCK_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Clock PWR board {{x}}",
+          "refId": "E"
+        },
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_DC_DC_48V_12V_VOUT_R\"}",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "DC-DC board {{x}}",
+          "refId": "F"
+        }
+      ],
+      "title": "Uniboard2 Power Supply Voltages",
+      "type": "timeseries"
+    },
+    {
+      "collapsed": true,
+      "datasource": null,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 18
+      },
+      "id": 20,
+      "panels": [],
+      "title": "Clock stability",
+      "type": "row"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Measured difference between PTP and PPS",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": 60000,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "decimals": 2,
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "red",
+                "value": null
+              },
+              {
+                "color": "green",
+                "value": 0.001
+              },
+              {
+                "color": "red",
+                "value": 0.1
+              }
+            ]
+          },
+          "unit": "s"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 5,
+        "x": 0,
+        "y": 19
+      },
+      "id": 14,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "hidden",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.1.2",
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "device_attribute{device=\"lts/sdp/1\",name=\"TR_tod_pps_delta_R\"}",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "legendFormat": "{{x}}",
+          "refId": "A"
+        }
+      ],
+      "title": "FPGA Clock offset",
+      "transformations": [],
+      "type": "timeseries"
+    }
+  ],
+  "schemaVersion": 31,
+  "style": "dark",
+  "tags": [],
+  "templating": {
+    "list": []
+  },
+  "time": {
+    "from": "now-30m",
+    "to": "now"
+  },
+  "timepicker": {},
+  "timezone": "",
+  "title": "Sensors",
+  "uid": "KMRmQzd7z",
+  "version": 3
+}
diff --git a/docker-compose/grafana/dashboards/version-information.json b/docker-compose/grafana/dashboards/version-information.json
index e82135a1ad0867223a061481c79bb8a0dd8f0d9f..8b5e17bebd870d923d8944293a2bc66bddf79544 100644
--- a/docker-compose/grafana/dashboards/version-information.json
+++ b/docker-compose/grafana/dashboards/version-information.json
@@ -679,7 +679,7 @@
   },
   "timepicker": {},
   "timezone": "",
-  "title": "Version information",
+  "title": "Versions",
   "uid": "eR9posS7z",
   "version": 1
 }
diff --git a/docker-compose/integration-test.yml b/docker-compose/integration-test.yml
index 239dce0235dcd2b2a6a2a731f373e84c49ea671b..e0d1c6baf58948cdbee5a71ff2f859ab429dcd4b 100644
--- a/docker-compose/integration-test.yml
+++ b/docker-compose/integration-test.yml
@@ -26,4 +26,4 @@ services:
       - --timeout=30
       - --strict
       - --
-      - tox -e integration
+      - tox --recreate -e integration
diff --git a/docker-compose/itango/lofar-requirements.txt b/docker-compose/itango/lofar-requirements.txt
index 29942e272353180f3622f4ad6d36fb7c31307eb1..1349c50ca993b51bb866a7880e3e7fb185049de8 100644
--- a/docker-compose/itango/lofar-requirements.txt
+++ b/docker-compose/itango/lofar-requirements.txt
@@ -1,9 +1,8 @@
 parso == 0.7.1
 jedi == 0.17.2
-opcua >= 0.98.13
+asyncua
 astropy 
 python-logstash-async
 gitpython
 PyMySQL[rsa]
 sqlalchemy
-timeout-decorator
diff --git a/docker-compose/jupyter/Dockerfile b/docker-compose/jupyter/Dockerfile
index b69ddfa7e5b6d6eaeab11b25f99258d0f0743daa..8be3e9f3900b01e80893d38aedcb4f6397aa8fd0 100644
--- a/docker-compose/jupyter/Dockerfile
+++ b/docker-compose/jupyter/Dockerfile
@@ -10,6 +10,9 @@ ENV HOME=/home/user
 RUN sudo mkdir -p ${HOME}
 RUN sudo chown ${CONTAINER_EXECUTION_UID} -R ${HOME}
 
+# ipython 7.28 is broken in combination with Jupyter, it causes connection errors with notebooks
+RUN sudo pip3 install ipython==7.27.0
+
 RUN sudo pip3 install jupyter
 RUN sudo pip3 install ipykernel
 RUN sudo pip3 install jupyter_bokeh
@@ -46,7 +49,7 @@ COPY jupyter-notebook /usr/local/bin/jupyter-notebook
 RUN sudo pip3 install PyMySQL[rsa] sqlalchemy
 
 # Packages to interface with testing hardware directly
-RUN sudo pip3 install pyvisa pyvisa-py
+RUN sudo pip3 install pyvisa pyvisa-py opcua
 
 # Add Tini. Tini operates as a process subreaper for jupyter. This prevents kernel crashes.
 ENV TINI_VERSION v0.6.0
diff --git a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
index df75d5962a1327041995aa04c41d6d1e1c2ae914..05914fbf1bb3bbde3793c15f2f62b3e306bb022a 100644
--- a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
+++ b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
@@ -1,9 +1,13 @@
 # Create shortcuts for our devices
+apsct = DeviceProxy("LTS/APSCT/1")
+apspu = DeviceProxy("LTS/APSPU/1")
 recv = DeviceProxy("LTS/RECV/1")
 sdp = DeviceProxy("LTS/SDP/1")
 sst = DeviceProxy("LTS/SST/1")
 xst = DeviceProxy("LTS/XST/1")
 unb2 = DeviceProxy("LTS/UNB2/1")
+boot = DeviceProxy("LTS/Boot/1")
+docker = DeviceProxy("LTS/Docker/1")
 
 # Put them in a list in case one wants to iterate
-devices = [recv, sdp, sst, xst, unb2]
+devices = [apsct, apspu, recv, sdp, sst, xst, unb2, boot, docker]
diff --git a/docker-compose/lofar-device-base/lofar-requirements.txt b/docker-compose/lofar-device-base/lofar-requirements.txt
index 2214412a4365f4b804d6b20b0576c390482b1481..31b22c71689b481357cef56bf4940c1575a3b01d 100644
--- a/docker-compose/lofar-device-base/lofar-requirements.txt
+++ b/docker-compose/lofar-device-base/lofar-requirements.txt
@@ -1,4 +1,4 @@
-opcua >= 0.98.9
+asyncua
 astropy
 python-logstash-async
 gitpython
diff --git a/docker-compose/recv-sim/Dockerfile b/docker-compose/pypcc-sim-base/Dockerfile
similarity index 100%
rename from docker-compose/recv-sim/Dockerfile
rename to docker-compose/pypcc-sim-base/Dockerfile
diff --git a/docker-compose/recv-sim/requirements.txt b/docker-compose/pypcc-sim-base/requirements.txt
similarity index 100%
rename from docker-compose/recv-sim/requirements.txt
rename to docker-compose/pypcc-sim-base/requirements.txt
diff --git a/docker-compose/recv-sim.yml b/docker-compose/recv-sim.yml
index 7b1f704fa8854f12d411c7088b7caf0a74f328f0..effee8b298b855e2007e50c379fa3df45010bd05 100644
--- a/docker-compose/recv-sim.yml
+++ b/docker-compose/recv-sim.yml
@@ -9,12 +9,9 @@ version: '2'
 services:
   recv-sim:
     build:
-        context: recv-sim
+        context: pypcc-sim-base
     container_name: ${CONTAINER_NAME_PREFIX}recv-sim
     networks:
       - control
-    volumes:
-        - ${HOME}:/hosthome
-    ports:
-        - "4843:4843"
+    entrypoint: python3 pypcc2.py --simulator --port 4840 --config RECVTR
     restart: on-failure
diff --git a/docker-compose/sdptr-sim.yml b/docker-compose/sdptr-sim.yml
index 70c1edf63acdf84df8a7d294aa17ea9489c9b9a7..c81c3db9ae4744e013b5a92f1ebb5e9bdaa6e92c 100644
--- a/docker-compose/sdptr-sim.yml
+++ b/docker-compose/sdptr-sim.yml
@@ -13,6 +13,4 @@ services:
     container_name: ${CONTAINER_NAME_PREFIX}sdptr-sim
     networks:
       - control
-    ports:
-        - "4840:4840"
-    restart: on-failure
+    restart: unless-stopped
diff --git a/docker-compose/tangotest.yml b/docker-compose/tangotest.yml
index 3a44fc61b73b18a78d9e5bbd6a6fef6ac2d648fd..357c91df487b51379db221f7cb984bc05018f5e3 100644
--- a/docker-compose/tangotest.yml
+++ b/docker-compose/tangotest.yml
@@ -25,5 +25,5 @@ services:
       - --
       - /usr/local/bin/TangoTest
       - test
-    restart: on-failure
+    restart: unless-stopped
 
diff --git a/docker-compose/unb2-sim.yml b/docker-compose/unb2-sim.yml
index e031e20f54ad6addec1fdbabf972661d6f4c8f9a..d1ecaaa70a3c1e52f39ab1453d2ec8eb191f8831 100644
--- a/docker-compose/unb2-sim.yml
+++ b/docker-compose/unb2-sim.yml
@@ -9,12 +9,9 @@ version: '2'
 services:
   unb2-sim:
     build:
-        context: unb2-sim
+        context: pypcc-sim-base
     container_name: ${CONTAINER_NAME_PREFIX}unb2-sim
     networks:
       - control
-    volumes:
-        - ${HOME}:/hosthome
-    ports:
-        - "4844:4844"
+    entrypoint: python3 pypcc2.py --simulator --port 4841 --config UNB2
     restart: on-failure
diff --git a/docker-compose/unb2-sim/Dockerfile b/docker-compose/unb2-sim/Dockerfile
deleted file mode 100644
index cbb4ce80185ee1cf0a84aabc457a7983e57b5651..0000000000000000000000000000000000000000
--- a/docker-compose/unb2-sim/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM ubuntu:20.04
-
-COPY requirements.txt /requirements.txt
-
-RUN apt-get update && apt-get install -y python3 python3-pip python3-yaml git && \
-    pip3 install -r requirements.txt && \
-    git clone --depth 1 --branch master https://git.astron.nl/lofar2.0/pypcc
-
-WORKDIR /pypcc
-CMD ["python3","pypcc2.py","--simulator", "--port=4844", "--config=UNB2"]
diff --git a/docker-compose/unb2-sim/requirements.txt b/docker-compose/unb2-sim/requirements.txt
deleted file mode 100644
index 5badf0e57069366adedc43ca2c2b59dc7dc4b35d..0000000000000000000000000000000000000000
--- a/docker-compose/unb2-sim/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-#check if this file is necessary
-opcua
-numpy
-recordclass>=0.16,<0.16.1
\ No newline at end of file
diff --git a/docs/source/configure_station.rst b/docs/source/configure_station.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0796d098044b64cf22e8984a450f3f51752e5f0b
--- /dev/null
+++ b/docs/source/configure_station.rst
@@ -0,0 +1,76 @@
+Enter your LOFAR2.0 Hardware Configuration
+===========================================
+
+The software will need to be told various aspects of your station configuration, for example, the hostnames of the station hardware to control. The following settings are installation specific, and are stored as *properties* in the :ref:`tangodb`.
+
+Stock configurations are provided for several stations, as well as using simulators to simulate the station's interface (which is the default after bootstrapping a station). These are provided in the ``CDB/stations/`` directory, and can be loaded using for example::
+
+    sbin/update_ConfigDb.sh CDB/stations/LTS_ConfigDb.json
+
+The following sections describe the settings that are station dependent, and thus must or can be set.
+
+Mandatory settings
+-------------------
+
+Without these settings, you will not obtain the associated functionality:
+
+:RECV.OPC_Server_Name: Hostname of RECVTR.
+
+  :type: ``string``
+
+:UNB2.OPC_Server_Name: Hostname of UNB2TR.
+
+  :type: ``string``
+
+:SDP.OPC_Server_Name: Hostname of SDPTR.
+
+  :type: ``string``
+
+:SST.OPC_Server_Name: Hostname of SDPTR.
+
+  :type: ``string``
+
+:SST.FPGA_sst_offload_hdr_eth_destination_mac_RW_default: MAC address of the network interface on the host running this software stack, on which the SSTs are to be received. This network interface must be capable of receiving Jumbo (MTU=9000) frames.
+
+  :type: ``string[N_fpgas]``
+
+:SST.FPGA_sst_offload_hdr_ip_destination_address_RW_default: IP address of the network interface on the host running this software stack, on which the SSTs are to be received.
+
+  :type: ``string[N_fpgas]``
+
+:XST.OPC_Server_Name: Hostname of SDPTR.
+
+  :type: ``string``
+
+:XST.FPGA_xst_offload_hdr_eth_destination_mac_RW_default: MAC address of the network interface on the host running this software stack, on which the XSTs are to be received. This network interface must be capable of receiving Jumbo (MTU=9000) frames.
+
+  :type: ``string[N_fpgas]``
+
+:XST.FPGA_xst_offload_hdr_ip_destination_address_RW_default: IP address of the network interface on the host running this software stack, on which the XSTs are to be received.
+
+  :type: ``string[N_fpgas]``
+
+Optional settings
+-------------------
+
+These settings make life nicer, but are not strictly necessary to get your software up and running:
+
+:RECV.Ant_mask_RW_default: Which antennas are installed.
+
+  :type: ``bool[N_RCUs][N_antennas_per_RCU]``
+
+:SDP.RCU_mask_RW_default: Which RCUs are installed.
+
+  :type: ``bool[N_RCUs]``
+
+:UNB2.UNB2_mask_RW_default: Which Uniboard2s are installed in SDP.
+
+  :type: ``bool[N_unb]``
+
+:SDP.TR_fpga_mask_RW_default: Which FPGAs are installed in SDP.
+
+  :type: ``bool[N_fpgas]``
+
+:SDP.FPGA_sdp_info_station_id_RW_default: Numeric identifier for this station.
+
+  :type: ``uint32[N_fpgas]``
diff --git a/docs/source/developer.rst b/docs/source/developer.rst
new file mode 100644
index 0000000000000000000000000000000000000000..517dfa324298e9451bfa5f9b25eef9726476686e
--- /dev/null
+++ b/docs/source/developer.rst
@@ -0,0 +1,61 @@
+Developer information
+=========================
+
+This chapter describes key areas useful for developers.
+
+Docker compose
+-------------------------
+
+The docker setup is managed using ``make`` in the ``docker-compose`` directory. Key commands are:
+
+- ``make status`` to check which containers are running,
+- ``make build <container>`` to rebuild the image for the container,
+- ``make build-nocache <container>`` to rebuild the image for the container from scratch,
+- ``make restart <container>`` to restart a specific container, for example to effectuate a code change.
+- ``make clean`` to remove all images and containers, and the ``tangodb`` volume. To do a deeper clean, we need to remove all volumes and rebuild all containers from scratch::
+
+     make clean
+     docker volume prune
+     docker build-nocache
+
+Since the *Python code is taken from the host when the container starts*, restarting is enough to use the code you have in your local git repo. Rebuilding is unnecessary.
+
+Docker networking
+-------------------------
+
+The Docker containers started use a *virtual network* to communicate among each other. This means that:
+
+- Containers address each other by a host name equal to the container name (f.e. ``elk`` for the elk stack, and ``databaseds`` for the TANGO_HOST),
+- ``localhost`` cannot be used within the containers to access ports of other containers.
+- ``host.docker.internal`` resolves to the actual host running the containers,
+- All ports used by external parties need to be exposed explicitly in the docker-compose files. The container must open the same port as is thus exposed, or the port will not be reachable.
+
+The networks are defined in ``docker-compose/networks.yml``:
+
+.. literalinclude:: ../../docker-compose/networks.yml
+
+The ``$NETWORK_MODE`` defaults to ``tangonet`` in the ``docker-compose/Makefile``.
+
+.. _corba:
+
+CORBA
+````````````````````
+
+Tango devices use CORBA, which require all servers to be able to reach each other directly. Each CORBA device opens a port and advertises its address to the CORBA broker. The broker then forwards this address to any interested clients. A device within a docker container cannot know under which name it can be reached, however, and any port opened needs to be exposed explicitly in the docker-compose file for the device. To solve all this, we *assign a unique port to each device*, and explictly tell CORBA to use that port, and what the hostname is under which others can reach it. Each device thus has these lines in their compose file::
+
+    ports:
+      - "5701:5701" # unique port for this DS
+    entrypoint:
+      # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA
+      # can't know about our Docker port forwarding
+      - python3 -u /opt/lofar/tango/devices/devices/sdp/sdp.py LTS -v -ORBendPoint giop:tcp:0:5701 -ORBendPointPublish giop:tcp:${HOSTNAME}:5701
+
+Specifying the wrong ``$HOSTNAME`` or port can make your device unreachable, even if it is running. Note that ``$HOSTNAME`` is advertised as is, that is, it is resolved to an IP address by any client that wants to connect. This means the ``$HOSTNAME`` needs to be correct for both the other containers, and external clients.
+
+The ``docker-compose/Makefile`` tries to set a good default for ``$HOSTNAME``, but you can override it by exporting the environment variable yourself (and run ``make restart <container>`` to effectuate the change).
+
+For more information, see:
+
+- https://huihoo.org/ace_tao/ACE-5.2+TAO-1.2/TAO/docs/ORBEndpoint.html
+- http://omniorb.sourceforge.net/omni42/omniNames.html
+- https://sourceforge.net/p/omniorb/svn/HEAD/tree/trunk/omniORB/src/lib/omniORB/orbcore/tcp/tcpEndpoint.cc
diff --git a/docs/source/devices/boot.rst b/docs/source/devices/boot.rst
new file mode 100644
index 0000000000000000000000000000000000000000..53e2bab88d35f4a751c8e3809a24c1d3a0113f6b
--- /dev/null
+++ b/docs/source/devices/boot.rst
@@ -0,0 +1,26 @@
+.. _boot:
+
+Boot
+====================
+
+The ``boot == DeviceProxy("LTS/Boot/1")`` device is responsible for (re)starting and initialising the other devices. Devices which are not reachable, for example because their docker container is explicitly stopped, are skipped during initialisation. This device provides the following commands:
+
+:initialise_station(): Stop and start the other devices in the correct order, set their default values, and command them to initialise their hardware. This procedure runs asynchronously, causing this command to return immediately. Initialisation is aborted if an error is encountered.
+
+  :returns: ``None``
+
+The initialisation process can subsequently be followed through monitoring the following attributes:
+
+:initialising_R: Whether the initialisation procedure is still ongoing.
+
+  :type: ``bool``
+
+:initialisation_progress_R: Percentage completeness of the initialisation procedure. Each succesfully configured device increments progress.
+
+  :type: ``int``
+
+:initialisation_status_R: A description of what the device is currently trying to do. If an error occurs, this will hint towards the cause.
+
+  :type: ``str``
+
+A useful pattern is thus to call ``initialise_station()``, wait for ``initialising_R == False``, and then check whether the initalisation was succesful, if ``initialisation_progress_R == 100``. If a device fails to initialise, most likely the :doc:`../interfaces/logs` will need to be consulted.
diff --git a/docs/source/devices/configure.rst b/docs/source/devices/configure.rst
new file mode 100644
index 0000000000000000000000000000000000000000..074cc4776b11bfef1b1a8908aca64eb3e060b3c5
--- /dev/null
+++ b/docs/source/devices/configure.rst
@@ -0,0 +1,63 @@
+Device Configuration
+=========================
+
+The devices receive their configuration from two sources:
+
+- The TangoDB database, for static *properties*,
+- Externally, from the user, or a control system, that set *control attributes* (see the section for each device for what to set, and :ref:`attributes` for how to set them).
+
+.. _tangodb:
+
+TangoDB
+-------------------------
+
+The TangoDB database is a persistent store for the properties of each device. The properties encode static settings, such as the hardware addresses, and default values for control attributes.
+
+Each device queries the TangoDB for the value of its properties during the ``initialise()`` call. Default values for control attributes can then be applied by explicitly calling ``set_defaults()``. The ``boot`` device also calls ``set_defaults()`` when initialising the station. The rationale being that the defaults can be applied at boot, but shouldn't be applied automatically during operations, as not to disturb running hardware.
+
+Device interaction
+````````````````````````````
+
+The properties of a device can be queried from the device directly::
+
+  # get a list of all the properties
+  property_names = device.get_property_list("*")
+
+  # fetch the values of the given properties. returns a {property: value} dict.
+  property_dict = device.get_property(property_names)
+
+Properties can also be changed::
+
+  changeset = { "property": "new value" }
+
+  device.put_property(changeset)
+
+Note that new values for properties will only be picked up by the device during ``initialise()``, so you will have to turn the device off and on.
+
+Command-line interaction
+``````````````````````````
+
+The content of the TangoDB can be dumped from the command line using::
+
+  bin/dump_ConfigDb.sh > tangodb-dump.json
+
+and changes can be applied using::
+
+  bin/update_ConfigDb.sh changeset.json
+
+.. note:: The ``dsconfig`` docker container needs to be running for these commands to work.
+
+Jive
+``````````````````````````
+
+The TangoDB can also be interactively queried and modified using Jive. Jive is an X11 application provided by the ``jive`` image as part of the software stack of the station. It must however be started on-demand, with a correctly configured ``$DISPLAY``::
+
+  cd docker-compose
+  make start jive
+
+If Jive does not appear, check ``docker logs jive`` to see what went wrong.
+
+For information on how to use Jive, see https://tango-controls.readthedocs.io/en/latest/tools-and-extensions/built-in/jive/.
+
+.. note:: If you need an X11 server on Windows, see :ref:`x11_on_windows`.
+
diff --git a/docs/source/devices/docker.rst b/docs/source/devices/docker.rst
new file mode 100644
index 0000000000000000000000000000000000000000..df80cf64dc6be38f405688d9d11c7519c59079c3
--- /dev/null
+++ b/docs/source/devices/docker.rst
@@ -0,0 +1,18 @@
+.. _docker:
+
+Docker
+====================
+
+The ``docker == DeviceProxy("LTS/Docker/1")`` device controls the docker containers. It allows starting and stopping them, and querying whether they are running. Each container is represented by two attributes:
+
+:<container>_R: Returns whether the container is running.
+
+  :type: ``bool``
+
+:<container>_RW: Set to ``True`` to start the container, and to ``False`` to stop it.
+
+  :type: ``bool``
+
+.. warning:: Do *not* stop the ``tango`` container, as doing so cripples the Tango infrastructure, leaving the station inoperable. It is also not wise to stop the ``device_docker`` container, as doing so would render this device unreachable.
+
+
diff --git a/docs/source/devices/recv.rst b/docs/source/devices/recv.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d92ac6eca48eacc17667133b057bc9b127e5e08f
--- /dev/null
+++ b/docs/source/devices/recv.rst
@@ -0,0 +1,15 @@
+RECV
+====================
+
+The ``recv == DeviceProxy("LTS/RECV/1")`` device controls the RCUs, the LBA antennas, and HBA tiles. Central to its operation are the masks (see also :ref:`attribute-masks`):
+
+:RCU_mask_RW: Controls which RCUs will actually be configured when attributes referring to RCUs are written.
+
+  :type: ``bool[N_RCUs]``
+
+:Ant_mask_RW: Controls which antennas will actually be configured when attributes referring to antennas are written.
+
+  :type: ``bool[N_RCUs][N_antennas_per_RCU]``
+
+Typically, ``N_RCUs == 32``, and ``N_antennas_per_RCU == 3``.
+
diff --git a/docs/source/devices/sdp.rst b/docs/source/devices/sdp.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b5f38ca5b2d8fe346a1ee90ec5a3a49c0b939af7
--- /dev/null
+++ b/docs/source/devices/sdp.rst
@@ -0,0 +1,95 @@
+SDP
+====================
+
+The ``sdp == DeviceProxy("LTS/SDP/1")``` device controls the digital signal processing in SDP, performed by the firmware on the FPGAs on the Uniboards. Central to its operation is the mask (see also :ref:`attribute-masks`):
+
+:TR_fpga_mask_RW: Controls which FPGAs will actually be configured when attributes referring to FPGAs are written.
+
+  :type: ``bool[N_fpgas]``
+
+Typically, ``N_fpgas == 16``.
+
+See the following links for a full description of the SDP monitoring and control points:
+
+- https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L2+STAT+Decision%3A+SC+-+SDP+OPC-UA+interface
+- https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
+
+Basic configuration
+---------------------
+
+The following points are significant for the operations of this device:
+
+:FPGA_processing_enable_R: Whether the FPGA is processing its input.
+
+  :type: ``bool[N_fpgas]``
+
+:TR_fpga_communication_error_R: Whether the FPGAs can be reached.
+
+  :type: ``bool[N_fpgas]``
+
+Data-quality information
+---------------------------
+
+The following fields describe the data quality:
+
+:FPGA_signal_input_mean_R: Mean value of the last second of input (in ADC quantisation units). Should be close to 0.
+
+  :type: ``double[N_fpgas][N_ants_per_fpga]``
+
+:FPGA_signal_input_rms_R: Root means square value of the last second of input (in ADC quantisation units). ``rms^2 = mean^2 + std^2``. Values above 2048 indicate strong RFI.
+
+  :type: ``double[N_fpgas][N_ants_per_fpga]``
+
+Version Information
+---------------------
+
+The following fields provide version information:
+
+:FPGA_firmware_version_R: The active firmware images.
+
+  :type: ``str[N_fpgas]``
+
+:FPGA_hardware_version_R: The versions of the boards hosting the FPGAs.
+
+  :type: ``str[N_fpgas]``
+
+:TR_software_version_R: The version of the server providing the OPC-UA interface.
+
+  :type: ``str[N_fpgas]``
+
+Waveform Generator
+---------------------
+
+The antenna input of SDP can be replaced by an internal waveform generator for debugging and testing purposes. The generator is configured per antenna per FPGA:
+
+:FPGA_wg_enable_RW: Whether the waveform generator is enabled for each input.
+
+  :type: ``bool[N_fpgas][N_ants_per_fpga]``
+
+:FPGA_wg_phase_RW: The phases of the generated waves (in degrees). The generator needs to be turned off and on if this is changed, in order to bring the generators in sync.
+
+  :type: ``float32[N_fpgas][N_ants_per_fpga]``
+
+:FPGA_wg_frequency_RW: The frequencies of the generated waves (in Hz). The frequency of a subband ``s`` is LBA: ``s * 200e6/1024``, HBA low band: ``(512 + s) * 200e6/1024``, HBA high band: ``(1024 + s) * 200e6/1024``.
+
+  :type: ``float32[N_fpgas][N_ants_per_fpga]``
+
+:FPGA_wg_amplitude_RW: The amplitudes of the generated waves. Useful is a value of ``0.1``, as higher risks clipping.
+
+  :type: ``float32[N_fpgas][N_ants_per_fpga]``
+
+Usage example
+```````````````````````
+
+For example, the following code inserts a wave on LBA subband 102 on FPGAs 8 - 11::
+
+  # configure FPGAs to control
+  sdp.TR_fpga_mask_RW = [False] * 8 + [True] * 4 + [False] * 4
+
+  # configure waveform generator
+  sdp.FPGA_wg_phase_RW     = [[0] * 12] * 16
+  sdp.FPGA_wg_amplitude_RW = [[0.1] * 12] * 16
+  sdp.FPGA_wg_frequency_RW = [[102 * 200e6/1024] * 12] * 16
+
+  # enable waveform generator
+  sdp.FPGA_wg_enable_RW = [[True] * 12] * 16
diff --git a/docs/source/devices/sst-xst.rst b/docs/source/devices/sst-xst.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b5c5c1c57cdd72da3f4b71c23110b75dc009fe6c
--- /dev/null
+++ b/docs/source/devices/sst-xst.rst
@@ -0,0 +1,109 @@
+SST and XST
+====================
+
+The ``sst == DeviceProxy("LTS/SST/1")`` and ``xst == DeviceProxy("LTS/XST/1")`` devices manages the SSTs (subband statistics) and XSTs (crosslet statistics), respectively. The statistics are emitted piece-wise through UDP packets by the FPGAs on the Uniboards in SDP. By default, each device configures the statistics to be streamed to itself (the device), from where the user can obtain them.
+
+The statistics are exposed in two ways, as:
+
+- *Attributes*, representing the most recently received values,
+- *TCP stream*, to allow the capture and recording of the statistics over any period of time.
+
+See the following links for a full description of the SST and XST monitoring and control points:
+
+- https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L2+STAT+Decision%3A+SC+-+SDP+OPC-UA+interface
+- https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
+
+SST Statistics attributes
+------------------------------
+
+The SSTs represent the amplitude of the signal in each subband, for each antenna, as an integer value. They are exposed through the following attributes:
+
+:sst_R: Amplitude of each subband, from each antenna.
+
+  :type: ``uint64[N_ant][N_subbands]``
+
+:sst_timestamp_R: Timestamp of the data, per antenna.
+
+  :type: ``uint64[N_ant]``
+
+:integration_interval_R: Timespan over which the SSTs were integrated, per antenna.
+
+  :type: ``float32[N_ant]``
+
+:subbands_calibrated_R: Whether the subband data was calibrated using the subband weights.
+
+  :type: ``bool[N_ant]``
+
+Typically, ``N_ant == 192``, and ``N_subbands == 512``.
+
+XST Statistics attributes
+------------------------------
+
+The XSTs represent the cross-correlations between each pair of antennas, as complex values. The phases and amplitudes of the XSTs represent the phase and amplitude difference between the antennas, respectively. They are exposed as a matrix ``xst[a][b]``, of which only the triangle ``a<=b`` is filled, as the cross-correlation between antenna pairs ``(b,a)`` is equal to the complex conjugate of the cross-correlation of ``(a,b)``. The other triangle contains incidental values, but will be mostly 0.
+
+Complex values which cannot be represented in Tango attributes. Instead, the XST matrix is exposed as both their carthesian and polar parts:
+
+:xst_power_R, xst_phase_R: Amplitude and phase (in radians) of the crosslet statistics.
+
+  :type: ``float32[N_ant][N_ant]``
+
+:xst_real_R, xst_imag_R: Real and imaginary parts of the crosslet statistics.
+
+  :type: ``float32[N_ant][N_ant]``
+
+:xst_timestamp_R: Timestamp of each block.
+
+  :type: ``int64[N_blocks]``
+
+:integration_interval_R: Timespan over which the XSTs were integrated, for each block.
+
+  :type: ``float32[N_blocks]``
+
+Typically, ``N_ant == 192``, and ``N_blocks == 136``.
+
+The metadata refers to the *blocks*, which are emitted by the FPGAs to represent the XSTs between 12 x 12 consecutive antennas. The following code converts block numbers to the indices of the first antenna pair in a block::
+
+  from common.baselines import baseline_from_index
+
+  def first_antenna_pair(block_nr: int) -> int:
+      coarse_a, coarse_b = baseline_from_index(block_nr)
+      return (coarse_a * 12, coarse_b * 12)
+
+Conversely, to calculate the block index for an antenna pair ``(a,b)``, use::
+
+  from common.baselines import baseline_index
+
+  def block_nr(a: int, b: int) -> int:
+      return baseline_index(a // 12, b // 12)
+
+Subscribe to statistics streams
+---------------------------------
+
+The TCP stream interface allows a user to subscribe to the statistics packet streams, combined into a single TCP stream. The statistics will be streamed until the user disconnects, or the device is turned off. Any number of subscribers is supported, as bandwidth allows. Simply connect to the following port:
+
++----------+----------------+
+| Device   | TCP end point  |
++==========+================+
+| SST      | localhost:5101 |
++----------+----------------+
+| XST      | localhost:5102 |
++----------+----------------+
+
+The easiest way to capture this stream is to use our ``statistics_writer``, which will capture the statistics and store them in HDF5 file(s). The writer:
+
+- computes packet boundaries,
+- processes the data of each packet, and stores their values into the matrix relevant for the mode,
+- stores a matrix per timestamp,
+- stores packet header information per timestamp, as HDF5 attributes,
+- writes to a new file at a configurable interval.
+
+To run the writer::
+
+  cd devices/statistics_writer
+  python3 statistics_writer.py --mode SST --host localhost
+
+The correct port will automatically be chosen, depending on the given mode. See also ``statistics_writer.py -h`` for more information.
+
+The writer can also parse a statistics stream stored in a file. This allows the stream to be captured and processed independently. Capturing the stream can for example be done using ``netcat``::
+
+  nc localhost 5101 > SST-packets.bin
diff --git a/docs/source/devices/using.rst b/docs/source/devices/using.rst
new file mode 100644
index 0000000000000000000000000000000000000000..66760ebfd53de7df20fe4e58144c7d4b99dc3ecb
--- /dev/null
+++ b/docs/source/devices/using.rst
@@ -0,0 +1,143 @@
+Using Devices
+=============
+
+The station exposes *devices*, each of which is a remote software object that manages part of the station. Each device has the following properties:
+
+- It has a *state*,
+- Many devices manage and represent hardware in the station,
+- It exposes *read-only attributes*, that expose values from within the device or from the hardware it represents,
+- It exposes *read-write attributes*, that allow controlling the functionality of the device, or the hardware it represents,
+- It exposes *properties*, which are fixed configuration parameters (such as port numbers and timeouts),
+- It exposes *commands*, that request the execution of a procedure in the device or in the hardware it manages.
+
+The devices are accessed remotely using ``DeviceProxy`` objects. See :doc:`../interfaces/control` on how to do this.
+
+States
+------------
+
+The state of a device is then queried with ``device.state()``. Each device can be in one of the following states:
+
+- ``DevState.OFF``: The device is not operating,
+- ``DevState.INIT``: The device is being initialised,
+- ``DevState.STANDBY``: The device is initialised and ready to be configured further,
+- ``DevState.ON``: The device is operational.
+- ``DevState.FAULT``: The device is malfunctioning. Functionality cannot be counted on.
+- The ``device.state()`` function can throw an error, if the device cannot be reached at all. For example, because it's docker container is not running. See the :ref:`docker` device on how to start it.
+
+Each device provides the following commands to change the state:
+
+:off(): Turn the device ``OFF`` from any state.
+
+:initialise(): Initialise the device from the ``OFF`` state, to bring it to the ``STANDBY`` state.
+
+:on(): Mark the device as operational, from the ``STANDBY`` state, bringing it to ``ON``.
+
+The following procedure is a good way to bring a device to ``ON`` from any state::
+
+  def force_start(device):
+      if device.state() == DevState.FAULT:
+          device.off()
+      if device.state() == DevState.OFF:
+          device.initialise()
+      if device.state() == DevState.STANDBY:
+          device.on()
+
+      return device.state()
+
+.. hint:: If a command gives you a timeout, the command will still be running until it finishes. You just won't know when it does or its result. In order to increase the timeout, use ``device.set_timeout_millis(timeout * 1000)``.
+
+FAULT
+``````````
+
+If a device enters the ``FAULT`` state, it means an error occurred that is fundamental to the operation of the software device. For example, the connection
+to the hardware was lost.
+
+Interaction with the device in the ``FAULT`` state is undefined, and attributes cannot be read or written. The device needs to be reinitialised, which
+typically involves the following sequence of commands::
+
+  # turn the device off completely first.
+  device.off()
+
+  # setup any connections and threads
+  device.initialise()
+
+  # turn on the device
+  device.on()
+
+Of course, the device could go into ``FAULT`` again, even during the ``initialise()`` command, for example because the hardware it manages is unreachable. To debug the fault condition, check the :doc:`../interfaces/logs` of the device in question.
+
+Initialise hardware
+````````````````````
+
+Most devices provide the following commands, in order to configure the hardware with base settings:
+
+:set_defaults(): Upload default attribute settings from the TangoDB to the hardware.
+
+:initialise_hardware(): For devices that control hardware, this command runs the hardware initialisation procedure.
+
+Typically, ``set_defaults()`` and ``initialise_hardware()`` are called in that order in the ``STANDBY`` state. See also :ref:`boot`, which provides functionality to initialise all the devices.
+
+.. _attributes:
+
+Attributes
+------------
+
+The device can be operated in ``ON`` state, where it exposes *attributes* and *commands*. The attributes can be accessed as python properties, for example::
+
+  recv = DeviceProxy("LTS/RECV/1")
+
+  # turn on all LED0s
+  recv.RCU_LED0_RW = [True] * 32
+
+  # retrieve the status of all LED0s
+  print(recv.RCU_LED0_R)
+
+The attributes with an:
+
+- ``_R`` suffix are monitoring points, reflecting the state of the hardware, and are thus read-only.
+- ``_RW`` suffix are control points, reflecting the desired state of the hardware. They are read-write, where writing requests the hardware to set the specified value. Reading them returns the last requested value.
+
+Meta data
+`````````````
+
+A description of the attribute can be retrieved using::
+
+  print(recv.get_attribute_config("RCU_LED0_R").description)
+
+.. _attribute-masks:
+
+Attribute masks
+---------------------
+
+Several devices employ *attribute masks* in order to toggle which elements in their hardware array are actually to be controlled. This construct is necessary as most control points consist of arrays of values that cover all hardware elements. These array control points are always fully sent: it is not possible to update only a single element without uploading the rest. Without a mask, it is impossible to control a subset of the hardware.
+
+The masks only affect *writing* to attributes. Reading attributes (monitoring points) always result in data for all elements in the array.
+
+For example, the ``RCU_mask_RW`` array is the RCU mask in the ``recv`` device. It behaves as follows, when we interact with the ``RCU_LED0_R(W)`` attributes::
+
+  recv = DeviceProxy("LTS/RECV/1")
+
+  # set mask to control all RCUs
+  recv.RCU_mask_RW = [True] * 32
+
+  # request to turn off LED0 for all RCUs
+  recv.RCU_LED0_RW = [False] * 32
+
+  # <--- all LED0s are now off
+  # recv.RCU_LED0_R should show this,
+  # if you have the RCU hardware installed.
+
+  # set mask to only control RCU 3 
+  mask = [False] * 32
+  mask[3] = True
+  recv.RCU_mask_RW = mask
+
+  # request to turn on LED0, for all RCUs
+  # due to the mask, only LED0 on RCU 3
+  # will be set.
+  recv.RCU_LED0_RW = [True] * 32
+
+  # <--- only LED0 on RCU3 is now on
+  # recv.RCU_LED0_R should show this,
+  # if you have the RCU hardware installed.
+
diff --git a/docs/source/faq.rst b/docs/source/faq.rst
new file mode 100644
index 0000000000000000000000000000000000000000..8e35fceab3ec6ea07124e1181fccffdbe3cea679
--- /dev/null
+++ b/docs/source/faq.rst
@@ -0,0 +1,152 @@
+FAQ
+===================================
+
+Connecting to devices
+--------------------------------------------------------------------------------------------------------------
+
+My device is unreachable, but the device logs say it's running fine?
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+The ``$HOSTNAME`` may have been incorrectly guessed by ``docker-compose/Makefile``, or you accidently set it to an incorrect value. If you have ``$HOSTNAME`` set in the shell running ``make``, try::
+
+  unset HOSTNAME
+  make build
+  make stop
+  make start
+
+If this does not work, you need to set ``$HOSTNAME`` to something that resolves to your machine, both for external parties and for docker containers. See :ref:`corba`.
+
+I get "API_CorbaException: TRANSIENT CORBA system exception: TRANSIENT_NoUsableProfile" when trying to connect to a device?
+````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+See the previous answer.
+
+Docker
+--------------------------------------------------------------------------------------------------------------
+
+How do I prevent my containers from starting when I boot my computer?
+````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+You have to explicitly stop a container to prevent it from restarting. Use::
+
+  cd docker-compose
+  make stop <container>
+
+or plain ``make stop`` to stop all of them.
+
+Windows
+--------------------------------------------------------------------------------------------------------------
+
+How do I develop from Windows?
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+Our setup is Linux-based, so the easiest way to develop is by using WSL2, which lets you run a Linux distro under Windows. You'll need to:
+
+- Install WSL2. See f.e. https://www.omgubuntu.co.uk/how-to-install-wsl2-on-windows-10
+- Install `Docker Desktop <https://hub.docker.com/editions/community/docker-ce-desktop-windows/>`_
+- Enable the WSL2 backend in Docker Desktop
+- We also recommend to install `Windows Terminal <https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701>`_
+
+.. _x11_on_windows:
+
+How do I run X11 applications on Windows?
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+If you need an X11 server on Windows:
+
+- Install `VcXsrv <https://sourceforge.net/projects/vcxsrv/>`_
+- Disable access control during its startup, 
+- Use ``export DISPLAY=host.docker.internal:0`` in WSL.
+
+You should now be able to run X11 applications from WSL and Docker. Try running ``xterm`` or ``xeyes`` to test.
+
+
+SSTs/XSTs
+--------------------------------------------------------------------------------------------------------------
+
+Some SSTs/XSTs packets do arrive, but not all, and/or the matrices remain zero?
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+So ``sst.nof_packets_received`` / ``xst.nof_packets_received`` is increasing, telling you packets are arriving. But they're apparently dropped or contain zeroes. First, check the following settings:
+
+- ``sdp.TR_fpga_mask_RW[x] == True``, to make sure we're actually configuring the FPGAs,
+- ``sdp.FPGA_wg_enable_RW[x] == False``, or the Waveform Generator might be replacing our the antenna data with zeroes,
+- ``sdp.FPGA_processing_enabled_R[x] == True``, to verify that the FPGAs are processing, or the values and timestamps will be zero,
+- For XSTs, ``xst.FPGA_xst_processing_enabled_R[x] == True``, to verify that the FPGAs are computing XSTs, or the values will be zero.
+
+Furthermore, the ``sst`` and ``xst`` devices expose several packet counters to indicate where incoming packets were dropped before or during processing:
+
+- ``nof_invalid_packets_R`` increases if packets arrive with an invalid header, or of the wrong statistic for this device,
+- ``nof_packets_dropped_R`` increases if packets could not be processed because the processing queue is full, so the CPU cannot keep up with the flow,
+- ``nof_payload_errors_R`` increases if the packet was marked by the FPGA to have an invalid payload, which causes the device to discard the packet,
+
+I am not receiving any XSTs and/or SSTs packets from SDP!
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+Are you sure? If ``sst.nof_packets_received`` / ``xst.nof_packets_received`` is actually increasing, the packets are arriving, but are not parsable by the SST/XST device. If so, see the previous question.
+
+Many settings need to be correct for the statistics emitted by the SDP FPGAs to reach our devices correctly. Here is a brief overview:
+
+- ``sdp.TR_fpga_mask_RW[x] == True``, to make sure we're actually configuring the FPGAs,
+- ``sdp.FPGA_communication_error_R[x] == False``, to verify the FPGAs can be reached by SDP,
+- SSTs:
+
+  - ``sst.FPGA_sst_offload_enable_RW[x] == True``, to verify that the FPGAs are actually emitting the SSTs,
+  - ``sst.FPGA_sst_offload_hdr_eth_destination_mac_R[x] == <MAC of your machine's mtu=9000 interface>``, or the FPGAs will not send it to your machine. Use f.e. ``ip addr`` on the host to find the MAC address of your interface, and verify that its MTU is 9000,
+  - ``sst.FPGA_sst_offload_hdr_ip_destination_address_R[x] == <IP of your machine's mtu=9000 interface>``, or the packets will be dropped by the network or the kernel of your machine,
+  - ``sst.FPGA_sst_offload_hdr_ip_destination_address_R[x] == 5001``, or the packets will not be sent to a port that the SST device listens on.
+
+- XSTs:
+
+  - ``xst.FPGA_sst_offload_enable_RW[x] == True``, to verify that the FPGAs are actually emitting the SSTs,
+  - ``xst.FPGA_xst_offload_hdr_eth_destination_mac_R[x] == <MAC of your machine's mtu=9000 interface>``, or the FPGAs will not send it to your machine. Use f.e. ``ip addr`` on the host to find the MAC address of your interface, and verify that its MTU is 9000,
+  - ``xst.FPGA_xst_offload_hdr_ip_destination_address_R[x] == <IP of your machine's mtu=9000 interface>``, or the packets will be dropped by the network or the kernel of your machine,
+  - ``xst.FPGA_xst_offload_hdr_ip_destination_address_R[x] == 5002``, or the packets will not be sent to a port that the XST device listens on.
+
+If this fails, see the next question.
+
+I am still not receiving XSTs and/or SSTs, even though the settings appear correct!
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+Let's see where the packets get stuck. Let us assume your MTU=9000 network interface is called ``em2`` (see ``ip addr`` to check):
+
+- Check whether the data arrives on ``em2``. Run ``tcpdump -i em2 udp -nn -vvv -c 10`` to capture the first 10 packets. Verify:
+
+  - The destination MAC must match that of ``em2``, 
+  - The destination IP must match that of ``em2``,
+  - The destination port is correct (5001 for SST, 5002 for XST),
+  - The source IP falls within the netmask of ``em2`` (unless ``net.ipv4.conf.em2.rp_filter=0`` is configured),
+  - TTL >= 2,
+
+- If you see no data at all, the network will have swallowed it. Try to use a direct network connection, or a hub (which broadcasts all packets, unlike a switch), to see what is being emitted by the FPGAs.
+- Check whether the data reaches user space on the host:
+
+  - Turn off the ``sst`` or ``xst`` device. This will not stop the FPGAs from sending.
+  - Run ``nc -u -l -p 5001 -vv`` (or port 5002 for XSTs). You should see raw packets being printed.
+  - If not, the Linux kernel is swallowing the packets, even before it can be sent to our docker container.
+
+- Check whether the data reaches kernel space in the container:
+
+  - Enter the docker device by running ``docker exec -it device-sst bash``.
+  - Run ``sudo bash`` to become root,
+  - Run ``apt-get install -y tcpdump`` to install tcpdump,
+  - Check whether packets arrive using ``tcpdump -i eth0 udp -c 10 -nn``,
+  - If not, Linux is not routing the packets to the docker container.
+
+- Check whether the data reaches user space in the container:
+
+  - Turn off the ``sst`` or ``xst`` device. This will not stop the FPGAs from sending.
+  - Enter the docker device by running ``docker exec -it device-sst bash``.
+  - Run ``sudo bash`` to become root,
+  - Run ``apt-get install -y netcat`` to install netcat,
+  - Check whether packets arrive using ``nc -u -l -p 5001 -vv`` (or port 5002 for XSTs),
+  - If not, Linux is not routing the packets to the docker container correctly.
+
+- If still on error was found, you've likely hit a bug in our software.
+
+Other containers
+--------------------------------------------------------------------------------------------------------------
+
+The ELK container won't start, saying "max virtual memory areas vm.max_map_count [65530] is too low"?
+``````````````````````````````````````````````````````````````````````````````````````````````````````````````
+
+The ELK stack needs the ``vm.max_map_count`` sysctl kernel parameter to be at least 262144 to run. See :ref:`elk-kernel-settings`.
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 5e6c6564940391ea5171403a833a2f83ed015adc..b81b9c631131a08319d1ec2e07f868455a9a956a 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -6,10 +6,28 @@
 Welcome to LOFAR2.0 Station Control's documentation!
 ====================================================
 
+LOFAR2.0 Station Control is a software stack aimed to monitor, control, and manage a LOFAR2.0 station. In order to do so, it whips up a series of Docker containers, and combines the power of `Tango Controls <https://www.tango-controls.org/>`_, `PyTango <https://pytango.readthedocs.io/en/stable/>`_, `Docker <https://www.docker.com/>`_, `Grafana <https://grafana.com/>`_, `ELK <https://www.elastic.co/what-is/elk-stack>`_, `Jupyter Notebook <https://jupyter.org/>`_, and many others to provide a rich and powerful experience in using the station.
+
+Full monitoring and control access to the LOFAR2.0 station hardware is provided, by marshalling their rich `OPC-UA <https://opcfoundation.org/about/opc-technologies/opc-ua/>`_ interfaces. Higher-level logic makes it possible to easily configure and obtain the LOFAR station data products (beamlets, XSTs, SSTs, BSTs) from your local machine using Python, or through one of our provided web interfaces.
+
+Even without having access to any LOFAR2.0 hardware, you can install the full stack on your laptop, and experiment with the software interfaces.
+
 .. toctree::
    :maxdepth: 2
    :caption: Contents:
 
+   installation
+   interfaces/overview
+   devices/using
+   devices/boot
+   devices/docker
+   devices/recv
+   devices/sdp
+   devices/sst-xst
+   devices/configure
+   configure_station
+   developer
+   faq
 
 
 Indices and tables
diff --git a/docs/source/installation.rst b/docs/source/installation.rst
new file mode 100644
index 0000000000000000000000000000000000000000..58ccf2cd360261256774826a7904973ac6c44b70
--- /dev/null
+++ b/docs/source/installation.rst
@@ -0,0 +1,83 @@
+Installation
+==================
+
+You will need the following dependencies installed:
+
+- docker
+- docker-compose
+- git
+- make
+
+You start with checking out the source code, f.e. the master branch, as well as the git submodules we use::
+
+  git clone https://git.astron.nl/lofar2.0/tango.git
+  cd tango
+  git submodule init
+  git submodule update
+
+Next, we bootstrap the system. This will build our docker images, start key ones, and load the base configuration. This may take a while::
+
+  cd docker-compose
+  make bootstrap
+
+If you do have access to LOFAR station hardware, you must upload its configuration to the configuration database. See :doc:`configure_station`.
+
+Now we are ready to start the other containers::
+
+  make start
+
+and make sure they are all up and running::
+
+  make status
+
+You should see the following state:
+
+- Containers ``astor``, ``hdbpp-viewer``, ``jive``, ``log-viewer`` and ``pogo`` will have State ``Exit 1``. These are containers that are interactive X11 tools, and not needed for now,
+- Other containers have either State ``Up`` or ``Exit 0``.
+
+If not, you can inspect why with ``docker logs <container>``. Note that the containers will automatically be restarted on failure, and also if you reboot. Stop them explicitly to bring them down (``make stop <container>``).
+
+Post-boot Initialisation
+---------------------------
+
+After bootstrapping, and after a reboot, the software and hardware of the station needs to be explicitly initialised. Note that the docker containers do restart automatically at system boot.
+
+The following commands start all the software devices to control the station hardware, and initialise the hardware with the configured default settings. Go to http://localhost:8888, start a new *Station Control* notebook, and initiate the software boot sequence::
+
+  # reset our boot device
+  boot.off()
+  assert boot.state() == DevState.OFF
+  boot.initialise()
+  assert boot.state() == DevState.STANDBY
+  boot.on()
+  assert boot.state() == DevState.ON
+
+  # start and initialise the other devices
+  boot.initialise_station()
+
+  # wait for the devices to be initialised
+  import time
+
+  while boot.initialising_station_R:
+    print(f"Still initialising station. {boot.initialisation_progress_R}% complete. State: {boot.initialisation_status_R}")
+    time.sleep(1)
+
+  # print conclusion
+  if boot.initialisation_progress_R == 100:
+    print("Done initialising station.")
+  else:
+    print(f"Failed to initialise station: {boot.initialisation_status_R}")
+
+See :ref:`boot` for more information on the ``boot`` device.
+
+.. _elk-kernel-settings:
+
+ELK
+````
+
+The ELK stack requires some kernel settings to be tuned, before it will start. Although ``make bootstrap`` configures the kernel, these settings will not stick after a reboot. You will need to run either::
+
+  make start elk-configure-host
+  make restart elk
+
+after reboot, or configure your system to set ``sysctl -w vm.max_map_count=262144`` (or higher) as root during boot.
diff --git a/docs/source/interfaces/control.rst b/docs/source/interfaces/control.rst
new file mode 100644
index 0000000000000000000000000000000000000000..3c514f11d7a3e5a4bbc1c7339bac3bed0820d70f
--- /dev/null
+++ b/docs/source/interfaces/control.rst
@@ -0,0 +1,84 @@
+Monitoring & Control
+========================
+
+The main API to control the station is through the `Tango Controls <https://tango-controls.readthedocs.io/en/latest/>`_ API we expose on port 10000, which is most easily accessed using a `PyTango <https://pytango.readthedocs.io/en/stable/client_api/index.html>`_ client. The Jupyter Notebook installation we provide is such a client.
+
+.. _jupyter:
+
+Jupyter Notebooks
+------------------------
+
+The station offers Juypyter notebooks On http://localhost:8888, which allow one to interact with the station, for example to set control points, access monitoring points, or to graph their values.
+
+The notebooks provide some predefined variables, so you don't have to look them up:
+
+.. literalinclude:: ../../../docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
+
+Note: the Jupyter notebooks use enhancements from the ``itango`` suite, which provide tab completions, but also the ``Device`` alias for ``DeviceProxy`` as was used in the Python examples in the next section.
+
+For example, you can start a new *Station Control* notebook (File->New Notebook->StationControl), and access these devices:
+
+.. image:: jupyter_basic_example.png
+
+.. _pytango-section:
+
+PyTango
+------------------------
+
+To access a station from scratch using Python, we need to install some dependencies::
+
+  pip3 install tango
+
+Then, if we know what devices are available on the station, we can access them directly::
+
+  import tango
+  import os
+
+  # Tango needs to know where our Tango API is running.
+  os.environ["TANGO_HOST"] = "localhost:10000"
+
+  # Construct a remote reference to a specific device.
+  # One can also use "tango://localhost:10000/LTS/Boot/1" if TANGO_HOST is not set
+  boot_device = tango.DeviceProxy("LTS/Boot/1")
+
+  # Print the device's state.
+  print(boot_device.state())
+
+To obtain a list of all devices, we need to access the database::
+
+  import tango
+
+  # Tango needs to know where our Tango API is running.
+  import os
+  os.environ["TANGO_HOST"] = "localhost:10000"
+
+  # Connect to the database.
+  db = tango.Database()
+
+  # Retrieve the available devices, excluding any Tango-internal ones.
+  # This returns for example: ['LTS/Boot/1', 'LTS/Docker/1', ...]
+  devices = list(db.get_device_exported("LTS/*"))
+
+  # Connect to any of them.
+  any_device = tango.DeviceProxy(devices[0])
+
+  # Print the device's state.
+  print(any_device.state())
+
+.. _rest-api:
+
+ReST API
+------------------------
+
+We also provide a ReST API to allow the station to be controlled without needing to use the Tango API. The root access point is http://localhost:8080/tango/rest/v10/hosts/databaseds;port=10000/ (credentials: tango-cs/tango). This API allows for:
+
+- getting and setting attribute values,
+- calling commands,
+- retrieving the device state,
+- and more.
+
+For example, retrieving http://localhost:8080/tango/rest/v10/hosts/databaseds;port=10000/devices/LTS/SDP/1/state returns the following JSON document::
+
+  {"state":"ON","status":"The device is in ON state."}
+
+For a full description of this API, see https://tango-rest-api.readthedocs.io/en/latest/.
diff --git a/docs/source/interfaces/elk_last_hour.png b/docs/source/interfaces/elk_last_hour.png
new file mode 100644
index 0000000000000000000000000000000000000000..d6f2a73c9ba754a5a6d5aeece1382906040acb15
Binary files /dev/null and b/docs/source/interfaces/elk_last_hour.png differ
diff --git a/docs/source/interfaces/elk_log_fields.png b/docs/source/interfaces/elk_log_fields.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5774931f23933be6033e396220b2459409b1def
Binary files /dev/null and b/docs/source/interfaces/elk_log_fields.png differ
diff --git a/docs/source/interfaces/grafana_dashboard_1.png b/docs/source/interfaces/grafana_dashboard_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..448a9bd993b264cf35e98229f12829256f775029
Binary files /dev/null and b/docs/source/interfaces/grafana_dashboard_1.png differ
diff --git a/docs/source/interfaces/grafana_dashboard_2.png b/docs/source/interfaces/grafana_dashboard_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7c34991d97cd22a209d1f02502afa1f439acf4e
Binary files /dev/null and b/docs/source/interfaces/grafana_dashboard_2.png differ
diff --git a/docs/source/interfaces/jupyter_basic_example.png b/docs/source/interfaces/jupyter_basic_example.png
new file mode 100644
index 0000000000000000000000000000000000000000..c7e35204cc72b63e8ea2d81c2bdad337d3ce72a1
Binary files /dev/null and b/docs/source/interfaces/jupyter_basic_example.png differ
diff --git a/docs/source/interfaces/logs.rst b/docs/source/interfaces/logs.rst
new file mode 100644
index 0000000000000000000000000000000000000000..960efcd95b5306ab1904ffd8519e36af85099f0f
--- /dev/null
+++ b/docs/source/interfaces/logs.rst
@@ -0,0 +1,44 @@
+Logs
+==================
+
+The devices, and the docker containers in general, produce logging output. The easiest way to access the logs of a specific container is to ask docker directly. For example, to access and follow the most recent logs of the ``device-sdp`` container, execute on the host::
+
+  docker logs -n 100 -f device-sdp
+
+This is mostly useful for interactive use.
+
+.. _elk:
+
+ELK
+------------------
+
+To monitor the logs remotely, or to browse older logs, use the *ELK stack* that is included on the station, and served on http://localhost:5601. ELK, or ElasticSearch + Logstash + Kibana, is a popular log collection and querying system. Currently, the following logs are collected in our ELK installation:
+
+- Logs of all devices,
+- Logs of the Jupyter notebook server.
+
+If you browse to the ELK stack (actually, it is Kibana providing the GUI), your go-to is the *Discover* view at http://localhost:5601/app/discover. There, you can construct (and save, load) a dashboard that provides a custom view of the logs, based on the *index pattern* ``logstash-*``. There is a lot to take in, and there are excellent Kibana tutorials on the web.
+
+To get going, use for example `this dashboard <http://localhost:5601/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-60m,to:now))&_a=(columns:!(extra.lofar_id,level,message),filters:!(),index:'1e8ca200-1be0-11ec-a85f-b97e4206c18b',interval:auto,query:(language:kuery,query:''),sort:!())>`_, which shows the logs of the last hour, with some useful columns added to the default timestamp and message columns. Expand the time range if no logs appear, to look further back. You should see something like:
+
+.. image:: elk_last_hour.png
+
+ELK allows you to filter, edit the columns, and a lot more. We enrich the log entries with several extra fields, for example the device that generated it, and stack traces if available. Click on the ``>`` before a log entry and the information expands, showing for example:
+
+.. image:: elk_log_fields.png
+
+Furthermore, statistics from the ELK stack, such as the number of ERROR log messages, are made available as a data source in :doc:`monitoring`.
+
+LogViewer
+------------------
+
+For each device, Tango collects the logs as well. These can be viewed with the LogViewer X11 application. Make sure ``$DISPLAY`` is set, and run::
+
+  cd docker-compose
+  make start logviewer
+
+If LogViewer does not appear, check ``docker logs logviewer`` to see what went wrong.
+
+For information on how to use the LogViewer, see https://tango-controls.readthedocs.io/en/latest/tools-and-extensions/built-in/logviewer/logviewer.html.
+
+.. note:: If you need an X11 server on Windows, see :ref:`x11_on_windows`.
diff --git a/docs/source/interfaces/monitoring.rst b/docs/source/interfaces/monitoring.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7d8a85fdf5bd7c103119a89a8dbae127040a5240
--- /dev/null
+++ b/docs/source/interfaces/monitoring.rst
@@ -0,0 +1,51 @@
+Monitoring GUIs
+========================
+
+Each device exposes a list of monitoring points as attributes with the ``_R`` prefix. These can be accessed interactively from a controle console (such as Jupyter), but that will not scale.
+
+Grafana
+------------------------
+
+We offer `Grafana <https://grafana.com/>`_ dashboards on http://localhost:3000 that provide a quick overview of the station's status, including temperatures and settings. Several dashboards are included. An example:
+
+.. image:: grafana_dashboard_1.png
+.. image:: grafana_dashboard_2.png
+
+NOTE: These dashboards are highly subject to change. The above examples provide an impression of a possible overview of the station state.
+
+You are encouraged to inspect each panel (graph) to see the underlying database query and settings. Use the small arrow in the panel's title to get a drop-down menu of options, and select *inspect*. See the Grafana documentation for further information.
+
+The Grafana dashboards are configured with the following data sources:
+
+- :ref:`prometheus-section`, the time-series database that caches the latest values of all monitoring points (see next section),
+- *Archiver DB*, the database that provides a long-term cache of attributes,
+- :ref:`tangodb`, providing access to device properties (fixed settings),
+- :ref:`elk`, the log output of the devices.
+
+.. _prometheus-section:
+
+Prometheus
+-------------------------
+
+`Prometheus <https://prometheus.io/docs/introduction/overview/>`_ is a low-level monitoring system that allows us to periodically retrieve the values of all the attributes of all our devices, and cache them to be used in Grafana:
+
+- Every several seconds, Prometheus scrapes our `TANGO-Grafana Exporter <https://git.astron.nl/lofar2.0/ska-tango-grafana-exporter>`_ (our fork of https://gitlab.com/ska-telescope/TANGO-grafana.git), collecting all values of all the device attributes (except the large ones, for performance reasons).
+- Prometheus can be queried directly on http://localhost:9090,
+- The TANGO-Grafana Exporter can be queried directly on http://localhost:8000,
+- The query language is `PromQL <https://prometheus.io/docs/prometheus/latest/querying/basics/>`_, which is also used in Grafana to query Prometheus,
+
+Prometheus stores attributes in the following format::
+
+  device_attribute{device="lts/recv/1",
+                   dim_x="32", dim_y="0",
+                   instance="tango-prometheus-exporter:8000",
+                   job="tango",
+                   label="RCU_temperature_R",
+                   name="RCU_temperature_R",
+                   type="float",
+                   x="00", y="0"} 
+
+The above describes a single data point and its labels. The primary identifying labels are ``device`` and ``name``. Each point furthermore has a value (integer) and a timestamp. The following transformations take place:
+
+- For 1D and 2D attributes, each array element is its own monitoring point, with ``x`` and ``y`` labels describing the indices. The labels ``dim_x`` and ``dim_y`` describe the array dimensionality,
+- Attributes with string values get a ``str_value`` label describing their value.
diff --git a/docs/source/interfaces/overview.rst b/docs/source/interfaces/overview.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a00ab5710ad863b4f10d1bb0ee93ab3f547826d5
--- /dev/null
+++ b/docs/source/interfaces/overview.rst
@@ -0,0 +1,41 @@
+Interfaces
+======================
+
+The station provides the following interfaces accessible through your browser (assuming you run on `localhost`):
+
++---------------------+---------+----------------------+-------------------+
+|Interface            |Subsystem|URL                   |Default credentials|
++=====================+=========+======================+===================+
+| :ref:`jupyter`      |Jupyter  |http://localhost:8888 |                   |
++---------------------+---------+----------------------+-------------------+
+| :doc:`monitoring`   |Grafana  |http://localhost:3000 |admin/admin        |
++---------------------+---------+----------------------+-------------------+
+| :doc:`logs`         |Kibana   |http://localhost:5601 |                   |
++---------------------+---------+----------------------+-------------------+
+
+Futhermore, there are some low-level interfaces:
+
++---------------------------+------------------+-----------------------+-------------------+
+|Interface                  |Subsystem         |URL                    |Default credentials|
++===========================+==================+=======================+===================+
+| :ref:`pytango-section`    |Tango             |tango://localhost:10000|                   |
++---------------------------+------------------+-----------------------+-------------------+
+| :ref:`prometheus-section` |Prometheus        |http://localhost:9090  |                   |
++---------------------------+------------------+-----------------------+-------------------+
+| TANGO-Grafana Exporter    |Python HTTPServer |http://localhost:8000  |                   |
++---------------------------+------------------+-----------------------+-------------------+
+| :ref:`rest-api`           |tango-rest        |http://localhost:8080  |tango-cs/tango     |
++---------------------------+------------------+-----------------------+-------------------+
+| :ref:`tangodb`            |MariaDB           |http://localhost:3306  |tango/tango        |
++---------------------------+------------------+-----------------------+-------------------+
+|Archive Database           |MariaDB           |http://localhost:3307  |tango/tango        |
++---------------------------+------------------+-----------------------+-------------------+
+|Log Database               |ElasticSearch     |http://localhost:9200  |                   |
++---------------------------+------------------+-----------------------+-------------------+
+
+.. toctree::
+   :hidden:
+
+   control
+   monitoring
+   logs
diff --git a/jupyter-notebooks/Home.ipynb b/jupyter-notebooks/Home.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1b6001f9e5a87a0d626e310cc8038ede2d5f589f
--- /dev/null
+++ b/jupyter-notebooks/Home.ipynb
@@ -0,0 +1,166 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "e051e48d",
+   "metadata": {},
+   "source": [
+    "# Welcome to your LOFAR2.0 station!\n",
+    "\n",
+    "The following interfaces are available to you, on the same host as this notebook, but on different ports:\n",
+    "\n",
+    "|Interface |Subsystem |Port|Credentials   |\n",
+    "|----------|----------|----|--------------|\n",
+    "|Scripting |Jupyter   |8888|              |\n",
+    "|Monitoring|Grafana   |3000|admin/admin   |\n",
+    "|Logs      |Kibana    |5601|              |\n",
+    "|ReST      |tango-rest|8080|tango-cs/tango|\n",
+    "\n",
+    "Below are codes to manage the station at high level. For more detailed status information, look in Grafana."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "32ae8bcf",
+   "metadata": {},
+   "source": [
+    "## (Re)boot station\n",
+    "The code below is used to:\n",
+    "* Reboot all station software\n",
+    "* Reset the hardware configuration"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "38037a71",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Restart boot device itself\n",
+    "boot.off()\n",
+    "assert boot.state() == DevState.OFF, boot.state()\n",
+    "\n",
+    "boot.initialise()\n",
+    "assert boot.state() == DevState.STANDBY, boot.state()\n",
+    "\n",
+    "boot.on()\n",
+    "assert boot.state() == DevState.ON, boot.state()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "21aba361",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Request to reinitialise the station.\n",
+    "#\n",
+    "# WARNING: This will reset settings across the station!\n",
+    "boot.initialise_station()\n",
+    "assert boot.state() != DevState.FAULT"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c00b465a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import time\n",
+    "\n",
+    "while boot.initialising_station_R:\n",
+    "  print(f\"Still initialising station. {boot.initialisation_progress_R}% complete. State: {boot.initialisation_status_R}\")\n",
+    "  time.sleep(1)\n",
+    "\n",
+    "if boot.initialisation_progress_R == 100:\n",
+    "    print(\"Done initialising station.\")\n",
+    "else:\n",
+    "    print(f\"Failed to initialise station: {boot.initialisation_status_R}\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b444b751",
+   "metadata": {},
+   "source": [
+    "## Inspect Docker status\n",
+    "Docker containers that are not running will not provide any functionality, and are ignored when the station is rebooted."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8b09f9da",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "container_status = {attr_name: getattr(docker, attr_name)\n",
+    "                    for attr_name in docker.get_attribute_list()\n",
+    "                    if attr_name.endswith(\"_R\")\n",
+    "                    and attr_name != 'version_R'}\n",
+    "\n",
+    "not_running_containers = [container for container, running in container_status.items() if running is False]\n",
+    "\n",
+    "if not not_running_containers:\n",
+    "    print(\"All docker containers are running\")\n",
+    "else:\n",
+    "    print(f\"Docker containers that are NOT running: {not_running_containers}\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "55f3981d",
+   "metadata": {},
+   "source": [
+    "## Inspect Device status\n",
+    "Check whether all software devices are indeed up and running."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "637e6e22",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "for d in devices:\n",
+    "    try:\n",
+    "        print(f\"Device {d.dev_name()} is in state {d.state()}\")\n",
+    "    except ConnectionFailed as e:\n",
+    "        print(f\"Device {d.dev_name()} is in state DOWN: {e.args[0].desc}\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "23008885",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "StationControl",
+   "language": "python",
+   "name": "stationcontrol"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.7.3"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/jupyter-notebooks/UNB2_notebook.ipynb b/jupyter-notebooks/UNB2_notebook.ipynb
index e140631ffc4ea0cee80e2374ec6b5f1289dbba24..d95aebef21b589d381ac137874282eaf579b8776 100644
--- a/jupyter-notebooks/UNB2_notebook.ipynb
+++ b/jupyter-notebooks/UNB2_notebook.ipynb
@@ -1,479 +1,479 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 25,
-   "id": "waiting-chance",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import time"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 26,
-   "id": "moving-alexandria",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "d=DeviceProxy(\"LTS/UNB2/1\")"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 28,
-   "id": "ranking-aluminum",
-   "metadata": {
-    "scrolled": false
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Device is now in on state\n"
-     ]
-    }
-   ],
-   "source": [
-    "state = str(d.state())\n",
-    "\n",
-    "\n",
-    "if state == \"OFF\" or state == \"FAULT\":\n",
-    "    d.initialise()\n",
-    "    time.sleep(1)\n",
-    "state = str(d.state())\n",
-    "if state == \"STANDBY\":\n",
-    "    d.on()\n",
-    "state = str(d.state())\n",
-    "if state == \"ON\":\n",
-    "    print(\"Device is now in on state\")\n",
-    "else:\n",
-    "    print(\"warning, expected device to be in on state, is: \", state)\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 29,
-   "id": "0caa8146",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "version_R *L2SS-268-LR1_2_Read_hardware_status_of_UB2c_from_SDPHW [b2db449162be8e52013dbbd1a44d6d90a12491b5]\n",
-      "UNB2_Power_ON_OFF_RW [False False]\n",
-      "UNB2_Front_Panel_LED_RW [0 0]\n",
-      "UNB2_Front_Panel_LED_R [0 0]\n",
-      "UNB2_mask_RW [False False]\n",
-      "UNB2_I2C_bus_STATUS_R [False False]\n",
-      "UNB2_EEPROM_Unique_ID_R [0 0]\n",
-      "UNB2_DC_DC_48V_12V_VIN_R [0. 0.]\n",
-      "UNB2_DC_DC_48V_12V_VOUT_R [0. 0.]\n",
-      "UNB2_DC_DC_48V_12V_IOUT_R [0. 0.]\n",
-      "UNB2_DC_DC_48V_12V_TEMP_R [0. 0.]\n",
-      "UNB2_POL_QSFP_N01_VOUT_R [0. 0.]\n",
-      "UNB2_POL_QSFP_N01_IOUT_R [0. 0.]\n",
-      "UNB2_POL_QSFP_N01_TEMP_R [0. 0.]\n",
-      "UNB2_POL_QSFP_N23_VOUT_R [0. 0.]\n",
-      "UNB2_POL_QSFP_N23_IOUT_R [0. 0.]\n",
-      "UNB2_POL_QSFP_N23_TEMP_R [0. 0.]\n",
-      "UNB2_POL_SWITCH_1V2_VOUT_R [0. 0.]\n",
-      "UNB2_POL_SWITCH_1V2_IOUT_R [0. 0.]\n",
-      "UNB2_POL_SWITCH_1V2_TEMP_R [0. 0.]\n",
-      "UNB2_POL_SWITCH_PHY_VOUT_R [0. 0.]\n",
-      "UNB2_POL_SWITCH_PHY_IOUT_R [0. 0.]\n",
-      "UNB2_POL_SWITCH_PHY_TEMP_R [0. 0.]\n",
-      "UNB2_POL_CLOCK_VOUT_R [0. 0.]\n",
-      "UNB2_POL_CLOCK_IOUT_R [0. 0.]\n",
-      "UNB2_POL_CLOCK_TEMP_R [0. 0.]\n",
-      "UNB2_FPGA_DDR4_SLOT_TEMP_R [[0. 0. 0. 0. 0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0. 0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_CORE_IOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_CORE_TEMP_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_ERAM_VOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_ERAM_IOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_ERAM_TEMP_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_RXGXB_VOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_RXGXB_IOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_RXGXB_TEMP_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_TXGXB_VOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_TXGXB_IOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_HGXB_VOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_HGXB_IOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_HGXB_TEMP_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_PGM_VOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_PGM_IOUT_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "UNB2_FPGA_POL_PGM_TEMP_R [[0. 0. 0. 0.]\n",
-      " [0. 0. 0. 0.]]\n",
-      "State <function __get_command_func.<locals>.f at 0x7f4c210e1ea0>\n",
-      "Status <function __get_command_func.<locals>.f at 0x7f4c210e1ea0>\n"
-     ]
-    }
-   ],
-   "source": [
-    "attr_names = d.get_attribute_list()\n",
-    "\n",
-    "\n",
-    "for i in attr_names:\n",
-    "    exec(\"value = print(i, d.{})\".format(i))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 30,
-   "id": "929965c2",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Old values:\n",
-      " [0 0]\n",
-      "Values to be set:\n",
-      " [1 3]\n",
-      "Values set in RW:\n",
-      " [1 3]\n",
-      "Values read back after setting:\n",
-      " [0 0]\n"
-     ]
-    }
-   ],
-   "source": [
-    "#Test the LED CP\n",
-    "led = d.UNB2_Front_Panel_LED_R\n",
-    "print(\"Old values:\\n\",  led)\n",
-    "led[0] = 1\n",
-    "led[1] = 3\n",
-    "print(\"Values to be set:\\n\", led)\n",
-    "d.UNB2_Front_Panel_LED_RW = led\n",
-    "print(\"Values set in RW:\\n\",d.UNB2_Front_Panel_LED_RW)\n",
-    "print(\"Values read back after setting:\\n\",d.UNB2_Front_Panel_LED_R)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 22,
-   "id": "6813164e",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Old values:\n",
-      " [False False]\n",
-      "Values to be set:\n",
-      " [False False]\n",
-      "Values set in RW:\n",
-      " [False False]\n"
-     ]
-    }
-   ],
-   "source": [
-    "#Test the ON OFF CP\n",
-    "onoff = d.UNB2_Power_ON_OFF_RW\n",
-    "print(\"Old values:\\n\",  onoff)\n",
-    "onoff[0] = False\n",
-    "onoff[1] = False\n",
-    "print(\"Values to be set:\\n\", onoff)\n",
-    "d.UNB2_Power_ON_OFF_RW = onoff\n",
-    "print(\"Values set in RW:\\n\",d.UNB2_Power_ON_OFF_RW)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 23,
-   "id": "e9b32ec7",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Old values:\n",
-      " [False False]\n",
-      "Values to be set:\n",
-      " [False False]\n",
-      "Values read back after setting:\n",
-      " [False False]\n"
-     ]
-    }
-   ],
-   "source": [
-    "#Test the MASK CP\n",
-    "mask = d.UNB2_mask_RW\n",
-    "print(\"Old values:\\n\",  mask)\n",
-    "mask[0] = False\n",
-    "mask[1] = False\n",
-    "print(\"Values to be set:\\n\", mask)\n",
-    "d.UNB2_mask_RW = mask\n",
-    "print(\"Values read back after setting:\\n\",d.UNB2_mask_RW)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 24,
-   "id": "transsexual-battle",
-   "metadata": {},
-   "outputs": [
-    {
-     "ename": "AttributeError",
-     "evalue": "FPGA_mask_RW",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
-      "\u001b[0;32m/tmp/ipykernel_22/2885399456.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m values = [\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_mask_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_mask_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_status_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_status_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__getattr\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m    353\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_pipe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    354\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 355\u001b[0;31m     \u001b[0msix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_from\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    356\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    357\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/six.py\u001b[0m in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n",
-      "\u001b[0;31mAttributeError\u001b[0m: FPGA_mask_RW"
-     ]
-    }
-   ],
-   "source": [
-    "values = [\n",
-    "    [d.FPGA_mask_RW, \"FPGA_mask_RW\"],\n",
-    "    [d.FPGA_scrap_R, \"FPGA_scrap_R\"],\n",
-    "    [d.FPGA_scrap_RW, \"FPGA_scrap_RW\"],\n",
-    "    [d.FPGA_status_R, \"FPGA_status_R\"],\n",
-    "    [d.FPGA_temp_R, \"FPGA_temp_R\"],\n",
-    "    [d.FPGA_version_R, \"FPGA_version_R\"],\n",
-    "    [d.FPGA_weights_R, \"FPGA_weights_R\"],\n",
-    "    [d.FPGA_weights_RW, \"FPGA_weights_RW\"],\n",
-    "    [d.TR_busy_R, \"TR_busy_R\"],\n",
-    "    [d.TR_reload_RW, \"TR_reload_RW\"],\n",
-    "    # [d.TR_tod_R, \"TR_tod_R\"],\n",
-    "    # [d.TR_uptime_R, \"TR_uptime_R\"]\n",
-    "]\n",
-    "\n",
-    "for i in values:\n",
-    "    print(\"🟦🟦🟦\", i[1], \": \", i[0])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 19,
-   "id": "b88868c5",
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
-       "       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
-       "       [1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
-       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]],\n",
-       "      dtype=float32)"
-      ]
-     },
-     "execution_count": 19,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "wgswitches = d.FPGA_wg_enable_R\n",
-    "print(\"Old values:\\n\",  wgswitches)\n",
-    "wgswitches[9][0] = True\n",
-    "wgswitches[10][0] = True\n",
-    "print(\"Values to be set:\\n\", wgswitches)\n",
-    "d.FPGA_wg_enable_RW =wgswitches\n",
-    "time.sleep(7)\n",
-    "print(\"Values read back after setting:\\n\",d.FPGA_wg_enable_R)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 18,
-   "id": "8f3db8c7",
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "array([[119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
-       "        119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
-       "        119.99817, 119.99817, 119.99817, 119.99817],\n",
-       "       [119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
-       "        119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
-       "        119.99817, 119.99817, 119.99817, 119.99817],\n",
-       "       [119.99817, 119.99817, 119.99817, 119.99817,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
-       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
-       "          0.     ,   0.     ,   0.     ,   0.     ]], dtype=float32)"
-      ]
-     },
-     "execution_count": 18,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "phases = d.FPGA_wg_phase_R\n",
-    "print(\"Old values:\\n\",  phases)\n",
-    "phases[9][0] = 1.0334\n",
-    "phases[9][1] = 20.15\n",
-    "phases[10][0] = 130\n",
-    "print(\"Values to be set:\\n\", phases)\n",
-    "d.FPGA_wg_phase_RW = phases\n",
-    "time.sleep(7)\n",
-    "print(\"Values read back after setting:\\n\", d.FPGA_wg_phase_R)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 13,
-   "id": "e45b4874",
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "array([[29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
-       "        29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
-       "        29921878., 29921878., 29921878., 29921878.],\n",
-       "       [29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
-       "        29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
-       "        29921878., 29921878., 29921878., 29921878.],\n",
-       "       [29921878., 29921878., 29921878., 29921878.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.],\n",
-       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
-       "               0.,        0.,        0.,        0.]], dtype=float32)"
-      ]
-     },
-     "execution_count": 13,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "amplitudes = d.FPGA_wg_amplitude_R\n",
-    "print(\"Old values:\\n\",  amplitudes)\n",
-    "amplitudes[9][0] = 1.0\n",
-    "amplitudes[9][1] = 1.99\n",
-    "amplitudes[10][0] = 0.5\n",
-    "print(\"Values to be set:\\n\", amplitudes)\n",
-    "d.FPGA_wg_amplitude_RW = amplitudes\n",
-    "time.sleep(7)\n",
-    "print(\"Values read back after setting:\\n\", d.FPGA_wg_amplitude_R)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "9b1bbd3e",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "frequencies = d.FPGA_wg_frequency_R\n",
-    "print(\"Old values:\\n\",  frequencies)\n",
-    "frequencies[9][0] = 19000000\n",
-    "frequencies[9][1] = 20000000\n",
-    "frequencies[10][0] = 22000000\n",
-    "print(\"Values to be set:\\n\", frequencies)\n",
-    "d.FPGA_wg_frequency_RW = frequencies\n",
-    "print(\"Values read back after setting:\\n\", d.FPGA_wg_frequency_R)"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "StationControl",
-   "language": "python",
-   "name": "stationcontrol"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.7.3"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "waiting-chance",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import time"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "moving-alexandria",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "d=DeviceProxy(\"LTS/UNB2/1\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "ranking-aluminum",
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Device is now in on state\n"
+     ]
+    }
+   ],
+   "source": [
+    "state = str(d.state())\n",
+    "\n",
+    "\n",
+    "if state == \"OFF\" or state == \"FAULT\":\n",
+    "    d.initialise()\n",
+    "    time.sleep(1)\n",
+    "state = str(d.state())\n",
+    "if state == \"STANDBY\":\n",
+    "    d.on()\n",
+    "state = str(d.state())\n",
+    "if state == \"ON\":\n",
+    "    print(\"Device is now in on state\")\n",
+    "else:\n",
+    "    print(\"warning, expected device to be in on state, is: \", state)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "id": "0caa8146",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "version_R *L2SS-268-LR1_2_Read_hardware_status_of_UB2c_from_SDPHW [b2db449162be8e52013dbbd1a44d6d90a12491b5]\n",
+      "UNB2_Power_ON_OFF_RW [False False]\n",
+      "UNB2_Front_Panel_LED_RW [0 0]\n",
+      "UNB2_Front_Panel_LED_R [0 0]\n",
+      "UNB2_mask_RW [False False]\n",
+      "UNB2_I2C_bus_STATUS_R [False False]\n",
+      "UNB2_EEPROM_Unique_ID_R [0 0]\n",
+      "UNB2_DC_DC_48V_12V_VIN_R [0. 0.]\n",
+      "UNB2_DC_DC_48V_12V_VOUT_R [0. 0.]\n",
+      "UNB2_DC_DC_48V_12V_IOUT_R [0. 0.]\n",
+      "UNB2_DC_DC_48V_12V_TEMP_R [0. 0.]\n",
+      "UNB2_POL_QSFP_N01_VOUT_R [0. 0.]\n",
+      "UNB2_POL_QSFP_N01_IOUT_R [0. 0.]\n",
+      "UNB2_POL_QSFP_N01_TEMP_R [0. 0.]\n",
+      "UNB2_POL_QSFP_N23_VOUT_R [0. 0.]\n",
+      "UNB2_POL_QSFP_N23_IOUT_R [0. 0.]\n",
+      "UNB2_POL_QSFP_N23_TEMP_R [0. 0.]\n",
+      "UNB2_POL_SWITCH_1V2_VOUT_R [0. 0.]\n",
+      "UNB2_POL_SWITCH_1V2_IOUT_R [0. 0.]\n",
+      "UNB2_POL_SWITCH_1V2_TEMP_R [0. 0.]\n",
+      "UNB2_POL_SWITCH_PHY_VOUT_R [0. 0.]\n",
+      "UNB2_POL_SWITCH_PHY_IOUT_R [0. 0.]\n",
+      "UNB2_POL_SWITCH_PHY_TEMP_R [0. 0.]\n",
+      "UNB2_POL_CLOCK_VOUT_R [0. 0.]\n",
+      "UNB2_POL_CLOCK_IOUT_R [0. 0.]\n",
+      "UNB2_POL_CLOCK_TEMP_R [0. 0.]\n",
+      "UNB2_FPGA_DDR4_SLOT_TEMP_R [[0. 0. 0. 0. 0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0. 0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_CORE_IOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_CORE_TEMP_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_ERAM_VOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_ERAM_IOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_ERAM_TEMP_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_RXGXB_VOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_RXGXB_IOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_RXGXB_TEMP_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_TXGXB_VOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_TXGXB_IOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_HGXB_VOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_HGXB_IOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_HGXB_TEMP_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_PGM_VOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_PGM_IOUT_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "UNB2_FPGA_POL_PGM_TEMP_R [[0. 0. 0. 0.]\n",
+      " [0. 0. 0. 0.]]\n",
+      "State <function __get_command_func.<locals>.f at 0x7f4c210e1ea0>\n",
+      "Status <function __get_command_func.<locals>.f at 0x7f4c210e1ea0>\n"
+     ]
+    }
+   ],
+   "source": [
+    "attr_names = d.get_attribute_list()\n",
+    "\n",
+    "\n",
+    "for i in attr_names:\n",
+    "    exec(\"value = print(i, d.{})\".format(i))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "929965c2",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Old values:\n",
+      " [0 0]\n",
+      "Values to be set:\n",
+      " [1 3]\n",
+      "Values set in RW:\n",
+      " [1 3]\n",
+      "Values read back after setting:\n",
+      " [0 0]\n"
+     ]
+    }
+   ],
+   "source": [
+    "#Test the LED CP\n",
+    "led = d.UNB2_Front_Panel_LED_R\n",
+    "print(\"Old values:\\n\",  led)\n",
+    "led[0] = 1\n",
+    "led[1] = 3\n",
+    "print(\"Values to be set:\\n\", led)\n",
+    "d.UNB2_Front_Panel_LED_RW = led\n",
+    "print(\"Values set in RW:\\n\",d.UNB2_Front_Panel_LED_RW)\n",
+    "print(\"Values read back after setting:\\n\",d.UNB2_Front_Panel_LED_R)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "id": "6813164e",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Old values:\n",
+      " [False False]\n",
+      "Values to be set:\n",
+      " [False False]\n",
+      "Values set in RW:\n",
+      " [False False]\n"
+     ]
+    }
+   ],
+   "source": [
+    "#Test the ON OFF CP\n",
+    "onoff = d.UNB2_Power_ON_OFF_RW\n",
+    "print(\"Old values:\\n\",  onoff)\n",
+    "onoff[0] = False\n",
+    "onoff[1] = False\n",
+    "print(\"Values to be set:\\n\", onoff)\n",
+    "d.UNB2_Power_ON_OFF_RW = onoff\n",
+    "print(\"Values set in RW:\\n\",d.UNB2_Power_ON_OFF_RW)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "id": "e9b32ec7",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Old values:\n",
+      " [False False]\n",
+      "Values to be set:\n",
+      " [False False]\n",
+      "Values read back after setting:\n",
+      " [False False]\n"
+     ]
+    }
+   ],
+   "source": [
+    "#Test the MASK CP\n",
+    "mask = d.UNB2_mask_RW\n",
+    "print(\"Old values:\\n\",  mask)\n",
+    "mask[0] = False\n",
+    "mask[1] = False\n",
+    "print(\"Values to be set:\\n\", mask)\n",
+    "d.UNB2_mask_RW = mask\n",
+    "print(\"Values read back after setting:\\n\",d.UNB2_mask_RW)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "id": "transsexual-battle",
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "AttributeError",
+     "evalue": "FPGA_mask_RW",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
+      "\u001b[0;32m/tmp/ipykernel_22/2885399456.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m values = [\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_mask_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_mask_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_status_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_status_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__getattr\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m    353\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_pipe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    354\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 355\u001b[0;31m     \u001b[0msix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_from\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    356\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    357\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/six.py\u001b[0m in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n",
+      "\u001b[0;31mAttributeError\u001b[0m: FPGA_mask_RW"
+     ]
+    }
+   ],
+   "source": [
+    "values = [\n",
+    "    [d.FPGA_mask_RW, \"FPGA_mask_RW\"],\n",
+    "    [d.FPGA_scrap_R, \"FPGA_scrap_R\"],\n",
+    "    [d.FPGA_scrap_RW, \"FPGA_scrap_RW\"],\n",
+    "    [d.FPGA_status_R, \"FPGA_status_R\"],\n",
+    "    [d.FPGA_temp_R, \"FPGA_temp_R\"],\n",
+    "    [d.FPGA_version_R, \"FPGA_version_R\"],\n",
+    "    [d.FPGA_weights_R, \"FPGA_weights_R\"],\n",
+    "    [d.FPGA_weights_RW, \"FPGA_weights_RW\"],\n",
+    "    [d.TR_busy_R, \"TR_busy_R\"],\n",
+    "    [d.TR_reload_RW, \"TR_reload_RW\"],\n",
+    "    # [d.TR_tod_R, \"TR_tod_R\"],\n",
+    "    # [d.TR_uptime_R, \"TR_uptime_R\"]\n",
+    "]\n",
+    "\n",
+    "for i in values:\n",
+    "    print(\"🟦🟦🟦\", i[1], \": \", i[0])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "b88868c5",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
+       "       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
+       "       [1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
+       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]],\n",
+       "      dtype=float32)"
+      ]
+     },
+     "execution_count": 19,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "wgswitches = d.FPGA_wg_enable_R\n",
+    "print(\"Old values:\\n\",  wgswitches)\n",
+    "wgswitches[9][0] = True\n",
+    "wgswitches[10][0] = True\n",
+    "print(\"Values to be set:\\n\", wgswitches)\n",
+    "d.FPGA_wg_enable_RW =wgswitches\n",
+    "time.sleep(7)\n",
+    "print(\"Values read back after setting:\\n\",d.FPGA_wg_enable_R)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "id": "8f3db8c7",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "array([[119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
+       "        119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
+       "        119.99817, 119.99817, 119.99817, 119.99817],\n",
+       "       [119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
+       "        119.99817, 119.99817, 119.99817, 119.99817, 119.99817, 119.99817,\n",
+       "        119.99817, 119.99817, 119.99817, 119.99817],\n",
+       "       [119.99817, 119.99817, 119.99817, 119.99817,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ],\n",
+       "       [  0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ,   0.     ,   0.     ,\n",
+       "          0.     ,   0.     ,   0.     ,   0.     ]], dtype=float32)"
+      ]
+     },
+     "execution_count": 18,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "phases = d.FPGA_wg_phase_R\n",
+    "print(\"Old values:\\n\",  phases)\n",
+    "phases[9][0] = 1.0334\n",
+    "phases[9][1] = 20.15\n",
+    "phases[10][0] = 130\n",
+    "print(\"Values to be set:\\n\", phases)\n",
+    "d.FPGA_wg_phase_RW = phases\n",
+    "time.sleep(7)\n",
+    "print(\"Values read back after setting:\\n\", d.FPGA_wg_phase_R)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "e45b4874",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "array([[29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
+       "        29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
+       "        29921878., 29921878., 29921878., 29921878.],\n",
+       "       [29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
+       "        29921878., 29921878., 29921878., 29921878., 29921878., 29921878.,\n",
+       "        29921878., 29921878., 29921878., 29921878.],\n",
+       "       [29921878., 29921878., 29921878., 29921878.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.],\n",
+       "       [       0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.,        0.,        0.,\n",
+       "               0.,        0.,        0.,        0.]], dtype=float32)"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "amplitudes = d.FPGA_wg_amplitude_R\n",
+    "print(\"Old values:\\n\",  amplitudes)\n",
+    "amplitudes[9][0] = 1.0\n",
+    "amplitudes[9][1] = 1.99\n",
+    "amplitudes[10][0] = 0.5\n",
+    "print(\"Values to be set:\\n\", amplitudes)\n",
+    "d.FPGA_wg_amplitude_RW = amplitudes\n",
+    "time.sleep(7)\n",
+    "print(\"Values read back after setting:\\n\", d.FPGA_wg_amplitude_R)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9b1bbd3e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "frequencies = d.FPGA_wg_frequency_R\n",
+    "print(\"Old values:\\n\",  frequencies)\n",
+    "frequencies[9][0] = 19000000\n",
+    "frequencies[9][1] = 20000000\n",
+    "frequencies[10][0] = 22000000\n",
+    "print(\"Values to be set:\\n\", frequencies)\n",
+    "d.FPGA_wg_frequency_RW = frequencies\n",
+    "print(\"Values read back after setting:\\n\", d.FPGA_wg_frequency_R)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "StationControl",
+   "language": "python",
+   "name": "stationcontrol"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.7.3"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh
index 9d9ec12ae79a2336d5bfd88191930f8c6fa9db36..2175f2774e771ac31e9dcd1cb1ade68da51f923e 100755
--- a/sbin/run_integration_test.sh
+++ b/sbin/run_integration_test.sh
@@ -1,27 +1,27 @@
 #!/bin/bash -e
 
-if [ -z "$LOFA20_DIR"]; then
+if [ -z "$LOFAR20_DIR" ]; then
     # We assume we aren't in the PATH, so we can derive our path.
     # We need our parent directory.
-    LOFAR20_DIR_RELATIVE=`dirname "$0"`/..
+    LOFAR20_DIR_RELATIVE=$(dirname "$0")/..
 
     # As an absolute path
-    LOFAR20_DIR=`readlink -f "${LOFAR20_DIR_RELATIVE}"`
+    LOFAR20_DIR=$(readlink -f "${LOFAR20_DIR_RELATIVE}")
 fi
 
 # Start and stop sequence
 cd "$LOFAR20_DIR/docker-compose" || exit 1
-make stop device-sdp device-recv device-sst device-unb2 device-xst sdptr-sim recv-sim unb2-sim
+make stop device-sdp device-recv device-sst device-unb2 device-xst sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim
 make start databaseds dsconfig jupyter elk
 
 # Give dsconfig and databaseds time to start
 sleep 15
 
 # Update the dsconfig
-${LOFAR20_DIR}/sbin/update_ConfigDb.sh ${LOFAR20_DIR}/CDB/integration_ConfigDb.json
+"${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/integration_ConfigDb.json
 
 cd "$LOFAR20_DIR/docker-compose" || exit 1
-make start sdptr-sim recv-sim unb2-sim
+make start sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim
 
 # Give the simulators time to start
 sleep 5
diff --git a/sbin/tag_and_push_docker_image.sh b/sbin/tag_and_push_docker_image.sh
index ad94ae4b2ca6418e0d89347d4b37b47ef1a16a5a..799ab1cd779bb5caf840685f339080b57916063b 100755
--- a/sbin/tag_and_push_docker_image.sh
+++ b/sbin/tag_and_push_docker_image.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env bash -e
+#!/bin/bash -e
 
 # Tag and push which image version?
 DOCKER_TAG=latest
@@ -10,16 +10,16 @@ SKA_REPO="nexus.engageska-portugal.pt/ska-docker"
 LOFAR_REPO="git.astron.nl:5000/lofar2.0/tango"
 
 # Compile a list of the SKA images
-SKA_IMAGES=$(for i in $(docker images | egrep ${DOCKER_TAG} | egrep ${SKA_REPO} | cut -d' ' -f1); do printf "%s " ${i}; done)
+SKA_IMAGES=$(for i in $(docker images | grep -E ${DOCKER_TAG} | grep -E ${SKA_REPO} | cut -d' ' -f1); do printf "%s " "${i}"; done)
 
 # Compile a list of LOFAR2.0 images
-LOFAR_IMAGES=$(for i in $(docker images | egrep ${DOCKER_TAG} | egrep -v "${SKA_REPO}|${LOFAR_REPO}" | cut -d' ' -f1); do printf "%s " ${i}; done)
+LOFAR_IMAGES=$(for i in $(docker images | grep -E ${DOCKER_TAG} | grep -E -v "${SKA_REPO}|${LOFAR_REPO}" | cut -d' ' -f1); do printf "%s " "${i}"; done)
 
 function tag_and_push()
 {
     (
-        docker tag ${1} ${2}
-        docker push ${2}
+        docker tag "${1}" "${2}"
+        docker push "${2}"
     ) &
 }
 
@@ -27,14 +27,14 @@ function tag_and_push()
 # and push them to the LOFAR2.0 repo
 for IMAGE in ${SKA_IMAGES}; do
     PUSH_IMAGE=${IMAGE//${SKA_REPO}/${LOFAR_REPO}}:${VERSION}
-    tag_and_push ${IMAGE} ${PUSH_IMAGE}
+    tag_and_push "${IMAGE}" "${PUSH_IMAGE}"
 done
 
 # Rename the LOFAR2.0 images for the LOFAR2.0 repo
 # and push them to the LOFAR2.0 repo
 for IMAGE in ${LOFAR_IMAGES}; do
-    PUSH_IMAGES=${LOFAR_REPO}/${IMAGE}:${VERSIN}
-    tag_and_push ${IMAGE} ${PUSH_IMAGE}
+    PUSH_IMAGE=${LOFAR_REPO}/${IMAGE}:${VERSION}
+    tag_and_push "${IMAGE}" "${PUSH_IMAGE}"
 done
 
 wait