diff --git a/docker-compose/lofar-device-base/Dockerfile b/docker-compose/lofar-device-base/Dockerfile
index d280bf4f3f76f4b71e17cf0fcf6c8fb7ff32e572..0d7c98235c903bfea6a66339a7feb6b2a5440f56 100644
--- a/docker-compose/lofar-device-base/Dockerfile
+++ b/docker-compose/lofar-device-base/Dockerfile
@@ -9,13 +9,13 @@ RUN sudo apt-get install -y python3-dev libboost-python-dev pkg-config && sudo a
 RUN sudo apt-get install -y rsync && sudo apt-get clean
 
 COPY lofar-device-base/lofar-requirements.txt /lofar-requirements.txt
-RUN sudo pip3 install -r /lofar-requirements.txt
 
 # Manually install all requirements from the .txt as part of the base image
 # This reduces runtime overhead as well as preventing issues around dependency
 # installation for development builds (pip install ./ ignores requirements.txt)
 COPY tmp/requirements.txt /tangostationcontrol-requirements.txt
-RUN sudo pip3 install -r /tangostationcontrol-requirements.txt
+
+RUN sudo pip3 install -r /tangostationcontrol-requirements.txt -r /lofar-requirements.txt
 
 # install and use ephimerides and geodetic ("measures") tables for casacore.
 # we install a _stub_ since the tables need to be deployed explicitly from within the software.
diff --git a/docker-compose/loki.yml b/docker-compose/loki.yml
index 2007e16aa7e06726cc5b8be75553e4ef2df56475..6f634767bd04610a70e969cff2105c062f7ecb1e 100644
--- a/docker-compose/loki.yml
+++ b/docker-compose/loki.yml
@@ -4,7 +4,7 @@
 #
 #
 
-version: "3"
+version: "2.1"
 
 services:
   loki:
diff --git a/tangostationcontrol/requirements.txt b/tangostationcontrol/requirements.txt
index a6662e4b263ca26aa93ad216c9b104ffd0e8e735..8d628544905096b9a717719b18bb25293bb0e72d 100644
--- a/tangostationcontrol/requirements.txt
+++ b/tangostationcontrol/requirements.txt
@@ -3,7 +3,7 @@
 # integration process, which may cause wedges in the gate later.
 
 importlib-metadata<2.0.0,>=0.12;python_version<"3.8"
-lofar-station-client@git+https://git.astron.nl/lofar2.0/lofar-station-client@0.9.1
+lofar-station-client@git+https://git.astron.nl/lofar2.0/lofar-station-client@0.9.2
 numpy
 mock
 asyncua >= 0.9.90 # LGPLv3
diff --git a/tangostationcontrol/setup.cfg b/tangostationcontrol/setup.cfg
index f42357ef73a2f50734d03f26444b32b905ac0042..bea7c5441230fe90a9ee104c788443121e0d7008 100644
--- a/tangostationcontrol/setup.cfg
+++ b/tangostationcontrol/setup.cfg
@@ -26,7 +26,7 @@ package_dir=
 packages=find:
 python_requires => 3.7
 install_requires =
-    importlib-metadata>=0.12, <5.0;python_version<"3.8"
+    importlib-metadata<2.0.0,>=0.12;python_version<"3.8"
     pip>=1.5
 
 [options.packages.find]
diff --git a/tangostationcontrol/tangostationcontrol/common/type_checking.py b/tangostationcontrol/tangostationcontrol/common/type_checking.py
index f6686b54b86b94aa745ac311b9f71e622ec87ef8..ac146170d2274cc950a6bffa326404c9481fd072 100644
--- a/tangostationcontrol/tangostationcontrol/common/type_checking.py
+++ b/tangostationcontrol/tangostationcontrol/common/type_checking.py
@@ -3,23 +3,14 @@
 # Distributed under the terms of the APACHE license.
 # See LICENSE.txt for more info.
 
-from collections.abc import Sequence
-
-import numpy
-
-
-def is_sequence(obj):
-    """True for sequences, positionally ordered collections
-    See https://www.pythontutorial.net/advanced-python/python-sequences/
-    """
-    return isinstance(obj, Sequence) or isinstance(obj, numpy.ndarray)
+from tango.utils import is_seq
 
 
 def sequence_not_str(obj):
     """True for sequences that are not str, bytes or bytearray"""
-    return is_sequence(obj) and not isinstance(obj, (str, bytes, bytearray))
+    return is_seq(obj) and not isinstance(obj, (str, bytes, bytearray))
 
 
 def type_not_sequence(obj):
     """True for types that are not sequences"""
-    return not is_sequence(obj) and isinstance(obj, type)
+    return not is_seq(obj) and isinstance(obj, type)
diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_observation.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_observation.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb9011a00e0f3448a4a84a74d1fef8ac15178291
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_observation.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of the LOFAR 2.0 Station Software
+#
+#
+#
+# Distributed under the terms of the APACHE license.
+# See LICENSE.txt for more info.
+
+from tangostationcontrol.test.devices.test_observation_base import TestObservationBase
+from tangostationcontrol.integration_test import base
+from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy
+
+from lofar_station_client.observation.observation import Observation
+
+from os import environ
+from json import loads
+
+from tango import DevState
+
+class TestObservation(base.IntegrationTestCase):
+
+    def setUp(self):
+        self.observation_control_proxy = TestDeviceProxy("STAT/ObservationControl/1")
+        self.observation_control_proxy.off()
+        self.observation_control_proxy.warm_boot()
+
+    def test_observation(self):
+        """Test of the observation_wrapper class basic functionality"""
+
+        # convert the JSON specificiation to a dict for this class
+        specification_dict = loads(TestObservationBase.VALID_JSON)
+
+        # create an observation class using the dict and as host just get it using a util function
+        observation = Observation(specification=specification_dict, host=environ["TANGO_HOST"])
+
+        # Assert the observation is running after starting it
+        observation.start()
+        self.assertTrue(observation.is_running())
+
+        # Assert the proxy is on
+        proxy = observation.observation_proxy()
+        self.assertTrue(proxy.state() == DevState.ON)
+
+        # Assert the observation has stopped after aborting
+        observation.abort()
+        self.assertFalse(observation.is_running())
diff --git a/tangostationcontrol/tangostationcontrol/test/common/test_type_checking.py b/tangostationcontrol/tangostationcontrol/test/common/test_type_checking.py
index 253fb6182006a426188e84576bf295344f973549..342e1ba9b7834981397bbaf79a97b06075ba4d96 100644
--- a/tangostationcontrol/tangostationcontrol/test/common/test_type_checking.py
+++ b/tangostationcontrol/tangostationcontrol/test/common/test_type_checking.py
@@ -6,6 +6,8 @@
 #
 # Distributed under the terms of the APACHE license.
 # See LICENSE.txt for more info.
+
+from tango.utils import is_seq
 import numpy
 
 from tangostationcontrol.common import type_checking
@@ -32,7 +34,10 @@ class TestTypeChecking(base.TestCase):
             return False
 
     def sequence_test(self, obj):
-        """Test object is sequence based on properties and verify is_sequence"""
+        """Test object is sequence based on properties and verify is_sequence
+
+        Recover alternative is_sequence method from commit 73177e9 if tests fail
+        """
 
         result = (
             self.subscriptable(obj) & self.iterable(obj)
@@ -40,12 +45,15 @@ class TestTypeChecking(base.TestCase):
         )
 
         self.assertEqual(
-            result, type_checking.is_sequence(obj),
+            result, is_seq(obj),
             F"Test failed for type {type(obj)}"
         )
 
     def test_is_sequence_for_types(self):
-        """Types to be tested by is_sequence"""
+        """Types to be tested by is_sequence
+
+        Recover alternative is_seq method from commit 73177e9 if tests fail
+        """
 
         test_types = [
             (False,),
diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py
index d14a36871e6ba9cd28491549a587508a9102b1be..8bb7ae978483d54904c9a15825047855afce0f5b 100644
--- a/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py
+++ b/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py
@@ -368,44 +368,6 @@ class TestAntennaToRecvMapper(base.TestCase):
         actual = mapper.map_write("HBAT_PWR_on_RW", set_values)
         numpy.testing.assert_equal(expected, actual)
 
-    # def test_merge_write(self):
-    #     """Verify all None fields are replaced by merge_write if no control"""
-    #
-    #     mapper = AntennaToRecvMapper(
-    #         self.CONTROL_NOT_CONNECTED, self.POWER_NOT_CONNECTED, 1
-    #     )
-    #
-    #     merge_values = [[None] * N_rcu] * MAX_ANTENNA
-    #     current_values = [[False] * N_rcu] * MAX_ANTENNA
-    #
-    #     mapper.merge_write(merge_values, current_values)
-    #     numpy.testing.assert_equal(merge_values, current_values)
-    #
-    #     results = []
-    #     for _i in range(25):
-    #         start_time = time.monotonic_ns()
-    #         mapper.merge_write(merge_values, current_values)
-    #         stop_time = time.monotonic_ns()
-    #         results.append(stop_time - start_time)
-    #
-    #     logging.error(
-    #         f"Merge write performance: Median {statistics.median(results) / 1.e9} "
-    #         f"Stdev {statistics.stdev(results) / 1.e9}"
-    #     )
-    #
-    # def test_merge_write_values(self):
-    #     """Verify all fields with values are retained by merge_write"""
-    #
-    #     mapper = AntennaToRecvMapper(
-    #         self.CONTROL_NOT_CONNECTED, self.POWER_NOT_CONNECTED, 1
-    #     )
-    #
-    #     merge_values = [[True] * N_rcu] * 2 + [[None] * N_rcu] * (MAX_ANTENNA - 2)
-    #     current_values = [[True] * N_rcu] * 2 + [[False] * N_rcu] * (MAX_ANTENNA - 2)
-    #
-    #     mapper.merge_write(merge_values, current_values)
-    #     numpy.testing.assert_equal(merge_values, current_values)
-
 
 class TestAntennafieldDevice(device_base.DeviceTestCase):
 
diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py
index a57a2846a18580e3752b175ee82a9a649d752c09..3a91941bb1366c98ef07b04709d72655effc7f00 100644
--- a/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py
+++ b/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py
@@ -7,12 +7,20 @@
 # Distributed under the terms of the APACHE license.
 # See LICENSE.txt for more info.
 
+import numpy
+
 from tango.test_context import DeviceTestContext
 from tango.server import attribute
-from tango import DevState, DevFailed
+from tango.server import command
+from tango import AttrWriteType
+from tango import DevFailed
+from tango import DevState
+from tango import DevVarBooleanArray
 
 from tangostationcontrol.devices import lofar_device
 
+from unittest import mock
+
 from tangostationcontrol.test.devices import device_base
 
 
@@ -75,8 +83,54 @@ class TestLofarDevice(device_base.DeviceTestCase):
 
             # Just for demo, do not use class variables to store attribute state
             _bool_array = [False] * BOOL_ARRAY_DIM
+            bool_array = attribute(
+                dtype=(bool,), max_dim_x=BOOL_ARRAY_DIM,
+                access=AttrWriteType.READ_WRITE, fget="get_bool_array",
+                fset="set_bool_array"
+            )
 
-
-            @attribute(dtype=(bool,), max_dim_x=BOOL_ARRAY_DIM)
-            def bool_array(self):
+            def get_bool_array(self):
                 return self._bool_array
+
+            def set_bool_array(self, bool_array):
+                self._bool_array = bool_array
+
+            @command(dtype_in=DevVarBooleanArray)
+            def do_read_modify_write(self, values: numpy.array):
+                bool_array_half = int(self.BOOL_ARRAY_DIM / 2)
+
+                # We have to mock the proxy because lofar_device.proxy will be
+                # patched
+                t_write = mock.Mock()
+                t_proxy = mock.Mock(
+                    read_attribute=mock.Mock(
+                        return_value=mock.Mock(
+                            value=numpy.array(self._bool_array)
+                        )
+                    ),
+                    write_attribute=t_write
+                )
+
+                self.atomic_read_modify_write_attribute(
+                    values, t_proxy, "bool_array",
+                    numpy.array([True, False] * bool_array_half)
+                )
+
+                # Fake the write, extract the call argument from t_write mock
+                self._bool_array = t_write.call_args[0][1]
+
+        with DeviceTestContext(
+            AttributeLofarDevice, process=True
+        ) as proxy:
+
+            bool_array_half = int(AttributeLofarDevice.BOOL_ARRAY_DIM / 2)
+            excepted_result = [True, False] * bool_array_half
+
+            proxy.initialise()
+            proxy.do_read_modify_write(
+                [True] * AttributeLofarDevice.BOOL_ARRAY_DIM
+            )
+
+            numpy.testing.assert_array_equal(
+                excepted_result, proxy.bool_array
+            )