diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 71fc65f375ad40e2ae137cc52673e7b1f1040957..ff325354dd075c64c76301d9e900d687e457dea7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -330,45 +330,6 @@ release_job:
     tag_name: '$CI_COMMIT_TAG'
     description: '$CI_COMMIT_TAG'
 
-.base_deploy:
-  stage: deploy
-  image: ubuntu:bionic
-  when: manual
-  rules:
-    - if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH) || $CI_COMMIT_TAG
-  before_script:
-    - apt-get update
-    - apt-get install ansible openssh-client -y
-    # Use Gitlab protected variable to provide key
-    - echo "$DEPLOY_KEY" > id_rsa
-    - chmod 400 id_rsa
-    - ssh-keygen -y -f id_rsa > id_rsa.pub
-    # Add ssh key to agent
-    - eval $(ssh-agent)
-    - ssh-add id_rsa
-    - ansible --version
-  script:
-    - echo "Deploying version $CI_COMMIT_TAG"
-    - cd deploy
-    # Prevent error of ansible being run in world writeable directory
-    - chmod o-w .
-    # Generate hosts file for deployment
-    - echo "[all]" > hosts
-    - echo "stat ansible_host=$DEPLOY_HOST ansible_user=$DEPLOY_USER" >> hosts
-    # Run deployment with populated variables
-    - ansible-playbook -v deploy.yml --extra-vars station_version=$CI_COMMIT_TAG --extra-vars station_config=$DEPLOY_CONFIG
-.deploy_l2ts_base:
-  extends: .base_deploy
-  variables:
-    DEPLOY_USER: $L2TS_USERNAME
-    DEPLOY_HOST: $L2TS_HOSTNAME
-    DEPLOY_CONFIG: $L2TS_CONFIG
-    DEPLOY_KEY: $L2TS_DEPLOY_KEY
-deploy_l2ts_start:
-  extends: .deploy_l2ts_base
-  environment:
-    name: l2ts
-
 deploy_nomad:
   stage: deploy
   image:
diff --git a/README.md b/README.md
index 14db1df8fbbd0570e39707cae7c87ef1ae216683..3e697d952c0f1a624b1243d87ecfa5163d7d6773 100644
--- a/README.md
+++ b/README.md
@@ -134,6 +134,7 @@ Next change the version in the following places:
 
 # Release Notes
 
+* 0.22.0 Migrate execution environment to nomad
 * 0.21.1 Implement multi project integration downstream pipeline
 * 0.21.0 Use radians instead of degrees when interpreting pointings
 * 0.20.5 Manage both polarisations in RCU_band_select_R(W), Antenna_Loss_R, and Frequency_Band_RW
diff --git a/deploy/README.md b/deploy/README.md
deleted file mode 100644
index 5f49ffc5c340dacf671e607f55c36f68f4db774a..0000000000000000000000000000000000000000
--- a/deploy/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Deployments
-
-Deploying is achieved through gitlab environments as well as ansible.
-Concretely the following files are involved:
-
-1. [deploy.yml](deploy.yml)
-2. [ansible.cfg](ansible.cfg)
-3. [.gitlab-ci.yml](../.gitlab-ci.yml)
-
-Once a tagged commit hits master a job is created for this tag that needs to
-be manually triggered. You should be able to find this pipeline on the
-[tags overview](https://git.astron.nl/lofar2.0/tango/-/tags).
-
-From here, with prior consent, the deployment can be started for any
-environment.
-
-The gitlab-ci.yml job defines each of the environments in parameterized way.
-The templated `.base_deploy` needs to be extended and have several variables
-defined. These variables need to be fed from
-[protected variables](https://git.astron.nl/lofar2.0/tango/-/settings/ci_cd)
-within gitlab.
-
-Below is a practical example of how to define an environment.
-
-```
-.deploy_example_base:
-  extends: .base_deploy
-  variables:
-    DEPLOY_USER: $EXAMPLE_USERNAME
-    DEPLOY_HOST: $EXAMPLE_HOSTNAME
-    DEPLOY_CONFIG: $EXAMPLE_CONFIG
-    DEPLOY_KEY: $EXAMPLE_KEY
-deploy_l2ts_start:
-  extends: .deploy_example_base
-  environment:
-    name: example
-```
-
-Such an environment will only appear in the
-[environments overview](https://git.astron.nl/lofar2.0/tango/-/environments)
-after the first deployment.
-
-The process of this deployment is handled through ansible as found in
-`deploy.yml`.
diff --git a/deploy/ansible.cfg b/deploy/ansible.cfg
deleted file mode 100644
index 8da5e9439f11320c5e90d51bbe6ad7d7f8d9798c..0000000000000000000000000000000000000000
--- a/deploy/ansible.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[defaults]
-host_key_checking = False
-inventory = hosts
diff --git a/deploy/deploy.yml b/deploy/deploy.yml
deleted file mode 100644
index 455c9da59ea78e724dc448e476df8fffa0ff6522..0000000000000000000000000000000000000000
--- a/deploy/deploy.yml
+++ /dev/null
@@ -1,106 +0,0 @@
----
-- name: StationControl Early Deployment
-  hosts: all
-  vars:
-    base_station_config: "LOFAR_ConfigDb.json"
-    install_path: ~/git/tango
-    databaseds_port: 10000
-  tasks:
-     - name: Check make installed
-       include_tasks:
-         file: tasks/check_binary_install.yml
-       vars:
-         program: make
-     - name: Check git installed
-       include_tasks:
-         file: tasks/check_binary_install.yml
-       vars:
-         program: git
-     - name: Register tango directory status
-       shell: cd {{ install_path }}
-       args:
-         chdir: ~
-       changed_when: false
-       failed_when: tango_directory.rc not in [0,1]
-       register: tango_directory
-     - name: Register pending changes
-       shell: "! (git status | grep Changes)"
-       args:
-         chdir: "{{ install_path }}"
-       changed_when: false
-       failed_when: pending_changes.rc not in [0,1]
-       register: pending_changes
-# Several issues with this variable being unset in ansible 2.2
-# where encountered, keep debug in case needed
-     - debug: var=pending_changes
-     - name: Check tango directory status
-       fail:
-         msg: "Tango directory appears to be missing!"
-       when: tango_directory.rc not in [0]
-     - name: Check pending changes
-       fail:
-         msg: "Deployment repository seems to have pending changes!"
-       when: pending_changes.rc not in [0]
-     - name: Stop Current Station
-       changed_when: false
-       shell: "make stop"
-       args:
-         chdir: "{{ install_path }}/docker-compose"
-     - name: Git Fetch All
-       changed_when: false
-       shell: "git fetch --all"
-       args:
-         chdir: "{{ install_path }}"
-     - name: Update Sources
-       changed_when: false
-       shell: "git checkout {{ station_version }}"
-       args:
-         chdir: "{{ install_path }}"
-     - name: Pull Images
-       changed_when: false
-       shell: "make pull"
-       args:
-         chdir: "{{ install_path }}/docker-compose"
-     - name: Build Images
-       changed_when: false
-       shell: "make build"
-       args:
-         chdir: "{{ install_path }}/docker-compose"
-     - name: Start Database
-       changed_when: false
-       shell: "make minimal"
-       args:
-         chdir: "{{ install_path }}/docker-compose"
-     - name: Wait for databaseds
-       ansible.builtin.wait_for:
-         port: "{{ databaseds_port }}"
-         delay: 10
-     - name: Update Base Database Config
-       include_tasks:
-         file: tasks/update_database_config.yml
-       vars:
-         database_config: "{{ base_station_config }}"
-         base_path: "{{ install_path }}"
-     - name: Verify Base Database Config
-       include_tasks:
-         file: tasks/verify_database_config.yml
-       vars:
-         database_config: "{{ base_station_config }}"
-         base_path: "{{ install_path }}"
-     - name: Update Station Database Config
-       include_tasks:
-         file: tasks/update_database_config.yml
-       vars:
-         database_config: "stations/{{ station_config }}"
-         base_path: "{{ install_path }}"
-     - name: Verify Station Database Config
-       include_tasks:
-         file: tasks/verify_database_config.yml
-       vars:
-         database_config: "stations/{{ station_config }}"
-         base_path: "{{ install_path }}"
-     - name: Start Station
-       changed_when: false
-       shell: "make start"
-       args:
-         chdir: "{{ install_path }}/docker-compose"
diff --git a/deploy/tasks/check_binary_install.yml b/deploy/tasks/check_binary_install.yml
deleted file mode 100644
index f114fd87e7b7bd25d7f6b848b25c32aa9324efa2..0000000000000000000000000000000000000000
--- a/deploy/tasks/check_binary_install.yml
+++ /dev/null
@@ -1,9 +0,0 @@
- - name: Register installation status
-   command: which {{ program }}
-   changed_when: false
-   failed_when: installed.rc not in [0,1]
-   register: installed
- - name: Check installation status
-   fail:
-     msg: "{{ program }} does not appear to be installed!"
-   when: installed.rc not in [0]
\ No newline at end of file
diff --git a/deploy/tasks/update_database_config.yml b/deploy/tasks/update_database_config.yml
deleted file mode 100644
index ad60bcf8c9bec3ae6ec7777e7a2ef225c67f50e3..0000000000000000000000000000000000000000
--- a/deploy/tasks/update_database_config.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-- name: Update Database Config
-  changed_when: false
-  shell: "./sbin/dsconfig.sh --load CDB/{{ database_config }}"
-  args:
-    chdir: "{{ base_path }}"
diff --git a/deploy/tasks/verify_database_config.yml b/deploy/tasks/verify_database_config.yml
deleted file mode 100644
index 52eb71aca090abf9a7af4797282aa1831413f791..0000000000000000000000000000000000000000
--- a/deploy/tasks/verify_database_config.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-- name: Get Database Config
-  changed_when: false
-  shell: "./sbin/dsconfig.sh --load CDB/{{ database_config }} 2>&1"
-  register: dsconfig_result
-  args:
-    chdir: "{{ base_path }}"
-- name: Verify Database Config
-  when: '"No changes needed" in dsconfig_result.stdout'
-  debug: msg="Database changes stored"
diff --git a/docker-compose/Makefile b/docker-compose/Makefile
index 9e14471e9494eb60cce688ee32b392a899d7b8f0..5950a98ec596424a22a235f92a7dda6d22f0ffd7 100644
--- a/docker-compose/Makefile
+++ b/docker-compose/Makefile
@@ -13,10 +13,11 @@ DOCKER_COMPOSE ?= docker compose
 DOCKER_COMPOSE_ENV_FILE := $(abspath .env)
 COMPOSE_FILES := $(wildcard *.yml)
 ATTACH_COMPOSE_FILE_ARGS := $(foreach yml,$(filter-out tango.yml,$(COMPOSE_FILES)),-f $(yml))
+BUILD_ONLY_FILE_ARGS := -f tango.yml
 COMPOSE_FILE_ARGS := --env-file $(DOCKER_COMPOSE_ENV_FILE) $(ATTACH_COMPOSE_FILE_ARGS)
 
 
-# The default Docker network mode is tangonet.  The "host" network
+# The default Docker network mode is station.  The "host" network
 # mode will make the tangodb and archiverdb ports clash,
 # But we allow to overwrite it.
 NETWORK_MODE ?= station
@@ -178,15 +179,15 @@ ifneq ($(NO_BASE),1)
 endif
 
 base-nocache: context ## Rebuild base lofar device image
-	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) build --no-cache --progress=plain lofar-device-base
+	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) $(BUILD_ONLY_FILE_ARGS) build --no-cache --progress=plain lofar-device-base
 
 build: base ## build images
 	# docker-compose does not support build dependencies, so manage those here
-	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) -f tango.yml build --parallel --progress=plain $(SERVICE)
+	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) $(BUILD_ONLY_FILE_ARGS) build --parallel --progress=plain $(SERVICE)
 
 build-nocache: base-nocache ## rebuild images from scratch
 	# docker-compose does not support build dependencies, so manage those here
-	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) -f tango.yml build --no-cache --progress=plain $(SERVICE)
+	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) $(BUILD_ONLY_FILE_ARGS) build --no-cache --progress=plain $(SERVICE)
 
 up: base minimal  ## start the base TANGO system and prepare requested services
 	$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) up --no-start --no-recreate $(SERVICE)
diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh
index 967d0947c492b21b212eae7246457a3e0df5db01..05019444099176022c707fbc56e88de950195793 100755
--- a/sbin/run_integration_test.sh
+++ b/sbin/run_integration_test.sh
@@ -4,6 +4,9 @@
 # SPDX-License-Identifier: Apache-2.0
 #
 
+# Url to the jumppad download location
+jumppad_download="https://git.astron.nl/lofar2.0/tango/-/package_files/37347/download"
+
 # Usage function explains how parameters are parsed
 function usage {
     echo "./$(basename "$0")
@@ -96,7 +99,7 @@ docker network rm station || true
 if ! [ -x "$(command -v jumppad)" ]; then
   echo 'Install jumppad'
   mkdir -p ./.bin
-  wget https://git.astron.nl/lofar2.0/tango/-/package_files/37347/download -O ./.bin/jumppad
+  wget "${jumppad_download}" -O ./.bin/jumppad
   chmod +x ./.bin/jumppad
   bin_dir=$(realpath ./.bin)
   PATH="$PATH:$bin_dir"
diff --git a/sbin/run_integration_test.sh.orig b/sbin/run_integration_test.sh.orig
deleted file mode 100755
index e6e82dc50dbb5b93bc763bc20882168667271288..0000000000000000000000000000000000000000
--- a/sbin/run_integration_test.sh.orig
+++ /dev/null
@@ -1,243 +0,0 @@
-#!/bin/bash -e
-#
-# Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy)
-# SPDX-License-Identifier: Apache-2.0
-#
-
-# Usage function explains how parameters are parsed
-function usage {
-    echo "./$(basename "$0")
-      no arguments, builds and configures all docker containers and starts each
-      stage of the integration test one after the other. Between each stage the
-      dsconfig is updated accordingly."
-    echo ""
-    echo "./$(basename "$0") -h --help
-      displays this help message"
-    echo ""
-    echo "./$(basename "$0") --no-build
-      disables building of docker images"
-}
-
-# Configure the config database, restart containers and run a specific
-# integration module or even specific tests
-# integration_test module restarted_containers config_files specific_test
-function integration_test {
-  IFS=" " read -r -a restarts <<< "${2}"
-  IFS=" " read -r -a configs <<< "${3}"
-  for config in "${configs[@]}"; do
-    echo "Updating config ${config} ..."
-    bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${config}"
-  done
-  if [ -n "${2+x}" ]; then
-    # shellcheck disable=SC2145
-    echo "make restart ${restarts[@]} ..."
-    make restart "${restarts[@]}"
-    # shellcheck disable=SC2145
-    echo "make await ${restarts[@]} ..."
-    make await "${restarts[@]}"
-  fi
-
-  echo "make integration ${1} ..."
-  make integration "${1}"
-}
-
-# list of arguments expected in the input
-optstring_long="help,no-build,preserve,save-logs"
-optstring="hnb"
-
-options=$(getopt -l ${optstring_long} -o ${optstring} -- "$@")
-
-eval set -- "$options"
-
-while true; do
-  case ${1} in
-    -h|--help)
-      usage
-      exit 0
-      ;;
-    --no-build)
-      echo "Disable docker compose build step"
-      export no_build=1
-      export NO_BASE=${no_build}
-      ;;
-    --preserve)
-      echo "Preserve test environment"
-      export preserve=1
-      ;;
-    --save-logs)
-      echo "Save logs after execution"
-      export save_logs=1
-      ;;
-    --)
-    shift
-    break;;
-  esac
-  shift
-done
-
-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")/..
-
-    # As an absolute path
-    LOFAR20_DIR=$(readlink -f "${LOFAR20_DIR_RELATIVE}")
-fi
-
-<<<<<<< HEAD
-if [ -z "$TAG" ]; then
-  TAG="latest"
-fi
-
-[ -n "${no_build}" ] || make build dsconfig
-
-docker network rm station || true
-
-if ! [ -x "$(command -v jumppad)" ]; then
-  echo 'Install jumppad'
-  mkdir -p ./.bin
-  wget https://git.astron.nl/lofar2.0/tango/-/package_files/37347/download -O ./.bin/jumppad
-  chmod +x ./.bin/jumppad
-  bin_dir=$(realpath ./.bin)
-  PATH="$PATH:$bin_dir"
-fi
-
-make -C infra/jobs/station DIR_OUT="$( realpath "infra/dev/jobs/station")" render
-
-# prepare a docker volume for nomad
-tmp_volume="test_$(hexdump -n 16 -v -e '/1 "%02X"' /dev/urandom)"
-
-function cleanup {
-  cd "$LOFAR20_DIR"
-  if [ -n "${save_logs}" ]; then
-    mkdir -p log
-    for container in $(docker ps -a --format "{{.Names}}")
-    do
-      echo "Saving log for container $container"
-      docker logs "${container}" >& "log/${container}.log"
-    done
-    bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --dump >& log/dump_ConfigDb.log
-  fi
-  if [ -z "${preserve}" ]; then
-    make stop > /dev/null 2>&1
-    HOME="$JUMPPAD_HOME" jumppad down infra/dev
-    docker volume rm "$tmp_volume" || true
-  fi
-}
-
-trap cleanup EXIT
-
-docker volume create "$tmp_volume"
-
-docker pull -q bash
-docker run -i --rm -v "$tmp_volume":/mnt bash bash -c 'mkdir -p /mnt/volumes/tango-database'
-
-rm -rf ~/.jumppad/
-
-if [ -z "$JUMPPAD_HOME" ]; then
-  JUMPPAD_HOME="$HOME"
-fi
-
-HOME="$JUMPPAD_HOME" jumppad up --var="host_volume=$tmp_volume" infra/dev || true
-
-echo -n "Waiting for tango service to become available .."
-until [[ $(dig @127.0.0.1 -p 8600 tango.service.consul +short) ]]; do
-  sleep 2
-  echo -n "."
-done
-echo ". [ok]"
-
-TANGO_PORT=$(dig @127.0.0.1 -p 8600 tango.service.consul SRV +short  | awk '{printf "%s",$3}')
-TANGO_HOST=$(dig @127.0.0.1 -p 8600 tango.service.consul +short)
-
-export TANGO_HOST="$TANGO_HOST:$TANGO_PORT"
-
-export HOSTNAME=192.168.123.1
-export DNS=192.168.123.100
-
-echo "Using tango host $TANGO_HOST"
-
-cd "$LOFAR20_DIR/docker-compose" || exit 1
-
-=======
-export TANGO_SKIP_BUILD=1
-
-cd "$LOFAR20_DIR/docker-compose" || exit 1
-
-# Start the database server first, `-z ${y+x}` is the inverse of `-n ${y}`
-if [ -z "${no_build+x}" ]; then
-    rm -rf "${LOFAR20_DIR}/tangostationcontrol/dist"
-    cd "${LOFAR20_DIR}/tangostationcontrol" || exit 1
-    tox -e build
-    cd "$LOFAR20_DIR/docker-compose" || exit 1
-    make build databaseds dsconfig
-fi
-
-make start databaseds dsconfig
-
-# Give dsconfig and databaseds time to start
-sleep 5 # dsconfig container must be up and running...
-# shellcheck disable=SC2016
-echo '/usr/local/bin/wait-for-it.sh ${TANGO_HOST} --strict --timeout=300 -- true' | make run dsconfig bash -
-
->>>>>>> master
-# Devices list is used to explitly word split when supplied to commands, must
-# disable shellcheck SC2086 for each case.
-DEVICES=(device-station-manager device-boot device-aps device-apsct device-ccd device-ec device-apspu device-sdpfirmware device-sdp device-recvh device-recvl device-bst device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-psoc device-pcon device-antennafield device-temperature-manager device-observation-control device-configuration device-calibration)
-
-SIMULATORS=(sdptr-sim recvh-sim recvl-sim unb2-sim apsct-sim apspu-sim ccd-sim ec-sim)
-
-# Build only the required images, please do not build everything that makes CI
-# take really long to finish, especially grafana / jupyter / prometheus.
-# jupyter is physically large > 2.5gb and overlayfs is really slow.
-
-[ -n "${no_build}" ] || make build "${SIMULATORS[@]}"
-[ -n "${no_build}" ] || make build logstash integration-test http-json-schemas
-
-# Start and stop sequence
-make stop http-json-schemas
-make stop object-storage init-object-storage
-make stop "${DEVICES[@]}" "${SIMULATORS[@]}"
-make stop device-docker # this one does not test well in docker-in-docker
-make stop logstash
-
-make start logstash http-json-schemas object-storage init-object-storage
-
-# Update the dsconfig
-# Do not remove `bash`, otherwise statement ignored by gitlab ci shell!
-docker pull -q "git.astron.nl:5000/lofar2.0/tango/dsconfig:$TAG"
-
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --load "${LOFAR20_DIR}"/CDB/stations/common.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/l0.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/l1.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/lba.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/h0.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/hba_core.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/cs001.json
-bash "${LOFAR20_DIR}"/sbin/dsconfig.sh --update "${LOFAR20_DIR}"/CDB/stations/testenv_cs001.json
-
-cd "$LOFAR20_DIR/docker-compose" || exit 1
-make start "${SIMULATORS[@]}"
-
-# Give the simulators time to start
-sleep 5
-
-# shellcheck disable=SC2086
-make start "${DEVICES[@]}"
-
-# Wait for devices to restart
-make await "${DEVICES[@]}"
-
-# Start the integration test
-cd "$LOFAR20_DIR/docker-compose" || exit 1
-make up integration-test
-
-integration_test default
-
-integration_test tilebeam_performance "device-sdpfirmware device-sdp device-recvh device-recvl device-tilebeam device-antennafield" "${LOFAR20_DIR}/CDB/integrations/tilebeam_cluster_ConfigDb.json"
-
-integration_test digitalbeam_performance "device-sdpfirmware device-sdp device-recvh device-recvl device-digitalbeam device-beamlet device-antennafield" "${LOFAR20_DIR}/CDB/integrations/digitalbeam_cluster_ConfigDb.json"
-
-integration_test configuration "device-configuration"
-
-make restart "${DEVICES[@]}"
diff --git a/tangostationcontrol/VERSION b/tangostationcontrol/VERSION
index a67cebaf7ff61ccbf2741283f4341147d2fadae8..2157409059873c80aa93884ecb847639add77b7a 100644
--- a/tangostationcontrol/VERSION
+++ b/tangostationcontrol/VERSION
@@ -1 +1 @@
-0.21.1
+0.22.0
diff --git a/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py b/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py
index f4ef6ea42fa61fd7dbc470d64794cc6afca4c2bf..e982221b82f8d37b730fee52121c76ad55a8e68d 100644
--- a/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py
+++ b/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py
@@ -25,9 +25,9 @@ logger = logging.getLogger()
 class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
     antenna_qualities_ok = numpy.array([AntennaQuality.OK] * MAX_ANTENNA)
     antenna_qualities_only_second = numpy.array(
-        [AntennaQuality.BROKEN]
-        + [AntennaQuality.OK]
-        + [AntennaQuality.BROKEN] * (MAX_ANTENNA - 2)
+            [AntennaQuality.BROKEN]
+            + [AntennaQuality.OK]
+            + [AntennaQuality.BROKEN] * (MAX_ANTENNA - 2)
     )
     antenna_use_ok = numpy.array([AntennaUse.AUTO] * MAX_ANTENNA)
 
@@ -94,18 +94,18 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         control_mapping = [[1, i] for i in range(NR_TILES)]
         sdp_mapping = [[i // 6, i % 6] for i in range(NR_TILES)]
         antennafield_proxy.put_property(
-            {
-                "Control_to_RECV_mapping": numpy.array(control_mapping).flatten(),
-                "Antenna_to_SDP_Mapping": numpy.array(sdp_mapping).flatten(),
-                "Antenna_Quality": antenna_qualities,
-                "Antenna_Use": antenna_use,
-                "Antenna_Cables": ["50m", "80m"] * (CS001_TILES // 2),
-                "Antenna_Sets": ["FIRST", "ALL"],
-                "Antenna_Set_Masks": [
-                    "1" + ("0" * (NR_TILES - 1)),
-                    "1" * NR_TILES,
-                ],
-            }
+                {
+                    "Control_to_RECV_mapping": numpy.array(control_mapping).flatten(),
+                    "Antenna_to_SDP_Mapping" : numpy.array(sdp_mapping).flatten(),
+                    "Antenna_Quality"        : antenna_qualities,
+                    "Antenna_Use"            : antenna_use,
+                    "Antenna_Cables"         : ["50m", "80m"] * (CS001_TILES // 2),
+                    "Antenna_Sets"           : ["FIRST", "ALL"],
+                    "Antenna_Set_Masks"      : [
+                        "1" + ("0" * (NR_TILES - 1)),
+                        "1" * NR_TILES,
+                    ],
+                }
         )
         antennafield_proxy.off()
         antennafield_proxy.boot()
@@ -133,9 +133,9 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
 
         # Point to Zenith
         self.proxy.set_pointing(
-            numpy.array(
-                [["AZELGEO", "0rad", "1.570796rad"]] * self.proxy.nr_beamlets_R
-            ).flatten()
+                numpy.array(
+                        [["AZELGEO", "0rad", "1.570796rad"]] * self.proxy.nr_beamlets_R
+                ).flatten()
         )
 
         # beam weights should now be non-zero, we don't actually check their values for correctness
@@ -152,7 +152,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         FPGA_bf_weights_pp_clock160 = self.beamlet_proxy.FPGA_bf_weights_pp_RW.flatten()
         # Assert some values are different
         self.assertNotEqual(
-            sum(FPGA_bf_weights_pp_clock160), sum(FPGA_bf_weights_pp_clock200)
+                sum(FPGA_bf_weights_pp_clock160), sum(FPGA_bf_weights_pp_clock200)
         )
 
     def test_pointing_to_zenith_subband_change(self):
@@ -166,8 +166,8 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
 
         self.beamlet_proxy = self.initialise_beamlet_proxy()
         self.beamlet_proxy.subband_select_RW = numpy.array(
-            list(range(317)) + [316] + list(range(318, N_beamlets_ctrl)),
-            dtype=numpy.uint32,
+                list(range(317)) + [316] + list(range(318, N_beamlets_ctrl)),
+                dtype=numpy.uint32,
         )
         self.beamlet_proxy.on()
 
@@ -177,9 +177,9 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
 
         # Point to Zenith
         self.proxy.set_pointing(
-            numpy.array(
-                [["AZELGEO", "0rad", "1.570796rad"]] * self.proxy.nr_beamlets_R
-            ).flatten()
+                numpy.array(
+                        [["AZELGEO", "0rad", "1.570796rad"]] * self.proxy.nr_beamlets_R
+                ).flatten()
         )
         # Store values with first subband configuration
         FPGA_bf_weights_pp_subband_v1 = (
@@ -197,7 +197,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         )
         # Assert some values are different
         self.assertNotEqual(
-            sum(FPGA_bf_weights_pp_subband_v1), sum(FPGA_bf_weights_pp_subband_v2)
+                sum(FPGA_bf_weights_pp_subband_v1), sum(FPGA_bf_weights_pp_subband_v2)
         )
 
     def test_set_pointing_masked_enable(self):
@@ -210,7 +210,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         self.setup_sdpfirmware_proxy()
         self.setup_sdp_proxy()
         self.antennafield_proxy = self.setup_antennafield_proxy(
-            self.antenna_qualities_ok, self.antenna_use_ok
+                self.antenna_qualities_ok, self.antenna_use_ok
         )
 
         self.proxy.initialise()
@@ -225,32 +225,32 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         self.beamlet_proxy.FPGA_bf_weights_pp_RW = impossible_values
 
         self.proxy.set_pointing(
-            numpy.array(
-                [["AZELGEO", "0rad", "1.570796rad"]] * self.proxy.nr_beamlets_R
-            ).flatten()
+                numpy.array(
+                        [["AZELGEO", "0rad", "1.570796rad"]] * self.proxy.nr_beamlets_R
+                ).flatten()
         )
 
         # Verify all impossible values are replaced with other values for all inputs
         # which should be non-zero for the first antenna, and zero for the rest
         FPGA_bf_weights_pp_RW = self.beamlet_proxy.FPGA_bf_weights_pp_RW.reshape(
-            (N_pn * A_pn, -1)
+                (N_pn * A_pn, -1)
         )
 
         # first antenna should have values from the beamformer, so not 0 and not 2
         self.assertTrue(
-            numpy.all(numpy.not_equal(0, FPGA_bf_weights_pp_RW[0, :])),
-            f"{FPGA_bf_weights_pp_RW}",
+                numpy.all(numpy.not_equal(0, FPGA_bf_weights_pp_RW[0, :])),
+                f"{FPGA_bf_weights_pp_RW}",
         )
         self.assertTrue(
-            numpy.all(numpy.not_equal(2, FPGA_bf_weights_pp_RW[0, :])),
-            f"{FPGA_bf_weights_pp_RW}",
+                numpy.all(numpy.not_equal(2, FPGA_bf_weights_pp_RW[0, :])),
+                f"{FPGA_bf_weights_pp_RW}",
         )
 
         # rest of the antennas should have been given a weight of 0, as they
         # were not in the usage mask.
         self.assertTrue(
-            numpy.all(numpy.equal(0, FPGA_bf_weights_pp_RW[1:CS001_TILES, :])),
-            f"{FPGA_bf_weights_pp_RW}",
+                numpy.all(numpy.equal(0, FPGA_bf_weights_pp_RW[1:CS001_TILES, :])),
+                f"{FPGA_bf_weights_pp_RW}",
         )
 
     @timeout_decorator.timeout(15)
@@ -270,9 +270,10 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         self.proxy.on()
 
         interval = float(
-            self.proxy.get_property("Beam_tracking_interval")["Beam_tracking_interval"][
-                0
-            ]
+                self.proxy.get_property("Beam_tracking_interval")[
+                    "Beam_tracking_interval"][
+                    0
+                ]
         )
 
         # Allow beam tracking time to settle
@@ -280,11 +281,11 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
 
         # We have to poll at regular interval due to not working subscribe
         # events
-        # for _ in range(0, 5):
-        #    error = self.proxy.Pointing_error_R[0]
-        #    self.assertTrue(
-        #            -interval * 0.10 < error < interval * 0.10,
-        #            f"Error: {error} larger than {interval * 0.10}",
-        #    )
-        #    logger.info("BeamTracking error: %s", error)
-        #    time.sleep(interval)
+        for _ in range(0, 5):
+            error = self.proxy.Pointing_error_R[0]
+            self.assertTrue(
+                    -interval * 0.10 < error < interval * 0.10,
+                    f"Error: {error} larger than {interval * 0.10}",
+            )
+            logger.info("BeamTracking error: %s", error)
+            time.sleep(interval)