diff --git a/PCC/PCC/PCC.py b/PCC/PCC/PCC.py
index 1b8fca093bbd64af1c1ddd5a657857ae26da3136..ce4de28c8c0f5f0e45dfe006ecc46e86f5d4a49b 100644
--- a/PCC/PCC/PCC.py
+++ b/PCC/PCC/PCC.py
@@ -87,6 +87,10 @@ class PCC(Device):
     # Attributes
     # ----------
 
+    RCU_state_R = attribute(
+        dtype = (numpy.str),
+    )
+
     RCU_mask_RW = attribute(
         dtype=(numpy.bool_,),
         max_dim_x=32,
@@ -204,6 +208,11 @@ class PCC(Device):
         access=AttrWriteType.READ_WRITE,
     )
 
+    uC_ID_R = attribute(
+        dtype=(numpy.int64,),
+        max_dim_x=32,
+    )
+
     RCU_monitor_rate_RW = attribute(
         dtype=numpy.float_,
         access=AttrWriteType.READ_WRITE,
@@ -233,6 +242,8 @@ class PCC(Device):
 
         self.debug_stream("Mapping OPC-UA MP/CP to attributes...")
 
+        self.attribute_mapping["RCU_state_R"] = self.get_pcc_node("RCU_state_R")
+
         self.attribute_mapping["RCU_mask_RW"] = self.get_pcc_node("RCU_mask_RW")
 
         self.attribute_mapping["Ant_mask_RW"] = self.get_pcc_node("Ant_mask_RW")
@@ -277,6 +288,8 @@ class PCC(Device):
 
         self.attribute_mapping["HBA_element_pwr_RW"] = self.get_pcc_node("HBA_element_pwr_RW")
 
+        self.attribute_mapping["uC_ID_R"] = self.get_pcc_node("uC_ID  _R")
+
         self.attribute_mapping["RCU_monitor_rate_RW"] = self.get_pcc_node("RCU_monitor_rate_RW")
 
         self.function_mapping["RCU_off"] = self.get_pcc_node("RCU_off")
@@ -314,6 +327,9 @@ class PCC(Device):
 
         # Set default values in the RW/R attributes and add them to
         # the mapping.
+        self._RCU_state_R = ""
+        self.attribute_mapping["RCU_state_R"] = {}
+
         self._RCU_mask_RW = numpy.full(32, False)
         self.attribute_mapping["RCU_mask_RW"] = {}
 
@@ -380,6 +396,9 @@ class PCC(Device):
         self._HBA_element_pwr_RW = numpy.full((96, 32), 0)
         self.attribute_mapping["HBA_element_pwr_RW"] = {}
 
+        self._uC_ID_R = numpy.full(32, 0)
+        self.attribute_mapping["uC_ID_R"] = {}
+
         self._RCU_monitor_rate_RW = 30.0
         self.attribute_mapping["RCU_monitor_rate_RW"] = {}
 
@@ -450,6 +469,13 @@ class PCC(Device):
     # ------------------
     # Attributes methods
     # ------------------
+    @only_when_on
+    @fault_on_error
+    def read_RCU_state_R(self):
+        """Return the RCU_state_R attribute."""
+        self._RCU_state_R = self.attribute_mapping["RCU_state_R"].get_value()
+        return self._RCU_state_R
+
     @only_when_on
     @fault_on_error
     def read_RCU_mask_R(self):
@@ -675,6 +701,13 @@ class PCC(Device):
         self.attribute_mapping["HBA_element_pwr_RW"].set_value(value.flatten().tolist())
         self._HBA_element_pwr_RW = value
 
+    @only_when_on
+    @fault_on_error
+    def read_uC_ID_R(self):
+        """Return the uC_ID_R attribute."""
+        self._uC_ID_R = numpy.array(self.attribute_mapping["uC_ID_R"].get_value())
+        return self._uC_ID_R
+
     @only_when_on
     @fault_on_error
     def read_RCU_monitor_rate_RW(self):
diff --git a/docker-compose/Makefile b/docker-compose/Makefile
index 6c2e767c8dfcac11cd1fb1d54f035e7b73b1f48a..65de8951a33821b2f06c3b530b11b2f3c1fbc355 100644
--- a/docker-compose/Makefile
+++ b/docker-compose/Makefile
@@ -92,6 +92,8 @@ pull: ## pull the images from the Docker hub
 	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) pull
 
 build: ## rebuild images
+	# docker-compose does not support build dependencies, so manage those here
+	$(DOCKER_COMPOSE_ARGS) docker-compose -f lofar-device-base.yml build
 	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) build
 
 up: minimal  ## start the base TANGO system and prepare all services
@@ -122,6 +124,9 @@ attach:  ## attach a service to an existing Tango network
 status:  ## show the container status
 	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) ps
 
+images:  ## show the container images
+	$(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) images
+
 clean: down  ## clear all TANGO database entries
 	docker volume rm $(BASEDIR)_tangodb
 
diff --git a/docker-compose/device-pcc.yml b/docker-compose/device-pcc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..96eb6901583216b69035b1d2e906a2c1744e6644
--- /dev/null
+++ b/docker-compose/device-pcc.yml
@@ -0,0 +1,31 @@
+#
+# 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-pcc:
+    image: lofar-device-base
+    container_name: ${CONTAINER_NAME_PREFIX}device-pcc
+    network_mode: ${NETWORK_MODE}
+    volumes:
+        - ${TANGO_LOFAR_CONTAINER_MOUNT}
+    environment:
+      - TANGO_HOST=${TANGO_HOST}
+    entrypoint:
+      - /usr/local/bin/wait-for-it.sh
+      - ${TANGO_HOST}
+      - --timeout=30
+      - --strict
+      - --
+      - python3 -u ${TANGO_LOFAR_CONTAINER_DIR}/PCC/PCC LTS -v
+    restart: on-failure
diff --git a/docker-compose/device-sdp.yml b/docker-compose/device-sdp.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8fbc3cbc536360658446d2f21c57231d29b8d6ca
--- /dev/null
+++ b/docker-compose/device-sdp.yml
@@ -0,0 +1,31 @@
+#
+# 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-sdp:
+    image: lofar-device-base
+    container_name: ${CONTAINER_NAME_PREFIX}device-sdp
+    network_mode: ${NETWORK_MODE}
+    volumes:
+        - ${TANGO_LOFAR_CONTAINER_MOUNT}
+    environment:
+      - TANGO_HOST=${TANGO_HOST}
+    entrypoint:
+      - /usr/local/bin/wait-for-it.sh
+      - ${TANGO_HOST}
+      - --timeout=30
+      - --strict
+      - --
+      - python3 -u ${TANGO_LOFAR_CONTAINER_DIR}/SDP/SDP LTS -v
+    restart: on-failure
diff --git a/docker-compose/itango.yml b/docker-compose/itango.yml
index ef825b5c20526f2db03e8d03f26bbdf5c145ee5c..d131d405371bc6ff7e59892587b2bd2aba9d1fd6 100644
--- a/docker-compose/itango.yml
+++ b/docker-compose/itango.yml
@@ -37,3 +37,4 @@ services:
       - --strict
       - --
       - /venv/bin/itango3
+    restart: on-failure
diff --git a/docker-compose/jupyter.yml b/docker-compose/jupyter.yml
index 7f0011446935a0c49cef406f5addb870d3fad515..f1970916f7e9facc25908c08c63f0938be0c4eb7 100644
--- a/docker-compose/jupyter.yml
+++ b/docker-compose/jupyter.yml
@@ -18,6 +18,7 @@ services:
     volumes:
         - ${TANGO_SKA_CONTAINER_MOUNT}
         - ${TANGO_LOFAR_CONTAINER_MOUNT}
+        - ${TANGO_LOFAR_LOCAL_DIR}/jupyter-notebooks:/jupyter-notebooks:rw
         - ${HOME}:/hosthome
     environment:
       - TANGO_HOST=${TANGO_HOST}
@@ -25,7 +26,7 @@ services:
       - DISPLAY=${DISPLAY}
     ports:
       - "8888:8888"
-    working_dir: ${TANGO_LOFAR_CONTAINER_DIR}/jupyter-notebooks
+    working_dir: /jupyter-notebooks
     entrypoint:
       - /usr/local/bin/wait-for-it.sh
       - ${TANGO_HOST}
@@ -33,3 +34,4 @@ services:
       - --strict
       - --
       - /usr/bin/tini -- jupyter notebook --port=8888 --no-browser --ip=0.0.0.0 --allow-root --NotebookApp.token= --NotebookApp.password=
+    restart: on-failure
diff --git a/docker-compose/lofar-device-base.yml b/docker-compose/lofar-device-base.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3d40f0f63554222907e6094bc61f1342cc8fabfa
--- /dev/null
+++ b/docker-compose/lofar-device-base.yml
@@ -0,0 +1,21 @@
+#
+# Docker compose file that forms the basis for LOFAR tango devices
+#
+# This is an abstract image that does not need to be spinned up, but
+# might be out of consistency with other images.
+#
+# Defines:
+#   - device-base: Base configuration for devices.
+#
+# Requires:
+#   - tango.yml
+#
+version: '2'
+
+services:
+  lofar-device-base:
+    image: lofar-device-base
+    build:
+        context: lofar-device-base
+    container_name: ${CONTAINER_NAME_PREFIX}lofar-device-base
+    network_mode: ${NETWORK_MODE}
diff --git a/docker-compose/lofar-device-base/Dockerfile b/docker-compose/lofar-device-base/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..cd6b59511f7e0a3e515ab282775edeadec6b9aaf
--- /dev/null
+++ b/docker-compose/lofar-device-base/Dockerfile
@@ -0,0 +1,4 @@
+FROM nexus.engageska-portugal.pt/ska-docker/tango-itango:latest
+
+COPY lofar-requirements.txt /lofar-requirements.txt
+RUN pip3 install -r /lofar-requirements.txt
diff --git a/docker-compose/lofar-device-base/lofar-requirements.txt b/docker-compose/lofar-device-base/lofar-requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..90d21efe0e5ac0601204d4f05ce7efcd16dca2de
--- /dev/null
+++ b/docker-compose/lofar-device-base/lofar-requirements.txt
@@ -0,0 +1,2 @@
+opcua >= 0.98.9
+astropy 
diff --git a/docker-compose/pypcc-sim.yml b/docker-compose/pypcc-sim.yml
index bb6d519f2e98a3beb8bc34711d44f16f8aad29ce..d1c47c0465affd6b7bcb2de27dfa340c48e681ce 100644
--- a/docker-compose/pypcc-sim.yml
+++ b/docker-compose/pypcc-sim.yml
@@ -16,3 +16,4 @@ services:
         - ${HOME}:/hosthome
     ports:
         - "4842:4842"
+    restart: on-failure
diff --git a/jupyter-notebooks/Start All Devices.ipynb b/jupyter-notebooks/Start All Devices.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..beb52a381c89a4cda30b08374d36c337def29eae
--- /dev/null
+++ b/jupyter-notebooks/Start All Devices.ipynb	
@@ -0,0 +1,73 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "social-massachusetts",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def force_start(device):\n",
+    "    if device.state() == DevState.FAULT:\n",
+    "        device.Off()\n",
+    "    if device.state() == DevState.OFF:\n",
+    "        device.initialise()\n",
+    "    if device.state() == DevState.INIT:\n",
+    "        device.Standby()\n",
+    "    if device.state() == DevState.STANDBY:\n",
+    "        device.On()\n",
+    "        \n",
+    "    return device.state()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "defined-apache",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Device PCC(lts/pcc/1) is now in state FAULT\n",
+      "Device SDP(lts/sdp/1) is now in state ON\n"
+     ]
+    }
+   ],
+   "source": [
+    "for d in devices:\n",
+    "    print(\"Device %s is now in state %s\" % (d, force_start(d)))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "superior-wheel",
+   "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
+}