diff --git a/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml b/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml
index be75fe2bccdff73b2aead2aaefb4d1f256d6382f..b6645926453ca505e2732cd9a09225e1f7b733cc 100644
--- a/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml
+++ b/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml
@@ -13,7 +13,7 @@
     <option name="ADD_SOURCE_ROOTS" value="true" />
     <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
     <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
-    <option name="PARAMETERS" value="-m 3 -s 17 -o 129 -c 1 -t 2.2" />
+    <option name="PARAMETERS" value="-m 3 -s 17 -o 130 -c 1 -t 2.2" />
     <option name="SHOW_COMMAND_LINE" value="false" />
     <option name="EMULATE_TERMINAL" value="true" />
     <option name="MODULE_MODE" value="false" />
diff --git a/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml b/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml
index 62d76453220579e6f173b981fafee2a4fab08473..b7394cbce13ae7c4f410959e820edcf2c31248c5 100644
--- a/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml
+++ b/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml
@@ -13,7 +13,7 @@
     <option name="ADD_SOURCE_ROOTS" value="true" />
     <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
     <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
-    <option name="PARAMETERS" value="-m 3 -s 17 -o 128 -c 1 -t 2.2" />
+    <option name="PARAMETERS" value="-m 3 -s 17 -o 129 -c 1 -t 2.2" />
     <option name="SHOW_COMMAND_LINE" value="false" />
     <option name="EMULATE_TERMINAL" value="true" />
     <option name="MODULE_MODE" value="false" />
diff --git a/.idea/runConfigurations/tmtcclient_Run_Time_Stats_OBC_.xml b/.idea/runConfigurations/tmtcclient_Run_Time_Stats_OBC_.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8e3e5851b3f02f90adb088bc83c11d659719c433
--- /dev/null
+++ b/.idea/runConfigurations/tmtcclient_Run_Time_Stats_OBC_.xml
@@ -0,0 +1,24 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="tmtcclient Run Time Stats OBC " type="PythonConfigurationType" factoryName="Python" folderName="Serial Core">
+    <module name="tmtc" />
+    <option name="INTERPRETER_OPTIONS" value="" />
+    <option name="PARENT_ENVS" value="true" />
+    <envs>
+      <env name="PYTHONUNBUFFERED" value="1" />
+    </envs>
+    <option name="SDK_HOME" value="" />
+    <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+    <option name="IS_MODULE_SDK" value="true" />
+    <option name="ADD_CONTENT_ROOTS" value="true" />
+    <option name="ADD_SOURCE_ROOTS" value="true" />
+    <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+    <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
+    <option name="PARAMETERS" value="-m 3 -s Core -o A0 -c 1 -t 2.5" />
+    <option name="SHOW_COMMAND_LINE" value="false" />
+    <option name="EMULATE_TERMINAL" value="true" />
+    <option name="MODULE_MODE" value="false" />
+    <option name="REDIRECT_INPUT" value="false" />
+    <option name="INPUT_FILE" value="" />
+    <method v="2" />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml b/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d8483e91e0c5ee927bf310001149083e5b92467e
--- /dev/null
+++ b/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml
@@ -0,0 +1,24 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="tmtcclient Trigger Exceptions" type="PythonConfigurationType" factoryName="Python" folderName="Serial Utility">
+    <module name="tmtc" />
+    <option name="INTERPRETER_OPTIONS" value="" />
+    <option name="PARENT_ENVS" value="true" />
+    <envs>
+      <env name="PYTHONUNBUFFERED" value="1" />
+    </envs>
+    <option name="SDK_HOME" value="" />
+    <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+    <option name="IS_MODULE_SDK" value="true" />
+    <option name="ADD_CONTENT_ROOTS" value="true" />
+    <option name="ADD_SOURCE_ROOTS" value="true" />
+    <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+    <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
+    <option name="PARAMETERS" value="-m 3 -s 17 -o 150 -c 1 -t 2.2" />
+    <option name="SHOW_COMMAND_LINE" value="false" />
+    <option name="EMULATE_TERMINAL" value="true" />
+    <option name="MODULE_MODE" value="false" />
+    <option name="REDIRECT_INPUT" value="false" />
+    <option name="INPUT_FILE" value="" />
+    <method v="2" />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/config/obsw_com_config.py b/config/obsw_com_config.py
index 3de6c2863cc55bd60f83dc150043fe31ff972d53..93de2bae8f4a290d1d76a0ceba8d4f102e81289b 100644
--- a/config/obsw_com_config.py
+++ b/config/obsw_com_config.py
@@ -41,8 +41,7 @@ def set_communication_interface(tmtc_printer: TmTcPrinter) -> Union[Communicatio
                 g.G_SERIAL_DLE_MAX_QUEUE_LEN, g.G_SERIAL_DLE_MAX_FRAME_SIZE, serial_timeout)
         elif g.G_COM_IF == g.ComIF.QEMU:
             communication_interface = QEMUComIF(
-                tmtc_printer=tmtc_printer, tm_timeout=g.G_TM_TIMEOUT,
-                tc_timeout_factor=g.G_TC_SEND_TIMEOUT_FACTOR)
+                tmtc_printer=tmtc_printer, serial_timeout=g.G_TM_TIMEOUT)
         else:
             communication_interface = DummyComIF(tmtc_printer=tmtc_printer)
         if not communication_interface.valid:
diff --git a/gui/obsw_backend_test.py b/gui/obsw_backend_test.py
index c21caeec5ea9d5dacbc119a6c49e66b27237083a..d9e6c488a10a2a9c5050d4dd33f328f01d548abb 100644
--- a/gui/obsw_backend_test.py
+++ b/gui/obsw_backend_test.py
@@ -6,6 +6,7 @@ import logging
 
 LOGGER = get_logger()
 
+
 class TmTcBackend(Process):
     def __init__(self):
         from obsw_tmtc_client import TmTcHandler
@@ -20,7 +21,7 @@ class TmTcBackend(Process):
 
     def listen(self):
         self.conn = self.listener.accept()
-        LOGGER.info("TmTcBackend: Connection accepted from %s",str(self.listener.last_accepted))
+        LOGGER.info("TmTcBackend: Connection accepted from %s", str(self.listener.last_accepted))
         while True:
             msg = self.conn.recv()
             # do something with msg
diff --git a/gui/obsw_tmtc_gui.py b/gui/obsw_tmtc_gui.py
index 8c322d5e8e7f54f2ba7a23b5dd9b6209624db546..5c4ba4c80a2b757aa76f933fa979a974ea7d9ddd 100644
--- a/gui/obsw_tmtc_gui.py
+++ b/gui/obsw_tmtc_gui.py
@@ -21,6 +21,7 @@ import time
 
 LOGGER = get_logger()
 
+
 # A first simple version has drop down menus to chose all necessary options
 # which are normally handled by the args parser.
 # when pressing save, all chosen values get passed to the globals file (OBSW_Config)
diff --git a/requirements.txt b/requirements.txt
index 4a3f79dd0651dd1e85c8e72f74264a7f5a6cecde..4ac62a18eeebe75e7db2b6cc16666ea926ccad88 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
 aiohttp==3.6.2
 astroid==2.4.2
 async-timeout==3.0.1
-attrs==19.3.0
+attrs==20.2.0
 chardet==3.0.4
 colorama==0.4.3
 cpplint==1.5.4
@@ -9,18 +9,18 @@ crcmod>=1.7
 docopt==0.6.2
 future==0.18.2
 idna==2.10
-iso8601==0.1.12
-isort==5.4.2
+iso8601==0.1.13
+isort==5.6.3
 lazy-object-proxy==1.5.1
 mccabe==0.6.1
 multidict==4.7.6
-pylint>=2.5.3
-PyQt5>=5.15.0
-PyQt5-sip>=12.8.0
+pylint>=2.6.0
+PyQt5>=5.15.1
+PyQt5-sip>=12.8.1
 pyserial>=3.4
 PyYAML==5.3.1
 six==1.15.0
 toml==0.10.1
-typing-extensions==3.7.4.2
-wrapt==1.11.2
-yarl==1.5.1
+typing-extensions==3.7.4.3
+wrapt==1.12.1
+yarl==1.6.0
diff --git a/tc/obsw_image_handler.py b/tc/obsw_image_handler.py
index aa8a3f08020deee54644c73100e983d5a195787d..5f96ad68b051046aea733aa89bb2321f9c792f3d 100644
--- a/tc/obsw_image_handler.py
+++ b/tc/obsw_image_handler.py
@@ -1,5 +1,5 @@
 from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand, Deque
-from  tc.obsw_tc_service8 import make_action_id
+from tc.obsw_tc_service8 import make_action_id
 from tmtc_core.utility.obsw_logger import get_logger
 from config.obsw_config import SW_IMAGE_HANDLER_ID
 
diff --git a/tc/obsw_pus_tc_frame_packer.py b/tc/obsw_pus_tc_frame_packer.py
index 71d045feb2fdf3a4565384d88afd0678ee3fa7e7..12447d34e9288af1fcff012337ac936c21d9e0ff 100644
--- a/tc/obsw_pus_tc_frame_packer.py
+++ b/tc/obsw_pus_tc_frame_packer.py
@@ -49,4 +49,4 @@ def pack_tc_info(tc_list: List[PusTelecommand]) -> List[PusTcInfo]:
     tc_info_list = list()
     for tc in tc_list:
         tc_info_list.append(tc.pack_information())
-    return tc_info_list
\ No newline at end of file
+    return tc_info_list
diff --git a/tc/obsw_pus_tc_packer.py b/tc/obsw_pus_tc_packer.py
index 613044ace236b3acdba7fb62cdb7025671cae346..52152688dad6933afa6fa76d717a9be147d9f736 100644
--- a/tc/obsw_pus_tc_packer.py
+++ b/tc/obsw_pus_tc_packer.py
@@ -34,7 +34,8 @@ class ServiceQueuePacker:
     def __init__(self):
         pass
 
-    def pack_service_queue(self, service: Union[int, str], op_code: int, service_queue: TcQueueT):
+    @staticmethod
+    def pack_service_queue(service: Union[int, str], op_code: int, service_queue: TcQueueT):
         if service == 2:
             return pack_service2_test_into(service_queue)
         if service == 3:
diff --git a/tc/obsw_tc_gps.py b/tc/obsw_tc_gps.py
index 9d9e1eb29cd230694aab8ed3129e640c7eaf2f4f..1a047bf304543f8268967c814f068419fd3bfc96 100644
--- a/tc/obsw_tc_gps.py
+++ b/tc/obsw_tc_gps.py
@@ -11,6 +11,7 @@ from tc.obsw_tc_service2 import pack_mode_data
 
 import config.obsw_config as g
 
+
 def pack_gps_test_into(object_id: bytearray, tc_queue: TcQueueT) -> TcQueueT:
     if object_id == g.GPS0_DEVICE_ID:
         gps_string = "GPS0"
diff --git a/tc/obsw_tc_service20.py b/tc/obsw_tc_service20.py
index 1b316d68e38b0f2750857c2e78392f9968dc1d7e..24ce024e069c49f1b22d4b9c8dfb86ab6bbfa12e 100644
--- a/tc/obsw_tc_service20.py
+++ b/tc/obsw_tc_service20.py
@@ -14,7 +14,7 @@ from tc.obsw_tc_service200 import pack_mode_data
 
 
 def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) -> Deque:
-    #parameter IDs
+    # parameter IDs
     parameterID0 = 0
     parameterID1 = 1
     parameterID2 = 2
@@ -29,33 +29,33 @@ def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) -
     command = PusTelecommand(service=200, subservice=1, ssc=2000, app_data=mode_data)
     tc_queue.appendleft(command.pack_command_tuple())
 
-    #test invalid subservice
-    #use subservice 130 for invalid subservice check, as this is in use for dump reply
-    #(and therefore will never be a valid subservice)
-    #tc_queue.appendleft(("print", "Testing Service 20: Invalid subservice"))
-    #mode_data = pack_mode_data(object_id, 2, 0)
-    #command = PusTelecommand(service=20, subservice=130, ssc=810, app_data=mode_data)
-    #tc_queue.appendleft(command.pack_command_tuple())
-
-    #test invalid objectid //TODO: do we have an objectid known to be empty (even in future)?
-    #tc_queue.appendleft(("print", "Testing Service 20: Invalid object ID"))
-    #mode_data = pack_mode_data(object_id, 2, 0)
-    #command = PusTelecommand(service=20, subservice=128, ssc=810, app_data=mode_data)
-    #tc_queue.appendleft(command.pack_command_tuple())
-
-    #test invalid parameterID for load
-    #tc_queue.appendleft(("print", "Testing Service 20: Invalid parameter ID for load"))
-    #mode_data = pack_mode_data(object_id, 2, 0)
-    #command = PusTelecommand(service=20, subservice=128, ssc=810, app_data=mode_data)
-    #tc_queue.appendleft(command.pack_command_tuple())
-
-    #test invalid parameterID for dump
-    #tc_queue.appendleft(("print", "Testing Service 20: Invalid parameter ID for dump"))
-    #mode_data = pack_mode_data(object_id, 2, 0)
-    #command = PusTelecommand(service=20, subservice=129, ssc=810, app_data=mode_data)
-    #tc_queue.appendleft(command.pack_command_tuple())
-
-    #test checking Load for uint32_t
+    # test invalid subservice
+    # use subservice 130 for invalid subservice check, as this is in use for dump reply
+    # (and therefore will never be a valid subservice)
+    # tc_queue.appendleft(("print", "Testing Service 20: Invalid subservice"))
+    # mode_data = pack_mode_data(object_id, 2, 0)
+    # command = PusTelecommand(service=20, subservice=130, ssc=810, app_data=mode_data)
+    # tc_queue.appendleft(command.pack_command_tuple())
+
+    # test invalid objectid //TODO: do we have an objectid known to be empty (even in future)?
+    # tc_queue.appendleft(("print", "Testing Service 20: Invalid object ID"))
+    # mode_data = pack_mode_data(object_id, 2, 0)
+    # command = PusTelecommand(service=20, subservice=128, ssc=810, app_data=mode_data)
+    # tc_queue.appendleft(command.pack_command_tuple())
+
+    # test invalid parameterID for load
+    # tc_queue.appendleft(("print", "Testing Service 20: Invalid parameter ID for load"))
+    # mode_data = pack_mode_data(object_id, 2, 0)
+    # command = PusTelecommand(service=20, subservice=128, ssc=810, app_data=mode_data)
+    # tc_queue.appendleft(command.pack_command_tuple())
+
+    # test invalid parameterID for dump
+    # tc_queue.appendleft(("print", "Testing Service 20: Invalid parameter ID for dump"))
+    # mode_data = pack_mode_data(object_id, 2, 0)
+    # command = PusTelecommand(service=20, subservice=129, ssc=810, app_data=mode_data)
+    # tc_queue.appendleft(command.pack_command_tuple())
+
+    # test checking Load for uint32_t
     tc_queue.appendleft(("print", "Testing Service 20: Load uint32_t"))
     parameter_id = struct.pack(">I", parameterID0)
     parameter_data = struct.pack(">I", 42)
@@ -63,7 +63,7 @@ def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) -
     command = PusTelecommand(service=20, subservice=128, ssc=2001, app_data=payload)
     tc_queue.appendleft(command.pack_command_tuple())
 
-    #test checking Dump for uint32_t
+    # test checking Dump for uint32_t
     tc_queue.appendleft(("print", "Testing Service 20: Dump uint32_t"))
     parameter_id = struct.pack(">I", parameterID0)
     payload = object_id + parameter_id
@@ -101,9 +101,6 @@ def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) -
     tc_queue.appendleft(command.pack_command_tuple())
 """
 
-
-
-
 """
     # set mode on
     tc_queue.appendleft(("print", "Testing Service 8: Set On Mode"))
diff --git a/tc/obsw_tc_service23_sdcard.py b/tc/obsw_tc_service23_sdcard.py
index 1bd3a8b792de2b57e6a9885cb7f4f4474ea34c03..ccd07d808c1b253838c2d5e3e4b9322b88c0fdbf 100644
--- a/tc/obsw_tc_service23_sdcard.py
+++ b/tc/obsw_tc_service23_sdcard.py
@@ -318,14 +318,8 @@ def generate_create_file_srv23_1_packet(
             max_size_of_app_data, filename, repository_path):
         LOGGER.error("generate_create_file_srv23_1_packet: Initial data too large!")
         return None
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator to repository_path
-    data_to_pack.append(0)
-    data_to_pack += filename.encode('utf-8')
-    # Add string terminator to filename
-    data_to_pack.append(0)
-
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
     data_to_pack += initial_data
     return PusTelecommand(service=23, subservice=1, ssc=ssc, app_data=data_to_pack)
 
@@ -339,18 +333,28 @@ def generate_rm_file_srv23_2_packet(filename: str, repository_path: str,
     @param repository_path: The path where the directory shall be created
     @param ssc: source sequence count
     @param object_id: The object ID of the memory handler which manages the file system
-    :return The TC[23,2] PUS packet
+    @return The telecommand.
     """
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator to repository_path
-    data_to_pack.append(0)
-    data_to_pack += filename.encode('utf-8')
-    # Add string terminator to filename
-    data_to_pack.append(0)
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
     return PusTelecommand(service=23, subservice=2, ssc=ssc, app_data=data_to_pack)
 
 
+def generate_report_file_attr_srv23_3_packet(
+        filename: str, repository_path: str, ssc: int,
+        object_id=g.SD_CARD_HANDLER_ID) -> PusTelecommand:
+    """
+    @param filename: The name of the file to delete
+    @param repository_path: The path where the directory shall be created
+    @param ssc: source sequence count
+    @param object_id: The object ID of the memory handler which manages the file system
+    @return The telecommand.
+    """
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
+    return PusTelecommand(service=23, subservice=3, ssc=ssc, app_data=data_to_pack)
+
+
 def generate_mkdir_srv23_9_packet(directory_name: str, ssc: int, repository_path: str = "/",
                                   object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand:
     """
@@ -359,15 +363,10 @@ def generate_mkdir_srv23_9_packet(directory_name: str, ssc: int, repository_path
     @param repository_path: The name of the directory to create
     @param ssc: source sequence count
     @param object_id: The object ID of the memory handler which manages the file system
-    :return
+    @return The telecommand.
     """
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator to repository path
-    data_to_pack.append(0)
-    data_to_pack += directory_name.encode('utf-8')
-    # Add string terminator to directory name
-    data_to_pack.append(0)
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=directory_name)
     return PusTelecommand(service=23, subservice=9, ssc=ssc, app_data=data_to_pack)
 
 
@@ -379,15 +378,10 @@ def generate_rmdir_srv23_10_packet(directory_name: str, repository_path: str, ss
     @param repository_path: Path to directory dirname
     @param ssc: source sequence count
     @param object_id: object ID of the memory handler (e.g. SD Card Handler)
-    @return The application data field of the (23,10) PUS packet
+    @return The telecommand.
     """
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator of repository path
-    data_to_pack.append(0)
-    data_to_pack += directory_name.encode('utf-8')
-    # Add string terminator of directory name
-    data_to_pack.append(0)
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=directory_name)
     return PusTelecommand(service=23, subservice=10, ssc=ssc, app_data=data_to_pack)
 
 
@@ -395,13 +389,8 @@ def generate_append_to_file_srv23_130_packet(
         filename: str, repository_path: str, packet_sequence_number: int,
         ssc: int, file_data: bytearray = bytearray([]),
         object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand:
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator of repository path
-    data_to_pack.append(0)
-    data_to_pack += filename.encode('utf-8')
-    # Add string terminator of filename
-    data_to_pack.append(0)
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
     data_to_pack += file_data
     data_to_pack.append(packet_sequence_number >> 8)
     data_to_pack.append(packet_sequence_number & 0xff)
@@ -411,13 +400,8 @@ def generate_append_to_file_srv23_130_packet(
 def generate_finish_append_to_file_srv23_131_packet(
         filename: str, repository_path: str,  ssc: int, lock_file: bool = False,
         object_id: bytearray = g.SD_CARD_HANDLER_ID):
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator of repository path
-    data_to_pack.append(0)
-    data_to_pack += filename.encode('utf-8')
-    # Add string terminator of filename
-    data_to_pack.append(0)
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
     data_to_pack.append(lock_file)
     return PusTelecommand(service=23, subservice=131, ssc=ssc, app_data=data_to_pack)
 
@@ -434,115 +418,55 @@ def generate_read_file_srv23_140_packet(
     @param object_id: object ID of the memory handler (e.g. SD Card Handler)
     @return: The application data field of the (23,129) PUS packet
     """
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator of repository paht
-    data_to_pack.append(0)
-    data_to_pack += filename.encode('utf-8')
-    # Add string terminator of filename
-    data_to_pack.append(0)
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
     return PusTelecommand(service=23, subservice=140, ssc=ssc, app_data=data_to_pack)
 
 
-def generate_lock_file_packet(ssc: int, lock: bool, repository_path: str, filename: str,
-                              object_id: bytearray = g.SD_CARD_HANDLER_ID):
-    data_to_pack = bytearray(object_id)
-    data_to_pack += repository_path.encode('utf-8')
-    # Add string terminator of repository paht
-    data_to_pack.append(0)
-    data_to_pack += filename.encode('utf-8')
-    # Add string terminator of filename
-    data_to_pack.append(0)
+def generate_lock_file_srv23_5_6_packet(ssc: int, lock: bool, repository_path: str,
+                                        filename: str, object_id: bytearray = g.SD_CARD_HANDLER_ID):
+    data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path,
+                                                    second_path=filename)
     if lock:
         return PusTelecommand(service=23, subservice=5, ssc=ssc, app_data=data_to_pack)
     else:
         return PusTelecommand(service=23, subservice=6, ssc=ssc, app_data=data_to_pack)
 
 
-def pack_service23_commands_into(tc_queue: Deque, op_code: int) -> Deque:
+def pack_service23_commands_into(tc_queue: TcQueueT, op_code: int) -> Deque:
     # sd_handler_id = g.SD_CARD_HANDLER_ID
     if op_code == 0:
-        tc_queue.appendleft(("print", "Testing Service 23"))
-
-        tc_queue.append(("print", "Create directory 'test'"))
-        command = generate_mkdir_srv23_9_packet(directory_name="test", repository_path="/", ssc=2300)
-        tc_queue.appendleft(command.pack_command_tuple())
-        tc_queue.append(("print", "Create subdirectory 'subdir' in 'test'"))
-        command = generate_mkdir_srv23_9_packet(repository_path="test", ssc=2301,
-                                                directory_name="subdir")
-        tc_queue.appendleft(command.pack_command_tuple())
-
-        tc_queue.appendleft(("print", "Create test.bin"))
-        command = generate_create_file_srv23_1_packet(
-             filename="test.bin", repository_path="test/subdir", ssc=2302,
-             initial_data=bytearray([0x01, 0x00, 0x01, 0x00]),
-             max_size_of_app_data=1024)
-        tc_queue.appendleft(command.pack_command_tuple())
-
-        tc_queue.appendleft(("print", "Printing file structure."))
-        command = generate_print_sd_card_packet(ssc=2300)
-        tc_queue.appendleft(command.pack_command_tuple())
-
-        tc_queue.appendleft(("print", "Clearing SD card"))
-        command = generate_clear_sd_card_packet(ssc=2301)
-        tc_queue.appendleft(command.pack_command_tuple())
-
-        tc_queue.appendleft(("print", "Printing file structure"))
-        command = generate_print_sd_card_packet(ssc=2302)
-        tc_queue.appendleft(command.pack_command_tuple())
-
-        # tc_queue.appendleft(("print", "Read data of test.bin"))
-        # command = generate_read_file_srv23_129_packet("test/subdir", "test.bin", ssc=2303)
-        # tc_queue.appendleft(command.pack_command_tuple())
-        tc_queue.appendleft(("print", "Delete 'test.bin'"))
-        command = generate_rm_file_srv23_2_packet(
-            filename="test.bin", repository_path="test/subdir", ssc=2304)
-        tc_queue.appendleft(command.pack_command_tuple())
-        tc_queue.appendleft(("print", "Delete 'subdir' directory"))
-        command = generate_rmdir_srv23_10_packet(directory_name="subdir", repository_path="test",
-                                                 ssc=2305)
-        tc_queue.appendleft(command.pack_command_tuple())
-        tc_queue.appendleft(("print", "Delete 'test' directory"))
-        command = generate_rmdir_srv23_10_packet(directory_name="test", repository_path="/",
-                                                 ssc=2306)
-        tc_queue.appendleft(command.pack_command_tuple())
-    elif op_code == "A2":
-        tc_queue.append(("print", "Printing active file system"))
-        command = generate_print_sd_card_packet(ssc=2300)
-        tc_queue.appendleft(command.pack_command_tuple())
-    elif op_code == "A20":
-        tc_queue.append(("print", "Clearing active file system"))
-        command = generate_clear_sd_card_packet(ssc=2300)
-        tc_queue.appendleft(command.pack_command_tuple())
-    elif op_code == "A21":
-        tc_queue.append(("print", "Formatting active file system"))
-        command = generate_format_sd_card_packet(ssc=2300)
-        tc_queue.appendleft(command.pack_command_tuple())
-    elif op_code == "C0A":
-        tc_queue.append(("print", "Generating generic folder structure on AT91"))
-        generate_generic_folder_structure(tc_queue, init_ssc=0, iobc=False)
-    elif op_code == "C0I":
-        tc_queue.append(("print", "Generating generic folder structure on iOBC"))
-        generate_generic_folder_structure(tc_queue, init_ssc=0, iobc=True)
+        generate_generic_service_23_test(tc_queue)
+    elif op_code == "3" or op_code == 3:
+        LOGGER.info("Press h in the following input requests")
+        LOGGER.info("to send a command to display the folder structure instead")
+        (repo_path, filename) = prompt_for_repo_filename()
+        if repo_path == "" and filename == "h":
+            tc_queue.appendleft(generate_print_sd_card_packet(ssc=0).pack_command_tuple())
+        elif repo_path == "" and filename == "c":
+            return tc_queue
+        else:
+            tc_queue.append(("print", "Requesting file attributes"))
+            command = generate_report_file_attr_srv23_3_packet(
+                ssc=0, filename=filename, repository_path=repo_path)
+            tc_queue.appendleft(command.pack_command_tuple())
     elif op_code == "5" or op_code == 5:
-
         LOGGER.info("Press h in the following input requests")
-        LOGGER.info("to send a command to display the folder sturcture instead")
+        LOGGER.info("to send a command to display the folder structure instead")
         (repo_path, filename) = prompt_for_repo_filename()
         if repo_path == "" and filename == "h":
             tc_queue.append(("print", "Printing active file system"))
-            tc_queue.appendleft(generate_print_sd_card_packet(ssc=0))
+            tc_queue.appendleft(generate_print_sd_card_packet(ssc=0).pack_command_tuple())
         elif repo_path == "" and filename == "c":
             return tc_queue
         else:
             tc_queue.append(("print", "Locking file"))
-            command = generate_lock_file_packet(0, repository_path=repo_path, filename=filename,
-                                                lock=True)
+            command = generate_lock_file_srv23_5_6_packet(ssc=0, repository_path=repo_path,
+                                                          filename=filename, lock=True)
             tc_queue.appendleft(command.pack_command_tuple())
     elif op_code == "6" or op_code == 6:
-
         LOGGER.info("Press h in the following input requests to send a command to display the"
-                    "folder sturcture instead")
+                    "folder structure instead")
         (repo_path, filename) = prompt_for_repo_filename()
         if repo_path == "" and filename == "h":
             tc_queue.append(("print", "Printing active file system"))
@@ -551,12 +475,78 @@ def pack_service23_commands_into(tc_queue: Deque, op_code: int) -> Deque:
             return tc_queue
         else:
             tc_queue.append(("print", "Unlocking file"))
-            command = generate_lock_file_packet(0, repository_path=repo_path, filename=filename,
-                                                lock=False)
+            command = generate_lock_file_srv23_5_6_packet(ssc=0, repository_path=repo_path,
+                                                          filename=filename, lock=False)
             tc_queue.appendleft(command.pack_command_tuple())
+    elif op_code == "A2":
+        tc_queue.append(("print", "Printing active file system"))
+        command = generate_print_sd_card_packet(ssc=2300)
+        tc_queue.appendleft(command.pack_command_tuple())
+    elif op_code == "A20":
+        tc_queue.append(("print", "Clearing active file system"))
+        command = generate_clear_sd_card_packet(ssc=2300)
+        tc_queue.appendleft(command.pack_command_tuple())
+    elif op_code == "A21":
+        tc_queue.append(("print", "Formatting active file system"))
+        command = generate_format_sd_card_packet(ssc=2300)
+        tc_queue.appendleft(command.pack_command_tuple())
+    elif op_code == "C0A":
+        tc_queue.append(("print", "Generating generic folder structure on AT91"))
+        generate_generic_folder_structure(tc_queue, init_ssc=0, iobc=False)
+    elif op_code == "C0I":
+        tc_queue.append(("print", "Generating generic folder structure on iOBC"))
+        generate_generic_folder_structure(tc_queue, init_ssc=0, iobc=True)
+
     return tc_queue
 
 
+def generate_generic_service_23_test(tc_queue: TcQueueT):
+    tc_queue.appendleft(("print", "Testing Service 23"))
+
+    tc_queue.append(("print", "Create directory 'test'"))
+    command = generate_mkdir_srv23_9_packet(directory_name="test", repository_path="/", ssc=2300)
+    tc_queue.appendleft(command.pack_command_tuple())
+    tc_queue.append(("print", "Create subdirectory 'subdir' in 'test'"))
+    command = generate_mkdir_srv23_9_packet(repository_path="test", ssc=2301,
+                                            directory_name="subdir")
+    tc_queue.appendleft(command.pack_command_tuple())
+
+    tc_queue.appendleft(("print", "Create test.bin"))
+    command = generate_create_file_srv23_1_packet(
+        filename="test.bin", repository_path="test/subdir", ssc=2302,
+        initial_data=bytearray([0x01, 0x00, 0x01, 0x00]),
+        max_size_of_app_data=1024)
+    tc_queue.appendleft(command.pack_command_tuple())
+
+    tc_queue.appendleft(("print", "Printing file structure."))
+    command = generate_print_sd_card_packet(ssc=2300)
+    tc_queue.appendleft(command.pack_command_tuple())
+
+    tc_queue.appendleft(("print", "Clearing SD card"))
+    command = generate_clear_sd_card_packet(ssc=2301)
+    tc_queue.appendleft(command.pack_command_tuple())
+
+    tc_queue.appendleft(("print", "Printing file structure"))
+    command = generate_print_sd_card_packet(ssc=2302)
+    tc_queue.appendleft(command.pack_command_tuple())
+
+    # tc_queue.appendleft(("print", "Read data of test.bin"))
+    # command = generate_read_file_srv23_129_packet("test/subdir", "test.bin", ssc=2303)
+    # tc_queue.appendleft(command.pack_command_tuple())
+    tc_queue.appendleft(("print", "Delete 'test.bin'"))
+    command = generate_rm_file_srv23_2_packet(
+        filename="test.bin", repository_path="test/subdir", ssc=2304)
+    tc_queue.appendleft(command.pack_command_tuple())
+    tc_queue.appendleft(("print", "Delete 'subdir' directory"))
+    command = generate_rmdir_srv23_10_packet(directory_name="subdir", repository_path="test",
+                                             ssc=2305)
+    tc_queue.appendleft(command.pack_command_tuple())
+    tc_queue.appendleft(("print", "Delete 'test' directory"))
+    command = generate_rmdir_srv23_10_packet(directory_name="test", repository_path="/",
+                                             ssc=2306)
+    tc_queue.appendleft(command.pack_command_tuple())
+
+
 def calculate_allowed_file_data_size(max_app_data_size: int, filename: str, repository: str):
     # Subtract two because of '\0' terminators
     return max_app_data_size - len(filename) - len(repository) - 2
@@ -581,3 +571,14 @@ def prompt_for_repo_filename():
         if input_confirmation in ['y', "yes", 1]:
             input_confirmation = True
     return repo_path, filename
+
+
+def pack_generic_file_command_header(object_id: bytearray, first_path: str, second_path: str):
+    data_to_pack = bytearray(object_id)
+    data_to_pack += first_path.encode('utf-8')
+    # Add string terminator of repository paht
+    data_to_pack.append(0)
+    data_to_pack += second_path.encode('utf-8')
+    # Add string terminator of filename
+    data_to_pack.append(0)
+    return data_to_pack
diff --git a/tc/obsw_tc_service5_17.py b/tc/obsw_tc_service5_17.py
index 4b4a94aacc0d3ebf71bd1d5f036812adf38a891f..23dbd25701c81f31e544a658d3a617df6f281a03 100644
--- a/tc/obsw_tc_service5_17.py
+++ b/tc/obsw_tc_service5_17.py
@@ -36,7 +36,7 @@ def pack_service5_test_into(tc_queue: TcQueueT) -> TcQueueT:
     return tc_queue
 
 
-def pack_service17_test_into(tc_queue: TcQueueT, op_code: int) -> TcQueueT:
+def pack_service17_test_into(tc_queue: TcQueueT, op_code: int = 0) -> TcQueueT:
     if op_code == 0:
         tc_queue.appendleft(("print", "Testing Service 17"))
         # ping test
@@ -56,9 +56,9 @@ def pack_service17_test_into(tc_queue: TcQueueT, op_code: int) -> TcQueueT:
         command = PusTelecommand(service=17, subservice=243, ssc=1702)
         tc_queue.appendleft(command.pack_command_tuple())
         tc_queue.appendleft(("export", "log/tmtc_log_service17.txt"))
-    elif op_code == 128:
-        pack_enable_periodic_print_packet(tc_queue, True, 0)
     elif op_code == 129:
+        pack_enable_periodic_print_packet(tc_queue, True, 0)
+    elif op_code == 130:
         pack_enable_periodic_print_packet(tc_queue, False, 0)
     elif op_code == 150:
         pack_trigger_exception_packet(tc_queue, 0)
@@ -68,9 +68,9 @@ def pack_service17_test_into(tc_queue: TcQueueT, op_code: int) -> TcQueueT:
 def pack_enable_periodic_print_packet(tc_queue: TcQueueT, enable: bool, ssc: int):
     tc_queue.appendleft(("print", "Enabling periodic printout"))
     if enable:
-        command = PusTelecommand(service=17, subservice=128, ssc=ssc)
-    else:
         command = PusTelecommand(service=17, subservice=129, ssc=ssc)
+    else:
+        command = PusTelecommand(service=17, subservice=130, ssc=ssc)
     tc_queue.appendleft(command.pack_command_tuple())
 
 
diff --git a/tc/obsw_tc_service9.py b/tc/obsw_tc_service9.py
index 507b57ffbba4723c9661970c4194ed97034a8aee..7970b0e5215faba74de4de94156f4a6236f16e29 100644
--- a/tc/obsw_tc_service9.py
+++ b/tc/obsw_tc_service9.py
@@ -36,4 +36,4 @@ def pack_service9_test_into(tc_queue: TcQueueT) -> TcQueueT:
     tc_queue.appendleft(command.pack_command_tuple())
     # TODO: Add other time formats here
     tc_queue.appendleft(("export", "log/tmtc_log_service9.txt"))
-    return tc_queue
\ No newline at end of file
+    return tc_queue
diff --git a/tm/obsw_pus_tm_factory_hook.py b/tm/obsw_pus_tm_factory_hook.py
index 29ec55a1af3839f859f7611378c53e58081f76d1..6effae10a4852b37511e9a0d243dc7351e9e5dcf 100644
--- a/tm/obsw_pus_tm_factory_hook.py
+++ b/tm/obsw_pus_tm_factory_hook.py
@@ -144,4 +144,4 @@ class Service200TM(PusTelemetry):
         elif self.isModeReply:
             array.append("Mode")
             array.append("Submode")
-        return
\ No newline at end of file
+        return
diff --git a/tm/obsw_tm_service_23.py b/tm/obsw_tm_service_23.py
index 65cf912b3d08cac2b9c685aaf971400248631ae8..b4668c332ff5c583f286129cbed23a6e5a5dafd3 100644
--- a/tm/obsw_tm_service_23.py
+++ b/tm/obsw_tm_service_23.py
@@ -1,4 +1,9 @@
+import struct
+
 from tmtc_core.tm.obsw_pus_tm_base import PusTelemetry
+from tmtc_core.utility.obsw_logger import get_logger
+
+LOGGER = get_logger()
 
 
 class Service23TM(PusTelemetry):
@@ -7,28 +12,68 @@ class Service23TM(PusTelemetry):
 
     def __init__(self, byte_array):
         super().__init__(byte_array)
+        if len(self.get_tm_data()) < 4:
+            LOGGER.error("Service23TM: Invalid packet format!")
+            return
+        self.object_id = struct.unpack('!I', self._tm_data[0:4])[0]
         self.repo_path = ""
         self.filename = ""
+        self.file_size = 0
+        self.lock_status = False
         self.data_start_idx = 0
-        if self.get_subservice() == 132:
-            # self.unpack_repo_and_filename()
+        if self.get_subservice() == 4:
+            self.unpack_repo_and_filename()
+            self.unpack_file_attributes()
+        elif self.get_subservice() == 132:
+            self.unpack_repo_and_filename()
             pass
 
     def unpack_repo_and_filename(self):
         repo_path_found = False
         path_idx_start = 0
-        for idx in range(self.MAX_FILENAME_LENGTH + self.MAX_REPOSITORY_LENGTH):
-            if self._tm_data[idx] == "\0":
-                repo_bytes = self._tm_data[0:idx-1]
+        max_len_to_scan = len(self.get_tm_data()) - 4
+        for idx in range(4, max_len_to_scan):
+            if not repo_path_found and self._tm_data[idx] == 0:
+                repo_bytes = self._tm_data[4:idx]
                 self.repo_path = repo_bytes.decode('utf-8')
-                print(self.repo_path)
                 path_idx_start = idx + 1
+                idx += 1
                 repo_path_found = True
             if repo_path_found:
-                if self._tm_data[idx] == "\0":
-                    filename_bytes = self._tm_data[path_idx_start:idx-1]
+                if self._tm_data[idx] == 0:
+                    filename_bytes = self._tm_data[path_idx_start:idx]
                     self.filename = filename_bytes.decode('utf-8')
-                    print(self.filename)
                     self.data_start_idx = idx + 1
+                    break
+
+    def unpack_file_attributes(self):
+        # Size of file length (4) + lock status (1), adapt if more field are added!
+        print(len(self.get_tm_data()) - self.data_start_idx)
+        if len(self.get_tm_data()) - self.data_start_idx != 5:
+            LOGGER.error("Service23TM: Invalid lenght of file attributes data")
+            return
+        self.file_size = struct.unpack('!I', self.get_tm_data()[
+                                             self.data_start_idx: self.data_start_idx + 4])[0]
+        self.lock_status = self.get_tm_data()[self.data_start_idx + 4]
+
+    def append_telemetry_content(self, content_list: list):
+        super().append_telemetry_content(content_list)
+        content_list.append(hex(self.object_id))
+        content_list.append(self.repo_path)
+        content_list.append(self.filename)
+        if self.get_subservice() == 4:
+            content_list.append(self.file_size)
+            if self.lock_status == 0:
+                content_list.append("No")
+            else:
+                content_list.append("Yes")
 
+    def append_telemetry_column_headers(self, header_list: list):
+        super().append_telemetry_column_headers(header_list)
+        header_list.append("Object ID")
+        header_list.append("Repo Path")
+        header_list.append("File Name")
+        if self.get_subservice() == 4:
+            header_list.append("File Size")
+            header_list.append("Locked")
 
diff --git a/tm/obsw_tm_service_3.py b/tm/obsw_tm_service_3.py
index 96be1223fc42fdfb94298ffabd993dfdc1434ede..ddb4376333700671b40b2f244a48a4a14f8b691a 100644
--- a/tm/obsw_tm_service_3.py
+++ b/tm/obsw_tm_service_3.py
@@ -122,8 +122,8 @@ class Service3TM(PusTelemetry):
         # TODO: size check. sth not right with gps 0 test
         self.number_of_parameters = 9
         self.hk_header = ["Fix Mode", "SV in Fix", "GNSS Week", "Time of Week", "Latitude",
-                         "Longitude", "Mean Sea Altitude", "Position X", "Position Y", "Position Z",
-                         "Velocity X", "Velocity Y", "Velocity Z"]
+                          "Longitude", "Mean Sea Altitude", "Position X", "Position Y",
+                          "Position Z", "Velocity X", "Velocity Y", "Velocity Z"]
         fix_mode = self._tm_data[4]
         sv_in_fix = self._tm_data[5]
         gnss_week = struct.unpack('>H', self._tm_data[6:8])[0]
diff --git a/tmtc_core b/tmtc_core
index e8708d8ded3537dce1cb8478058b5c66ef71713d..233383842fdaca1480d25ce4568da54e8305ffaa 160000
--- a/tmtc_core
+++ b/tmtc_core
@@ -1 +1 @@
-Subproject commit e8708d8ded3537dce1cb8478058b5c66ef71713d
+Subproject commit 233383842fdaca1480d25ce4568da54e8305ffaa
diff --git a/utility/binary_writer.py b/utility/binary_writer.py
index 577d7ba0bcf24041f9c8ba5b9f6e2450370d4ecb..c07ab66cdf39ec3d3a3e6aa5c6bdf129d0124079 100644
--- a/utility/binary_writer.py
+++ b/utility/binary_writer.py
@@ -18,7 +18,6 @@ def main():
     with open(file_path, "rb+") as file:
         # Read the first seven ARM vectors. The sixth one will be replaced.
         arm_vectors = file.read(4 * 7)
-        arm_vector_6 = arm_vectors[5*4:5*4 + 4]
         print("ARM vectors: ")
         # print(''.join('{:02x}'.format(x) for x in arm_vectors))
         for x in range(0, 28, 4):
diff --git a/utility/obsw_binary_uploader.py b/utility/obsw_binary_uploader.py
index ed98abd04cee4023a57cd6a6a3c7e8dd3b20e034..7f27a9e3f6255ef4cac7671785d2af0ee00f9e31 100644
--- a/utility/obsw_binary_uploader.py
+++ b/utility/obsw_binary_uploader.py
@@ -19,7 +19,7 @@ import config.obsw_config as g
 from tmtc_core.utility.obsw_tmtc_printer import TmTcPrinter, DisplayMode
 from tmtc_core.utility.obsw_logger import get_logger
 from tmtc_core.sendreceive.obsw_tm_listener import TmListener
-from tmtc_core.tm.obsw_pus_tm_factory import PusTelemetryFactory, PusTmQueueT
+from tmtc_core.tm.obsw_pus_tm_factory import PusTmQueueT
 
 LOGGER = get_logger()
 
@@ -116,13 +116,6 @@ def perform_file_upload(com_if: CommunicationInterface, tmtc_printer: TmTcPrinte
         # now we calculate the hamming code
         pass
 
-    # Read file as binary file
-    if file_path != ():
-        with open(file_path, 'rb') as file:
-            data_to_read = bytearray(file.read())
-    else:
-        LOGGER.info("Specified path invalid..")
-
     tc_queue = deque()
 
     # Delete existing binary file first, otherwise data might be appended to otherwise