diff --git a/README.md b/README.md
index 346d8e5a24051ba60a43b4efedbb80b2b892b140..b2358f3e3ff9dde79b8b04e026729370a714025f 100644
--- a/README.md
+++ b/README.md
@@ -49,3 +49,11 @@ Funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation)
 
 Funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) under Project-ID 432233186 -- AIMS.
 
+## License of used third-party libraries
+
+| Library  | License                     |
+|----------|-----------------------------|
+| numpy    | BSD License                 |
+| requests | BSD License                 |
+| toml     | MIT License                 |
+| wzl-udi  | MIT License                 |
\ No newline at end of file
diff --git a/assets/interfaces/cartCMM.soil b/assets/interfaces/cartCMM.soil
new file mode 100644
index 0000000000000000000000000000000000000000..2a4ce6cdae95a1fbd8725b4777663998bf925c40
--- /dev/null
+++ b/assets/interfaces/cartCMM.soil
@@ -0,0 +1,29 @@
+import tool;
+import toolChanger;
+import part;
+
+enum CoordinateSystems {
+    MachineCsy
+    MovableMachineCsy
+    MultipleArmCsy
+    RotaryTableVarCsy
+    PartCsy
+}
+
+variable ActiveCsy {
+    name: "ActiveCsy"
+    description: "The currently active coordinate system."
+    datatype: enum
+    dimension: []
+    range: CoordinateSystems
+}
+
+component CartCMM {
+    name: "CartCMM"
+    description: "Cartesian Coordinate Measuring Machine"
+    components:
+        toolChanger.ToolChanger toolChanger
+        part.Part part
+    parameters:
+        tool.Id activeTool
+}
\ No newline at end of file
diff --git a/assets/interfaces/ipp.soil b/assets/interfaces/ipp.soil
new file mode 100644
index 0000000000000000000000000000000000000000..87ce326409fad5c25f88017be36bd03ece30e1bc
--- /dev/null
+++ b/assets/interfaces/ipp.soil
@@ -0,0 +1,23 @@
+import cartCMM;
+
+function AbortE {
+    name: "AbortE"
+    description: "Aborts all pending transactions and stops the machine from moving."
+}
+
+function ClearAllErrors {
+    name: "ClearAllErrors"
+    description: "Is called to recover from an error."
+}
+
+component Ipp {
+    name: "I++"
+    description: "The top-level component of the Server."
+    components:
+        cartCMM.CartCMM cmm
+    functions:
+        AbortE abortE
+        ClearAllErrors clearAllErrors
+}
+
+interface Ipp IppServer {}
\ No newline at end of file
diff --git a/assets/interfaces/part.soil b/assets/interfaces/part.soil
new file mode 100644
index 0000000000000000000000000000000000000000..05ac5037da2cdd900367b1fbf14ebc3b46622087
--- /dev/null
+++ b/assets/interfaces/part.soil
@@ -0,0 +1,29 @@
+@prefix quantitykind: <http://qudt.org/vocab/quantitykind/> ;
+@prefix unit: <http://qudt.org/vocab/unit/> ;
+
+variable Temperature defines <quantitykind:Temperature> {
+    name: "Temperature"
+    description: "Current temperature of the part."
+    datatype: float
+    dimension: []
+    range: (-50, 200)
+    unit: <unit:DEG_C>
+}
+
+variable Approach defines <quantitykind:Distance>{
+    name: "Approach"
+    description: "Currently specified approach distance of the part."
+    datatype: float
+    dimension: []
+    range: (0, 500)
+    unit: <unit:MilliM>
+}
+
+component Part {
+    name: "Part"
+    description: "Soil representation of a Part."
+    measurements:
+        Temperature temperature
+    parameters:
+        Approach approach
+}
\ No newline at end of file
diff --git a/assets/interfaces/tool.soil b/assets/interfaces/tool.soil
new file mode 100644
index 0000000000000000000000000000000000000000..0c24d70705184bc4f9c033c0d13d2a13b02478af
--- /dev/null
+++ b/assets/interfaces/tool.soil
@@ -0,0 +1,59 @@
+@prefix quantitykind: <http://qudt.org/vocab/quantitykind/> ;
+@prefix unit: <http://qudt.org/vocab/unit/> ;
+
+variable Name {
+    name: "Name"
+    description: "Name of a Tool"
+    datatype: string
+    dimension: []
+}
+
+variable Id {
+    name: "Id"
+    description: "Id of a Tool"
+    datatype: string
+    dimension: []
+}
+
+# variable PositionList {
+#     name: "PositionList"
+#     description: "List of Points used for ScanOnCurve"
+#     datatype: float
+#     dimension: [0, 3]
+# }
+
+variable Position defines <quantitykind:CartesianCoordinates> {
+    name: "Position"
+    description: "Current position of the tool, consisting of the I++ X, Y and Z values."
+    datatype: float
+    dimension: [3]
+    unit: <unit:MilliM>
+}
+
+function ScanOnCurve {
+    name: "ScanOnCurve"
+    description: "Function that issues a ScanOnCurve command on the I++ Server"
+    arguments:
+        PositionList posL
+}
+
+function PtMeas {
+    name: "PtMeas"
+    description: "Function that issues a PtMeas command on the I++ Server"
+    arguments:
+        Position pos
+}
+
+component Tool {
+    name: "Tool"
+    description: "The currently active Tool."
+    measurements:
+        Position pos
+    parameters:
+        constant Name name
+        constant Id id
+        PositionList posL
+    functions:
+        PtMeas ptMeas
+        ScanOnCurve scanOnCurve
+}
\ No newline at end of file
diff --git a/assets/interfaces/toolChanger.soil b/assets/interfaces/toolChanger.soil
new file mode 100644
index 0000000000000000000000000000000000000000..f2859ed56e833b071bae31bd5033f795078fe569
--- /dev/null
+++ b/assets/interfaces/toolChanger.soil
@@ -0,0 +1,23 @@
+import tool;
+
+function EnumTools {
+    name: "EnumTools"
+    description: "Function that issues an EnumTools command on the I++ server."
+}
+
+function ChangeTool {
+    name: "EnumTools"
+    description: "Function that issues an ChangeTool command on the I++ server."
+    arguments:
+        tool.Id tool_id
+}
+
+component ToolChanger {
+    name: "ToolChanger"
+    description: "ToolChanger component"
+    components:
+        dynamic tool.Tool tools
+    functions:
+        EnumTools enumTools
+        ChangeTool changeTool
+}
\ No newline at end of file
diff --git a/init.bat b/init.bat
index b412275364f36b4d5a0e93b667be2916c7a58c75..2821a3da30811c65263e1dc294f8e1e1b9e7eee4 100644
--- a/init.bat
+++ b/init.bat
@@ -1,4 +1,5 @@
 cd scripts
+:: python generate.py ipp.soil -g shell -s -hwc
 python generate.py robot.soil -g remote -s -hwc
 python generate.py lasertracker.soil -g remote -s -hwc
 python generate.py monitoring.soil -g remote -s -hwc
diff --git a/requirements.txt b/requirements.txt
index afee9be188c475d4ac141a122018f663c83093a3..4b8519b2e5c54433e47d7f91686c00cc0e5c13af 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-numpy
-requests
-toml
-wzl-udi==9.3.8
+numpy==1.24.2
+requests==0.10.2
+toml==
+wzl-udi==10.0.0
diff --git a/requirements_dev.txt b/requirements_dev.txt
index f80a93443af2e7c02ebb6dfaaceebffb50b3e932..2092c7c79057ad3675960608a936b25de4e69dc6 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -2,7 +2,7 @@ numpy
 requests
 toml
 tqdm
-wzl-udi==9.3.3
+wzl-udi==10.0.0
 kaleido
 plotly
 pandas
\ No newline at end of file
diff --git a/scripts/generate.py b/scripts/generate.py
index 70aeb9fa48f794a8a378d4d7b2e2d7da3d35bc54..7aaf085ca77176fdc446655801866f367d3ca4e7 100644
--- a/scripts/generate.py
+++ b/scripts/generate.py
@@ -71,6 +71,6 @@ if __name__ == '__main__':
                                    stderr=subprocess.PIPE)
         stdout, stderr = process.communicate()
         print(stdout.decode())
-        print(stderr.decode())
+        print(stderr.decode('latin-1'))
     else:
         print(f'Generator type "{args.generator}" is unknown, must be one of "shell", "local", "remote".')
diff --git a/src/assessment.py b/src/assessment.py
index db1542fb3f08d4cd39fee86b239ee993c713fef9..ff7ba1c5a56bc98b7eeeb58bf83cb2b03986d2d1 100644
--- a/src/assessment.py
+++ b/src/assessment.py
@@ -9,7 +9,7 @@ from assessment.framework import Framework, AssessmentError, FUJI, FAIRChecker
 SRC = os.path.join('.')
 OUT = os.path.join('..', 'out')
 
-PROFILES = True
+PROFILES = False
 METADATA = True
 
 
diff --git a/src/evaluation.py b/src/evaluation.py
index 177a41880aa1327801ab2ec810849dbd9d273e3c..241b83fe5c89222b7a43fdbed9c08872c03950bc 100644
--- a/src/evaluation.py
+++ b/src/evaluation.py
@@ -8,14 +8,14 @@ SRC = os.path.join('..', 'src')
 ASSESSMENTS = os.path.join('..', 'out')
 OUT = os.path.join('..', 'out')
 
-PROFILES = True
+PROFILES = False
 METADATA = True
 
 if __name__ == '__main__':
 
     dummies = ['lasertracker', 'monitoring', 'robot']
     profile_scores = pandas.DataFrame()
-    metadata_scores = {'f-uji': [], 'fair-checker': []}
+    metadata_scores = pandas.DataFrame(columns=["framework", "dummy", "principle", "value"])
 
     for dummy in dummies:
 
@@ -26,15 +26,18 @@ if __name__ == '__main__':
         for framework in frameworks:
 
             if PROFILES:
-                profile_scores[framework.name] += [
-                    framework.evaluate(os.path.join(ASSESSMENTS, framework.name, dummy, 'profiles'))]
+                framework.evaluate(os.path.join(ASSESSMENTS, framework.name, dummy, 'profiles'), dummy)
 
             if METADATA:
-                metadata_scores[framework.name] += [
-                    framework.evaluate(os.path.join(ASSESSMENTS, framework.name, dummy, 'profiles'))]
+                score = framework.evaluate(os.path.join(ASSESSMENTS, framework.name, dummy, 'metadata'), dummy)
+                metadata_scores = pandas.concat([metadata_scores, score], ignore_index=True)
 
-    average_profile_scores = [profile_scores[key].mean() for key in profile_scores]
-    average_metadata_scores = [metadata_scores[key].mean() for key in metadata_scores]
+    average_scores = metadata_scores.groupby(['framework', 'principle'], as_index=False).agg({'value': 'mean'})
 
-    Framework.visualize(average_profile_scores, list(profile_scores.keys()), 'profiles.png')
-    Framework.visualize(average_metadata_scores, list(profile_scores.keys()), 'metadata.png')
+    print(average_scores)
+
+    # average_profile_scores = [profile_scores[key].mean() for key in profile_scores]
+    # average_metadata_scores = [metadata_scores[key].mean() for key in metadata_scores]
+
+    # Framework.visualize(average_profile_scores, list(profile_scores.keys()), 'profiles.png')
+    Framework.visualize(metadata_scores, 'metadata.png')
diff --git a/src/ipp/hwc/__init__.py b/src/ipp/hwc/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/ipp/hwc/com_tool.py b/src/ipp/hwc/com_tool.py
new file mode 100644
index 0000000000000000000000000000000000000000..200433381844ebc2d0cda5b62e7c0afb39ad7392
--- /dev/null
+++ b/src/ipp/hwc/com_tool.py
@@ -0,0 +1,17 @@
+from scripts.gen.ipp.tool.com_tool import COMToolTOP
+from scripts.gen.ipp.hwc.device import Device
+
+
+class COMTool(COMToolTOP):
+    def __init__(self, device: Device, name: str = "", id: str = "", posl: list[float] = None ):
+        COMToolTOP.__init__(self, device, name, id)
+        self._device = device
+
+    def fun_ptmeas(self, arg_pos):
+        self._device.pt_meas(arg_pos[0], arg_pos[1], arg_pos[2])
+
+    def scanoncurve(self, posl):
+        self._device.scanoncurve(posl)
+
+    def get_mea_pos(self):
+        return self._device.position
diff --git a/src/ipp/hwc/device.py b/src/ipp/hwc/device.py
new file mode 100644
index 0000000000000000000000000000000000000000..604cef5785c9293e615e3aa666c20117fa553571
--- /dev/null
+++ b/src/ipp/hwc/device.py
@@ -0,0 +1,55 @@
+import asyncio
+import time
+from scripts.gen.ipp.device import DeviceTOP
+from threading import Thread
+from . import ipp_client
+import re
+
+
+class Tool(object):
+    def __init__(self, position):
+        self._position = position
+
+    def update(self, position):
+        self._position = position
+
+    @property
+    def position(self):
+        return self._position
+
+
+class Device(DeviceTOP, Thread):
+    def __init__(self):
+        DeviceTOP.__init__(self)
+        Thread.__init__(self)
+        self._x = 0
+        self._y = 0
+        self._z = 0
+        self._tool = Tool(self.position)
+        self._error = False
+        self._ipp_client = None
+
+    async def goto(self, x, y, z):
+        await self._ipp_client.transaction("GoTo(X(" + x + "), Y(" + y + "), Z(" + z + "))", False)
+
+    def pt_meas(self, x, y, z):
+        self._ipp_client.transaction("PtMeas(X(" + str(x) + "), Y(" + str(y) + "), Z(" + str(z) + "))", False)
+
+    @property
+    def position(self):
+        return [self._x, self._y, self._z]
+
+    def run(self):
+        self._ipp_client = ipp_client.IPPClient(self)
+        self._ipp_client.start()
+        time.sleep(1)
+        self._ipp_client.transaction("StartSession()", False)
+        self._ipp_client.transaction("PtMeas(X(1), Y(2), Z(3))", False)
+        self._ipp_client.transaction("GoTo(X(1), Y(2), Z(3))", False)
+        for i in range(1000):
+            self._ipp_client.transaction("ABC(1,2,3)", False)
+        self._ipp_client.transaction("OnMoveReport(X(), Y(), Z())", True)
+
+    def stop(self):
+        loop = asyncio.get_event_loop()
+        loop.run_until_complete(self._ipp_client.transaction("EndSession()", False))
diff --git a/src/ipp/hwc/ippServerConfig.toml b/src/ipp/hwc/ippServerConfig.toml
new file mode 100644
index 0000000000000000000000000000000000000000..1f90202fec649f5c9f1364737f4b9b7b8d00e84e
--- /dev/null
+++ b/src/ipp/hwc/ippServerConfig.toml
@@ -0,0 +1,5 @@
+dataformat = 'json'
+
+[tcp]
+    address='localhost'
+    port=1294
\ No newline at end of file
diff --git a/src/ipp/hwc/ipp_client.py b/src/ipp/hwc/ipp_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..ccbf668ad7c7e3c1b6f9ad24644d959d9502db7b
--- /dev/null
+++ b/src/ipp/hwc/ipp_client.py
@@ -0,0 +1,126 @@
+from __future__ import annotations
+import socket
+from threading import Thread
+import typing
+from . import transaction
+
+if typing.TYPE_CHECKING:
+    from .device import Device
+
+
+class UnexpectedTagError(Exception):
+    def __init__(self):
+        self.message = "The received message contains an unexpected tag."
+
+
+class MissingACKError(Exception):
+    def __init__(self):
+        self.message = "Was expecting an ACK response but received something else."
+
+
+class MissingTransactionCompleteResponseError(Exception):
+    def __init__(self):
+        self.message = "Transaction complete response is missing."
+
+
+class DaemonNonDataMessage(Exception):
+    def __init__(self):
+        self.message = "Received a daemon message that is not a data message!"
+
+
+class IPPClient(Thread):
+    def __init__(self, device_i: Device):
+        Thread.__init__(self)
+        self._socket = None
+        self._active = False
+        self._command_tag = 1
+        self._transaction_log = {}
+        self._data_log = {}
+        self._daemon_log = {}
+        self._active_streams = []
+        self._device = device_i
+
+    def _handle_event(self, tag, message_type, message_body):
+        non_event_tag = "0" + tag[1:5]
+        if non_event_tag in self._active_streams:
+            daemon = self._transaction_log.get(non_event_tag)
+            if message_type != "#":
+                raise DaemonNonDataMessage()
+            daemon['cb'].update_device(message_body.split(","))
+
+
+    def _parse_message(self, message):
+        print("<-- " + message)
+        message = message.split(" ")
+        tag = message[0]
+        message_type = message[1]
+        if tag[0] == "E":
+            self._handle_event(tag, message_type, "".join(message[2:]))
+            return
+
+        transaction = self._transaction_log.get(tag)
+        if not transaction['ACK']:
+            if message_type == '&':
+                transaction['ACK'] = True
+                return
+            else:
+                raise MissingACKError()
+
+        if message_type == '#':
+            self._data_log[tag + '#' + transaction['uuid']].append(message[::2])
+            return
+
+        if message_type == '%':
+            if not transaction['daemon']:
+                self._transaction_log.pop(tag)
+            return
+
+        return
+
+    def _send(self, message):
+        print("--> " + message.decode())
+        self._socket.sendall(message)
+
+    def transaction(self, command, streams):
+        tag = str(self._command_tag).zfill(5)
+        command_name = command.split('(')[0]
+
+        if streams:
+            self._active_streams.append(tag)
+
+        # Add transaction to pending transaction log
+        self._transaction_log[tag] = {
+            'ACK': False,
+            'uuid': command,
+            'daemon': streams,
+            'cb': transaction.create(command_name, tag, self._device)
+        }
+
+        self._send(str.encode(tag + " " + command + "\n"))
+        self._command_tag = self._command_tag + 1
+
+    def _listen(self):
+        buffer = []
+        stitch = False
+        while True:
+            if (len(buffer) > 0 and not stitch) or (len(buffer) > 1):
+                self._parse_message(buffer[0])
+                buffer.pop(0)
+                continue
+            data, _ = self._socket.recvfrom(1024)
+            data = data.decode()
+            buffer = buffer + (data.splitlines())
+            if stitch:
+                buffer[0:2] = ["".join(buffer[0:2])]
+                stitch = False
+            if len(data) > 0:
+                if data[-1] != '\n':
+                    stitch = True
+
+    def run(self):
+        self._active = True
+        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self._socket.connect(('localhost', 1294))
+
+        listener = Thread(target=self._listen)
+        listener.start()
diff --git a/src/ipp/hwc/transaction.py b/src/ipp/hwc/transaction.py
new file mode 100644
index 0000000000000000000000000000000000000000..82b67f64fc15bb31248ea1caa469e7b3d73c50e5
--- /dev/null
+++ b/src/ipp/hwc/transaction.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+from abc import ABC, abstractmethod
+import re
+import typing
+from sys import modules
+
+if typing.TYPE_CHECKING:
+    from .device import Device
+
+
+class TransactionNotImplementedException(Exception):
+    def __init__(self):
+        self.message = "Tried to use an unimplemented Transaction."
+
+
+class Transaction(ABC):
+
+    def __init__(self, tag: str, device: Device):
+        self._tag = tag
+        self._device = device
+
+    @property
+    def tag(self) -> str:
+        return self._tag
+
+    @abstractmethod
+    def update_device(self, data):
+        ...
+
+
+class OnMoveReportTransaction(Transaction):
+    def __init__(self, tag: str, device: Device):
+        Transaction.__init__(self, tag, device)
+
+    def update_device(self, data):
+        print("OnMoveReport update: " + '[%s]' % ', '.join(map(str, data)))
+        for data_point in data:
+            axis = data_point.split("(")[0]
+            value = re.findall(r"-?\d+\.\d+", data_point)
+            value = value[0]
+            match axis:
+                case "X":
+                    self._device._x = float(value)
+                case "Y":
+                    self._device._y = float(value)
+                case "Z":
+                    self._device._z = float(value)
+        # self._tool.update([self._x, self._y, self._z])
+
+
+class StartSessionTransaction(Transaction):
+    def __init__(self, tag: str, device: Device):
+        Transaction.__init__(self, tag, device)
+
+    def update_device(self, data):
+        pass
+
+
+class PtMeasTransaction(Transaction):
+    def __init__(self, tag: str, device: Device):
+        Transaction.__init__(self, tag, device)
+
+    def update_device(self, data):
+        pass
+
+
+class ScanOnCurveTransaction(Transaction):
+    def __init__(self, tag: str, device: Device):
+        Transaction.__init__(self, tag, device)
+
+    def update_device(self, data):
+        pass
+
+
+class GoToTransaction(Transaction):
+    def __init__(self, tag: str, device: Device):
+        Transaction.__init__(self, tag, device)
+
+    def update_device(self, data):
+        pass
+
+
+def create(command: str, tag: str, device: Device) -> Transaction | None:
+    module = modules[__name__]
+    try:
+        transaction = getattr(module, '{}Transaction'.format(command))(tag, device)
+    except Exception:
+        print("Unknown command: " + '"' + command + '"')
+        print("No callback registered.")
+        return None
+    return transaction
+
diff --git a/src/ipp/main.py b/src/ipp/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..25e0a0699d5f0fbe464c341bb3d98758d8d113d0
--- /dev/null
+++ b/src/ipp/main.py
@@ -0,0 +1,12 @@
+import toml
+
+import start
+from hwc.device import Device
+from com_ipp import COMIpp
+
+if __name__ == '__main__':
+    device = Device()
+    soilClient = COMIpp(device)
+    device.start()
+
+    start.start(soilClient, toml.load('config.toml'), 'model.json')
\ No newline at end of file
diff --git a/src/lasertracker/hwc/com_base.py b/src/lasertracker/hwc/com_base.py
index bd8dbfce26a9ae3bd29e6ee71739cdb184558cbb..478847c52e776955aa456a8e5f256d0584477d43 100644
--- a/src/lasertracker/hwc/com_base.py
+++ b/src/lasertracker/hwc/com_base.py
@@ -24,13 +24,13 @@ class COMBase(COMBaseTOP):
         self._device.point_to(*par_position)
 
     def get_mea_azimuth(self):
-        return self._device.azimuth
+        return self._device.azimuth, random.random() * 10e-10
 
     def get_mea_elevation(self):
-        return self._device.elevation
+        return self._device.elevation, random.random() * 10e-10
 
     def get_mea_distance(self):
-        return self._device.distance
+        return self._device.distance, random.random() * 10e-9
 
     def get_par_state(self):
         return str(self._device.state)
diff --git a/src/lasertracker/hwc/com_target.py b/src/lasertracker/hwc/com_target.py
index 0c0d817b6272910927221a8c88c6d7059fe71216..cb0710f363c7dc078f33b2e3c0cbef39856c8ef7 100644
--- a/src/lasertracker/hwc/com_target.py
+++ b/src/lasertracker/hwc/com_target.py
@@ -1,3 +1,5 @@
+import random
+
 import time
 from typing import List
 
@@ -21,7 +23,7 @@ class COMTarget(COMTargetTOP):
             yield self.get_mea_position(), arg_label
 
     def get_mea_position(self):
-        return self._device.target.position
+        return self._device.target.position, [[random.random()*10e-9 for j in range(3)] for i in range(3)]
 
     def get_par_state(self):
         return str(self._device.target.state)
diff --git a/src/monitoring/hwc/com_environmentalsensor.py b/src/monitoring/hwc/com_environmentalsensor.py
index dc1bd5aae9c581defea49776011c74cd595e1dd9..ab7f19ab37252e03a1313bf8ce096f85ae5f9033 100644
--- a/src/monitoring/hwc/com_environmentalsensor.py
+++ b/src/monitoring/hwc/com_environmentalsensor.py
@@ -1,3 +1,7 @@
+from typing import Tuple, Any
+
+import random
+
 from com_environmentalsensor import COMEnvironmentalSensorTOP
 from hwc.device import Device
 
@@ -8,20 +12,20 @@ class COMEnvironmentalSensor(COMEnvironmentalSensorTOP):
         COMEnvironmentalSensorTOP.__init__(self, device, location)
         self.uuid = id
         
-    def get_mea_temperature(self) -> float:
-        return self._device.sensors[self.uuid].temperature
+    def get_mea_temperature(self) -> Tuple[float, Any]:
+        return self._device.sensors[self.uuid].temperature, random.random() * 10e-2
 
-    def get_mea_pressure(self) -> float:
-        return self._device.sensors[self.uuid].pressure
+    def get_mea_pressure(self) -> Tuple[float, Any]:
+        return self._device.sensors[self.uuid].pressure, random.random() * 10e-1
 
-    def get_mea_humidity(self) -> float:
-        return self._device.sensors[self.uuid].humidity
+    def get_mea_humidity(self) -> Tuple[float, Any]:
+        return self._device.sensors[self.uuid].humidity, random.random() * 10e-3
 
-    def get_mea_signalstrength(self) -> int:
-        return self._device.sensors[self.uuid].signal_strength
+    def get_mea_signalstrength(self) -> Tuple[int, Any]:
+        return self._device.sensors[self.uuid].signal_strength, None
 
-    def get_mea_batterylevel(self) -> int:
-        return self._device.sensors[self.uuid].battery_level
+    def get_mea_batterylevel(self) -> Tuple[int, Any]:
+        return self._device.sensors[self.uuid].battery_level, None
 
     def get_par_location(self) -> str:
         return self._par_location
diff --git a/src/robot/hwc/com_mobilerobot.py b/src/robot/hwc/com_mobilerobot.py
index d428f154514221ca363fd5615136afb4237ef5cb..3665c28fd8bf3e89af80f59952297b02ca6abf79 100644
--- a/src/robot/hwc/com_mobilerobot.py
+++ b/src/robot/hwc/com_mobilerobot.py
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Any, Tuple
 
 import numpy
 
@@ -13,11 +13,11 @@ class COMMobileRobot(COMMobileRobotTOP):
         self._mea_position = numpy.array([0, 0, 0], dtype=float)
         self._device.start()
 
-    def get_mea_position(self) -> List[float]:
-        return self._device.position.tolist()
+    def get_mea_position(self) -> Tuple[List[float], Any]:
+        return self._device.position.tolist(), None
 
-    def get_mea_batterylevel(self) -> int:
-        return self._device.batterylevel
+    def get_mea_batterylevel(self) -> Tuple[int, Any]:
+        return self._device.batterylevel, None
 
     def get_par_auto(self) -> bool:
         return self._device.mode == Mode.AUTO
diff --git a/src/robot/hwc/com_robot.py b/src/robot/hwc/com_robot.py
index 62cfdd3588df27e8ea1ff77a00317c5804ee8358..db212f07366b10bbaf1a80a1d0def50e92b2456f 100644
--- a/src/robot/hwc/com_robot.py
+++ b/src/robot/hwc/com_robot.py
@@ -1,5 +1,5 @@
 import time
-from typing import List
+from typing import List, Tuple, Any
 
 import numpy
 
@@ -16,8 +16,8 @@ class COMRobot(COMRobotTOP):
         self._mea_position = numpy.array([0, 0, 0], dtype=float)
         self._com_gripper = COMGripper(device, open=True)
 
-    def get_mea_position(self) -> List[float]:
-        return self._device.position.tolist()
+    def get_mea_position(self) -> Tuple[List[float], Any]:
+        return self._device.position.tolist(), None
 
     def fun_goto(self, arg_position: List[float] = None):
         self._device.goto(numpy.array(arg_position))