diff --git a/.gitignore b/.gitignore
index a15b9233fb1eaf13a108d3a161c2d72f9c52a510..47e3242aa7cbc3177f1176fe4b1fc4d47ddf4aa5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -78,3 +78,4 @@ __pycache__
 
 # IDEs
 .vscode
+.DS_Store
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0b3ef569bb6f779875aacc94788e471b2e836135..fdc375a8c758b58f4a066d8e636fc913261ee5dd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -40,17 +40,19 @@ cppcheck:
       - ./cppcheck-html-report
 
 clang-tidy:
-  image: spacedot/clang-tools:13.0.0-html-1.3.7
+  image: spacedot/clang-tools:13.0.0-html-1.4.1
   stage: analyze
   script:
     - cd $CI_PROJECT_DIR
     - cmake -B ./build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-    - clang-tidy -p $CI_PROJECT_DIR/build/compile_commands.json --checks=* `find $CI_PROJECT_DIR/src -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'` >> clang-tidy-output.log
+    - clang-tidy -p $CI_PROJECT_DIR/build/compile_commands.json --config-file=$CI_PROJECT_DIR/ci/.clang-tidy --use-color `find $CI_PROJECT_DIR/src $CI_PROJECT_DIR/inc -not -path "*/Platform/*" -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'` | tee clang-tidy-output.log
   after_script:
+    - sed -e 's/\x1b\[[0-9;]*m//g' -i clang-tidy-output.log
     - mkdir clang-tidy-html-report
     - clang-tidy-html clang-tidy-output.log
     - mv clang.html clang-tidy-html-report
   artifacts:
+    when: always
     paths:
       - ./clang-tidy-html-report
 
@@ -85,9 +87,8 @@ ikos:
   script:
     - cd $CI_PROJECT_DIR
     - ikos-scan cmake .
-    - ikos-scan make
+    - ikos-scan make tests
     - ikos tests.bc
-    - ikos ecss_services.bc
     - ikos-report -o=ikos-report.txt output.db
   after_script:
     - mv ikos-report.txt ikos-report
@@ -105,7 +106,7 @@ tests:
     - cd $CI_PROJECT_DIR
     - cmake . -DCMAKE_CXX_FLAGS="-g -O0 --coverage" && make tests -j$(nproc)
     - lcov -q --capture --initial --directory . -o coverage_base
-    - ./tests --use-colour yes
+    - ./tests --colour-mode ansi
     - lcov -q --capture --directory . -o coverage_tests
     - lcov -q -a coverage_base -a coverage_tests -o coverage_total_unfiltered
     - lcov -q --remove coverage_total_unfiltered "${PWD}/lib/*" "${PWD}/CMakeFiles/*" "${PWD}/test/*" "${PWD}/src/main.cpp" -o coverage_total_filtered
@@ -126,8 +127,10 @@ pages:
     - find ./.public
     - mv .public public
   after_script:
+    - "echo Artifacts for this build: ${CI_JOB_URL}/artifacts/browse"
     - "echo Base page for this branch: ${CI_PAGES_URL}"
   artifacts:
+    expose_as: 'build artifacts and documentation'
     paths:
       - public # Upload the resulting website
       #  only:
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 72b50578eec402676f04dcd624ca933b979aeb3e..388f330c5907583761a5dca29765574542fc76fd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -3,10 +3,8 @@
   <component name="VcsDirectoryMappings">
     <mapping directory="$PROJECT_DIR$" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/ci/page_style/doxygen_dark_theme" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/doxygen-awesome-css" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/lib/Catch2" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/lib/etl" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/lib/logger" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/lib/logger/lib/etl" vcs="Git" />
   </component>
 </project>
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 24ae6a8fd012616ff86b4a546faef0c52dd084a2..9088f50cbff637517328b69234b6768a36a86836 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,8 @@ set(ECSS_CONFIGURATION "${PROJECT_SOURCE_DIR}/inc/Platform/x86" CACHE PATH
         )
 include_directories(${ECSS_CONFIGURATION})
 
+add_compile_options(-Wvla)
+
 # Specify the .cpp files common across all targets
 add_library(common OBJECT
         lib/logger/src/Logger.cpp
@@ -73,5 +75,5 @@ IF (EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt")
             ${test_main_SRC}
             ${test_SRC}
             )
-    target_link_libraries(tests Catch2::Catch2)
+    target_link_libraries(tests Catch2::Catch2WithMain)
 ENDIF ()
diff --git a/Doxyfile b/Doxyfile
index 419b742a3ebf4acbc6929bfea78c59b610269b4d..713a0c961b63058f89cd68f9fbb437732586a0fa 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1534,7 +1534,7 @@ FORMULA_TRANSPARENT    = YES
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-USE_MATHJAX            = NO
+USE_MATHJAX            = YES
 
 # When MathJax is enabled you can set the default output format to be used for
 # the MathJax output. See the MathJax site (see:
diff --git a/ci/.clang-tidy b/ci/.clang-tidy
index 478e052795977bbfe87cab6a8dc73eeeee60e665..e86d3dac3087d45dd2185437a3b8a88b3624a0ce 100644
--- a/ci/.clang-tidy
+++ b/ci/.clang-tidy
@@ -1,5 +1,5 @@
 ---
-Checks:          >
+Checks: >
   -clang-diagnostic-error,
   clang-analyzer-*,
   bugprone-*,
@@ -7,20 +7,26 @@ Checks:          >
   cppcoreguidelines-*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-c-arrays,
   misc-*,-misc-non-private-member-variables-in-classes,
   fuchsia-multiple-inheritance,
-  google-*,-google-readability-todo,
+  google-*,-google-readability-todo,-google-build-using-namespace,-google-runtime-int,
   fuchsia-statically-constructed-objects,
   hicpp-exception-baseclass,
   hicpp-signed-bitwise,
-  llvm-*,-llvm-include-order,-llvm-header-guard,
+  llvm-*,-llvm-include-order,-llvm-header-guard,-llvm-else-after-return,
   modernize-use-auto,
   modernize-use-equals-default,
   misc-*,
   -misc-non-private-member-variables-in-classes,
   performance-*,
-  readability-*,-readability-magic-numbers,
+  readability-*,-readability-magic-numbers,-readability-else-after-return,
   zircon-*
-WarningsAsErrors: '*,-misc-unused-parameters,-llvm-header-guard,-cppcoreguidelines-pro-type-member-init,-google-runtime-references,-clang-diagnostic-tautological-constant-out-of-range-compare,-readability-redundant-declaration,-modernize-use-equals-default,-fuchsia-statically-constructed-objects,-hicpp-signed-bitwise,-cert-err58-cpp,-clang-diagnostic-error,-misc-noexcept-move-constructor'
-HeaderFilterRegex: 'ecss-services\/((?!lib\/).)*$'
+WarningsAsErrors: '*,-bugprone-easily-swappable-parameters,-misc-unused-parameters,-llvm-header-guard,
+-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-non-private-member-variables-in-classes,
+-google-runtime-references,-clang-diagnostic-tautological-constant-out-of-range-compare,
+-readability-redundant-declaration,-modernize-use-equals-default,-fuchsia-statically-constructed-objects,
+-hicpp-signed-bitwise,-cert-err58-cpp,-clang-diagnostic-error,-misc-noexcept-move-constructor,
+-performance-no-int-to-ptr'
+#HeaderFilterRegex: '^ecss-services\/((?!lib\/).)*$'
+#HeaderFilterRegex: '^((?!/lib/).)*$'
 AnalyzeTemporaryDtors: false
 ...
 
diff --git a/docs/ecss_overview.md b/docs/ecss_overview.md
index 82e0011181d26b321d3163e2f5bb1d947e97eb54..ba95f4d2cc280dd5d5bb119d90fc4fb522380a67 100644
--- a/docs/ecss_overview.md
+++ b/docs/ecss_overview.md
@@ -63,6 +63,8 @@ Each service is further divided into some **subservices** that are logical group
 large space mission may split every subservice into different parts of the hardware. However, this implementation _makes
 no distinction between subservices_.
 
+### Standard's Services
+
 <b>`ST[01]`: Request verification</b>
 
 Provides acknowledgement or failure reports for executed commands. This service essentially informs the operators about
@@ -182,7 +184,11 @@ Provides the capability of executing TCs when the spacecraft reaches a specific
 Provides the capability of managing on-board file systems, with functions such as *copy*, *move*, *delete*, or *create
 directory*.
 
-The capability also exists to define _custom_ services and message types, if needed for each mission.
+### Custom Services
+
+<b>`ST[128]`: Dummy Service</b>
+
+Provides the capability of storing log strings as ECSS Messages.
 
 ## Trivia
 - Version C of the standard contains 656 pages, often filled with verbose requirements and difficult definitions. Every
diff --git a/docs/usage_with_microcontroller.md b/docs/usage_with_microcontroller.md
index 05f09b6f1f8e3e714846e0a0eab2e618b4d81c35..293072c75069b4ac6ddbac858131addf68b75894 100644
--- a/docs/usage_with_microcontroller.md
+++ b/docs/usage_with_microcontroller.md
@@ -17,6 +17,7 @@ compile this library independently for different projects.
 ## Examples
 
 Some people have already integrated this library with their own code:
+
 - [AcubeSAT OBC Software](https://gitlab.com/acubesat/obc/obc-software), integration with ATSAMV71Q21 and FreeRTOS
 - [AcubeSAT FDIR Thesis](https://github.com/kongr45gpen/fdir-demo), integration with ATSAMV71Q21 and FreeRTOS
 - [AcubeSAT OBC Mockup](https://gitlab.com/acubesat/obc/mockup-4), integration with STM32L4S9 and FreeRTOS
@@ -57,13 +58,15 @@ your project.
 The following sections list and explain the functions that need to be implemented by library users. It is enough to
 place the function body inside a compiled `.cpp` file. Otherwise, the linker will show errors about undefined functions.
 
-For more details on the requirements, arguments and return values of each function, refer to their respective documentation.
+For more details on the requirements, arguments and return values of each function, refer to their respective
+documentation.
 
 ### Logger
 
 The logger is responsible for outputting messages through a serial interface used for debugging purposes.
 
 You need to define the following function:
+
 ```cpp
 void Logger::log(Logger::LogLevel level, etl::istring & message);
 ```
@@ -73,6 +76,7 @@ be inspected by the developers. It is suggested to add any extra information tha
 execution thread.
 
 An example definition can be as follows:
+
 ```cpp
 void Logger::log(Logger::LogLevel level, etl::istring &message) {
     etl::string<20> time;
@@ -88,16 +92,19 @@ void Logger::log(Logger::LogLevel level, etl::istring &message) {
 ```
 
 #### Setting the log level
+
 You will also need to set the **minimum log level** of your application by setting the relevant `LOGLEVEL` constants.
 
 For example, you can add this to your `CMakeLists.txt` to log all messages:
+
 ```cmake
 add_compile_definitions(LOGLEVEL_TRACE)
 ```
 
 For a list of all possible log levels, refer to the documentation of the Logger.
 
-@note If you want to have different log levels for different parts of your application, you can use [`target_compile_definitions`](https://cmake.org/cmake/help/latest/command/target_compile_definitions.html).
+@note If you want to have different log levels for different parts of your application, you can
+use [`target_compile_definitions`](https://cmake.org/cmake/help/latest/command/target_compile_definitions.html).
 
 @note All logs with a level lower than the specified one will not be compiled at all, and will not be included in any
 form in the resulting binary. This means that disabled log messages _will not_ have any negative impact on the
@@ -111,6 +118,7 @@ Whenever PUS telemetry is generated, it needs to be transmitted or sent to a rec
 In this function, you can transmit the message via an antenna, send it through an interface for debugging, or both.
 
 An example definition can be as follows:
+
 ```cpp
 void Service::storeMessage(Message& message) {
 	message.finalize();
@@ -129,6 +137,7 @@ The @ref ErrorHandler::logError is responsible for logging errors for debugging
 ErrorHandler::logError function is used strictly for debugging purposes, and can be left empty if desired.
 
 An example definition can be as follows:
+
 ```cpp
 template <typename ErrorType>
 void ErrorHandler::logError(const Message& message, ErrorType errorType) {
@@ -144,13 +153,35 @@ void ErrorHandler::logError(ErrorType errorType) {
 }
 ```
 
+### Using the Timer
+
+A significant portion of the PUS functionalities uses timestamps, for example in order to compare message reception times,
+or reporting event times as telemetry. However, time tracking is performed by the hardware, so the time-related functions
+existing in the Services should be re-implemented, as the current functions contain dummy values. The **TimeGetter** class
+is responsible for giving access to a Real-Time Clock, enabling the above capabilities.
+
+#### Getting the current UTC time
+
+The **getCurrentTimeUTC** function computes the current UTC time. In order to actually acquire the current time,
+modify the arguments (which are dummy by default), so that they correspond to their real values. An example is given
+below.
+
+```cpp
+UTCTimestamp TimeGetter::getCurrentTimeUTC() {
+	UTCTimestamp currentTime(onBoardYear, onBoardMonth, onBoardDay, onBoardHour, onBoardMinute, onBoardSecond);
+	return currentTime;
+}
+```
+
 ## Service initialisation
 
 Platform-specific code also gives a chance to every Service to use pre-initialised entities (e.g. parameters, monitoring
 definitions etc.) during boot. The following functions are called at initialisation:
+
 1. @ref ParameterService::initializeParameterMap
 
 An example definition can be as follows:
+
 ```cpp
 Parameter<uint8_t> parameter1(200);
 Parameter<uint8_t> parameter2(150);
@@ -160,11 +191,62 @@ void ParameterService::initializeParameterMap() {
 	parameters = {{0, parameter1}, {1, parameter2}, {2, parameter3}};
 }
 ```
+2. @ref TimeBasedSchedulingService::notifyNewActivityAddition
+
+The TimeBasedSchedulingService is responsible for storing the activities/TCs to be executed. However, if this list of 
+stored activities is emptied, the Platform Task responsible to execute these TCs should be paused. With this 
+function, a notifier can be implemented and called by `TimeBasedScheduling::insertActivities()` to notify the 
+Task to restart after a new activity is inserted.
+
+An example implementation for FreeRTOS can be as follows:
+```cpp
+void TimeBasedSchedulingService::notifyNewActivityAddition() {
+    if (scheduledActivities.size() >= 1) {
+        xTaskNotify(TaskList::timeBasedSchedulingTask->taskHandle, 0, eNoAction);
+    }
+}
+```
+
+3. @ref ParameterStatisticsService::initializeStatisticsMap
+
+The function is called by the constructor of the class, making sure that the statistics will be initialized properly
+after creating an instance of the ST04 Service. This function should be implemented according to the specific
+needs, structure and parameters of an individual project. It basically iterates over the statistics list and initializes
+statistics for parameters of selected IDs. An example is provided below. Let's assume that we have stored the
+parameter IDs, and we use a data structure to store the statistics. Our initialization function, based on such
+structure should look like this:
+
+```c++
+namespace PlatformParameters {
+    enum ParameterIDs : uint16_t {
+        OnBoardMinute = 0,
+        Temperature = 1,
+    };
+}
+
+namespace ParameterStatistics {
+	static etl::array<Statistic, ECSSMaxStatisticParameters> statistics = {
+	    Statistic(),
+	    Statistic(),
+	};
+}
+
+void ParameterStatisticsService::initializeStatisticsMap() {
+	using namespace PlatformParameters;
+	uint16_t statisticParameterIDs[] = {parameterIDs::onBoardMinute, parameterIDs::temperature};
+	uint8_t idIndex = 0;
+
+    for (auto& statistic: ParameterStatistics::statistics) {
+        statisticsMap.insert({statisticParameterIDs[idIndex++], statistic});
+    }
+}
+```
 
 ## Receiving messages
 
 After making sure that your code compiles, you need to provide a way of feeding received TC into the services. This can
 be done easily:
+
 ```cpp
 MessageParser::parse(string, size);
 ```
diff --git a/inc/ECSS_Definitions.hpp b/inc/ECSS_Definitions.hpp
index 79eb5bd7b14d153b5230a8359e314eed492a4cc9..9801dbb6b1875570c5bec58444ff3b7f4502fc66 100644
--- a/inc/ECSS_Definitions.hpp
+++ b/inc/ECSS_Definitions.hpp
@@ -1,6 +1,7 @@
 #ifndef ECSS_SERVICES_ECSS_DEFINITIONS_H
 #define ECSS_SERVICES_ECSS_DEFINITIONS_H
 
+#include <chrono>
 #include <cstdint>
 /**
  * @defgroup ECSSDefinitions ECSS Defined Constants
@@ -24,10 +25,25 @@
  */
 inline const uint16_t ECSSMaxMessageSize = 1024U;
 
+/**
+ * The size of each CCSDS Space packet primary header
+ */
+inline const uint16_t CCSDSPrimaryHeaderSize = 6U;
+
+/**
+ * The size of each ECSS Telemetry packet's secondary header
+ */
+inline const uint16_t ECSSSecondaryTMHeaderSize = 11U;
+
+/**
+ * The size of each ECSS Telecommand packet's secondary header
+ */
+inline const uint16_t ECSSSecondaryTCHeaderSize = 5U;
+
 /**
  * The maximum size of a regular ECSS message, plus its headers and trailing data, in bytes
  */
-inline const uint16_t CCSDSMaxMessageSize = ECSSMaxMessageSize + 6u + 6u + 2u;
+inline const uint16_t CCSDSMaxMessageSize = ECSSMaxMessageSize + CCSDSPrimaryHeaderSize + ECSSSecondaryTMHeaderSize + 2U;
 
 /**
  * The maximum size of a string to be read or appended to a Message, in bytes
@@ -92,7 +108,7 @@ inline const uint8_t ECSSMaxNumberOfTimeSchedActivities = 10;
  * have in order
  * @see TimeBasedSchedulingService
  */
-inline const uint8_t ECSSTimeMarginForActivation = 60;
+inline constexpr std::chrono::duration<uint8_t> ECSSTimeMarginForActivation(60);
 
 /**
  * @brief Maximum size of an event's auxiliary data
@@ -104,7 +120,7 @@ inline const uint8_t ECSSEventDataAuxiliaryMaxSize = 64;
  * @brief Size of the multimap that holds every event-action definition
  * @see EventActionService
  */
-inline const uint16_t ECSSEventActionStructMapSize = 256;
+inline const uint16_t ECSSEventActionStructMapSize = 100;
 
 /**
  * The maximum delta between the specified release time and the actual release time
@@ -115,7 +131,7 @@ inline const uint8_t ECSSMaxDeltaOfReleaseTime = 60;
 /**
  * The max number of simply commutated parameters per housekeeping structure in ST[03]
  */
-inline const uint16_t ECSSMaxSimplyCommutatedParameters = 10;
+inline const uint16_t ECSSMaxSimplyCommutatedParameters = 30;
 
 /**
  * The number of functions supported by the \ref FunctionManagementService
@@ -142,7 +158,7 @@ inline const uint16_t LoggerMaxMessageSize = 512;
 /**
  * @brief Size of the map holding references to each Parameter object for the ST[20] parameter service
  */
-inline const uint8_t ECSSParameterCount = 12;
+inline const uint16_t ECSSParameterCount = 500;
 
 /**
  * @brief Defines whether the optional CRC field is included
@@ -167,7 +183,7 @@ inline const uint16_t ECSSMaxPacketStoreSizeInBytes = 1000;
 /**
  * @brief the max number of TM packets that a packet store in ST[15] can store
  */
-inline const uint16_t ECSSMaxPacketStoreSize = 20;
+inline const uint16_t ECSSMaxPacketStoreSize = 10;
 
 /**
  * @brief the max number of packet stores that a packet selection subservice can handle in ST[15]
@@ -226,7 +242,7 @@ inline const uint8_t ECSSMaxEventDefinitionIDs = 15;
 /**
  * Limits noting the minimum and maximum valid Virtual Channels used by the Storage and Retrieval subservice
  */
-inline struct {
+inline const struct {
 	uint8_t min = 1;
 	uint8_t max = 10;
 } VirtualChannelLimits;
@@ -236,5 +252,11 @@ inline struct {
  */
 inline const uint8_t ECSSMaxMonitoringDefinitions = 4;
 
+/**
+ * 6.18.2.2 The applicationId that is assigned on the specific device that runs these Services.
+ * In the ECSS-E-ST-70-41C the application ID is also referred as application process.
+ */
+inline const uint16_t ApplicationId = 1;
+
 /** @} */
 #endif // ECSS_SERVICES_ECSS_DEFINITIONS_H
diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp
index 216c9b1bce25a21d9903973c7f1a4dcf543b033e..b10eee51c56186d2c56a6972c49778d504337358 100644
--- a/inc/ErrorHandler.hpp
+++ b/inc/ErrorHandler.hpp
@@ -60,7 +60,6 @@ public:
 		 * Asked a Message type that doesn't exist
 		 */
 		UnknownMessageType = 7,
-
 		/**
 		 * Asked to append unnecessary spare bits
 		 */
@@ -93,6 +92,14 @@ public:
 		 * Invalid TimeStamp parameters at creation
 		 */
 		InvalidTimeStampInput = 15,
+		/**
+		 * A requested element is not found
+		 */
+		ElementNotInArray = 16,
+		/**
+		 * Timestamp out of bounds to be stored or converted
+		 */
+		TimeStampOutOfBounds = 17,
 	};
 
 	/**
@@ -131,240 +138,250 @@ public:
 		UnknownExecutionStartError = 0,
 		/**
 		 * In the Event Action Service, in the addEventActionDefinition function an attempt was
-		 * made to add an event Action Definition with an eventActionDefinitionID that exists
+		 * made to add an event Action Definition with an eventDefinitionID that exists
 		 */
-		EventActionDefinitionIDExistsError = 1,
+		EventDefinitionIDExistsError = 1,
+
+		/**
+		 *In the Event Action Service, in the addEventActionDefinition function an attempt was
+		 * made to add an event Action Definition that is already enabled
+		 */
+		EventActionEnabledError = 2,
 		/**
 		 * In the Event Action Service, in the deleteEventActionDefinition function, an attempt
 		 * was made to delete an event action definition that was enabled
 		 */
-		EventActionDeleteEnabledDefinitionError = 2,
+		EventActionDeleteEnabledDefinitionError = 3,
 		/**
 		 * In the Event Action Service, an access attempt was made to an unknown event
 		 * action definition
 		 */
-		EventActionUnknownEventDefinitionError = 3,
+		EventActionUnknownEventActionDefinitionError = 4,
 		/**
 		 * EventAction refers to the service, EventActionIDefinitionID refers to the variable
-		 * In the Event Action Service, an access attempt was made to an unknown eventActionDefinitionID
+		 * In the Event Action Service, an access attempt was made to an unknown eventDefinitionID
 		 */
-		EventActionUnknownEventActionDefinitionIDError = 4,
-		SubServiceExecutionStartError = 5,
-		InstructionExecutionStartError = 6,
+		EventActionUnknownEventActionDefinitionIDError = 5,
+		SubServiceExecutionStartError = 6,
+		InstructionExecutionStartError = 7,
 		/**
 		 * Attempt to change the value of a non existing parameter (ST[20])
 		 */
-		SetNonExistingParameter = 7,
+		SetNonExistingParameter = 8,
 		/**
 		 * Attempt to access a non existing parameter (ST[20])
 		 */
-		GetNonExistingParameter = 8,
+		GetNonExistingParameter = 9,
 		/**
 		 * Attempt to access a packet store that does not exist (ST[15])
 		 */
-		NonExistingPacketStore = 9,
+		NonExistingPacketStore = 10,
 		/**
 		 * Attempt to change the start time tag of a packet store, whose open retrieval status is in progress (ST[15])
 		 */
-		SetPacketStoreWithOpenRetrievalInProgress = 10,
+		SetPacketStoreWithOpenRetrievalInProgress = 11,
 		/**
 		 * Attempt to resume open retrieval of a packet store, whose by-time-range retrieval is enabled (ST[15])
 		 */
-		SetPacketStoreWithByTimeRangeRetrieval = 11,
+		SetPacketStoreWithByTimeRangeRetrieval = 12,
 		/**
 		 * Attempt to access a packet with by-time range retrieval enabled (ST[15])
 		 */
-		GetPacketStoreWithByTimeRangeRetrieval = 12,
+		GetPacketStoreWithByTimeRangeRetrieval = 13,
 		/**
 		 * Attempt to start the by-time-range retrieval of packet store, whose open retrieval is in progress (ST[15])
 		 */
-		GetPacketStoreWithOpenRetrievalInProgress = 13,
+		GetPacketStoreWithOpenRetrievalInProgress = 14,
 		/**
 		 * Attempt to start by-time-range retrieval when its already enabled (ST[15])
 		 */
-		ByTimeRangeRetrievalAlreadyEnabled = 14,
+		ByTimeRangeRetrievalAlreadyEnabled = 15,
 		/**
 		 * Attempt to create packet store, whose ID already exists (ST[15])
 		 */
-		AlreadyExistingPacketStore = 15,
+		AlreadyExistingPacketStore = 16,
 		/**
 		 * Attempt to create packet store, when the max number of packet stores is already reached (ST[15])
 		 */
-		MaxNumberOfPacketStoresReached = 16,
+		MaxNumberOfPacketStoresReached = 17,
 		/**
 		 * Attempt to access a packet store with the storage status enabled (ST[15])
 		 */
-		GetPacketStoreWithStorageStatusEnabled = 17,
+		GetPacketStoreWithStorageStatusEnabled = 18,
 		/**
 		 * Attempt to delete a packet whose by time range retrieval status is enabled (ST[15])
 		 */
-		DeletionOfPacketWithByTimeRangeRetrieval = 18,
+		DeletionOfPacketWithByTimeRangeRetrieval = 19,
 		/**
 		 * Attempt to delete a packet whose open retrieval status is in progress (ST[15])
 		 */
-		DeletionOfPacketWithOpenRetrievalInProgress = 19,
+		DeletionOfPacketWithOpenRetrievalInProgress = 20,
 		/**
 		 * Requested a time window where the start time is larger than the end time (ST[15])
 		 */
-		InvalidTimeWindow = 20,
+		InvalidTimeWindow = 21,
 		/**
 		 * Attempt to copy a packet store to a destination packet store that is not empty (ST[15])
 		 */
-		DestinationPacketStoreNotEmtpy = 21,
+		DestinationPacketStoreNotEmtpy = 22,
 		/**
 		 * Attempt to set a reporting rate which is smaller than the parameter sampling rate.
 		 * ST[04]
 		 */
-		InvalidReportingRateError = 22,
+		InvalidReportingRateError = 23,
 		/**
 		 * Attempt to add definition to the struct map but its already full.(ST[19])
 		 */
-		EventActionDefinitionsMapIsFull = 23,
+		EventActionDefinitionsMapIsFull = 24,
 		/**
 		 * Attempt to report/delete non existing housekeeping structure (ST[03])
 		 */
-		RequestedNonExistingStructure = 24,
+		RequestedNonExistingStructure = 25,
 		/**
 		 * Attempt to create already created structure (ST[03])
 		 */
-		RequestedAlreadyExistingStructure = 25,
+		RequestedAlreadyExistingStructure = 26,
 		/**
 		 * Attempt to delete structure which has the periodic reporting status enabled (ST[03]) as per 6.3.3.5.2(d-2)
 		 */
-		RequestedDeletionOfEnabledHousekeeping = 26,
+		RequestedDeletionOfEnabledHousekeeping = 27,
 		/**
 		 * Attempt to append a new parameter ID to a housekeeping structure, but the ID is already in the structure
 		 * (ST[03])
 		 */
-		AlreadyExistingParameter = 27,
+		AlreadyExistingParameter = 28,
 		/**
 		 * Attempt to append a new parameter id to a housekeeping structure, but the periodic generation status is
 		 * enabled (ST[03])
 		 */
-		RequestedAppendToEnabledHousekeeping = 28,
+		RequestedAppendToEnabledHousekeeping = 29,
 		/**
 		 * Attempt to create a new housekeeping structure in Housekeeping Service, when the maximum number of
 		 * housekeeping structures is already reached (ST[03])
 		 */
-		ExceededMaxNumberOfHousekeepingStructures = 29,
+		ExceededMaxNumberOfHousekeepingStructures = 30,
 		/**
 		 * Attempt to add a new simply commutated parameter in a specific housekeeping structure, but the maximum
 		 * number of simply commutated parameters for this structure is already reached (ST[03])
 		 */
-		ExceededMaxNumberOfSimplyCommutatedParameters = 30,
+		ExceededMaxNumberOfSimplyCommutatedParameters = 31,
 		/**
 		 * Attempt to set a reporting rate which is smaller than the parameter sampling rate.
 		 * ST[04]
 		 */
-		InvalidSamplingRateError = 31,
+		InvalidSamplingRateError = 32,
 		/**
 		 * Attempt to add new statistic definition but the maximum number is already reached (ST[04])
 		 */
-		MaxStatisticDefinitionsReached = 32,
+		MaxStatisticDefinitionsReached = 33,
 		/**
 		 * Attempt to set the virtual channel of a packet store to a invalid value (ST[15])
 		 */
-		InvalidVirtualChannel = 33,
+		InvalidVirtualChannel = 34,
 		/**
 		 * Attempt to delete a packet store, whose storage status is enabled (ST[15])
 		 */
-		DeletionOfPacketStoreWithStorageStatusEnabled = 34,
+		DeletionOfPacketStoreWithStorageStatusEnabled = 35,
 		/**
 		 * Attempt to copy packets from a packet store to another, but either no packet timestamp falls inside the
 		 * specified timestamp, or more than one boolean argument were given as true in the 'copyPacketsTo' function
 		 * (ST[15])
 		 */
-		CopyOfPacketsFailed = 35,
+		CopyOfPacketsFailed = 36,
 		/**
 		 * Attempt to set a packet store size to a value that the available memory cannot handle (ST[15]).
 		 */
-		UnableToHandlePacketStoreSize = 36,
+		UnableToHandlePacketStoreSize = 37,
 		/**
 		 * Attempt to delete all parameter monitoring definitions but the Parameter Monitoring Function Status is
 		 * enabled.
 		 */
-		InvalidRequestToDeleteAllParameterMonitoringDefinitions = 37,
+		InvalidRequestToDeleteAllParameterMonitoringDefinitions = 38,
 		/**
 		 * Attempt to delete one parameter monitoring definition but its Parameter Monitoring Status is
 		 * enabled.
 		 */
-		InvalidRequestToDeleteParameterMonitoringDefinition = 38,
+		InvalidRequestToDeleteParameterMonitoringDefinition = 39,
 		/**
 		 * Attempt to add a parameter that already exists to the Parameter Monitoring List.
 		 */
-		AddAlreadyExistingParameter = 39,
+		AddAlreadyExistingParameter = 40,
 		/**
 		 * Attempt to add a parameter in the Parameter Monitoring List but it's full
 		 */
-		ParameterMonitoringListIsFull = 40,
+		ParameterMonitoringListIsFull = 41,
 		/**
 		 * Attempt to add or modify a limit check parameter monitoring definition, but the high limit is lower than
 		 * the low limit.
 		 */
-		HighLimitIsLowerThanLowLimit = 41,
+		HighLimitIsLowerThanLowLimit = 42,
 		/**
 		 * Attempt to add or modify a delta check parameter monitoring definition, but the high threshold is lower than
 		 * the low threshold.
 		 */
-		HighThresholdIsLowerThanLowThreshold = 42,
+		HighThresholdIsLowerThanLowThreshold = 43,
 		/**
 		 * Attempt to modify a non existent Parameter Monitoring definition.
 		 */
-		ModifyParameterNotInTheParameterMonitoringList = 43,
+		ModifyParameterNotInTheParameterMonitoringList = 44,
 		/**
 		 * Attempt to modify a parameter monitoring definition, but the instruction refers to a monitored parameter
 		 * that is not the one used in that parameter monitoring definition.
 		 */
-		DifferentParameterMonitoringDefinitionAndMonitoredParameter = 44,
+		DifferentParameterMonitoringDefinitionAndMonitoredParameter = 45,
 		/**
 		 * Attempt to get a parameter monitoring definition that does not exist.
 		 */
-		GetNonExistingParameterMonitoringDefinition = 45,
+		GetNonExistingParameterMonitoringDefinition = 46,
 		/**
 		 * Request to report a non existent parameter monitoring definition.
 		 */
-		ReportParameterNotInTheParameterMonitoringList = 46,
+		ReportParameterNotInTheParameterMonitoringList = 47,
 		/**
 		 * Attempt to add a new report type, when the addition of all report types is already enabled in the
 		 * Application Process configuration (ST[14])
 		 */
-		AllReportTypesAlreadyAllowed = 47,
-		/**
-		 * Attempt to add a new service type, when the addition of all service types is already enabled in the
-		 * Application Process configuration (ST[14])
-		 */
 		AllServiceTypesAlreadyAllowed = 48,
-
 		/**
 		 * Attempt to add a new report type, when the max number of reports types allowed per service type
 		 * definition in the Application Process configuration is already reached (ST[14])
 		 */
 		MaxReportTypesReached = 49,
-
 		/**
 		 * Attempt to add a new service type, when the max number of service types allowed per application process
 		 * definition in the Application Process configuration is already reached (ST[14])
 		 */
 		MaxServiceTypesReached = 50,
-
 		/**
 		 * Attempt to add a report/event definition/housekeeping report type, when the specified application process
 		 * ID is not controlled by the Service (ST[14])
 		 */
 		NotControlledApplication = 51,
+		/**
+		 * Parameter is requested, but the provider of the parameter value does not exist yet
+		 */
+		ParameterValueMissing = 52,
+		/**
+		 * Attempted to write to a read-only parameter
+		 */
+		ParameterReadOnly = 53,
+		/**
+		 * Attempted to read from a write-only parameter
+		 */
+		ParameterWriteOnly = 54,
 		/**
 		 * Attempt to access a non-existing report type definition, from the application process configuration (ST[14])
 		 */
-		NonExistingReportTypeDefinition = 52,
+		NonExistingReportTypeDefinition = 55,
 		/**
 		 * Attempt to access a non-existing service type definition, from the application process configuration (ST[14])
 		 */
-		NonExistingServiceTypeDefinition = 53,
+		NonExistingServiceTypeDefinition = 56,
 		/**
 		 * Attempt to access a non-existing application process definition, from the application process
 		 * configuration (ST[14])
 		 */
-		NonExistingApplication = 54,
+		NonExistingApplication = 57,
 	};
 
 	/**
@@ -499,7 +516,7 @@ public:
 	 * @return The corresponding ErrorSource
 	 */
 	template <typename ErrorType>
-	inline static ErrorSource findErrorSource(ErrorType error) {
+	inline static ErrorSource findErrorSource(ErrorType errorType) {
 		// Static type checking
 		ErrorSource source = Internal;
 
diff --git a/inc/Helpers/AllMessageTypes.hpp b/inc/Helpers/AllMessageTypes.hpp
index fb5c2c488647f0b54fa783dd09c72eff28801092..7e4ffd5aced08b9f539e4c4a9c188d30a4f42e34 100644
--- a/inc/Helpers/AllMessageTypes.hpp
+++ b/inc/Helpers/AllMessageTypes.hpp
@@ -13,7 +13,7 @@ namespace AllMessageTypes {
 	 * Map containing all the message types, per service. The key is the ServiceType and the value,
 	 * an etl vector containing the message types.
 	 */
-	extern etl::map<uint8_t, etl::vector<uint8_t, ECSSMaxReportTypeDefinitions>, ECSSMaxServiceTypeDefinitions> messagesOfService;
+	extern const etl::map<uint8_t, etl::vector<uint8_t, ECSSMaxReportTypeDefinitions>, ECSSMaxServiceTypeDefinitions> MessagesOfService;
 
 } // namespace AllMessageTypes
 
diff --git a/inc/Helpers/HousekeepingStructure.hpp b/inc/Helpers/HousekeepingStructure.hpp
index 98271aa37526f9b4254d357b454e9b871ed96a64..342568379fbc3a9f5bf00a1d269cd6b3f742a0bd 100644
--- a/inc/Helpers/HousekeepingStructure.hpp
+++ b/inc/Helpers/HousekeepingStructure.hpp
@@ -12,8 +12,7 @@
  *
  * @author Petridis Konstantinos <petridkon@gmail.com>
  */
-class HousekeepingStructure {
-public:
+struct HousekeepingStructure {
     uint8_t structureId;
 
     /**
@@ -34,4 +33,4 @@ public:
 	HousekeepingStructure() = default;
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/inc/Helpers/LazyParameter.hpp b/inc/Helpers/LazyParameter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d28c3baf3a85ce963bf54077739c2c6710b90c6b
--- /dev/null
+++ b/inc/Helpers/LazyParameter.hpp
@@ -0,0 +1,105 @@
+#ifndef ECSS_SERVICES_LAZYPARAMETER_HPP
+#define ECSS_SERVICES_LAZYPARAMETER_HPP
+
+#include <etl/optional.h>
+#include <functional>
+#include "Parameter.hpp"
+
+/**
+ * A Lazy Parameter is a ParameterService parameter that does not keep a value in
+ * memory, but calls an external function to fetch a new value whenever needed.
+ *
+ * The LazyParameter allows its users to call expensive value-fetching operators
+ * ONLY when a value is requested. This prevents having to update a value in
+ * memory every so often.
+ *
+ * This "lazy" fetching is useful when it is expensive (in terms of time, power
+ * etc.) to get updated values, e.g. from peripherals or difficult calculations.
+ *
+ * @warning This class is NOT re-entrant. The developer will have to make sure
+ * that only one thread has access to it at a time, otherwise undefined behaviour
+ * will occur.
+ *
+ * @tparam DataType The data type of the parameter's value
+ */
+template <typename DataType>
+class LazyParameter : public ParameterBase {
+public:
+	/**
+	 * The type of the function that returns the current value of this parameter.
+	 */
+	using Getter = std::function<DataType()>;
+
+	/**
+	 * LazyParameter constructor without a getter function.
+	 *
+	 * When a getter function is not present, an error may be shown when fetching a value
+	 * for the parameter. A @p fallback value will be returned in this case, if needed.
+	 * @param fallback
+	 */
+	explicit LazyParameter(const DataType& fallback = 0) : fallback(fallback) {}
+
+	/**
+	 * LazyParameter constructor with a pre-defined getter function
+	 * @param getter
+	 * @param fallback
+	 */
+	explicit LazyParameter(const Getter& getter, const DataType& fallback = 0) : getter(getter), fallback(fallback) {}
+
+	/**
+	 * Set a getter function for this parameter. The getter function is called
+	 * whenever a value for this parameter is requested.
+	 */
+	void setGetter(const Getter& _getter) {
+		LazyParameter::getter = _getter;
+	}
+
+	/**
+	 * Remove the getter function of this parameter.
+	 */
+	void unsetGetter() {
+		getter.reset();
+	}
+
+	/**
+	 * Get the current value of this parameter, if the getter is defined.
+	 *
+	 * @note This function may take some time to return a value, since it calls
+	 * the "expensive" getter function.
+	 */
+	etl::optional<DataType> getValue() {
+		if (getter) {
+			return (*getter)();
+		} else {
+			return {};
+		}
+	}
+
+	inline double getValueAsDouble() override {
+		if constexpr (std::is_arithmetic_v<DataType>) {
+			return static_cast<double>(getValue().value_or(fallback));
+		} else {
+			return 0;
+		}
+	}
+
+	inline void appendValueToMessage(Message& message) override {
+		if (getter) {
+			message.append<DataType>((*getter)());
+		} else {
+			message.append<DataType>(fallback);
+			ErrorHandler::reportError(message, ErrorHandler::ParameterValueMissing);
+		}
+	};
+
+	inline void setValueFromMessage(Message& message) override {
+		[[maybe_unused]] auto skippedBytes = message.read<DataType>();
+		ErrorHandler::reportError(message, ErrorHandler::ParameterReadOnly);
+	};
+private:
+	etl::optional<Getter> getter;
+	DataType fallback;
+};
+
+
+#endif //ECSS_SERVICES_LAZYPARAMETER_HPP
diff --git a/inc/Helpers/NotifyParameter.hpp b/inc/Helpers/NotifyParameter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..286b1d24bfdfa372aaac15f2ca99630b4202e5af
--- /dev/null
+++ b/inc/Helpers/NotifyParameter.hpp
@@ -0,0 +1,93 @@
+#ifndef ECSS_SERVICES_NOTIFYPARAMETER_HPP
+#define ECSS_SERVICES_NOTIFYPARAMETER_HPP
+
+#include <etl/optional.h>
+#include <functional>
+#include "Parameter.hpp"
+
+/**
+ * A Notifying parameter will call a function whenever its value is written to.
+ *
+ * This is useful for updating the state of things when a parameter is changed,
+ * for example to disable/enable peripherals, to make configuration changes etc.
+ *
+ * @warning Calling NotifyParameter::setValue will *not* call the notifier
+ * function. You should use setValueLoudly for this purpose instead.
+ *
+ * @tparam DataType The data type of the parameter's value
+ */
+template <typename DataType>
+class NotifyParameter : public Parameter<DataType> {
+public:
+	using Notifier = std::function<void(const DataType&)>;
+	using Parent = Parameter<DataType>;
+
+	/**
+	 * Constructor without a notifier function. Nothing will then happen when the parameter is updated.
+	 */
+	explicit NotifyParameter(DataType initialValue) : Parent(initialValue) {}
+
+	/**
+	 * Constructor with a default notifier function.
+	 */
+	NotifyParameter(DataType initialValue, const Notifier& notifier) : Parent(initialValue), notifier(notifier) {}
+
+	/**
+	 * Same as Parameter::setValue(), but also calls the NotifyParameter::notifier function, if it
+	 * exists.
+	 */
+	inline void setValueLoudly(DataType value) {
+		Parent::setValue(value);
+
+		if (notifier) {
+			(*notifier)(Parent::currentValue);
+		}
+	}
+
+	/**
+	 * Call the notifier if it exists, without updating the value
+	 */
+	inline void notify() {
+		if (notifier) {
+			(*notifier)(Parent::currentValue);
+		}
+	}
+
+	inline void setValueFromMessage(Message& message) override {
+		Parent::setValueFromMessage(message);
+
+		if (notifier) {
+			(*notifier)(Parent::currentValue);
+		}
+	}
+
+	/**
+	 * Set the notifier function, to be called whenever the value of this parameter is updated.
+	 *
+	 * @note This function will be called even when a _parameter update_ command is received, but the
+	 * new value is the same as the previous one. This is done so that there is an option to repair
+	 * systems with a weird or unknown state.
+	 * @param call Whether to also call the notifier function immediately, to ensure that a change is
+	 * made.
+	 */
+	void setNotifier(const Notifier& _notifier, bool call=true) {
+		notifier = _notifier;
+
+		if (call) {
+			_notifier(Parent::currentValue);
+		}
+	}
+
+	/**
+	 * Unset the notifier function, so that nothing is called when the value of this function is updated.
+	 */
+	void unsetNotifier() {
+		notifier.reset();
+	}
+
+private:
+	etl::optional<Notifier> notifier;
+};
+
+
+#endif //ECSS_SERVICES_NOTIFYPARAMETER_HPP
diff --git a/inc/Helpers/PMONBase.hpp b/inc/Helpers/PMONBase.hpp
index 66c00e58ff877d4b3c4f11b718ef6c83aeb7860e..0a56357ab63544a450c34f869f64de671386c3e2 100644
--- a/inc/Helpers/PMONBase.hpp
+++ b/inc/Helpers/PMONBase.hpp
@@ -1,13 +1,13 @@
 #ifndef ECSS_SERVICES_PMONBASE_HPP
 #define ECSS_SERVICES_PMONBASE_HPP
 #include <cstdint>
+#include "ECSS_Definitions.hpp"
+#include "Helpers/Parameter.hpp"
 #include "Message.hpp"
-#include "etl/array.h"
 #include "Service.hpp"
-#include "Helpers/Parameter.hpp"
-#include "etl/map.h"
-#include "ECSS_Definitions.hpp"
+#include "etl/array.h"
 #include "etl/list.h"
+#include "etl/map.h"
 
 /**
  * Base class for Parameter Monitoring definitions. Contains the common variables of all check types.
diff --git a/inc/Helpers/Parameter.hpp b/inc/Helpers/Parameter.hpp
index ccc55ae9d8e24241afd8176f50ccf373a55130ec..9341affdc47b02b13852a445ebf06955d31fb6ce 100644
--- a/inc/Helpers/Parameter.hpp
+++ b/inc/Helpers/Parameter.hpp
@@ -32,8 +32,22 @@
  */
 class ParameterBase {
 public:
+	/**
+	 * Given an ECSS message that contains this parameter as its first input, this loads the value from that parameter
+	 */
 	virtual void appendValueToMessage(Message& message) = 0;
+
+	/**
+	 * Appends the parameter as an ECSS value to an ECSS Message
+	 */
 	virtual void setValueFromMessage(Message& message) = 0;
+
+	/**
+	 * Converts the value of a parameter to a double.
+	 *
+	 * Some precision may be lost in the process. If the value is not arithmetic,
+	 * then usually 0 is returned.
+	 */
 	virtual double getValueAsDouble() = 0;
 };
 
@@ -44,7 +58,7 @@ public:
  */
 template <typename DataType>
 class Parameter : public ParameterBase {
-private:
+protected:
 	DataType currentValue;
 
 public:
@@ -59,19 +73,17 @@ public:
 	}
 
 	inline double getValueAsDouble() override {
-		return static_cast<double>(currentValue);
+		if constexpr (std::is_arithmetic_v<DataType>) {
+			return static_cast<double>(currentValue);
+		} else {
+			return 0;
+		}
 	}
 
-	/**
-	 * Given an ECSS message that contains this parameter as its first input, this loads the value from that paremeter
-	 */
 	inline void setValueFromMessage(Message& message) override {
 		currentValue = message.read<DataType>();
 	};
 
-	/**
-	 * Appends the parameter as an ECSS value to an ECSS Message
-	 */
 	inline void appendValueToMessage(Message& message) override {
 		message.append<DataType>(currentValue);
 	};
diff --git a/inc/Helpers/Statistic.hpp b/inc/Helpers/Statistic.hpp
index 8934b9fcc434346d57dd535b625e6177fd44b5dd..cbf122db76a3e8f9e12c1435051f2ed378e7d5f4 100644
--- a/inc/Helpers/Statistic.hpp
+++ b/inc/Helpers/Statistic.hpp
@@ -2,11 +2,10 @@
 #define ECSS_SERVICES_STATISTIC_HPP
 
 #include "ECSS_Definitions.hpp"
-#include "Service.hpp"
 #include "ErrorHandler.hpp"
+#include "Service.hpp"
+#include "TimeGetter.hpp"
 #include "etl/vector.h"
-#include <cmath>
-#include <cfloat>
 
 /**
  * Class containing all the statistics for every parameter. Includes functions that calculate and append the
@@ -16,8 +15,8 @@ class Statistic {
 public:
 	uint16_t selfSamplingInterval = 0;
 	uint16_t sampleCounter = 0;
-	uint32_t maxTime = 0;
-	uint32_t minTime = 0; // TODO: CUC Format timestamp
+	Time::DefaultCUC timeOfMaxValue;
+	Time::DefaultCUC timeOfMinValue;
 	double max = -std::numeric_limits<double>::infinity();
 	double min = std::numeric_limits<double>::infinity();
 	double sumOfSquares = 0;
@@ -40,7 +39,7 @@ public:
 	 * Appends itself to the received Message
 	 * message.
 	 */
-	void appendStatisticsToMessage(Message& report);
+	void appendStatisticsToMessage(Message& report) const;
 
 	/**
 	 * Setter function
@@ -50,7 +49,7 @@ public:
 	/**
 	 * Check if all the statistics are initialized
 	 */
-	bool statisticsAreInitialized();
+	bool statisticsAreInitialized() const;
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/inc/Helpers/TimeGetter.hpp b/inc/Helpers/TimeGetter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4417d6735d040c4be9e40dec10b9043552231cd9
--- /dev/null
+++ b/inc/Helpers/TimeGetter.hpp
@@ -0,0 +1,34 @@
+#ifndef ECSS_SERVICES_TIMEGETTER_HPP
+#define ECSS_SERVICES_TIMEGETTER_HPP
+
+#include <cstdint>
+#include <ctime>
+#include "Time/TimeStamp.hpp"
+#include "Time/UTCTimestamp.hpp"
+
+/**
+ * @brief Get the current time
+ */
+class TimeGetter {
+public:
+	/**
+	 * Returns the current UTC time.
+	 * @note
+	 * The information needed to compute the UTC time is implementation-specific. This function should
+	 * be reimplemented to work for every format of the time-related parameters.
+	 */
+	static UTCTimestamp getCurrentTimeUTC();
+
+	/**
+	 * Converts the current UTC time, to a CUC formatted timestamp.
+	 * @note
+	 * The original format of the CUC (etl array of bits), is not used here, because it's easier to append
+	 * a type uint32_t to a message object, rather than a whole array. Thus, we use the custom CUC format.
+	 *
+	 * @return CUC timestamp, formatted as elapsed ticks.
+	 * @see Time
+	 */
+	static Time::DefaultCUC getCurrentTimeDefaultCUC();
+};
+
+#endif // ECSS_SERVICES_TIMEGETTER_HPP
diff --git a/inc/Message.hpp b/inc/Message.hpp
index 9cb09f8281b1da17b104e74e1121f78e5073019a..f0b682b72ac88d037de60a3a8302de0edb523234 100644
--- a/inc/Message.hpp
+++ b/inc/Message.hpp
@@ -1,11 +1,12 @@
 #ifndef ECSS_SERVICES_PACKET_H
 #define ECSS_SERVICES_PACKET_H
 
-#include "ECSS_Definitions.hpp"
+#include <Time/TimeStamp.hpp>
 #include <cstdint>
 #include <etl/String.hpp>
 #include <etl/wstring.h>
-#include "ErrorHandler.hpp"
+#include "ECSS_Definitions.hpp"
+#include "Time/Time.hpp"
 #include "macros.hpp"
 
 /**
@@ -72,7 +73,7 @@ public:
 
 	enum PacketType {
 		TM = 0, ///< Telemetry
-		TC = 1 ///< Telecommand
+		TC = 1  ///< Telecommand
 	};
 
 	// The service and message IDs are 8 bits (5.3.1b, 5.3.3.1d)
@@ -89,7 +90,7 @@ public:
 	 */
 	uint16_t applicationId;
 
-	// 7.4.3.1b
+	//> 7.4.3.1b
 	uint16_t messageTypeCounter = 0;
 
 	// 7.4.1, as defined in CCSDS 133.0-B-1
@@ -147,6 +148,24 @@ public:
 	 */
 	void appendWord(uint32_t value);
 
+	/**
+	 * Appends any CUC timestamp to the message, including the header.
+	 */
+	template <class Ts>
+	void appendCUCTimeStamp(const Ts& timestamp) {
+		etl::array<uint8_t, Time::CUCTimestampMaximumSize> text = timestamp.formatAsCUC();
+
+		appendString(String<Time::CUCTimestampMaximumSize>(text.data(), text.size()));
+	}
+
+	/**
+	 * Appends a default timestamp object to the message, without the header
+	 */
+	void appendDefaultCUCTimeStamp(Time::DefaultCUC timestamp) {
+		static_assert(std::is_same_v<uint32_t, decltype(timestamp.formatAsBytes())>, "The default timestamp should be 4 bytes");
+		appendUint32(timestamp.formatAsBytes());
+	}
+
 	/**
 	 * Appends a number of bytes to the message
 	 *
@@ -224,8 +243,8 @@ public:
 	 */
 	void readCString(char* string, uint16_t size);
 
-public:
 	Message(uint8_t serviceType, uint8_t messageType, PacketType packetType, uint16_t applicationId);
+	Message(uint8_t serviceType, uint8_t messageType, Message::PacketType packetType);
 
 	/**
 	 * Adds a single-byte boolean value to the end of the message
@@ -339,6 +358,23 @@ public:
 		return appendWord(reinterpret_cast<uint32_t&>(value));
 	}
 
+
+	/**
+	 * Adds a 8 byte signed integer to the end of the message
+	 *
+	 * PTC = 4, PFC = 16
+	 */
+	void appendSint64(int64_t value) {
+		return appendUint64(reinterpret_cast<uint64_t&>(value));
+	}
+
+	/**
+	 * Adds an 8 byte time Offset to the message
+	 */
+	void appendRelativeTime(Time::RelativeTime value) {
+		return appendSint64(value);
+	}
+
 	/**
 	 * Adds a 4-byte single-precision floating point number to the end of the message
 	 *
@@ -506,6 +542,23 @@ public:
 		return reinterpret_cast<int32_t&>(value);
 	}
 
+	/**
+	 * Fetches a 4-byte unsigned integer from the current position in the message
+	 *
+	 * PTC = 4, PFC = 14
+	 */
+	int64_t readSint64() {
+		uint64_t value = readUint64();
+		return reinterpret_cast<int64_t&>(value);
+	}
+
+	/**
+	 * Fetches an 8 byte time Offset from the current position in the message
+	 */
+	Time::RelativeTime readRelativeTime() {
+		return readSint64();
+	};
+
 	/**
 	 * Fetches an 4-byte single-precision floating point number from the current position in the
 	 * message
@@ -521,13 +574,23 @@ public:
 		return reinterpret_cast<float&>(value);
 	}
 
-	float readDouble() {
+	double readDouble() {
 		static_assert(sizeof(uint64_t) == sizeof(double), "Double numbers must be 64 bits long");
 
 		uint64_t value = readUint64();
 		return reinterpret_cast<double&>(value);
 	}
 
+	/**
+	 * Fetches a timestamp in a custom CUC format consisting of 4 bytes from the current position in the message
+	 */
+	Time::DefaultCUC readDefaultCUCTimeStamp() {
+		auto time = readUint32();
+		std::chrono::duration<uint32_t, Time::DefaultCUC::Ratio> duration(time);
+
+		return Time::DefaultCUC(duration);
+	}
+
 	/**
 	 * Fetches a N-byte string from the current position in the message
 	 *
@@ -601,7 +664,7 @@ public:
 	 *
 	 * @return True if the message is of correct type, false if not
 	 */
-	bool assertType(Message::PacketType expectedPacketType, uint8_t expectedServiceType, uint8_t expectedMessageType) {
+	bool assertType(Message::PacketType expectedPacketType, uint8_t expectedServiceType, uint8_t expectedMessageType) const {
 		bool status = true;
 
 		if ((packetType != expectedPacketType) || (serviceType != expectedServiceType) ||
@@ -617,7 +680,7 @@ public:
 	 * Alias for Message::assertType(Message::TC, \p expectedServiceType, \p
 	 * expectedMessageType)
 	 */
-	bool assertTC(uint8_t expectedServiceType, uint8_t expectedMessageType) {
+	bool assertTC(uint8_t expectedServiceType, uint8_t expectedMessageType) const {
 		return assertType(TC, expectedServiceType, expectedMessageType);
 	}
 
@@ -625,7 +688,7 @@ public:
 	 * Alias for Message::assertType(Message::TM, \p expectedServiceType, \p
 	 * expectedMessageType)
 	 */
-	bool assertTM(uint8_t expectedServiceType, uint8_t expectedMessageType) {
+	bool assertTM(uint8_t expectedServiceType, uint8_t expectedMessageType) const {
 		return assertType(TM, expectedServiceType, expectedMessageType);
 	}
 };
@@ -676,6 +739,14 @@ template <>
 inline void Message::append(const double& value) {
 	appendDouble(value);
 }
+template <>
+inline void Message::append(const Time::DefaultCUC& value) {
+	appendDefaultCUCTimeStamp(value);
+}
+template <>
+inline void Message::append(const Time::RelativeTime& value) {
+	appendRelativeTime(value);
+}
 
 /**
  * Appends an ETL string to the message. ETL strings are handled as ECSS octet strings, meaning that the string size
@@ -686,7 +757,14 @@ template <>
 inline void Message::append(const etl::istring& value) {
 	appendOctetString(value);
 }
-
+template <typename T>
+inline void Message::append(const T& value) {
+	append(std::underlying_type_t<T>(value));
+}
+template <typename T>
+inline T Message::read() {
+	return static_cast<T>(read<std::underlying_type_t<T>>());
+}
 template <>
 inline uint8_t Message::read() {
 	return readUint8();
@@ -721,17 +799,23 @@ template <>
 inline bool Message::read<bool>() {
 	return readBoolean();
 }
-template <>
-inline char Message::read() {
-	return readByte();
-}
+
 template <>
 inline float Message::read() {
 	return readFloat();
 }
+
 template <>
 inline double Message::read() {
 	return readDouble();
 }
+template <>
+inline Time::DefaultCUC Message::read() {
+	return readDefaultCUCTimeStamp();
+}
+template <>
+inline Time::RelativeTime Message::read() {
+	return readRelativeTime();
+}
 
 #endif // ECSS_SERVICES_PACKET_H
diff --git a/inc/MessageParser.hpp b/inc/MessageParser.hpp
index 031a6fc505c992189f3169ceccb6877dac04ecb0..825548d9042c1dc42344cda2ca9d948f701c5471 100644
--- a/inc/MessageParser.hpp
+++ b/inc/MessageParser.hpp
@@ -75,7 +75,7 @@ public:
 	 * error. Messages smaller than \p size are padded with zeros. When `size = 0`, there is no size limit.
 	 * @return A String class containing the parsed Message
 	 */
-	static String<CCSDSMaxMessageSize> composeECSS(const Message& message, uint16_t size = 0u); // Ignore-MISRA
+	static String<CCSDSMaxMessageSize> composeECSS(const Message& message, uint16_t size = 0U); // Ignore-MISRA
 
 	/**
 	 * @brief Converts a TC or TM message to a packet string, appending the ECSS and then the CCSDS header
diff --git a/inc/Platform/x86/ECSS_Configuration.hpp b/inc/Platform/x86/ECSS_Configuration.hpp
index bd4e0163632d1b4b4b2bae10a6f96c24c1ff3872..bfce212b456249d58e9b7614c7d1fd1effd486a6 100644
--- a/inc/Platform/x86/ECSS_Configuration.hpp
+++ b/inc/Platform/x86/ECSS_Configuration.hpp
@@ -10,7 +10,7 @@
  */
 
 /**
- * @defgroup ServiceDefinitions Service compilation switches
+ * @name ServiceDefinitions Service compilation switches
  * These preprocessor defines control whether the compilation of each ECSS service is enabled. By not defining one of
  * those, the service will not be compiled, and no RAM or ROM will be spent storing it.
  *
@@ -18,7 +18,8 @@
  * @{
  */
 
-#define SERVICE_ALL
+#define SERVICE_ALL                       ///<  Enables compilation of all the ECSS services
+#define SERVICE_DUMMY                     ///<  Compile ST[128] dummy service
 #define SERVICE_EVENTACTION               ///<  Compile ST[19] event-action
 #define SERVICE_EVENTREPORT               ///<  Compile ST[05] event reporting
 #define SERVICE_FUNCTION                  ///<  Compile ST[08] function management
@@ -28,11 +29,12 @@
 #define SERVICE_ONBOARDMONITORING         ///<  Compile ST[12] on-board monitoring
 #define SERVICE_PARAMETER                 ///<  Compile ST[20] parameter management
 #define SERVICE_PARAMETERSTATISTICS       ///<  Compile ST[04] parameter statistics
-#define SERVICE_REALTIMEFORWARDINGCONTROL ///< Compile ST[14] real time forwarding control
+#define SERVICE_REALTIMEFORWARDINGCONTROL ///<  Compile ST[14] real time forwarding control
 #define SERVICE_REQUESTVERIFICATION       ///<  Compile ST[01] request verification
 #define SERVICE_STORAGEANDRETRIEVAL       ///<  Compile ST[15] storage-and-retrieval of tm packets
 #define SERVICE_TEST                      ///<  Compile ST[17] test
 #define SERVICE_TIME                      ///<  Compile ST[09] time management
 #define SERVICE_TIMESCHEDULING            ///<  Compile ST[11] time-based scheduling
+/** @} */
 
 #endif // ECSS_SERVICES_ECSS_CONFIGURATION_HPP
diff --git a/inc/Platform/x86/Helpers/EnumMagic.hpp b/inc/Platform/x86/Helpers/EnumMagic.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6e5582406bb1e09b75e5121ff75ea3c8c6158217
--- /dev/null
+++ b/inc/Platform/x86/Helpers/EnumMagic.hpp
@@ -0,0 +1,114 @@
+#pragma once
+
+#include <string>
+#include <utility>
+
+#if !defined(__GNUC__) && !defined(__clang__)
+#define __PRETTY_FUNCTION__ "E V = Sorry, feature not supported!"
+#endif
+
+/**
+ * A simplified version of https://github.com/Neargye/magic_enum, this file uses some gcc compiler options to provide an @ref enumName function.
+ * This function converts an enum value to a string. It's used for debugging purposes only, to improve the readability of values that are hidden
+ * behind enums.
+ *
+ * Use with care. NOT intended for a microcontroller.
+ *
+ * @note This functionality is designed for simple, sequence-like enums. Their values should start from 0 and increase 1-by-1 until the end. It will probably
+ * result in slow compilation or incorrect results if used for other, "weirder" enums.
+ *
+ * This hack aims to be safe from errors by using `constexpr` lavishly. Enum values which are out of bounds (e.g. not defined or beyond
+ * EnumMagic_::MaximumValues) will not throw errors or cause unexpected events, but will probably display some kind of string.
+ *
+ * @license MIT, Daniil Goncharov
+ */
+namespace EnumMagic_ {
+	/**
+	 * The highest enum value that can be handled.
+	 *
+	 * Values higher than this will just result in a number or malformed text, but _not_ a compilation or runtime error.
+	 */
+	constexpr auto MaximumValues = 256;
+
+	/**
+	 * Returns the identifier of an enum value.
+	 *
+	 * For example, if you define an enum:
+	 * @code
+	 * enum Something {
+	 *     First = 0,
+	 *     Second = 1
+	 * }
+	 * @endcode
+	 * then calling this function with `Something::First` will return the string `"Something::First"`.
+	 *
+	 * Internally, this function uses the [`__PRETTY_FUNCTION__`](https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html)
+	 * magic constant defined by GCC. The constant contains the template arguments of the function in a string,
+	 * which themselves contain the identifier of the enum value.
+	 *
+	 * @note Tested with GCC version 11 only, other versions or compilers might return incorrect values
+	 *
+	 * @tparam E Enum type
+	 * @tparam V Enum value (of type E)
+	 * @return The identifier of the enum value
+	 */
+	template <typename E, E V>
+	constexpr std::basic_string_view<char> enumHack() {
+		static_assert(std::is_enum_v<E>, "enumHack() requires enum type.");
+
+		std::string_view function = __PRETTY_FUNCTION__;
+		auto pos = function.find("E V = ");
+		std::string_view output = function.substr(pos + 6);
+		output.remove_suffix(1);
+		return output;
+	}
+
+	/**
+	 * Shortcut definition of enumHack for easier access
+	 */
+	template <typename Enum, Enum Value>
+	inline constexpr auto enumNameV = enumHack<Enum, Value>();
+
+	/**
+	 * Given an enum type and a sequence of values, this function returns a list
+	 *
+	 * @tparam Indexes A list of potential enum values in numerical format
+	 * @return An std::array of names for every enum value in the indexes
+	 */
+	template <typename Enum, std::size_t... Indexes>
+	constexpr auto names(std::index_sequence<Indexes...>) noexcept {
+		static_assert(std::is_enum_v<Enum>, "names() requires enum type.");
+
+		return std::array<std::string_view, sizeof...(Indexes)>{{enumNameV<Enum, static_cast<Enum>(Indexes)>...}};
+	}
+
+	/**
+	 * For the specified Enum enumeration, this variable will contain a list of the names of all its values
+	 */
+	template <typename Enum>
+	inline constexpr std::array namesV = names<Enum>(std::make_index_sequence<MaximumValues>{});
+
+	/**
+	 * Given a nested name (e.g. `Services::Parameter::value`), this function returns the innermost name (e.g. `value`)
+	 */
+	constexpr std::string_view removeNamespace(std::string_view in) {
+		auto pos = in.find_last_of("::");
+		return in.substr(pos + 1);
+	}
+} // namespace EnumMagic_
+
+/**
+ * Get the name of an enum value, as defined in the source code.
+ */
+template <typename Enum>
+std::string enumName(Enum value) {
+	using namespace EnumMagic_;
+
+	auto index = static_cast<size_t>(value);
+
+	if (index >= namesV<Enum>.size()) {
+		return "(Unknown)";
+	}
+
+	return std::string(removeNamespace(namesV<Enum>[index]));
+}
diff --git a/inc/Platform/x86/TimeGetter.hpp b/inc/Platform/x86/TimeGetter.hpp
deleted file mode 100644
index d5da817d62de9548c355a0e757c8ebc275e40614..0000000000000000000000000000000000000000
--- a/inc/Platform/x86/TimeGetter.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef ECSS_SERVICES_TIMEGETTER_HPP
-#define ECSS_SERVICES_TIMEGETTER_HPP
-
-#include <cstdint>
-#include <ctime>
-
-/**
- * @brief Get the current time
- */
-class TimeGetter {
-public:
-	/**
-	 * @brief Gets the current time in UNIX epoch
-	 * @return Current UNIX epoch time, in elapsed seconds
-	 */
-	static inline uint32_t getSeconds() {
-		return static_cast<uint32_t>(time(nullptr));
-	}
-};
-
-#endif // ECSS_SERVICES_TIMEGETTER_HPP
diff --git a/inc/Service.hpp b/inc/Service.hpp
index 53bf0bae49366814e9e8bff2a0d1436abbb877c8..763858973ef010e5a5f1e8dcd85177d15477e37e 100644
--- a/inc/Service.hpp
+++ b/inc/Service.hpp
@@ -4,8 +4,6 @@
 #include <cstdint>
 #include "Message.hpp"
 
-class ServicePool;
-
 /**
  * @defgroup Services Services
  * ECSS Services implementations, as defined in ECSS-E-ST-70-41C. These services receive TC Messages, and output TM
@@ -35,10 +33,9 @@ protected:
 	 * @param messageType The ID of the message type, as specified in the standard. For example,
 	 *                    the TC[17,3] message has `messageType = 3`.
 	 * @todo See if the Message must be returned by reference
-	 * @todo Set the application ID to the current application
 	 */
-	Message createTM(uint8_t messageType) {
-		return Message(serviceType, messageType, Message::TM, 0);
+	Message createTM(uint8_t messageType) const {
+		return Message(serviceType, messageType, Message::TM);
 	}
 
 	/**
diff --git a/inc/ServicePool.hpp b/inc/ServicePool.hpp
index 503d94cd55309a5f949b2b6f5a3706fbebd27b4a..23067caeec17d9fc3671c7bef920945dd3894106 100644
--- a/inc/ServicePool.hpp
+++ b/inc/ServicePool.hpp
@@ -2,6 +2,7 @@
 #define ECSS_SERVICES_SERVICEPOOL_HPP
 
 #include "ECSS_Configuration.hpp"
+#include "Services/DummyService.hpp"
 #include "Services/EventActionService.hpp"
 #include "Services/EventReportService.hpp"
 #include "Services/FunctionManagementService.hpp"
@@ -30,7 +31,6 @@ class ServicePool {
 	 * the number of the service, while the least significant 8 bits are the number of the Message. The value is the
 	 * counter of each MessageType.
 	 */
-
 	etl::map<uint16_t, uint16_t, ECSSTotalMessageTypes> messageTypeCounter;
 
 	/**
@@ -39,6 +39,10 @@ class ServicePool {
 	uint16_t packetSequenceCounter = 0;
 
 public:
+#ifdef SERVICE_DUMMY
+	DummyService dummyService;
+#endif
+
 #ifdef SERVICE_EVENTACTION
 	EventActionService eventAction;
 #endif
@@ -95,6 +99,7 @@ public:
 	TimeBasedSchedulingService timeBasedScheduling;
 #endif
 
+
 	/**
 	 * The default ServicePool constructor
 	 */
@@ -133,6 +138,6 @@ public:
 /**
  * A global variable that defines the basic pool where services can be fetched from
  */
-extern ServicePool Services;
+extern ServicePool Services; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 
 #endif // ECSS_SERVICES_SERVICEPOOL_HPP
diff --git a/inc/Services/DummyService.hpp b/inc/Services/DummyService.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0463ff75aed7710f10248a9970c536d57fd77b83
--- /dev/null
+++ b/inc/Services/DummyService.hpp
@@ -0,0 +1,41 @@
+#ifndef ECSS_SERVICES_DUMMYSERVICE_HPP
+#define ECSS_SERVICES_DUMMYSERVICE_HPP
+
+#include "Logger_Definitions.hpp"
+#include "Service.hpp"
+
+/**
+ * This is a dummy Service used during testing. Its functionality is to contain LOG_ data but be sent through CAN bus.
+ * During the environmental tests, we will use both CAN and UART to send data from the MCU to the PC. However, the
+ * current CAN protocol does not accommodate random data strings. Therefore, we will use this dummy service to send such
+ * messages.
+ *
+ * Per the ECSS-E-ST-70-41C standard, p. 27-28, custom Services and Messages should start above 127.
+ */
+class DummyService : public Service {
+private:
+	etl::string<1> termination = "\n";
+
+public:
+	inline static const uint8_t ServiceType = 128;
+	enum MessageType : uint8_t {
+		LogString = 128,
+	};
+
+	DummyService() {
+		serviceType = ServiceType;
+	}
+
+	/**
+     * Send data as a part of a custom ECSS Message
+     * Creates a TM[128, 128]
+     */
+	void logAsECSSMessage(const etl::string<LOGGER_MAX_MESSAGE_SIZE>& data) {
+		Message log = createTM(MessageType::LogString);
+		log.appendString(data);
+		log.appendString(termination);
+		storeMessage(log);
+	}
+};
+
+#endif //ECSS_SERVICES_DUMMYSERVICE_HPP
diff --git a/inc/Services/EventActionService.hpp b/inc/Services/EventActionService.hpp
index 6ed438d8f07834d475c6ada312d2c3ec8d1555d8..1d4776d90df5fdab48f2d22ee54c4c6bfd2e1d9d 100644
--- a/inc/Services/EventActionService.hpp
+++ b/inc/Services/EventActionService.hpp
@@ -2,8 +2,8 @@
 #define ECSS_SERVICES_EVENTACTIONSERVICE_HPP
 
 #include "Service.hpp"
-#include "etl/String.hpp"
 #include "Services/EventReportService.hpp"
+#include "etl/String.hpp"
 #include "etl/multimap.h"
 
 /**
@@ -12,34 +12,19 @@
  * ECSS 8.19 && 6.19
  *
  * @ingroup Services
- * @note Make sure to check the note in the addEventActionDefinition()
- * @note A third variable was added, the eventActionDefinitionID. This was added for the purpose of identifying
- * various eventActionDefinitions that correspond to the same eventDefinitionID. The goal is to have multiple actions
- * be executed when one event takes place. This defies the standard.
+ *
  * @note The application ID was decided to be abolished as an identifier of the event-action
  * definition
  * @attention Every event action definition ID should be different, regardless of the application ID
- *
- * @todo Since there are multiple actions per event and in delete/enable/disable functions are
- * multiple instances are accessed, should I find a more efficient way to access them?
- * @todo check if eventActionFunctionStatus should be private or not
- * @todo check if eventAction map of definitions should be private or not
  */
 class EventActionService : public Service {
 private:
 	/**
 	 * Event-action function status
 	 */
-	bool eventActionFunctionStatus;
-
-	/**
-	 * Custom function that is called right after an event takes place, to initiate
-	 * the execution of the action
-	 */
-	void executeAction(uint16_t eventID);
+	bool eventActionFunctionStatus = false;
 
 public:
-
 	inline static const uint8_t ServiceType = 19;
 
 	enum MessageType : uint8_t {
@@ -55,30 +40,26 @@ public:
 	};
 
 	struct EventActionDefinition {
-		// TODO: APID = 0 is the Ground Station APID. This should be changed
-		uint16_t applicationId = 0;
-		uint16_t eventDefinitionID = 65535; // The ID of the event that might take place
-		uint16_t eventActionDefinitionID = 0; // The ID of the event-action
-		String<64> request = "";
+		uint16_t applicationID = 0;
+		inline static const uint16_t MaxDefinitionID = 65535;
+		uint16_t eventDefinitionID = MaxDefinitionID;
+		String<ECSSTCRequestStringSize> request = "";
 		bool enabled = false;
+
+		EventActionDefinition(uint16_t applicationID, uint16_t eventDefinitionID, Message& message);
 	};
 
 	friend EventReportService;
 
 	etl::multimap<uint16_t, EventActionDefinition, ECSSEventActionStructMapSize>
-		eventActionDefinitionMap;
+	    eventActionDefinitionMap;
 
-	EventActionService() {
-		serviceType = 19;
-		eventActionFunctionStatus = true;
+	EventActionService() : eventActionFunctionStatus(true) {
+		serviceType = ServiceType;
 	}
 
 	/**
 	 * TC[19,1] add event-action definitions
-	 *
-	 * Note: We have abolished multiple additions in one Telecommand packet. Only one
-	 * event-action definition will be added per TC packet. That means there will be just an
-	 * application ID, an event definition ID and the TC request.
 	 */
 	void addEventActionDefinitions(Message& message);
 
@@ -118,7 +99,7 @@ public:
 	void enableEventActionFunction(Message& message);
 
 	/**
-	 * TC[19,9] disable the event-actioni function
+	 * TC[19,9] disable the event-action function
 	 */
 	void disableEventActionFunction(Message& message);
 
@@ -133,10 +114,16 @@ public:
 	 * Getter for event-action function status
 	 * @return eventActionFunctionStatus
 	 */
-	bool getEventActionFunctionStatus() {
+	bool getEventActionFunctionStatus() const {
 		return eventActionFunctionStatus;
 	}
 
+	/**
+	 * Custom function that is called right after an event takes place, to initiate
+	 * the execution of the action
+	 */
+	void executeAction(uint16_t eventDefinitionID);
+
 	/**
 	 * It is responsible to call the suitable function that executes a telecommand packet. The source of that packet
 	 * is the ground station.
diff --git a/inc/Services/EventReportService.hpp b/inc/Services/EventReportService.hpp
index 839dff8bc3ca013acee789fbb9ad257b730fa18e..a5e13105cfd57d92a8ba97a2334389ba886b186f 100644
--- a/inc/Services/EventReportService.hpp
+++ b/inc/Services/EventReportService.hpp
@@ -1,8 +1,8 @@
 #ifndef ECSS_SERVICES_EVENTREPORTSERVICE_HPP
 #define ECSS_SERVICES_EVENTREPORTSERVICE_HPP
 
-#include "Service.hpp"
 #include <etl/bitset.h>
+#include "Service.hpp"
 
 /**
  * Implementation of ST[05] event reporting service
@@ -20,7 +20,6 @@ private:
 	etl::bitset<numberOfEvents> stateOfEvents;
 
 public:
-
 	inline static const uint8_t ServiceType = 5;
 
 	enum MessageType : uint8_t {
@@ -35,34 +34,24 @@ public:
 	};
 
 	// Variables that count the event reports per severity level
-	uint16_t lowSeverityReportCount;
-	uint16_t mediumSeverityReportCount;
-	uint16_t highSeverityReportCount;
+	uint16_t lowSeverityReportCount = 0;
+	uint16_t mediumSeverityReportCount = 0;
+	uint16_t highSeverityReportCount = 0;
 
 	// Variables that count the event occurences per severity level
-	uint16_t lowSeverityEventCount;
-	uint16_t mediumSeverityEventCount;
-	uint16_t highSeverityEventCount;
+	uint16_t lowSeverityEventCount = 0;
+	uint16_t mediumSeverityEventCount = 0;
+	uint16_t highSeverityEventCount = 0;
 
-	uint16_t disabledEventsCount;
+	uint16_t disabledEventsCount = 0;
 
-	uint16_t lastLowSeverityReportID;
-	uint16_t lastMediumSeverityReportID;
-	uint16_t lastHighSeverityReportID;
+	uint16_t lastLowSeverityReportID = 65535;
+	uint16_t lastMediumSeverityReportID = 65535;
+	uint16_t lastHighSeverityReportID = 65535;
 
 	EventReportService() {
 		stateOfEvents.set();
-		serviceType = 5;
-		lowSeverityReportCount = 0;
-		mediumSeverityReportCount = 0;
-		highSeverityReportCount = 0;
-		disabledEventsCount = 0;
-		lowSeverityEventCount = 0;
-		mediumSeverityEventCount = 0;
-		highSeverityEventCount = 0;
-		lastLowSeverityReportID = 65535;
-		lastMediumSeverityReportID = 65535;
-		lastHighSeverityReportID = 65535;
+		serviceType = ServiceType;
 	}
 
 	/**
diff --git a/inc/Services/FunctionManagementService.hpp b/inc/Services/FunctionManagementService.hpp
index 4dd0922560dc4d550045ade585dc3b5d4e2dd942..78c771049d511a8f9eee0e2a7f7368ef28fdd12a 100644
--- a/inc/Services/FunctionManagementService.hpp
+++ b/inc/Services/FunctionManagementService.hpp
@@ -45,7 +45,9 @@ public:
 	 * Constructs the function pointer index with all the necessary functions at initialization time
 	 * These functions need to be in scope. Un-default when needed.
 	 */
-	FunctionManagementService() = default;
+	FunctionManagementService() {
+		serviceType = ServiceType;
+	}
 
 	/**
 	 * Calls the function described in the TC[8,1] message *msg*, passing the arguments contained
@@ -87,7 +89,7 @@ public:
 	 */
 	void include(String<ECSSFunctionNameLength> funcName, void (*ptr)(String<ECSSFunctionMaxArgLength>));
 
-	int getMapSize() {
+	size_t getMapSize() {
 		return funcPtrIndex.size();
 	}
 
diff --git a/inc/Services/HousekeepingService.hpp b/inc/Services/HousekeepingService.hpp
index 2336f094e8e15a0afee5f28927502541494fee86..8614b5529f153f757c68ab4c8029ff6b915f2743 100644
--- a/inc/Services/HousekeepingService.hpp
+++ b/inc/Services/HousekeepingService.hpp
@@ -1,11 +1,12 @@
 #ifndef ECSS_SERVICES_HOUSEKEEPINGSERVICE_HPP
 #define ECSS_SERVICES_HOUSEKEEPINGSERVICE_HPP
 
-#include "etl/map.h"
+#include <optional>
 #include "ECSS_Definitions.hpp"
-#include "Service.hpp"
 #include "ErrorHandler.hpp"
 #include "Helpers/HousekeepingStructure.hpp"
+#include "Service.hpp"
+#include "etl/map.h"
 
 /**
  * Implementation of the ST[03] Housekeeping Reporting Service. The job of the Housekeeping Service is to store
@@ -31,11 +32,11 @@ private:
 	static bool existsInVector(const etl::vector<uint16_t, ECSSMaxSimplyCommutatedParameters>& ids,
 	                           uint16_t parameterId);
 
-    /**
+	/**
      * Initializes Housekeeping Structures with the Parameters found in the obc-software.
      * The function definition is also found in the obc-software repo.
      */
-    void initializeHousekeepingStructures();
+	void initializeHousekeepingStructures();
 
 public:
 	inline static const uint8_t ServiceType = 3;
@@ -60,9 +61,152 @@ public:
 		HousekeepingPeriodicPropertiesReport = 35,
 	};
 
-    HousekeepingService() {
-        initializeHousekeepingStructures();
-    };
+	HousekeepingService() {
+		serviceType = ServiceType;
+		initializeHousekeepingStructures();
+	};
+
+	/**
+	 * Returns the periodic generation action status of a Housekeeping structure.
+	 * @param id Housekeeping structure ID
+	 * @return boolean True if periodic generation of housekeeping reports is enabled, false otherwise
+	 */
+	inline bool getPeriodicGenerationActionStatus(uint8_t id) {
+		HousekeepingStructure newStructure{};
+		if (hasNonExistingStructInternalError(id)) {
+			return newStructure.periodicGenerationActionStatus;
+		}
+		return housekeepingStructures.at(id).periodicGenerationActionStatus;
+	}
+
+	/**
+	 * Returns a reference to the structure at position of "id" in the map.
+	 * @param id Housekeeping structure ID
+	 * @return optional<std::reference_wrapper<HousekeepingStructure>> Reference to Housekeeping Structure
+	 */
+	inline std::optional<std::reference_wrapper<HousekeepingStructure>> getStruct(uint8_t id) {
+		if (hasNonExistingStructInternalError(id)) {
+			return {};
+		}
+		return housekeepingStructures.at(id);
+	}
+
+	/**
+	 * Returns the collection interval (how often data is collected) of a Housekeeping structure.
+	 * @param id Housekeeping structure ID
+	 * @return uint32_t Integer multiples of the minimum sampling interval
+	 */
+	inline uint32_t getCollectionInterval(uint8_t id) {
+		HousekeepingStructure newStructure{};
+		if (hasNonExistingStructInternalError(id)) {
+			return newStructure.collectionInterval;
+		}
+		return housekeepingStructures.at(id).collectionInterval;
+	}
+
+	/**
+	 * Sets the periodic generation action status of a Housekeeping structure.
+	 * @param id Housekeeping structure ID
+	 * @param status Periodic generation status of housekeeping reports
+	 */
+	inline void setPeriodicGenerationActionStatus(uint8_t id, bool status) {
+		if (hasNonExistingStructInternalError(id)) {
+			return;
+		}
+		housekeepingStructures.at(id).periodicGenerationActionStatus = status;
+	}
+
+	/**
+	 * Sets the collection interval of a Housekeeping structure.
+	 * @param id Housekeeping structure ID
+	 * @param interval Integer multiples of the minimum sampling interval
+	 */
+	inline void setCollectionInterval(uint8_t id, uint32_t interval) {
+		if (hasNonExistingStructInternalError(id)) {
+			return;
+		}
+		housekeepingStructures.at(id).collectionInterval = interval;
+	}
+
+	/**
+	 * Checks if the structure exists in the map.
+	 * @param id Housekeeping structure ID
+	 * @return boolean True if the structure exists, false otherwise
+	 */
+	inline bool structExists(uint8_t id) {
+		return (housekeepingStructures.find(id) != housekeepingStructures.end());
+	}
+
+	/**
+	 * Checks if the structure doesn't exist in the map and then accordingly reports execution start error.
+	 * @param id Housekeeping structure ID
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if the structure doesn't exist, false otherwise
+	 */
+	bool hasNonExistingStructExecutionError(uint8_t id, Message& request);
+
+	/**
+	 * Checks if the structure doesn't exist in the map and then accordingly reports error.
+	 * @param id Housekeeping structure ID
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if the structure doesn't exist, false otherwise
+	 */
+	bool hasNonExistingStructError(uint8_t id, Message& request);
+
+	/**
+	 * Checks if the structure doesn't exist in the map and then accordingly reports internal error.
+	 * @param id Housekeeping structure ID
+	 * @return boolean True if the structure doesn't exist, false otherwise
+	 */
+	bool hasNonExistingStructInternalError(uint8_t id);
+
+	/**
+	 * Checks if the parameter exists in the vector and if it does it reports an error.
+	 * @param id Parameter ID
+	 * @param housekeepingStruct Housekkeping Structure
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if the parameter exists, false otherwise
+	 */
+	static bool hasAlreadyExistingParameterError(HousekeepingStructure& housekeepingStruct, uint8_t id, Message& request);
+
+	/**
+	 * Checks if the struct requested exists and if it exists reports execution error.
+	 * @param id Housekeeping structure ID
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if the structure exists, false otherwise
+	 */
+	bool hasAlreadyExistingStructError(uint8_t id, Message& request);
+
+	/**
+	 * Reports execution error if the max number of housekeeping structures is exceeded.
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if max number of housekeeping structures is exceeded, false otherwise
+	 */
+	bool hasExceededMaxNumOfHousekeepingStructsError(Message& request);
+
+	/**
+	 * Reports execution error if it's attempted to append a new parameter id to a housekeeping structure, but the periodic generation status is enabled.
+	 * @param housekeepingStruct Housekkeping Structure
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if periodic generation status is enabled, false otherwise
+	 */
+	static bool hasRequestedAppendToEnabledHousekeepingError(HousekeepingStructure& housekeepingStruct, Message& request);
+
+	/**
+	 * Reports execution error if it's attempted to delete structure which has the periodic reporting status enabled.
+	 * @param id Housekeeping structure ID
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if periodic reporting status is enabled, false otherwise
+	 */
+	bool hasRequestedDeletionOfEnabledHousekeepingError(uint8_t id, Message& request);
+
+	/**
+	 * Reports execution error if the max number of simply commutated parameters is exceeded.
+	 * @param housekeepingStruct Housekkeping Structure
+	 * @param request Telemetry (TM) or telecommand (TC) message
+	 * @return boolean True if max number of simply commutated parameters is exceeded, false otherwise
+	 */
+	static bool hasExceededMaxNumOfSimplyCommutatedParamsError(HousekeepingStructure& housekeepingStruct, Message& request);
 
 	/**
 	 * Implementation of TC[3,1]. Request to create a housekeeping parameters report structure.
diff --git a/inc/Services/LargePacketTransferService.hpp b/inc/Services/LargePacketTransferService.hpp
index a3ef0a2770c0a745d80d31283f0ecb925bd10b98..154f7c6dfde4e41f421b540c3866be5b28ad2853 100644
--- a/inc/Services/LargePacketTransferService.hpp
+++ b/inc/Services/LargePacketTransferService.hpp
@@ -1,8 +1,8 @@
 #ifndef ECSS_SERVICES_LARGEPACKETTRANSFERSERVICE_HPP
 #define ECSS_SERVICES_LARGEPACKETTRANSFERSERVICE_HPP
 
-#include "Service.hpp"
 #include <etl/String.hpp>
+#include "Service.hpp"
 
 /**
  * Implementation of the ST[13] large packet transfer service
@@ -16,7 +16,6 @@
 
 class LargePacketTransferService : public Service {
 public:
-
 	inline static const uint8_t ServiceType = 13;
 
 
@@ -30,11 +29,11 @@ public:
 	 * Default constructor since only functions will be used.
 	 */
 	LargePacketTransferService() {
-		serviceType = 13;
+		serviceType = ServiceType;
 	}
 
 	/**
-	 * Function that handles the first part of the download report
+	 * TM[13,1] Function that handles the first part of the download report
 	 * @param largeMessageTransactionIdentifier The identifier of the large packet
 	 * @param partSequenceNumber The identifier of the part of the large packet
 	 * @param string The data contained in this part of the large packet
@@ -43,7 +42,7 @@ public:
 	                             const String<ECSSMaxFixedOctetStringSize>& string);
 
 	/**
-	 * Function that handles the n-2 parts of tbe n-part download report
+	 * TM[13,2] Function that handles the n-2 parts of tbe n-part download report
 	 * @param largeMessageTransactionIdentifier The identifier of the large packet
 	 * @param partSequenceNumber The identifier of the part of the large packet
 	 * @param string The data contained in this part of the large packet
@@ -52,7 +51,7 @@ public:
 	                                    const String<ECSSMaxFixedOctetStringSize>& string);
 
 	/**
-	 * Function that handles the last part of the download report
+	 * TM[13,3] Function that handles the last part of the download report
 	 * @param largeMessageTransactionIdentifier The identifier of the large packet
 	 * @param partSequenceNumber The identifier of the part of the large packet
 	 * @param string The data contained in this part of the large packet
@@ -64,23 +63,23 @@ public:
 	// a composeECSS function ready, I just return the given string.
 	// @TODO: Modify these functions properly
 	/**
-	 * Function that handles the first part of the uplink request
+	 * TC[13,9] Function that handles the first part of the uplink request
 	 * @param string This will change when these function will be modified
 	 */
-	String<ECSSMaxFixedOctetStringSize> firstUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string);
+	static String<ECSSMaxFixedOctetStringSize> firstUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string);
 
 	/**
-	 * Function that handles the n-2 parts of tbe n-part uplink request
+	 * TC[13,10] Function that handles the n-2 parts of the n-part uplink request
 	 * @param string This will change when these function will be modified
 	 */
-	String<ECSSMaxFixedOctetStringSize>
+	static String<ECSSMaxFixedOctetStringSize>
 	intermediateUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string);
 
 	/**
-	 * Function that handles the last part of the uplink request
+	 * TC[13,11] Function that handles the last part of the uplink request
 	 * @param string This will change when these function will be modified
 	 */
-	String<ECSSMaxFixedOctetStringSize> lastUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string);
+	static String<ECSSMaxFixedOctetStringSize> lastUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string);
 
 	/**
 	 * Function that splits large messages
diff --git a/inc/Services/MemoryManagementService.hpp b/inc/Services/MemoryManagementService.hpp
index 6439bfa64f844603916c2d148b5d46899b7628c4..1c208342843cffea3c0c294e338a5df302977aea 100644
--- a/inc/Services/MemoryManagementService.hpp
+++ b/inc/Services/MemoryManagementService.hpp
@@ -2,17 +2,16 @@
 #define ECSS_SERVICES_MEMMANGSERVICE_HPP
 
 #include <memory>
-#include "Service.hpp"
-#include "Helpers/CRCHelper.hpp"
 #include "ErrorHandler.hpp"
+#include "Helpers/CRCHelper.hpp"
 #include "Platform/STM32F7/MemoryAddressLimits.hpp"
+#include "Service.hpp"
 
 /**
  * @ingroup Services
  */
 class MemoryManagementService : public Service {
 public:
-
 	inline static const uint8_t ServiceType = 6;
 
 	enum MessageType : uint8_t {
@@ -30,7 +29,7 @@ public:
 		RAM_D2,
 		RAM_D3,
 		ITCMRAM,
-		FLASH,
+		FLASH_MEMORY,
 		EXTERNAL,
 	};
 
@@ -50,16 +49,6 @@ public:
 	public:
 		explicit RawDataMemoryManagement(MemoryManagementService& parent);
 
-		/**
-		 * TC[6,2] load raw values to memory
-		 *
-		 * @details This function loads new values to memory data areas
-		 * 			specified in the request
-		 * @param request Provide the received message as a parameter
-		 * @todo Only allow aligned memory address to be start addresses
-		 */
-		void loadRawData(Message& request);
-
 		/**
 		 * TC[6,5] read raw memory values
 		 *
@@ -82,9 +71,19 @@ public:
 		 * 		 different memory types
 		 * @todo Only allow aligned memory address to be start addresses
 		 */
-		void checkRawData(Message &request);
+		void checkRawData(Message& request);
 	} rawDataMemorySubservice;
 
+	/**
+	 * TC[6,2] load raw values to memory
+	 *
+	 * @details This function loads new values to memory data areas
+	 * 			specified in the request
+	 * @param request Provide the received message as a parameter
+	 * @todo Only allow aligned memory address to be start addresses
+	 */
+	static void loadRawData(Message& request);
+
 	/**
 	 * It is responsible to call the suitable function that executes a telecommand packet. The source of that packet
 	 * is the ground station.
@@ -101,20 +100,20 @@ private:
 	 * @param memId The ID of the memory to check is passed
 	 * @param address Takes the address to be checked for validity
 	 */
-	bool addressValidator(MemoryManagementService::MemoryID memId, uint64_t address);
+	static bool addressValidator(MemoryManagementService::MemoryID memId, uint64_t address);
 
 	/**
 	 * Check if the provided memory ID is valid
 	 *
 	 * @param memId The memory ID for validation
 	 */
-	bool memoryIdValidator(MemoryManagementService::MemoryID memId);
+	static bool memoryIdValidator(MemoryManagementService::MemoryID memId);
 
 	/**
 	 * Validate the data according to checksum calculation
 	 *
 	 */
-	bool dataValidator(const uint8_t* data, uint16_t checksum, uint16_t length);
+	static bool dataValidator(const uint8_t* data, uint16_t checksum, uint16_t length);
 };
 
 #endif // ECSS_SERVICES_MEMMANGSERVICE_HPP
diff --git a/inc/Services/OnBoardMonitoringService.hpp b/inc/Services/OnBoardMonitoringService.hpp
index 1ef954f2f6f4356436047b1909bc75dcd95d45b4..d67bf35176f980da78bcde8ca4c1c59f0f734f08 100644
--- a/inc/Services/OnBoardMonitoringService.hpp
+++ b/inc/Services/OnBoardMonitoringService.hpp
@@ -40,6 +40,11 @@ public:
 		ReportStatusOfParameterMonitoringDefinition = 13,
 		ParameterMonitoringDefinitionStatusReport = 14
 	};
+
+	OnBoardMonitoringService() {
+		serviceType = ServiceType;
+	}
+
 	/**
 	 * The maximum time between two transition reports.
 	 * Measured in "on-board parameter minimum sampling interval" units (see 5.4.3.2c in ECSS-E-ST-70-41C).
@@ -93,4 +98,4 @@ public:
 	void execute(Message& message);
 };
 
-#endif // ECSS_SERVICES_ONBOARDMONITORINGSERVICE_HPP
+#endif // ECSS_SERVICES_ONBOARDMONITORINGSERVICE_HPP
\ No newline at end of file
diff --git a/inc/Services/ParameterService.hpp b/inc/Services/ParameterService.hpp
index 437bd395ad06cffe0a97ef1d2959d4f2c531ee2f..8718015057d96e4332666f41d9ba195906835c85 100644
--- a/inc/Services/ParameterService.hpp
+++ b/inc/Services/ParameterService.hpp
@@ -3,9 +3,9 @@
 
 #include <optional>
 #include "ECSS_Definitions.hpp"
-#include "Service.hpp"
 #include "ErrorHandler.hpp"
 #include "Helpers/Parameter.hpp"
+#include "Service.hpp"
 #include "etl/map.h"
 
 /**
@@ -57,6 +57,7 @@ public:
 	 * by calling \fn initializeParametersArray
 	 */
 	ParameterService() {
+		serviceType = ServiceType;
 		initializeParameterMap();
 	}
 
@@ -104,7 +105,7 @@ public:
 	 *
 	 * @param newParamValues: a valid TC[20, 3] message carrying parameter ID and replacement value
 	 */
-	void setParameters(Message& newParamValues);
+	void setParameters(Message& newParamValues) const;
 
 	/**
 	 * It is responsible to call the suitable function that executes a telecommand packet. The source of that packet
diff --git a/inc/Services/ParameterStatisticsService.hpp b/inc/Services/ParameterStatisticsService.hpp
index b6f98580fca55357a6968d90fb7c4e9342e05db4..d04a12afa22932ba01b887b182bfbc7cd3fc36a5 100644
--- a/inc/Services/ParameterStatisticsService.hpp
+++ b/inc/Services/ParameterStatisticsService.hpp
@@ -2,9 +2,10 @@
 #define ECSS_SERVICES_PARAMETERSTATISTICSSERVICE_HPP
 
 #include "ECSS_Definitions.hpp"
-#include "Service.hpp"
 #include "ErrorHandler.hpp"
 #include "Helpers/Statistic.hpp"
+#include "Helpers/TimeGetter.hpp"
+#include "Service.hpp"
 #include "etl/deque.h"
 #include "etl/map.h"
 
@@ -15,6 +16,28 @@
  * @author Konstantinos Petridis <petridkon@gmail.com>
  */
 class ParameterStatisticsService : public Service {
+private:
+	/**
+	 * The time at which the evaluation of statistics is initialized. It is basically the time when the statistics
+	 * are reset.
+	 */
+	Time::DefaultCUC evaluationStartTime;
+
+	/**
+	 * true means that the periodic statistics reporting is enabled
+	 */
+	bool periodicStatisticsReportingStatus = true;
+
+	/**
+	 * The parameter statistics reporting interval
+	 */
+	uint16_t reportingIntervalMs = 700;
+
+	/**
+	 * Initializer of the statistics map, so that its content can be accessed by FreeRTOS tasks.
+	 */
+	void initializeStatisticsMap();
+
 public:
 	inline static const uint8_t ServiceType = 4;
 
@@ -30,15 +53,13 @@ public:
 		ParameterStatisticsDefinitionsReport = 9,
 	};
 
+	ParameterStatisticsService();
+
 	/**
 	 * Map containing parameters' IDs followed by the statistics that correspond to the specified parameter
 	 */
 	etl::map<uint16_t, Statistic, ECSSMaxStatisticParameters> statisticsMap;
 
-	/**
-	 * true means that the periodic statistics reporting is enabled
-	 */
-	bool periodicStatisticsReportingStatus = false;
 	/**
 	 * If true, after every report reset the parameter statistics.
 	 */
@@ -47,16 +68,43 @@ public:
 	 * Indicates whether to append/read the sampling interval to/from message
 	 */
 	const bool supportsSamplingInterval = true;
+
 	/**
-	 * The parameter statistics reporting interval
+	 * Returns the periodic statistics reporting status
+	 */
+	inline bool getPeriodicReportingStatus() const {
+		return periodicStatisticsReportingStatus;
+	}
+
+	/**
+	 * Sets the value of the periodic statistics reporting status
+	 */
+	inline void setPeriodicReportingStatus(bool status) {
+		periodicStatisticsReportingStatus = status;
+	}
+
+	/**
+	 * Returns the periodic statistics reporting status
 	 */
-	uint16_t reportingInterval = 5; // TODO: Must define units. Same as parameter sampling rates
+	inline uint16_t getReportingIntervalMs() const {
+		return reportingIntervalMs;
+	}
 
 	/**
 	 * TC[4,1] report the parameter statistics, by calling parameterStatisticsReport()
 	 */
 	void reportParameterStatistics(Message& request);
 
+	/**
+	 * Report the parameter statistics, by calling parameterStatisticsReport()
+	 * This is **NOT** the function called by TC. It was created so that this function could be called
+	 * from within a Platform (MCU, x86...) without needing to create a fake TC and pass through multiple functions.
+	 *
+	 * @param reset indicates whether each Statistic should be reset. Simulates the argument contained in the TC[4,1]
+	 * that calls reportParameterStatistics(Message& request)
+	 */
+	void reportParameterStatistics(bool reset);
+
 	/**
 	 * Constructs and stores a TM[4,2] packet containing the parameter statistics report.
 	 */
diff --git a/inc/Services/RealTimeForwardingControlService.hpp b/inc/Services/RealTimeForwardingControlService.hpp
index 580c5e61776b83aaf2766a40382a47d341c04e76..a43642d948f9b1a12ebdfed7e1d070f57eb95727 100644
--- a/inc/Services/RealTimeForwardingControlService.hpp
+++ b/inc/Services/RealTimeForwardingControlService.hpp
@@ -17,7 +17,7 @@
  *
  * @author Konstantinos Petridis <petridkon@gmail.com>
  */
-class RealTimeForwardingControlService {
+class RealTimeForwardingControlService : Service {
 public:
 	inline static const uint8_t ServiceType = 14;
 
@@ -27,7 +27,9 @@ public:
 		EventReportConfigurationContentReport = 16,
 	};
 
-	RealTimeForwardingControlService() = default;
+	RealTimeForwardingControlService() {
+		serviceType = ServiceType;
+	}
 
 	/**
 	 * Contains the Application IDs, controlled by the Service.
diff --git a/inc/Services/RequestVerificationService.hpp b/inc/Services/RequestVerificationService.hpp
index c6ccd8720f2a8de05349959fe3caaffe097e3ffd..08c00834cc68bbc5897a57474d5cce7976653263 100644
--- a/inc/Services/RequestVerificationService.hpp
+++ b/inc/Services/RequestVerificationService.hpp
@@ -1,10 +1,10 @@
 #ifndef ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP
 #define ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP
 
-#include "Service.hpp"
-#include "Message.hpp"
-#include "ErrorHandler.hpp"
 #include "ECSS_Definitions.hpp"
+#include "ErrorHandler.hpp"
+#include "Message.hpp"
+#include "Service.hpp"
 
 /**
  * Implementation of the ST[01] request verification service
@@ -20,7 +20,6 @@
  */
 class RequestVerificationService : public Service {
 public:
-
 	inline static const uint8_t ServiceType = 1;
 
 	enum MessageType : uint8_t {
@@ -36,7 +35,7 @@ public:
 	};
 
 	RequestVerificationService() {
-		serviceType = 1;
+		serviceType = ServiceType;
 	}
 
 	/**
@@ -133,7 +132,7 @@ public:
 	 * telecommand packet that failed the routing
 	 * @param errorCode The cause of creating this type of report
  	 */
-	void failRoutingVerification(const Message &request, ErrorHandler::RoutingErrorType errorCode);
+	void failRoutingVerification(const Message& request, ErrorHandler::RoutingErrorType errorCode);
 };
 
 #endif // ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP
diff --git a/inc/Services/StorageAndRetrievalService.hpp b/inc/Services/StorageAndRetrievalService.hpp
index 95142327f8d73d2e272de7cd5d192dec4252d33d..0387c8ff87c76fd9b42a00b215915144809ea9fe 100644
--- a/inc/Services/StorageAndRetrievalService.hpp
+++ b/inc/Services/StorageAndRetrievalService.hpp
@@ -206,7 +206,9 @@ public:
 		ChangeVirtualChannel = 28
 	};
 
-	StorageAndRetrievalService() = default;
+	StorageAndRetrievalService() {
+		serviceType = ServiceType;
+	}
 
 	/**
 	 * Adds new packet store into packet stores.
diff --git a/inc/Services/TestService.hpp b/inc/Services/TestService.hpp
index 82156b23e558583afad4183acd92bdfba9f354b8..63e3fbc258f4f4c51b95b4775ef84aceb5bfb1dc 100644
--- a/inc/Services/TestService.hpp
+++ b/inc/Services/TestService.hpp
@@ -10,8 +10,6 @@
  */
 class TestService : public Service {
 public:
-
-
 	inline static const uint8_t ServiceType = 17;
 
 	enum MessageType : uint8_t {
@@ -22,7 +20,7 @@ public:
 	};
 
 	TestService() {
-		serviceType = 17;
+		serviceType = ServiceType;
 	}
 
 	/**
@@ -30,19 +28,27 @@ public:
 	 */
 	void areYouAlive(Message& request);
 
+	/**
+	 * TM[17,2] are-you-alive connection test report to show that the MCU is alive and well
+	 */
+	void areYouAliveReport();
+
 	/**
 	 * TC[17,3] perform an on-board connection test
 	 *
-	 * @todo Only respond if we have the correct APID
 	 */
 	void onBoardConnection(Message& request);
 
+	/**
+	 * TM[17,4] on-board connection test report to show that the MCU is connected to the on-board
+	 */
+	void onBoardConnectionReport(uint16_t applicationProcessId);
+
 	/**
 	 * It is responsible to call the suitable function that execute the proper subservice. The
 	 * way that the subservices are selected is for the time being based on the messageType(class
 	 * member of class Message) of the param message
 	 *
-	 * @todo Error handling for the switch() in the implementation of this execute function
 	 */
 	void execute(Message& message);
 };
diff --git a/inc/Services/TimeBasedSchedulingService.hpp b/inc/Services/TimeBasedSchedulingService.hpp
index f49d8067a02a738a521c71ffcbee1d7b4718fc19..c0d5c3b62d33faf8cca15101a2ee88bcdd12efd0 100644
--- a/inc/Services/TimeBasedSchedulingService.hpp
+++ b/inc/Services/TimeBasedSchedulingService.hpp
@@ -1,14 +1,21 @@
 #ifndef ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
 #define ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
 
-#include "etl/list.h"
-#include "Service.hpp"
 #include "ErrorHandler.hpp"
-#include "MessageParser.hpp"
 #include "Helpers/CRCHelper.hpp"
+#include "MessageParser.hpp"
+#include "Service.hpp"
+#include "etl/list.h"
 
 // Include platform specific files
-#include "Platform/x86/TimeGetter.hpp"
+#include "Helpers/TimeGetter.hpp"
+
+
+/**
+ * @def GROUPS_ENABLED
+ * @brief Indicates whether scheduling groups are enabled
+ */
+#define GROUPS_ENABLED 0 // NOLINT(cppcoreguidelines-macro-usage)
 
 /**
  * @def SUB_SCHEDULES_ENABLED
@@ -16,21 +23,15 @@
  *
  * @details Sub-schedules are currently not implemented so this has no effect
  */
-/**
- * @def GROUPS_ENABLED
- * @brief Indicates whether scheduling groups are enabled
- */
-#define GROUPS_ENABLED 0
-#define SUB_SCHEDULES_ENABLED 0
+#define SUB_SCHEDULES_ENABLED 0 // NOLINT(cppcoreguidelines-macro-usage)
 
 /**
  * @brief Namespace to access private members during test
  *
  * @details Define a namespace for the access of the private members to avoid conflicts
  */
-namespace unit_test
-{
-struct Tester;
+namespace unit_test {
+	struct Tester;
 } // namespace unit_test
 
 /**
@@ -47,11 +48,11 @@ class TimeBasedSchedulingService : public Service {
 private:
 	/**
 	 * @brief Indicator of the schedule execution
-	 *
+	 * True indicates "enabled" and False "disabled" state
 	 * @details The schedule execution indicator will be updated by the process that is running
 	 * the time scheduling service.
 	 */
-	bool executionFunctionStatus = false; // True indicates "enabled" and False "disabled" state
+	bool executionFunctionStatus = false;
 
 	/**
 	 * @brief Request identifier of the received packet
@@ -62,7 +63,7 @@ private:
 	struct RequestID {
 		uint16_t applicationID = 0; ///< Application process ID
 		uint16_t sequenceCount = 0; ///< Packet sequence count
-		uint8_t sourceID = 0; ///< Packet source ID
+		uint8_t sourceID = 0;       ///< Packet source ID
 
 		bool operator!=(const RequestID& rightSide) const {
 			return (sequenceCount != rightSide.sequenceCount) or (applicationID != rightSide.applicationID) or
@@ -80,9 +81,9 @@ private:
 	 * @todo If groups are used, then the group ID has to be defined here
 	 */
 	struct ScheduledActivity {
-		Message request; ///< Hold the received command request
-		RequestID requestID; ///< Request ID, characteristic of the definition
-		uint32_t requestReleaseTime = 0; ///< Keep the command release time
+		Message request;                         ///< Hold the received command request
+		RequestID requestID;                     ///< Request ID, characteristic of the definition
+		Time::DefaultCUC requestReleaseTime{0}; ///< Keep the command release time
 	};
 
 	/**
@@ -99,7 +100,7 @@ private:
 	 * @details The ECSS standard requires that the activities are sorted in the TM message
 	 * response. Also it is better to have the activities sorted.
 	 */
-	inline void
+	inline static void
 	sortActivitiesReleaseTime(etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities>& schedActivities) {
 		schedActivities.sort([](ScheduledActivity const& leftSide, ScheduledActivity const& rightSide) {
 			// cppcheck-suppress
@@ -116,12 +117,12 @@ private:
 	 */
 	friend struct ::unit_test::Tester;
 
-public:
-
-	/*
-* ST[11] TimeBased Scheduling Service and Sub-Service Macros, for readability purpose
-*/
+	/**
+     * Notifies the timeBasedSchedulingTask after the insertion of activities to scheduleActivity list.
+     */
+	void notifyNewActivityAddition();
 
+public:
 	inline static const uint8_t ServiceType = 11;
 
 	enum MessageType : uint8_t {
@@ -145,6 +146,12 @@ public:
 	 */
 	TimeBasedSchedulingService();
 
+	/**
+	 * This function executes the next activity and removes it from the list.
+	 * @return the requestReleaseTime of next activity to be executed after this time
+	 */
+	Time::DefaultCUC executeScheduledActivity(Time::DefaultCUC currentTime);
+
 	/**
 	 * @brief TC[11,1] enable the time-based schedule execution function
 	 *
@@ -210,6 +217,15 @@ public:
 	 */
 	void detailReportAllActivities(Message& request);
 
+	/**
+	 * @brief TM[11,10] time-based schedule detail report
+	 *
+	 * @details Send a detailed report about the status of the activities listed
+	 * on the provided list. Generates a TM[11,10] response.
+	 * @param listOfActivities Provide the list of activities that need to be reported on
+	 */
+	void timeBasedScheduleDetailReport(const etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities>& listOfActivities);
+
 	/**
 	 * @brief TC[11,9] detail-report activities identified by request identifier
 	 *
@@ -237,6 +253,15 @@ public:
 	 */
 	void summaryReportActivitiesByID(Message& request);
 
+	/**
+	 * @brief TM[11,13] time-based schedule summary report
+	 *
+	 * @details Send a summary report about the status of the activities listed
+	 * on the provided list. Generates a TM[11,13] response.
+	 * @param listOfActivities Provide the list of activities that need to be reported on
+	 */
+	void timeBasedScheduleSummaryReport(const etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities>& listOfActivities);
+
 	/**
 	 * @brief TC[11,5] delete time-based scheduled activities identified by a request identifier
 	 *
@@ -260,7 +285,7 @@ public:
 	 * Also if an activity with a specified request identifier is not found, generate a failed
 	 * start of execution for that specific instruction.
 	 */
-	void timeShiftActivitiesByID(Message &request);
+	void timeShiftActivitiesByID(Message& request);
 
 	/**
 	 * It is responsible to call the suitable function that executes a telecommand packet. The source of that packet
diff --git a/inc/Time/Time.hpp b/inc/Time/Time.hpp
index 55dbaa16ec64dfac8a811d7b05ea719296c1e7b4..1b4fb89dc15b8d2665b91485c9a756e96f9ecaf2 100644
--- a/inc/Time/Time.hpp
+++ b/inc/Time/Time.hpp
@@ -1,8 +1,11 @@
-#pragma once
+#ifndef ECSS_TIMEHPP
+#define ECSS_TIMEHPP
+
+#include <chrono>
 #include <cstdint>
-#include <Message.hpp>
-#include "macros.hpp"
+#include "ErrorHandler.hpp"
 #include "etl/String.hpp"
+#include "macros.hpp"
 
 /**
  * @defgroup Time Time
@@ -68,201 +71,222 @@
  * @ingroup Time
  * @author Baptiste Fournier
  */
-namespace Time
-{
-inline constexpr uint8_t SecondsPerMinute = 60;
-inline constexpr uint16_t SecondsPerHour = 3600;
-inline constexpr uint32_t SecondsPerDay = 86400;
-static constexpr uint8_t DaysOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/**
- * Number of bytes used for the basic time units of the CUC header for this mission
- */
-inline constexpr uint8_t CUCSecondsBytes = 2;
-
-/**
- * Number of bytes used for the fractional time units of the CUC header for this mission
- */
-inline constexpr uint8_t CUCFractionalBytes = 2;
-
-/**
- * The system epoch (clock measurement starting time)
- * All timestamps emitted by the ECSS services will show the elapsed time (seconds, days etc.) from this epoch.
- */
-inline constexpr struct {
-	uint16_t year;
-	uint8_t month;
-	uint8_t day;
-} Epoch{
-    2020,
-    1,
-    1,
-};
-
-/**
- * Number of seconds elapsed between the UNIX epoch (1 January 1970) and the system epoch.
- *
- * The system epoch is defined by @ref Epoch.
- * This constant is used for conversion between Unix and other timestamps.
- * Leap seconds are not taken into account here.
- *
- * @warning This value MUST be updated after every change of the system @ref Epoch. You can use utilities such as
- * https://www.unixtimestamp.com/ to obtain a correct result.
- */
-inline constexpr uint32_t EpochSecondsFromUnix = 1577836800;
-
-/**
- * The maximum theoretical size in bytes of a CUC timestamp, including headers (P-field and T-field)
- */
-inline constexpr uint8_t CUCTimestampMaximumSize = 9;
-
-static_assert(Epoch.year >= 2019);
-static_assert(Epoch.month < 11 && Epoch.month >= 0);
-static_assert(Epoch.day < DaysOfMonth[Epoch.month]);
-
-/**
- * Builds the short P-field of the CUC (CCSDS Unsegmented Time Code) format, as defined in CCSDS 301.0-B-4.
- *
- * The short P-field contains only one byte. It is used when many octets are used to represent the basic or fractional
- * time units.
- *
- * @see CCSDS 301.0-B-4, Section 3.2.2
- * @tparam secondsBytes The number of octets used to represent the basic time units
- * @tparam fractionalBytes The number of octets used to represent the fractional time units
- * @return A single byte, representing the P-field contents
- */
-template <int secondsBytes, int fractionalBytes>
-inline constexpr uint8_t buildShortCUCHeader() {
-	static_assert(secondsBytes <= 4, "Use buildLongCUCHeader instead");
-	static_assert(fractionalBytes <= 3, "Use buildLongCUCHeader instead");
-
-	uint8_t header = 0;
-
-	// P-Field extension is 0, CUC header is not extended
-	header += 0;
-
-	// We are using a custom TAI epoch ("agency-defined epoch")
-	header <<= 3U;
-	header += 0b010;
-
-	// Number of bytes in the basic time unit
-	header <<= 2U;
-	header += secondsBytes - 1;
-
-	// Number of bytes in the fractional unit
-	header <<= 2U;
-	header += fractionalBytes;
-
-	return header;
-}
-
-/**
- * Builds the long P-field of the CUC (CCSDS Unsegmented Time Code) format, as defined in CCSDS 301.0-B-4.
- *
- * The long P-field contains two bytes. The 2nd byte is used to define the size of the additional octets added to the
- * timestamp, which could not fit in a short P-field.
- *
- * @see CCSDS 301.0-B-4, Section 3.2.2
- * @tparam secondsBytes The number of octets used to represent the basic time units
- * @tparam fractionalBytes The number of octets used to represent the fractional time units
- * @return Two bytes, representing the P-field contents
- */
-template <int secondsBytes, int fractionalBytes>
-inline constexpr uint16_t buildLongCUCHeader() {
-	// cppcheck-suppress redundantCondition
-	static_assert(secondsBytes > 4 || fractionalBytes > 3, "Use buildShortCUCHeader instead");
-	static_assert(secondsBytes <= 7, "Number of bytes for seconds over maximum number of octets allowed by CCSDS");
-	static_assert(fractionalBytes <= 6, "Number of bytes for seconds over maximum number of octets allowed by CCSDS");
-
-	uint16_t header = 0;
-
-	uint8_t octet1secondsBytes = std::min(4, secondsBytes);
-	uint8_t octet2secondsBytes = secondsBytes - octet1secondsBytes;
-
-	uint8_t octet1fractionalBytes = std::min(3, fractionalBytes);
-	uint8_t octet2fractionalBytes = fractionalBytes - octet1fractionalBytes;
-
-	// P-Field extension is 1, CUC header is extended
-	header += 1;
-
-	// We are using custom a TAI epoch
-	header <<= 3U;
-	header += 0b010;
-
-	// Number of bytes in the basic time unit
-	header <<= 2U;
-	header += octet1secondsBytes - 1;
-
-	// Number of bytes in the fractional unit
-	header <<= 2U;
-	header += octet1fractionalBytes;
-
-	// P-Field extension is 1, CUC header was extended
-	header <<= 1U;
-	header += 1;
-
-	// Number of bytes in the extended basic time unit
-	header <<= 2U;
-	header += octet2secondsBytes;
-
-	// Number of bytes in the extended fractional unit
-	header <<= 3U;
-	header += octet2fractionalBytes;
-
-	// Last 3 LSB are reserved for custom mission use
-	header <<= 2U;
-	header += 0;
-
-	return header;
-}
-
-/**
- * Builds the entire P-field of the CUC (CCSDS Unsegmented Time Code) format, as defined in CCSDS 301.0-B-4.
- *
- * The P-field contains the metadata of the timestamp, including information about its size and epoch. This function
- * is implemented for arbitrary sizes (_octet count_) for the basic and fractional time units.
- *
- * The following options cannot be changed:
- *   - Time-code identification is set to an _agency-defined epoch_. This is represented by @ref Epoch.
- *   - Bits 6-7 of octet 2 (_reserved_) are set to `0`
- *
- * @note The P-field (header) does not contain the timestamp information, but only the description of the timestamp's
- * structure. It may be entirely omitted if the structure is known beforehand.
- *
- * @see CCSDS 301.0-B-4, Section 3.2.2
- * @tparam T An arbitrary `uint` return type of the header
- * @tparam secondsBytes The number of octets used to represent the basic time units
- * @tparam fractionalBytes The number of octets used to represent the fractional time units
- * @return One or two bytes representing the header
- */
-template <typename T, int secondsBytes, int fractionalBytes>
-inline constexpr T buildCUCHeader() {
-	// TODO: Gitlab issue #106
-	static_assert((secondsBytes + fractionalBytes) <= 8, "Complete arbitrary precision not supported");
-	// cppcheck-suppress syntaxError
-	// cppcheck-suppress redundantCondition
-	if constexpr (secondsBytes <= 4 && fractionalBytes <= 3) {
-		return buildShortCUCHeader<secondsBytes, fractionalBytes>();
-	} else {
-		return buildLongCUCHeader<secondsBytes, fractionalBytes>();
+namespace Time {
+	inline constexpr uint8_t SecondsPerMinute = 60;
+	inline constexpr uint16_t SecondsPerHour = 3600;
+	inline constexpr uint32_t SecondsPerDay = 86400;
+	inline constexpr uint8_t MonthsPerYear = 12;
+	static constexpr uint8_t DaysOfMonth[MonthsPerYear] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+	/**
+	 * Number of bytes used for the basic time units of the CUC header for this mission
+	 */
+	inline constexpr uint8_t CUCSecondsBytes = 4;
+
+	/**
+	 * Number of bytes used for the fractional time units of the CUC header for this mission
+	 */
+	inline constexpr uint8_t CUCFractionalBytes = 0;
+
+	/**
+	 * The system epoch (clock measurement starting time).
+	 * All timestamps emitted by the ECSS services will show the elapsed time (seconds, days etc.) from this epoch.
+ 	*/
+	inline constexpr struct {
+		uint16_t year;
+		uint8_t month;
+		uint8_t day;
+	} Epoch{
+	    2020,
+	    1,
+	    1,
+	};
+
+	/**
+	 * Number of seconds elapsed between the UNIX epoch (1 January 1970) and the system epoch.
+	 *
+	 * The system epoch is defined by @ref Epoch.
+	 * This constant is used for conversion between Unix and other timestamps.
+	 * Leap seconds are not taken into account here.
+	 *
+	 * @warning This value MUST be updated after every change of the system @ref Epoch. You can use utilities such as
+	 * https://www.unixtimestamp.com/ to obtain a correct result.
+	 */
+	inline constexpr uint32_t EpochSecondsFromUnix = 1577836800;
+
+	/**
+	 * The maximum theoretical size in bytes of a CUC timestamp, including headers (P-field and T-field)
+	 */
+	inline constexpr uint8_t CUCTimestampMaximumSize = 9;
+
+	static_assert(Epoch.year >= 2019);
+	static_assert(Epoch.month < 11 && Epoch.month >= 0);
+	static_assert(Epoch.day < DaysOfMonth[Epoch.month]);
+
+	/**
+	 * Builds the short P-field of the CUC (CCSDS Unsegmented Time Code) format, as defined in CCSDS 301.0-B-4.
+	 *
+	 * The short P-field contains only one byte. It is used when many octets are used to represent the basic or fractional
+	 * time units.
+	 *
+	 * @see CCSDS 301.0-B-4, Section 3.2.2
+	 * @tparam secondsBytes The number of octets used to represent the basic time units
+	 * @tparam fractionalBytes The number of octets used to represent the fractional time units
+	 * @return A single byte, representing the P-field contents
+	 */
+	template <int secondsBytes, int fractionalBytes>
+	inline constexpr uint8_t buildShortCUCHeader() {
+		static_assert(secondsBytes <= 4, "Use buildLongCUCHeader instead");
+		static_assert(fractionalBytes <= 3, "Use buildLongCUCHeader instead");
+
+		uint8_t header = 0;
+
+		// P-Field extension is 0, CUC header is not extended
+		header += 0;
+
+		// We are using a custom TAI epoch ("agency-defined epoch")
+		header <<= 3U;
+		header += 0b010;
+
+		// Number of bytes in the basic time unit
+		header <<= 2U;
+		header += secondsBytes - 1;
+
+		// Number of bytes in the fractional unit
+		header <<= 2U;
+		header += fractionalBytes;
+
+		return header;
 	}
-}
 
-/**
- * Returns whether a year is a leap year according to the Gregorian calendar
- */
-constexpr bool isLeapYear(uint16_t year) {
-	if ((year % 4) != 0) {
-		return false;
+	/**
+	 * Builds the long P-field of the CUC (CCSDS Unsegmented Time Code) format, as defined in CCSDS 301.0-B-4.
+	 *
+	 * The long P-field contains two bytes. The 2nd byte is used to define the size of the additional octets added to the
+	 * timestamp, which could not fit in a short P-field.
+	 *
+	 * @see CCSDS 301.0-B-4, Section 3.2.2
+	 * @tparam secondsBytes The number of octets used to represent the basic time units
+	 * @tparam fractionalBytes The number of octets used to represent the fractional time units
+	 * @return Two bytes, representing the P-field contents
+	 */
+	template <int secondsBytes, int fractionalBytes>
+	inline constexpr uint16_t buildLongCUCHeader() {
+		// cppcheck-suppress redundantCondition
+		static_assert(secondsBytes > 4 || fractionalBytes > 3, "Use buildShortCUCHeader instead");
+		static_assert(secondsBytes <= 7, "Number of bytes for seconds over maximum number of octets allowed by CCSDS");
+		static_assert(fractionalBytes <= 6, "Number of bytes for seconds over maximum number of octets allowed by CCSDS");
+
+		uint16_t header = 0;
+
+		uint8_t octet1secondsBytes = std::min(4, secondsBytes);
+		uint8_t octet2secondsBytes = secondsBytes - octet1secondsBytes;
+
+		uint8_t octet1fractionalBytes = std::min(3, fractionalBytes);
+		uint8_t octet2fractionalBytes = fractionalBytes - octet1fractionalBytes;
+
+		// P-Field extension is 1, CUC header is extended
+		header += 1;
+
+		// We are using custom a TAI epoch
+		header <<= 3U;
+		header += 0b010;
+
+		// Number of bytes in the basic time unit
+		header <<= 2U;
+		header += octet1secondsBytes - 1;
+
+		// Number of bytes in the fractional unit
+		header <<= 2U;
+		header += octet1fractionalBytes;
+
+		// P-Field extension is 1, CUC header was extended
+		header <<= 1U;
+		header += 1;
+
+		// Number of bytes in the extended basic time unit
+		header <<= 2U;
+		header += octet2secondsBytes;
+
+		// Number of bytes in the extended fractional unit
+		header <<= 3U;
+		header += octet2fractionalBytes;
+
+		// Last 3 LSB are reserved for custom mission use
+		header <<= 2U;
+		header += 0;
+
+		return header;
 	}
-	if ((year % 100) != 0) {
-		return true;
+
+	/**
+	 * Builds the entire P-field of the CUC (CCSDS Unsegmented Time Code) format, as defined in CCSDS 301.0-B-4.
+	 *
+	 * The P-field contains the metadata of the timestamp, including information about its size and epoch. This function
+	 * is implemented for arbitrary sizes (_octet count_) for the basic and fractional time units.
+	 *
+	 * The following options cannot be changed:
+	 *   - Time-code identification is set to an _agency-defined epoch_. This is represented by @ref Epoch.
+	 *   - Bits 6-7 of octet 2 (_reserved_) are set to `0`
+	 *
+	 * @note The P-field (header) does not contain the timestamp information, but only the description of the timestamp's
+	 * structure. It may be entirely omitted if the structure is known beforehand.
+	 *
+	 * @see CCSDS 301.0-B-4, Section 3.2.2
+	 * @tparam T An arbitrary `uint` return type of the header
+	 * @tparam secondsBytes The number of octets used to represent the basic time units
+	 * @tparam fractionalBytes The number of octets used to represent the fractional time units
+	 * @return One or two bytes representing the header
+	 */
+	template <typename T, int secondsBytes, int fractionalBytes>
+	inline constexpr T buildCUCHeader() {
+		static_assert((secondsBytes + fractionalBytes) <= 8, "Complete arbitrary precision not supported");
+		// cppcheck-suppress syntaxError
+		// cppcheck-suppress redundantCondition
+		if constexpr (secondsBytes <= 4 && fractionalBytes <= 3) {
+			return buildShortCUCHeader<secondsBytes, fractionalBytes>();
+		} else {
+			return buildLongCUCHeader<secondsBytes, fractionalBytes>();
+		}
 	}
-	return (year % 400) == 0;
-}
 
-typedef struct {
-	uint64_t elapsed100msTicks = 0;
-} CustomCUC_t;
+	/**
+	* Returns whether a year is a leap year according to the Gregorian calendar
+	*/
+	constexpr bool isLeapYear(uint16_t year) {
+		if ((year % 4) != 0) {
+			return false;
+		}
+		if ((year % 100) != 0) {
+			return true;
+		}
+		return (year % 400) == 0;
+	}
 
+	/**
+ 	* A time shift for scheduled activities measured in seconds
+ 	*/
+	typedef int64_t RelativeTime;
+
+	/**
+	 * is_duration definition to check if a variable is std::chrono::duration
+	 */
+	template <typename T>
+	struct is_duration
+	    : std::false_type {};
+
+	/**
+	 * is_duration definition to check if a variable is std::chrono::duration
+	 */
+	template <typename Rep, typename Period>
+	struct is_duration<std::chrono::duration<Rep, Period>>
+	    : std::true_type {};
+
+	/**
+	 * True if T is std::chrono::duration, false if not
+	 */
+	template <class T>
+	inline constexpr bool is_duration_v = is_duration<T>::value;
 } // namespace Time
+
+#endif
diff --git a/inc/Time/TimeStamp.hpp b/inc/Time/TimeStamp.hpp
index 499fb3c66ac9869be384e9fde471e4eb903d5c05..5bdc1c3700dacdd686f67a2ea6975295493debbf 100644
--- a/inc/Time/TimeStamp.hpp
+++ b/inc/Time/TimeStamp.hpp
@@ -1,37 +1,95 @@
-#ifndef ECSS_SERVICES_TIME_HPP
-#define ECSS_SERVICES_TIME_HPP
+#pragma once
 
-#include <cstdint>
 #include <algorithm>
-#include "macros.hpp"
+#include <chrono>
+#include <cstdint>
 #include <etl/array.h>
 #include "Time.hpp"
 #include "UTCTimestamp.hpp"
+#include "macros.hpp"
 
 /**
  * A class that represents an instant in time, with convenient conversion
  * to and from usual time and date representations
  *
+ * This class is compatible with the CUC (Unsegmented Time Code) format defined in CCSDS 301.0-B-4. It allows specifying:
+ * - Different amount of bytes for the basic time unit
+ * - Different amount of bytes for the fractional time unit
+ * - Different basic time units
+ *
+ * The timestamp is defined in relation to a user-defined epoch, set in @ref Time::Epoch.
+ *
+ * @section baseunit Setting the base time unit
+ * By default, this class measures time in the order of **seconds**. Binary fractions of a second can be specified by increasing the FractionBytes.
+ * However, the user can change the base time unit by setting the @p Num and @p Denom template parameters.
+ *
+ * The base time unit (or period) is then represented by the following:
+ * \f[
+ * \text{time unit} = \frac{Num}{Denom} \cdot \text{second}
+ * \f]
+ *
  * @note
  * This class uses internally TAI time, and handles UTC leap seconds at conversion to and
  * from UTC time system.
  *
+ * @tparam BaseBytes The number of bytes used for the basic time units. This essentially defines the maximum duration from Epoch that this timestamp can represent.
+ * @tparam FractionBytes The number of bytes used for the fraction of one basic time unit. This essentially defines the precision of the timestamp.
+ * @tparam Num The numerator of the base type ratio (see @ref baseunit)
+ * @tparam Denom The numerator of the base type ratio (see @ref baseunit)
+ *
  * @ingroup Time
  * @author Baptiste Fournier
+ * @author Konstantinos Kanavouras
  * @see [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf)
  */
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
+template <uint8_t BaseBytes = 4, uint8_t FractionBytes = 0, int Num = 1, int Denom = 1>
 class TimeStamp {
+public:
+	/**
+	 * The period of the base type, in relation to the second
+	 *
+	 * This type represents the base type of the timestamp.
+	 *
+	 * A ratio of `<1, 1>` (or 1/1) means that this timestamp represents seconds. A ratio of `<60, 1>` (or 60/1) means
+	 * that this class represents 60s of seconds, or minutes. A ratio of `<1, 1000>` (or 1/1000) means that this class
+	 * represents 1000ths of seconds, or milliseconds.
+	 *
+	 * This type has essentially the same meaning of `Rep` in [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration).
+	 *
+	 * @note std::ratio will simplify the fractions numerator and denominator
+	 */
+	using Ratio = std::ratio<Num, Denom>;
+
 private:
-	static_assert(secondsBytes + fractionalBytes <= 8,
+	static_assert(BaseBytes + FractionBytes <= 8,
 	              "Currently, this class is not suitable for storage on internal counter larger than uint64_t");
-	typedef typename std::conditional<(secondsBytes < 4 && fractionalBytes < 3), uint8_t, uint16_t>::type CUCHeader_t;
-	typedef typename std::conditional<(secondsBytes + fractionalBytes < 4), uint32_t, uint64_t>::type TAICounter_t;
+	using CUCHeader_t = typename std::conditional<(BaseBytes < 4 && FractionBytes < 3), uint8_t, uint16_t>::type;
+	using TAICounter_t = typename std::conditional<(BaseBytes + FractionBytes <= 4), uint32_t, uint64_t>::type;
+
+	/**
+	 * The period of the internal counter
+	 *
+	 * Same as @ref Ratio, but instead of representing the Base bytes, it represents the entire value held by @ref taiCounter.
+	 */
+	using RawRatio = std::ratio<Num, Denom * 1UL << (8 * FractionBytes)>;
+
+	/**
+	 * An std::chrono::duration representation of the base type (without the fractional part)
+	 */
+	using BaseDuration = std::chrono::duration<TAICounter_t, Ratio>;
+
+	/**
+	 * An std::chrono::duration representation of the complete @ref taiCounter (including the fractional part)
+	 */
+	using RawDuration = std::chrono::duration<TAICounter_t, RawRatio>;
+
+	template <uint8_t, uint8_t, int, int>
+	friend class TimeStamp;
 
 	/**
 	 * Integer counter of time units since the @ref Time::Epoch. This number essentially represents the timestamp.
 	 *
-	 * The unit represented by this variable depends on `secondsBytes` and `fractionalBytes`. The fractional
+	 * The unit represented by this variable depends on `BaseBytes` and `FractionBytes`. The fractional
 	 * part is included as the least significant bits of this variable, and the base part follows.
 	 */
 	TAICounter_t taiCounter;
@@ -39,13 +97,20 @@ private:
 	/**
 	 * The constant header ("P-value") of the timestamp, if needed to be attached to any message
 	 */
-	static constexpr CUCHeader_t CUCHeader = Time::buildCUCHeader<CUCHeader_t, secondsBytes, fractionalBytes>();
+	static constexpr CUCHeader_t CUCHeader = Time::buildCUCHeader<CUCHeader_t, BaseBytes, FractionBytes>();
 
 	/**
-	 * The maximum value that can fit in @ref taiCounter, or the maximum number of seconds since epoch that can be
-	 * represented in this base class
+	 * The maximum value of the base type (seconds, larger or smaller) that can fit in @ref taiCounter
 	 */
-	static constexpr uint64_t maxSecondCounterValue = (1U << (8U * secondsBytes)) - 1;
+	static constexpr uint64_t MaxBase =
+	    (BaseBytes == 8)
+	        ? std::numeric_limits<uint64_t>::max()
+	        : (uint64_t{1} << 8 * BaseBytes) - 1;
+
+	/**
+	 * The maximum number of seconds since epoch that can be represented in this class
+	 */
+	static constexpr uint64_t MaxSeconds = std::chrono::duration_cast<std::chrono::duration<uint64_t>>(BaseDuration(MaxBase)).count();
 
 	/**
 	 * Returns whether the amount of `seconds` can be represented by this TimeStamp.
@@ -68,19 +133,10 @@ public:
 	 */
 	explicit TimeStamp(uint64_t taiSecondsFromEpoch);
 
-	/**
-	 * Initialize the TimeStamp from a count of 100ms ticks from epoch in TAI (leap seconds not accounted)
-	 *
-	 * @param customCUCTimestamp An struct containing a 64 bit unsigned number of 100ms
-	 * ticks from the custom @ref Time::Epoch
-	 */
-	explicit TimeStamp(Time::CustomCUC_t customCUCTimestamp);
-
 	/**
 	 * Initialize the TimeStamp from the bytes of a CUC time stamp
 	 *
-	 * @param timestamp A complete CUC timestamp including header, of the maximum possible size, zero padded to the
-	 * right
+	 * @param timestamp A complete CUC timestamp including header, of the maximum possible size, zero padded to the right
 	 */
 	explicit TimeStamp(etl::array<uint8_t, Time::CUCTimestampMaximumSize> timestamp);
 
@@ -92,25 +148,36 @@ public:
 	explicit TimeStamp(const UTCTimestamp& timestamp);
 
 	/**
-	 * Get the representation as seconds from epoch in TAI
+	 * Convert a TimeStamp to a TimeStamp with different parameters
 	 *
-	 * @return The seconds elapsed in TAI since @ref Time::Epoch. This function is explicitly defined
+	 * This constructor will convert based on the number of bytes, and base units
+	 *
+	 * @note Internally uses double-precision floating point to allow for arbitrary ratios
 	 */
-	TAICounter_t asTAIseconds();
+	template <uint8_t BaseBytesIn, uint8_t FractionBytesIn, int NumIn = 1, int DenomIn = 1>
+	explicit TimeStamp(TimeStamp<BaseBytesIn, FractionBytesIn, NumIn, DenomIn> input);
 
 	/**
-	 * Get the representation as a struct containing 100ms ticks from epoch in TAI
+	 * Convert an [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration) representing seconds from @ref Time::Epoch
+	 * to a timestamp
 	 *
-	 * @return An struct containing a 64 bit unsigned number of 100ms
-	 * ticks from the custom @ref Time::Epoch. This function is explicitly defined.
+	 * @warning This function does not perform overflow calculations. It is up to the user to ensure that the types are
+	 * compatible so that no overflow occurs.
 	 */
-	Time::CustomCUC_t asCustomCUCTimestamp();
+	template <class Duration, typename = std::enable_if_t<Time::is_duration_v<Duration>>>
+	explicit TimeStamp(Duration duration);
+
+	/**
+	 * Get the representation as seconds from epoch in TAI
+	 *
+	 * @return The seconds elapsed in TAI since @ref Time::Epoch. This function is explicitly defined
+	 */
+	TAICounter_t asTAIseconds();
 
 	/**
 	 * Get the representation as seconds from epoch in TAI, for a floating-point representation.
 	 * For an integer result, see the overloaded @ref asTAIseconds function.
 	 *
-	 * @todo Implement integer seconds in this function
 	 * @tparam T The return type of the seconds (float or double).
 	 * @return The seconds elapsed in TAI since @ref Time::Epoch
 	 */
@@ -118,11 +185,24 @@ public:
 	T asTAIseconds();
 
 	/**
-	 * Get the representation as CUC formatted bytes
+	 * Converts a TimeStamp to a duration of seconds since the @ref Time::Epoch.
 	 *
-	 * @return The TimeStamp, represented in the CCSDS CUC format
+	 * @warning This function does not perform overflow calculations. It is up to the user to ensure that the types are compatible so that no overflow occurs.
+	 */
+	template <class Duration = std::chrono::seconds>
+	Duration asDuration() const;
+
+	/**
+	 * Get the representation as CUC formatted bytes, including the header (P-field and T-field)
 	 */
-	etl::array<uint8_t, Time::CUCTimestampMaximumSize> toCUCtimestamp();
+	etl::array<uint8_t, Time::CUCTimestampMaximumSize> formatAsCUC();
+
+	/**
+	 * Get the representation as CUC formatted bytes, without the header (T-field only)
+	 */
+	TAICounter_t formatAsBytes() const {
+		return taiCounter;
+	}
 
 	/**
 	 * Get the representation as a UTC timestamp
@@ -132,37 +212,137 @@ public:
 	UTCTimestamp toUTCtimestamp();
 
 	/**
-	 * Compare two timestamps.
+	 * Get the maximum timestamp that can be represented by this class
 	 *
-	 * @param timestamp the date that will be compared with the pointer `this`
-	 * @return true if the condition is satisfied
+	 * Can be used to represent null or infinite amounts of time
 	 */
-	bool operator<(const TimeStamp<secondsBytes, fractionalBytes>& timestamp) const {
-		return taiCounter < timestamp.taiCounter;
+	static TimeStamp<BaseBytes, FractionBytes, Num, Denom> max() {
+		TimeStamp<BaseBytes, FractionBytes, Num, Denom> timestamp;
+		timestamp.taiCounter = std::numeric_limits<TAICounter_t>::max();
+		return timestamp;
 	}
 
-	bool operator>(const TimeStamp<secondsBytes, fractionalBytes>& timestamp) const {
-		return taiCounter > timestamp.taiCounter;
+	/**
+	 * Adds any arbitrary duration to a timestamp.
+	 *
+	 * You can play with default C++ durations with this function:
+	 * ```cpp
+	 * using namespace std::literals;
+	 *
+	 * timestamp + std::chrono::seconds(5);        // adds 5 seconds
+	 * timestamp + std::chrono::milliseconds(500); // adds 5 milliseconds
+	 * timestamp + 60s; // adds 60 seconds
+	 */
+	template <class Duration, typename = std::enable_if_t<Time::is_duration_v<Duration>>>
+	TimeStamp<BaseBytes, FractionBytes, Num, Denom> operator+(const Duration& duration) const {
+		auto output = *this;
+		output += duration;
+		return output;
 	}
 
-	bool operator==(const TimeStamp<secondsBytes, fractionalBytes>& timestamp) const {
-		return taiCounter == timestamp.taiCounter;
+	template <class Duration, typename = std::enable_if_t<Time::is_duration_v<Duration>>>
+	TimeStamp<BaseBytes, FractionBytes, Num, Denom>& operator+=(const Duration& duration) {
+		if (duration < Duration::zero()) {
+			taiCounter -= std::chrono::duration_cast<RawDuration>(-duration).count();
+		} else {
+			taiCounter += std::chrono::duration_cast<RawDuration>(duration).count();
+		}
+
+		return *this;
 	}
 
-	bool operator!=(const TimeStamp<secondsBytes, fractionalBytes>& timestamp) const {
-		return taiCounter != timestamp.taiCounter;
+	template <class Duration, typename = std::enable_if_t<Time::is_duration_v<Duration>>>
+	TimeStamp<BaseBytes, FractionBytes, Num, Denom> operator-(const Duration& duration) const {
+		auto output = *this;
+		output -= duration;
+		return output;
 	}
 
-	bool operator<=(const TimeStamp<secondsBytes, fractionalBytes>& timestamp) const {
-		return taiCounter <= timestamp.taiCounter;
+	template <class Duration, typename = std::enable_if_t<Time::is_duration_v<Duration>>>
+	TimeStamp<BaseBytes, FractionBytes, Num, Denom>& operator-=(const Duration& duration) {
+		if (duration < Duration::zero()) {
+			taiCounter += std::chrono::duration_cast<RawDuration>(-duration).count();
+		} else {
+			taiCounter -= std::chrono::duration_cast<RawDuration>(duration).count();
+		}
+
+		return *this;
 	}
 
-	bool operator>=(const TimeStamp<secondsBytes, fractionalBytes>& timestamp) const {
-		return taiCounter >= timestamp.taiCounter;
+	/**
+	 * Subtraction between two timestamps.
+	 *
+	 * Given 2 absolute moments in time, returns the relative duration between them.
+	 * @tparam Duration The duration returned is equal to the RawDuration of the first timestamp,
+	 * 					but it's signed instead of unsigned, so that negative results can be represented.
+	 */
+	template <
+	    uint8_t BaseBytesIn, uint8_t FractionBytesIn, int NumIn = 1, int DenomIn = 1, // Template parameters of the 2nd timestamp
+	    class Duration = std::chrono::duration<                                       // Create a new Duration based on our RawDuration...
+	        typename std::make_signed<typename RawDuration::rep>::type,               // the Duration base type is equal to the RawDuration, but converted to signed from unsigned
+	        typename RawDuration::period>>
+	Duration operator-(const TimeStamp<BaseBytesIn, FractionBytesIn, NumIn, DenomIn>& operand) const {
+		Duration myDuration = asDuration<Duration>();
+		Duration operandDuration = operand.template asDuration<Duration>();
+
+		return myDuration - operandDuration;
 	}
+
+	/**
+	 * @name Comparison operators between timestamps
+	 * @{
+	 */
+	template <class OtherTimestamp>
+	bool operator<(const OtherTimestamp& timestamp) const {
+		return RawDuration(taiCounter) < typename OtherTimestamp::RawDuration(timestamp.taiCounter);
+	}
+
+	template <class OtherTimestamp>
+	bool operator>(const OtherTimestamp& timestamp) const {
+		return RawDuration(taiCounter) > typename OtherTimestamp::RawDuration(timestamp.taiCounter);
+	}
+
+	template <class OtherTimestamp>
+	bool operator==(const OtherTimestamp& timestamp) const {
+		return RawDuration(taiCounter) == typename OtherTimestamp::RawDuration(timestamp.taiCounter);
+	}
+
+	template <class OtherTimestamp>
+	bool operator!=(const OtherTimestamp& timestamp) const {
+		return RawDuration(taiCounter) != typename OtherTimestamp::RawDuration(timestamp.taiCounter);
+	}
+
+	template <class OtherTimestamp>
+	bool operator<=(const OtherTimestamp& timestamp) const {
+		return RawDuration(taiCounter) <= typename OtherTimestamp::RawDuration(timestamp.taiCounter);
+	}
+
+	template <class OtherTimestamp>
+	bool operator>=(const OtherTimestamp& timestamp) const {
+		return RawDuration(taiCounter) >= typename OtherTimestamp::RawDuration(timestamp.taiCounter);
+	}
+	/**
+	 * @}
+	 */
 };
 
-#include "TimeStamp.tpp"
-typedef TimeStamp<Time::CUCSecondsBytes, Time::CUCFractionalBytes> AcubeSATTimeStamp_t;
+namespace Time {
+	using DefaultCUC = TimeStamp<4, 0, 1, 10>;
+
+	/**
+	 * Creates a custom literal to specify timestamp ticks.
+	 *
+	 * For example, this code:
+	 * ```cpp
+	 * Time::DefaultCUC timestamp(1000_t);
+	 * ```
+	 * will define a timestamp 1000 ticks from the epoch.
+	 *
+	 * The time amount of a "tick" is the period defined by the DefaultCUC::Ratio
+	 */
+	constexpr std::chrono::duration<uint32_t, DefaultCUC::Ratio> operator""_t(unsigned long long s) {
+		return std::chrono::duration<uint32_t, DefaultCUC::Ratio>(s);
+	}
+} // namespace Time
 
-#endif
+#include "TimeStamp.tpp"
diff --git a/inc/Time/TimeStamp.tpp b/inc/Time/TimeStamp.tpp
index 34edf5a2c291153b1a38778ebc0462ec661d9fd6..4df8d7990812fb72205165167f16d5022f88291a 100644
--- a/inc/Time/TimeStamp.tpp
+++ b/inc/Time/TimeStamp.tpp
@@ -1,46 +1,39 @@
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-constexpr bool TimeStamp<secondsBytes, fractionalBytes>::areSecondsValid(TimeStamp::TAICounter_t seconds) {
-	return seconds < maxSecondCounterValue;
+#include <cmath>
+#include "TimeStamp.hpp"
+
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+constexpr bool TimeStamp<BaseBytes, FractionBytes, Num, Denom>::areSecondsValid(TimeStamp::TAICounter_t seconds) {
+	return seconds <= MaxSeconds;
 }
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-TimeStamp<secondsBytes, fractionalBytes>::TimeStamp(uint64_t taiSecondsFromEpoch) {
-	ASSERT_INTERNAL(areSecondsValid((taiSecondsFromEpoch)), ErrorHandler::InternalErrorType::InvalidTimeStampInput);
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+TimeStamp<BaseBytes, FractionBytes, Num, Denom>::TimeStamp(uint64_t taiSecondsFromEpoch) {
+	ASSERT_INTERNAL(areSecondsValid((taiSecondsFromEpoch)), ErrorHandler::InternalErrorType::TimeStampOutOfBounds);
 
-	taiCounter = static_cast<TAICounter_t>(taiSecondsFromEpoch) << 8 * fractionalBytes;
-}
+	using FromDuration = std::chrono::duration<uint64_t>;
+	const auto duration = FromDuration(taiSecondsFromEpoch);
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-TimeStamp<secondsBytes, fractionalBytes>::TimeStamp(Time::CustomCUC_t customCUCTimestamp) {
-	ASSERT_INTERNAL(areSecondsValid((customCUCTimestamp.elapsed100msTicks / 10)),
-	                ErrorHandler::InternalErrorType::InvalidTimeStampInput);
-	taiCounter = static_cast<TAICounter_t>(customCUCTimestamp.elapsed100msTicks / 10);
-	if (fractionalBytes > 0) {
-		TAICounter_t fractionalPart = static_cast<TAICounter_t>(customCUCTimestamp.elapsed100msTicks) - 10 * taiCounter;
-		taiCounter = taiCounter << 8;
-		taiCounter += fractionalPart * 256 / 10;
-		taiCounter = taiCounter << 8 * (fractionalBytes - 1);
-	}
+	taiCounter = std::chrono::duration_cast<RawDuration>(duration).count();
 }
 
-template <uint8_t secondsCounter, uint8_t fractionalBytes>
-TimeStamp<secondsCounter, fractionalBytes>::TimeStamp(etl::array<uint8_t, Time::CUCTimestampMaximumSize> timestamp) {
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+TimeStamp<BaseBytes, FractionBytes, Num, Denom>::TimeStamp(etl::array<uint8_t, Time::CUCTimestampMaximumSize> timestamp) {
 	// process header
 	uint8_t headerSize = 1;
 	if ((timestamp[0] & 0b10000000U) != 0) {
 		headerSize = 2;
 	}
 
-	uint8_t inputSecondsBytes = ((timestamp[0] & 0b00001100U) >> 2U) + 1U;
-	uint8_t inputFractionalBytes = (timestamp[0] & 0b00000011U) >> 0U;
+	uint8_t inputBaseBytes = ((timestamp[0] & 0b00001100U) >> 2U) + 1U;
+	uint8_t inputFractionBytes = (timestamp[0] & 0b00000011U) >> 0U;
 
 	if (headerSize == 2) {
-		inputSecondsBytes += (timestamp[1] & 0b01100000U) >> 5U;
-		inputFractionalBytes += (timestamp[1] & 0b00011100U) >> 2U;
+		inputBaseBytes += (timestamp[1] & 0b01100000U) >> 5U;
+		inputFractionBytes += (timestamp[1] & 0b00011100U) >> 2U;
 	}
 
 	// check input validity (useless bytes set to 0)
-	for (int i = headerSize + inputSecondsBytes + inputFractionalBytes; i < Time::CUCTimestampMaximumSize; i++) {
+	for (int i = headerSize + inputBaseBytes + inputFractionBytes; i < Time::CUCTimestampMaximumSize; i++) {
 		if (timestamp[i] != 0) {
 			ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::InvalidTimeStampInput);
 			break;
@@ -48,78 +41,82 @@ TimeStamp<secondsCounter, fractionalBytes>::TimeStamp(etl::array<uint8_t, Time::
 	}
 
 	// do checks wrt template precision parameters
-	ASSERT_INTERNAL(inputSecondsBytes <= secondsCounter, ErrorHandler::InternalErrorType::InvalidTimeStampInput);
-	ASSERT_INTERNAL(inputFractionalBytes <= fractionalBytes, ErrorHandler::InternalErrorType::InvalidTimeStampInput);
+	ASSERT_INTERNAL(inputBaseBytes <= BaseBytes, ErrorHandler::InternalErrorType::InvalidTimeStampInput);
+	ASSERT_INTERNAL(inputFractionBytes <= FractionBytes, ErrorHandler::InternalErrorType::InvalidTimeStampInput);
 
 	// put timestamp into internal counter
 	taiCounter = 0;
 	// add seconds until run out of bytes on input array
-	for (auto i = 0; i < inputSecondsBytes + inputFractionalBytes; i++) {
+	for (auto i = 0; i < inputBaseBytes + inputFractionBytes; i++) {
 		taiCounter = taiCounter << 8;
 		taiCounter += timestamp[headerSize + i];
 	}
 	// pad rightmost bytes to full length
-	taiCounter = taiCounter << 8 * (fractionalBytes - inputFractionalBytes);
+	taiCounter = taiCounter << 8 * (FractionBytes - inputFractionBytes);
 }
 
-template <uint8_t seconds_counter_bytes, uint8_t fractional_counter_bytes>
-TimeStamp<seconds_counter_bytes, fractional_counter_bytes>::TimeStamp(const UTCTimestamp& timestamp) {
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+TimeStamp<BaseBytes, FractionBytes, Num, Denom>::TimeStamp(const UTCTimestamp& timestamp) {
 	TAICounter_t seconds = 0;
+
+	/**
+	 * Add to the seconds variable, with an overflow check
+	 */
+	auto secondsAdd = [&seconds](TAICounter_t value) {
+		seconds += value;
+		if (seconds < value) {
+			ErrorHandler::reportInternalError(ErrorHandler::TimeStampOutOfBounds);
+		}
+	};
+
 	for (int year = Time::Epoch.year; year < timestamp.year; ++year) {
-		seconds += (Time::isLeapYear(year) ? 366 : 365) * Time::SecondsPerDay;
+		secondsAdd((Time::isLeapYear(year) ? 366 : 365) * Time::SecondsPerDay);
 	}
 	for (int month = Time::Epoch.month; month < timestamp.month; ++month) {
-		seconds += Time::DaysOfMonth[month - 1] * Time::SecondsPerDay;
+		secondsAdd(Time::DaysOfMonth[month - 1] * Time::SecondsPerDay);
 		if ((month == 2U) && Time::isLeapYear(timestamp.year)) {
-			seconds += Time::SecondsPerDay;
+			secondsAdd(Time::SecondsPerDay);
 		}
 	}
-	seconds += (timestamp.day - Time::Epoch.day) * Time::SecondsPerDay;
-	seconds += timestamp.hour * Time::SecondsPerHour;
-	seconds += timestamp.minute * Time::SecondsPerMinute;
-	seconds += timestamp.second;
-	// TODO: Add check that `seconds` is within bounds (?)
-	taiCounter = static_cast<TAICounter_t>(seconds) << 8 * fractional_counter_bytes;
-}
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-typename TimeStamp<secondsBytes, fractionalBytes>::TAICounter_t
-TimeStamp<secondsBytes, fractionalBytes>::asTAIseconds() {
-	return taiCounter >> (8 * fractionalBytes);
+	secondsAdd((timestamp.day - Time::Epoch.day) * Time::SecondsPerDay);
+	secondsAdd(timestamp.hour * Time::SecondsPerHour);
+	secondsAdd(timestamp.minute * Time::SecondsPerMinute);
+	secondsAdd(timestamp.second);
+
+	ASSERT_INTERNAL(areSecondsValid(seconds), ErrorHandler::TimeStampOutOfBounds);
+
+	taiCounter = std::chrono::duration_cast<RawDuration>(std::chrono::duration<TAICounter_t>(seconds)).count();
 }
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-Time::CustomCUC_t TimeStamp<secondsBytes, fractionalBytes>::asCustomCUCTimestamp() {
-	TAICounter_t temp = taiCounter;
-	Time::CustomCUC_t return_s = {0};
-	if (fractionalBytes > 0) {
-		temp = temp >> 8 * (fractionalBytes - 1);
-		return_s.elapsed100msTicks += temp * 10 / 256;
-	} else {
-		return_s.elapsed100msTicks += temp * 10;
-	}
-	return return_s;
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+typename TimeStamp<BaseBytes, FractionBytes, Num, Denom>::TAICounter_t
+TimeStamp<BaseBytes, FractionBytes, Num, Denom>::asTAIseconds() {
+	const auto duration = RawDuration(taiCounter);
+	using ToDuration = std::chrono::duration<TAICounter_t>;
+
+	return std::chrono::duration_cast<ToDuration>(duration).count();
 }
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
 template <typename T>
-T TimeStamp<secondsBytes, fractionalBytes>::asTAIseconds() {
+T TimeStamp<BaseBytes, FractionBytes, Num, Denom>::asTAIseconds() {
 	static_assert(std::is_floating_point_v<T>, "TimeStamp::asTAIseconds() only accepts numeric types.");
-	static_assert(std::numeric_limits<T>::max() >= maxSecondCounterValue);
+	static_assert(std::numeric_limits<T>::max() >= MaxSeconds);
 
-	TAICounter_t decimalPart = taiCounter >> (8 * fractionalBytes);
+	TAICounter_t decimalPart = taiCounter >> (8 * FractionBytes);
 
-	T fractionalPart = taiCounter - (decimalPart << (8 * fractionalBytes));
-	T fractionalPartMax = (1U << (8U * fractionalBytes)) - 1U;
+	T fractionalPart = taiCounter - (decimalPart << (8 * FractionBytes));
+	T fractionalPartMax = (1U << (8U * FractionBytes)) - 1U;
 
 	return decimalPart + fractionalPart / fractionalPartMax;
 }
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-etl::array<uint8_t, Time::CUCTimestampMaximumSize> TimeStamp<secondsBytes, fractionalBytes>::toCUCtimestamp() {
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+etl::array<uint8_t, Time::CUCTimestampMaximumSize> TimeStamp<BaseBytes, FractionBytes, Num, Denom>::formatAsCUC() {
 	etl::array<uint8_t, Time::CUCTimestampMaximumSize> returnArray = {0};
 
-	static constexpr uint8_t headerBytes = (secondsBytes < 4 && fractionalBytes < 3) ? 1 : 2;
+	static constexpr uint8_t headerBytes = (BaseBytes < 4 && FractionBytes < 3) ? 1 : 2;
 
 	if (headerBytes == 1) {
 		returnArray[0] = static_cast<uint8_t>(CUCHeader);
@@ -128,60 +125,54 @@ etl::array<uint8_t, Time::CUCTimestampMaximumSize> TimeStamp<secondsBytes, fract
 		returnArray[0] = static_cast<uint8_t>(CUCHeader >> 8);
 	}
 
-	for (auto byte = 0; byte < secondsBytes + fractionalBytes; byte++) {
-		uint8_t taiCounterIndex = 8 * (secondsBytes + fractionalBytes - byte - 1);
+	for (auto byte = 0; byte < BaseBytes + FractionBytes; byte++) {
+		uint8_t taiCounterIndex = 8 * (BaseBytes + FractionBytes - byte - 1);
 		returnArray[headerBytes + byte] = taiCounter >> taiCounterIndex;
 	}
 
 	return returnArray;
 }
 
-template <uint8_t secondsBytes, uint8_t fractionalBytes>
-UTCTimestamp TimeStamp<secondsBytes, fractionalBytes>::toUTCtimestamp() {
-	using namespace Time;
-
-	uint32_t totalSeconds = asTAIseconds();
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+UTCTimestamp TimeStamp<BaseBytes, FractionBytes, Num, Denom>::toUTCtimestamp() {
+	UTCTimestamp timestamp(Time::Epoch.year, Time::Epoch.month, Time::Epoch.day, 0, 0, 0);
+	timestamp += RawDuration(taiCounter);
 
-	uint16_t yearUTC = Epoch.year;
-	uint8_t monthUTC = Epoch.month;
-	uint8_t dayUTC = Epoch.day;
-	uint8_t hour = 0;
-	uint8_t minute = 0;
-	uint8_t second = 0;
+	return timestamp;
+}
 
-	// calculate years
-	while (totalSeconds >= (isLeapYear(yearUTC) ? 366 : 365) * SecondsPerDay) {
-		totalSeconds -= (isLeapYear(yearUTC) ? 366 : 365) * SecondsPerDay;
-		yearUTC++;
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+template <uint8_t BaseBytesIn, uint8_t FractionBytesIn, int NumIn, int DenomIn>
+TimeStamp<BaseBytes, FractionBytes, Num, Denom>::TimeStamp(TimeStamp<BaseBytesIn, FractionBytesIn, NumIn, DenomIn> input) {
+	if constexpr (std::is_same_v<decltype(*this), decltype(input)>) {
+		taiCounter = input.taiCounter;
+		return;
 	}
 
-	// calculate months
-	int currentMonth = 0;
-	while (totalSeconds >= (DaysOfMonth[currentMonth] * SecondsPerDay)) {
-		monthUTC++;
-		totalSeconds -= (DaysOfMonth[currentMonth] * SecondsPerDay);
-		currentMonth++;
-		if ((currentMonth == 1U) && isLeapYear(yearUTC)) {
-			if (totalSeconds <= (28 * SecondsPerDay)) {
-				break;
-			}
-			monthUTC++;
-			totalSeconds -= 29 * SecondsPerDay;
-			currentMonth++;
-		}
-	}
+	constexpr double InputRatio = static_cast<double>(NumIn) / DenomIn;
+	constexpr double OutputRatio = static_cast<double>(Num) / Denom;
+
+	double inputSeconds = input.taiCounter / static_cast<double>(1 << (8 * FractionBytesIn));
+	inputSeconds *= InputRatio;
 
-	dayUTC = totalSeconds / SecondsPerDay;
-	totalSeconds -= dayUTC * SecondsPerDay;
-	dayUTC++; // add 1 day because we start count from 1 January (and not 0 January!)
+	ErrorHandler::assertInternal(inputSeconds <= MaxSeconds, ErrorHandler::TimeStampOutOfBounds);
 
-	hour = totalSeconds / SecondsPerHour;
-	totalSeconds -= hour * SecondsPerHour;
+	double output = inputSeconds / OutputRatio * (1UL << (8 * FractionBytes));
 
-	minute = totalSeconds / SecondsPerMinute;
-	totalSeconds -= minute * SecondsPerMinute;
+	taiCounter = static_cast<TAICounter_t>(round(output));
+}
 
-	second = totalSeconds;
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+template <class Duration>
+Duration TimeStamp<BaseBytes, FractionBytes, Num, Denom>::asDuration() const {
+	auto duration = RawDuration(taiCounter);
+
+	return std::chrono::duration_cast<Duration>(duration);
+}
 
-	return {yearUTC, monthUTC, dayUTC, hour, minute, second};
+template <uint8_t BaseBytes, uint8_t FractionBytes, int Num, int Denom>
+template <class Duration, typename>
+TimeStamp<BaseBytes, FractionBytes, Num, Denom>::TimeStamp(Duration duration) {
+	auto outputDuration = std::chrono::duration_cast<RawDuration>(duration);
+	taiCounter = outputDuration.count();
 }
diff --git a/inc/Time/UTCTimestamp.hpp b/inc/Time/UTCTimestamp.hpp
index 062402df0926efcf9d739cadd7182ca1710a8fe2..a2fe7bf6caa2d0159f078538ac1255e821d1db21 100644
--- a/inc/Time/UTCTimestamp.hpp
+++ b/inc/Time/UTCTimestamp.hpp
@@ -2,6 +2,7 @@
 
 #include <cstdint>
 #include <etl/String.hpp>
+#include "Time.hpp"
 
 /**
  * A class that represents a UTC time and date according to ISO 8601
@@ -29,8 +30,7 @@ public:
 	UTCTimestamp();
 
 	/**
-	 *
-	 * @todo See if this implements leap seconds
+	 * @todo Add support for leap seconds
 	 * @todo Implement leap seconds as ST[20] parameter
 	 * @param year the year as it used in Gregorian calendar
 	 * @param month the month as it used in Gregorian calendar (1-12 inclusive)
@@ -42,19 +42,92 @@ public:
 	UTCTimestamp(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second);
 
 	/**
-	 * @param textTimestamp the timestamp to parse into a UTC date
-	 * @todo Too expensive to implement (?). It is better to remove this and open it as another issue, or create
-	 * a platform-specific converter that will be only used in x86.
+	 * Add a duration to the timestamp
+	 *
+	 * @note Overflow checks are not performed.
+	 * @tparam Duration A duration of type std::chrono::duration. You can use the default values offered by C++, or anything
+	 * used by the TimeStamp class. Negative duration values are not supported.
 	 */
-	explicit UTCTimestamp(etl::string<32> textTimestamp);
+	template<class Duration, typename = std::enable_if_t<Time::is_duration_v<Duration>>>
+	void operator+=(const Duration& in) {
+		using namespace std::chrono;
+		using namespace Time;
+
+		if (in < Duration::zero()) {
+			ErrorHandler::reportInternalError(ErrorHandler::InvalidTimeStampInput);
+			return;
+		}
+
+	    uint64_t seconds = duration_cast<duration<uint64_t>>(in).count();
+
+		while (seconds >= (isLeapYear(year) ? 366L : 365L) * SecondsPerDay) {
+			seconds -= (isLeapYear(year) ? 366L : 365L) * SecondsPerDay;
+			year++;
+		}
+
+		while (seconds >= (daysOfMonth() * uint64_t{SecondsPerDay})) {
+			seconds -= daysOfMonth() * uint64_t{SecondsPerDay};
+		    month++;
+
+			if (month > MonthsPerYear) {
+				// Month overflow needs to be taken care here, so that daysOfMonth() knows
+				// what month it is.
+				month -= MonthsPerYear;
+				year++;
+			}
+		}
+
+		day += seconds / SecondsPerDay;
+		seconds -= (seconds / SecondsPerDay) * SecondsPerDay;
+
+		hour += seconds / SecondsPerHour;
+		seconds -= (seconds / SecondsPerHour) * SecondsPerHour;
+
+		minute += seconds / SecondsPerMinute;
+		seconds -= (seconds / SecondsPerMinute) * SecondsPerMinute;
+
+		second += seconds;
+
+		repair();
+	}
 
 	/**
-	 * Compare two timestamps.
-	 * @param Date the date that will be compared with the pointer `this`
+	 * @name Comparison operators
+	 * @{
 	 */
 	bool operator<(const UTCTimestamp& Date) const;
-	bool operator>(const UTCTimestamp& Date) const; ///< @copydoc UTCTimestamp::operator<
-	bool operator==(const UTCTimestamp& Date) const; ///< @copydoc UTCTimestamp::operator<
-	bool operator<=(const UTCTimestamp& Date) const; ///< @copydoc UTCTimestamp::operator<
-	bool operator>=(const UTCTimestamp& Date) const; ///< @copydoc UTCTimestamp::operator<
+	bool operator>(const UTCTimestamp& Date) const;
+	bool operator==(const UTCTimestamp& Date) const;
+	bool operator<=(const UTCTimestamp& Date) const;
+	bool operator>=(const UTCTimestamp& Date) const;
+	/**
+	 * @}
+	 */
+
+private:
+	/**
+	 * Makes sure that all time fields are within their bounds
+	 *
+	 * For example, if `hours == 1, minutes == 63`, then this function will carry over the numbers so that
+	 * `hours == 2, minutes == 3`.
+	 *
+	 * @note This performs max one propagation for every field.
+	 * For example, if `hours == 1, minutes == 123`, then only the first 60 minutes will be carried over.
+	 */
+	void repair();
+
+	/**
+	 * Find the number of days within the current @ref month.
+	 * Includes leap year calculation.
+	 */
+	uint8_t daysOfMonth() const {
+		using namespace Time;
+
+		uint8_t daysOfMonth = DaysOfMonth[month - 1];
+		if (month == 2 && isLeapYear(year)) {
+			daysOfMonth++;
+		}
+
+		return daysOfMonth;
+	}
 };
diff --git a/inc/etl/String.hpp b/inc/etl/String.hpp
index 7691f78323f636c5741a68b9cb2144e7c362fa86..c97573e96aba354afad870c822d91a0209159926 100644
--- a/inc/etl/String.hpp
+++ b/inc/etl/String.hpp
@@ -2,7 +2,7 @@
 #define ECSS_SERVICES_ETL_STRING_HPP
 
 #include <cstddef>
-#include <etl/cstring.h>
+#include <etl/string.h>
 
 /**
  * A fixed-size string
diff --git a/inc/etl_profile.h b/inc/etl_profile.h
index 14e6e6b8ff6105ce7d593d65e404171340b27107..8e82b7b11de0ca22e8a63c2a65a4eba9b447e8b2 100644
--- a/inc/etl_profile.h
+++ b/inc/etl_profile.h
@@ -5,7 +5,6 @@
 #ifndef ECSS_SERVICES_ETL_PROFILE_H
 #define ECSS_SERVICES_ETL_PROFILE_H
 
-#define ETL_THROW_EXCEPTIONS
 #define ETL_VERBOSE_ERRORS
 #define ETL_CHECK_PUSH_POP
 
diff --git a/inc/macros.hpp b/inc/macros.hpp
index 12cce6c0072f87f7b2a1d9c368dcca2f10aa8da5..473104869ba4d4401d16b90c660d512b1c02155a 100644
--- a/inc/macros.hpp
+++ b/inc/macros.hpp
@@ -6,6 +6,7 @@
  *
  * @todo Actually hold program execution or throw an exception here
  */
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
 #define ASSERT_INTERNAL(cond, error) (ErrorHandler::assertInternal((cond), (error)))
 
 /**
@@ -13,6 +14,7 @@
  *
  * Only to be used within the Message class.
  */
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
 #define ASSERT_REQUEST(cond, error) (ErrorHandler::assertRequest((cond), *this, (error)))
 
 #endif // ECSS_SERVICES_MACROS_HPP
diff --git a/lib/Catch2 b/lib/Catch2
index d63307279412de3870cf97cc6802bae8ab36089e..605a34765aa5d5ecbf476b4598a862ada971b0cc 160000
--- a/lib/Catch2
+++ b/lib/Catch2
@@ -1 +1 @@
-Subproject commit d63307279412de3870cf97cc6802bae8ab36089e
+Subproject commit 605a34765aa5d5ecbf476b4598a862ada971b0cc
diff --git a/lib/etl b/lib/etl
index 5a7e181100dae73659db133783ae964c7661437b..fce2b5ca8d2a139e0aefb450773b82e2cdfaa55f 160000
--- a/lib/etl
+++ b/lib/etl
@@ -1 +1 @@
-Subproject commit 5a7e181100dae73659db133783ae964c7661437b
+Subproject commit fce2b5ca8d2a139e0aefb450773b82e2cdfaa55f
diff --git a/lib/logger b/lib/logger
index 4de567283a883fa4d93f454b6979cd4c90c5382b..c71e518061bc3fff6287800d709b40c9e8312b97 160000
--- a/lib/logger
+++ b/lib/logger
@@ -1 +1 @@
-Subproject commit 4de567283a883fa4d93f454b6979cd4c90c5382b
+Subproject commit c71e518061bc3fff6287800d709b40c9e8312b97
diff --git a/src/Helpers/AllMessageTypes.cpp b/src/Helpers/AllMessageTypes.cpp
index c67e09b31d3ebf98fd7a477d051b23beb7949a62..0ee958f3081ca105e4af345ccad70ff2cfa326b3 100644
--- a/src/Helpers/AllMessageTypes.cpp
+++ b/src/Helpers/AllMessageTypes.cpp
@@ -12,17 +12,17 @@
 #include "Services/TimeBasedSchedulingService.hpp"
 
 namespace AllMessageTypes {
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st01Messages = {RequestVerificationService::MessageType::FailedAcceptanceReport,
-	                                                                   RequestVerificationService::MessageType::FailedCompletionOfExecution,
-	                                                                   RequestVerificationService::MessageType::FailedProgressOfExecution,
-	                                                                   RequestVerificationService::MessageType::FailedRoutingReport,
-	                                                                   RequestVerificationService::MessageType::FailedStartOfExecution,
-	                                                                   RequestVerificationService::MessageType::SuccessfulAcceptanceReport,
-	                                                                   RequestVerificationService::MessageType::SuccessfulCompletionOfExecution,
-	                                                                   RequestVerificationService::MessageType::SuccessfulProgressOfExecution,
-	                                                                   RequestVerificationService::MessageType::SuccessfulStartOfExecution};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST01Messages = {RequestVerificationService::MessageType::FailedAcceptanceReport,
+		                                                                     RequestVerificationService::MessageType::FailedCompletionOfExecution,
+		                                                                     RequestVerificationService::MessageType::FailedProgressOfExecution,
+		                                                                     RequestVerificationService::MessageType::FailedRoutingReport,
+		                                                                     RequestVerificationService::MessageType::FailedStartOfExecution,
+		                                                                     RequestVerificationService::MessageType::SuccessfulAcceptanceReport,
+		                                                                     RequestVerificationService::MessageType::SuccessfulCompletionOfExecution,
+		                                                                     RequestVerificationService::MessageType::SuccessfulProgressOfExecution,
+		                                                                     RequestVerificationService::MessageType::SuccessfulStartOfExecution};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st03Messages = {
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST03Messages = {
 	    HousekeepingService::MessageType::DisablePeriodicHousekeepingParametersReport,
 	    HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport,
 	    HousekeepingService::MessageType::GenerateOneShotHousekeepingReport,
@@ -30,43 +30,43 @@ namespace AllMessageTypes {
 	    HousekeepingService::MessageType::HousekeepingPeriodicPropertiesReport,
 	    HousekeepingService::MessageType::HousekeepingStructuresReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st04Messages = {
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST04Messages = {
 	    ParameterStatisticsService::MessageType::ParameterStatisticsDefinitionsReport,
 	    ParameterStatisticsService::MessageType::ParameterStatisticsReport,
 	};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st05Messages = {EventReportService::MessageType::HighSeverityAnomalyReport,
-	                                                                   EventReportService::MessageType::DisabledListEventReport,
-	                                                                   EventReportService::MessageType::InformativeEventReport,
-	                                                                   EventReportService::MessageType::LowSeverityAnomalyReport,
-	                                                                   EventReportService::MessageType::MediumSeverityAnomalyReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST05Messages = {EventReportService::MessageType::HighSeverityAnomalyReport,
+	                                                                         EventReportService::MessageType::DisabledListEventReport,
+	                                                                         EventReportService::MessageType::InformativeEventReport,
+	                                                                         EventReportService::MessageType::LowSeverityAnomalyReport,
+	                                                                         EventReportService::MessageType::MediumSeverityAnomalyReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st06Messages = {MemoryManagementService::MessageType::CheckRawMemoryDataReport,
-	                                                                   MemoryManagementService::MessageType::DumpRawMemoryDataReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST06Messages = {MemoryManagementService::MessageType::CheckRawMemoryDataReport,
+	                                                                         MemoryManagementService::MessageType::DumpRawMemoryDataReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st11Messages = {TimeBasedSchedulingService::MessageType::TimeBasedScheduledSummaryReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST11Messages = {TimeBasedSchedulingService::MessageType::TimeBasedScheduledSummaryReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st13Messages = {LargePacketTransferService::MessageType::FirstDownlinkPartReport,
-	                                                                   LargePacketTransferService::MessageType::InternalDownlinkPartReport,
-	                                                                   LargePacketTransferService::MessageType::LastDownlinkPartReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST13Messages = {LargePacketTransferService::MessageType::FirstDownlinkPartReport,
+	                                                                         LargePacketTransferService::MessageType::InternalDownlinkPartReport,
+	                                                                         LargePacketTransferService::MessageType::LastDownlinkPartReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st17Messages = {TestService::MessageType::AreYouAliveTestReport,
-	                                                                   TestService::MessageType::OnBoardConnectionTestReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST17Messages = {TestService::MessageType::AreYouAliveTestReport,
+	                                                                         TestService::MessageType::OnBoardConnectionTestReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st19Messages = {EventActionService::MessageType::EventActionStatusReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST19Messages = {EventActionService::MessageType::EventActionStatusReport};
 
-	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st20Messages = {ParameterService::MessageType::ParameterValuesReport};
+	const etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ST20Messages = {ParameterService::MessageType::ParameterValuesReport};
 
-	etl::map<uint8_t, etl::vector<uint8_t, ECSSMaxReportTypeDefinitions>, ECSSMaxServiceTypeDefinitions> messagesOfService = {
-	    {RequestVerificationService::ServiceType, st01Messages},
-	    {HousekeepingService::ServiceType, st03Messages},
-	    {ParameterStatisticsService::ServiceType, st04Messages},
-	    {EventReportService::ServiceType, st05Messages},
-	    {MemoryManagementService::ServiceType, st06Messages},
-	    {TimeBasedSchedulingService::ServiceType, st11Messages},
-	    {LargePacketTransferService::ServiceType, st13Messages},
-	    {TestService::ServiceType, st17Messages},
-	    {EventActionService::ServiceType, st19Messages},
-	    {ParameterService::ServiceType, st20Messages}};
+	const etl::map<uint8_t, etl::vector<uint8_t, ECSSMaxReportTypeDefinitions>, ECSSMaxServiceTypeDefinitions> MessagesOfService = {
+	    {RequestVerificationService::ServiceType, ST01Messages},
+	    {HousekeepingService::ServiceType, ST03Messages},
+	    {ParameterStatisticsService::ServiceType, ST04Messages},
+	    {EventReportService::ServiceType, ST05Messages},
+	    {MemoryManagementService::ServiceType, ST06Messages},
+	    {TimeBasedSchedulingService::ServiceType, ST11Messages},
+	    {LargePacketTransferService::ServiceType, ST13Messages},
+	    {TestService::ServiceType, ST17Messages},
+	    {EventActionService::ServiceType, ST19Messages},
+	    {ParameterService::ServiceType, ST20Messages}};
 
 } // namespace AllMessageTypes
diff --git a/src/Helpers/PMONBase.cpp b/src/Helpers/PMONBase.cpp
index 85f163fd24029d46f6dc3300b57a4dc79049d6e6..2e64cb3473b3ecd5a9fe705a74f9a1b97f7c113b 100644
--- a/src/Helpers/PMONBase.cpp
+++ b/src/Helpers/PMONBase.cpp
@@ -3,7 +3,5 @@
 
 
 PMONBase::PMONBase(uint16_t monitoredParameterId, uint16_t repetitionNumber)
-    : monitoredParameter(monitoredParameter), monitoredParameterId(monitoredParameterId),
-      repetitionNumber(repetitionNumber) {
-	monitoredParameter = Services.parameterManagement.getParameter(monitoredParameterId)->get();
-}
\ No newline at end of file
+    : monitoredParameter(Services.parameterManagement.getParameter(monitoredParameterId)->get()), monitoredParameterId(monitoredParameterId),
+      repetitionNumber(repetitionNumber) {}
\ No newline at end of file
diff --git a/src/Helpers/Statistic.cpp b/src/Helpers/Statistic.cpp
index 70236a557d90496c08ac807b8d3783c38aca069c..024c586bcd6b10977ae91ee9d74e5f28543fe2cb 100644
--- a/src/Helpers/Statistic.cpp
+++ b/src/Helpers/Statistic.cpp
@@ -1,20 +1,14 @@
-#include <iostream>
 #include "Helpers/Statistic.hpp"
+#include <cmath>
 
 void Statistic::updateStatistics(double value) {
-	/*
-	 * TODO:
-	 *      if periodic, just calculate next time without the CUC
-	 *      function.
-	 * */
-
 	if (value > max) {
 		max = value;
-		// TODO: maxTime = as_CUC_timestamp();
+		timeOfMaxValue = TimeGetter::getCurrentTimeDefaultCUC();
 	}
 	if (value < min) {
 		min = value;
-		// TODO: minTime = as_CUC_timestamp();
+		timeOfMinValue = TimeGetter::getCurrentTimeDefaultCUC();
 	}
 	if (sampleCounter + 1 > 0) {
 		mean = (mean * sampleCounter + value) / (sampleCounter + 1);
@@ -23,14 +17,14 @@ void Statistic::updateStatistics(double value) {
 	sampleCounter++;
 }
 
-void Statistic::appendStatisticsToMessage(Message& report) {
+void Statistic::appendStatisticsToMessage(Message& report) const {
 	report.appendFloat(static_cast<float>(max));
-	report.appendUint32(maxTime);
+	report.append(timeOfMaxValue);
 	report.appendFloat(static_cast<float>(min));
-	report.appendUint32(minTime);
+	report.append(timeOfMinValue);
 	report.appendFloat(static_cast<float>(mean));
 
-	if (SupportsStandardDeviation) {
+	if constexpr (SupportsStandardDeviation) {
 		double standardDeviation = 0;
 		if (sampleCounter == 0) {
 			standardDeviation = 0;
@@ -49,14 +43,15 @@ void Statistic::setSelfSamplingInterval(uint16_t samplingInterval) {
 void Statistic::resetStatistics() {
 	max = -std::numeric_limits<double>::infinity();
 	min = std::numeric_limits<double>::infinity();
-	maxTime = 0;
-	minTime = 0;
+	timeOfMaxValue = Time::DefaultCUC(0);
+	timeOfMinValue = Time::DefaultCUC(0);
 	mean = 0;
 	sumOfSquares = 0;
 	sampleCounter = 0;
 }
 
-bool Statistic::statisticsAreInitialized() {
-	return (sampleCounter == 0 and mean == 0 and sumOfSquares == 0 and maxTime == 0 and minTime == 0 and
+bool Statistic::statisticsAreInitialized() const {
+	return (sampleCounter == 0 and mean == 0 and sumOfSquares == 0 and
+	        timeOfMaxValue == Time::DefaultCUC(0) and timeOfMinValue == Time::DefaultCUC(0) and
 	        max == -std::numeric_limits<double>::infinity() and min == std::numeric_limits<double>::infinity());
 }
diff --git a/src/Message.cpp b/src/Message.cpp
index 0ba4d75aaed85e3584d6b7e81369390cb13bd6a3..c5846604e3b495d27ad98b85670635a739525c0d 100644
--- a/src/Message.cpp
+++ b/src/Message.cpp
@@ -1,13 +1,17 @@
 #include "Message.hpp"
-#include "macros.hpp"
-#include <cstring>
 #include <ErrorHandler.hpp>
-#include <ServicePool.hpp>
 #include <MessageParser.hpp>
+#include <cstring>
+#include "ServicePool.hpp"
+#include "macros.hpp"
+
 
-Message::Message(uint8_t serviceType, uint8_t messageType, Message::PacketType packetType, uint16_t applicationId)
+Message::Message(uint8_t serviceType, uint8_t messageType, PacketType packetType, uint16_t applicationId)
     : serviceType(serviceType), messageType(messageType), packetType(packetType), applicationId(applicationId) {}
 
+Message::Message(uint8_t serviceType, uint8_t messageType, PacketType packetType)
+    : serviceType(serviceType), messageType(messageType), packetType(packetType), applicationId(ApplicationId) {}
+
 void Message::appendBits(uint8_t numBits, uint16_t data) {
 	// TODO: Add assertion that data does not contain 1s outside of numBits bits
 	ASSERT_INTERNAL(numBits <= 16, ErrorHandler::TooManyBitsAppend);
@@ -174,7 +178,7 @@ void Message::appendString(const etl::istring& string) {
 void Message::appendFixedString(const etl::istring& string) {
 	ASSERT_INTERNAL((dataSize + string.max_size()) < ECSSMaxMessageSize, ErrorHandler::MessageTooLarge);
 	std::copy(string.data(), string.data() + string.size(), data + dataSize);
-	(void)memset(data + dataSize + string.size(), 0, string.max_size() - string.size());
+	(void) memset(data + dataSize + string.size(), 0, string.max_size() - string.size());
 	dataSize += string.max_size();
 }
 
diff --git a/src/MessageParser.cpp b/src/MessageParser.cpp
index 7ce06c23b64058b079a73eb0bf449462cd471b82..7ae9d4ac9f4322390013f4e1547990746d5736b7 100644
--- a/src/MessageParser.cpp
+++ b/src/MessageParser.cpp
@@ -86,7 +86,7 @@ void MessageParser::execute(Message& message) {
 }
 
 Message MessageParser::parse(uint8_t* data, uint32_t length) {
-	ASSERT_INTERNAL(length >= 6, ErrorHandler::UnacceptablePacket);
+	ASSERT_INTERNAL(length >= CCSDSPrimaryHeaderSize, ErrorHandler::UnacceptablePacket);
 
 	uint16_t packetHeaderIdentification = (data[0] << 8) | data[1];
 	uint16_t packetSequenceControl = (data[2] << 8) | data[3];
@@ -104,22 +104,22 @@ Message MessageParser::parse(uint8_t* data, uint32_t length) {
 	ASSERT_INTERNAL(versionNumber == 0U, ErrorHandler::UnacceptablePacket);
 	ASSERT_INTERNAL(secondaryHeaderFlag, ErrorHandler::UnacceptablePacket);
 	ASSERT_INTERNAL(sequenceFlags == 0x3U, ErrorHandler::UnacceptablePacket);
-	ASSERT_INTERNAL(packetDataLength == (length - 6U), ErrorHandler::UnacceptablePacket);
+	ASSERT_INTERNAL(packetDataLength == (length - CCSDSPrimaryHeaderSize), ErrorHandler::UnacceptablePacket);
 
 	Message message(0, 0, packetType, APID);
 	message.packetSequenceCount = packetSequenceCount;
 
 	if (packetType == Message::TC) {
-		parseECSSTCHeader(data + 6, packetDataLength, message);
+		parseECSSTCHeader(data + CCSDSPrimaryHeaderSize, packetDataLength, message);
 	} else {
-		parseECSSTMHeader(data + 6, packetDataLength, message);
+		parseECSSTMHeader(data + CCSDSPrimaryHeaderSize, packetDataLength, message);
 	}
 
 	return message;
 }
 
 void MessageParser::parseECSSTCHeader(const uint8_t* data, uint16_t length, Message& message) {
-	ErrorHandler::assertRequest(length >= 5, message, ErrorHandler::UnacceptableMessage);
+	ErrorHandler::assertRequest(length >= ECSSSecondaryTCHeaderSize, message, ErrorHandler::UnacceptableMessage);
 
 	// Individual fields of the TC header
 	uint8_t pusVersion = data[0] >> 4;
@@ -129,12 +129,12 @@ void MessageParser::parseECSSTCHeader(const uint8_t* data, uint16_t length, Mess
 	ErrorHandler::assertRequest(pusVersion == 2U, message, ErrorHandler::UnacceptableMessage);
 
 	// Remove the length of the header
-	length -= 5;
+	length -= ECSSSecondaryTCHeaderSize;
 
 	// Copy the data to the message
 	message.serviceType = serviceType;
 	message.messageType = messageType;
-	std::copy(data + 5, data + 5 + length, message.data);
+	std::copy(data + ECSSSecondaryTCHeaderSize, data + ECSSSecondaryTCHeaderSize + length, message.data);
 	message.dataSize = length;
 }
 
@@ -154,23 +154,33 @@ Message MessageParser::parseECSSTC(uint8_t* data) {
 }
 
 String<CCSDSMaxMessageSize> MessageParser::composeECSS(const Message& message, uint16_t size) {
-	uint8_t header[5];
+	// Unfortunately to avoid using VLAs, we will create an array with the maximum size.
+	uint8_t header[ECSSSecondaryTMHeaderSize];
 
 	if (message.packetType == Message::TC) {
 		header[0] = ECSSPUSVersion << 4U; // Assign the pusVersion = 2
+		header[0] |= 0x00;                //ack flags
 		header[1] = message.serviceType;
 		header[2] = message.messageType;
-		header[3] = 0;
-		header[4] = 0;
+		header[3] = message.applicationId >> 8U;
+		header[4] = message.applicationId;
 	} else {
 		header[0] = ECSSPUSVersion << 4U; // Assign the pusVersion = 2
+		header[0] |= 0x00;                // Spacecraft time reference status
 		header[1] = message.serviceType;
 		header[2] = message.messageType;
 		header[3] = static_cast<uint8_t>(message.messageTypeCounter >> 8U);
 		header[4] = static_cast<uint8_t>(message.messageTypeCounter & 0xffU);
+		header[5] = message.applicationId >> 8U; // DestinationID
+		header[6] = message.applicationId;
+		uint32_t ticks = TimeGetter::getCurrentTimeDefaultCUC().formatAsBytes();
+		header[7] = (ticks >> 24) & 0xffU;
+		header[8] = (ticks >> 16) & 0xffU;
+		header[9] = (ticks >> 8) & 0xffU;
+		header[10] = (ticks) & 0xffU;
 	}
 
-	String<CCSDSMaxMessageSize> dataString(header, 5);
+	String<CCSDSMaxMessageSize> dataString(header, ((message.packetType == Message::TM) ? ECSSSecondaryTMHeaderSize : ECSSSecondaryTCHeaderSize));
 	dataString.append(message.data, message.dataSize);
 
 	// Make sure to reach the requested size
@@ -190,20 +200,20 @@ String<CCSDSMaxMessageSize> MessageParser::composeECSS(const Message& message, u
 }
 
 String<CCSDSMaxMessageSize> MessageParser::compose(const Message& message) {
-	uint8_t header[6];
+	uint8_t header[CCSDSPrimaryHeaderSize];
 
 	// First, compose the ECSS part
 	String<CCSDSMaxMessageSize> ecssMessage = MessageParser::composeECSS(message);
 
 	// Sanity check that there is enough space for the string
-	ASSERT_INTERNAL((ecssMessage.size() + 6U) <= CCSDSMaxMessageSize, ErrorHandler::StringTooLarge);
+	ASSERT_INTERNAL((ecssMessage.size() + CCSDSPrimaryHeaderSize) <= CCSDSMaxMessageSize, ErrorHandler::StringTooLarge);
 
 	// Parts of the header
 	uint16_t packetId = message.applicationId;
 	packetId |= (1U << 11U);                                              // Secondary header flag
 	packetId |= (message.packetType == Message::TC) ? (1U << 12U) : (0U); // Ignore-MISRA
 	uint16_t packetSequenceControl = message.packetSequenceCount | (3U << 14U);
-	uint16_t packetDataLength = ecssMessage.size();
+	uint16_t packetDataLength = ecssMessage.size() - 1;
 
 	// Compile the header
 	header[0] = packetId >> 8U;
@@ -214,7 +224,7 @@ String<CCSDSMaxMessageSize> MessageParser::compose(const Message& message) {
 	header[5] = packetDataLength & 0xffU;
 
 	// Compile the final message by appending the header
-	String<CCSDSMaxMessageSize> ccsdsMessage(header, 6);
+	String<CCSDSMaxMessageSize> ccsdsMessage(header, CCSDSPrimaryHeaderSize);
 	ccsdsMessage.append(ecssMessage);
 
 #if ECSS_CRC_INCLUDED
@@ -228,7 +238,7 @@ String<CCSDSMaxMessageSize> MessageParser::compose(const Message& message) {
 }
 
 void MessageParser::parseECSSTMHeader(const uint8_t* data, uint16_t length, Message& message) {
-	ErrorHandler::assertRequest(length >= 5, message, ErrorHandler::UnacceptableMessage);
+	ErrorHandler::assertRequest(length >= ECSSSecondaryTMHeaderSize, message, ErrorHandler::UnacceptableMessage);
 
 	// Individual fields of the TM header
 	uint8_t pusVersion = data[0] >> 4;
@@ -238,11 +248,11 @@ void MessageParser::parseECSSTMHeader(const uint8_t* data, uint16_t length, Mess
 	ErrorHandler::assertRequest(pusVersion == 2U, message, ErrorHandler::UnacceptableMessage);
 
 	// Remove the length of the header
-	length -= 5;
+	length -= ECSSSecondaryTMHeaderSize;
 
 	// Copy the data to the message
 	message.serviceType = serviceType;
 	message.messageType = messageType;
-	std::copy(data + 5, data + 5 + length, message.data);
+	std::copy(data + ECSSSecondaryTMHeaderSize, data + ECSSSecondaryTMHeaderSize + length, message.data);
 	message.dataSize = length;
 }
diff --git a/src/Platform/x86/ErrorHandler.cpp b/src/Platform/x86/ErrorHandler.cpp
index ffddffd2d0501e688779674251ae1da83aa035d7..572d34246c301c3aa4f30c57ae48540fe4ac737f 100644
--- a/src/Platform/x86/ErrorHandler.cpp
+++ b/src/Platform/x86/ErrorHandler.cpp
@@ -8,6 +8,8 @@
 #include <ErrorHandler.hpp>
 #include <Message.hpp>
 #include <Logger.hpp>
+#include <type_traits>
+#include "Helpers/EnumMagic.hpp"
 
 // TODO: Find a way to reduce the number of copies of this chunk
 template void ErrorHandler::logError(const Message&, ErrorHandler::AcceptanceErrorType);
@@ -26,7 +28,7 @@ void ErrorHandler::logError(const Message& message, ErrorType errorType) {
 	     */
 	    << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr) << " Error "
 	    << "[" << static_cast<uint16_t>(message.serviceType) << "," << static_cast<uint16_t>(message.messageType)
-	    << "]: " << errorType;
+	    << "]: " << enumName(errorType) << " (" << static_cast<std::underlying_type_t<ErrorType>>(errorType) << ")";
 }
 
 template <typename ErrorType>
@@ -36,5 +38,7 @@ void ErrorHandler::logError(ErrorType errorType) {
 	     * Gets the error class name from the template
 	     * Note: This is g++-dependent code and should only be used for debugging.
 	     */
-	    << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr) << " Error: " << errorType;
+	    << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr)
+	    << " Error: "
+	    << enumName(errorType) << " (" << static_cast<std::underlying_type_t<ErrorType>>(errorType) << ")";
 }
diff --git a/src/Platform/x86/Service.cpp b/src/Platform/x86/Service.cpp
index 60786fc650c32da32cb98860886291537e378fce..f316a764a1a679cf1126e8f3f0e1994592b8c8bc 100644
--- a/src/Platform/x86/Service.cpp
+++ b/src/Platform/x86/Service.cpp
@@ -1,7 +1,47 @@
-#include <iostream>
-#include <iomanip>
-#include <Logger.hpp>
 #include "Service.hpp"
+#include <Logger.hpp>
+#include <MessageParser.hpp>
+#include <arpa/inet.h>
+#include <iomanip>
+#include <iostream>
+#include <netinet/in.h>
+#include <string>
+#include <sys/socket.h>
+#include <unistd.h>
+
+class PacketSender {
+private:
+	const char* hostname = "127.0.0.1";
+	const uint16_t port = 10015;
+	sockaddr_in destination;
+	int socket;
+
+public:
+	PacketSender() {
+		socket = ::socket(AF_INET, SOCK_DGRAM, 0);
+		destination.sin_family = AF_INET;
+		destination.sin_port = htons(port);
+		destination.sin_addr.s_addr = inet_addr(hostname);
+	};
+
+	~PacketSender() {
+		::close(socket);
+	};
+
+	void sendPacketToYamcs(Message& message) {
+		// Add ECSS and CCSDS header
+		String<CCSDSMaxMessageSize> createdPacket = MessageParser::compose(message);
+		auto bytesSent = ::sendto(socket, createdPacket.c_str(), createdPacket.length(), 0, reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
+		LOG_DEBUG << bytesSent << " bytes sent";
+	}
+};
+
+PacketSender packetSender;
+
+/**
+ * If set to true, the created messages will be sent to port 10025 on localhost for testing purposes.
+ */
+inline const bool SendToYamcs = true;
 
 void Service::storeMessage(Message& message) {
 	// appends the remaining bits to complete a byte
@@ -14,12 +54,17 @@ void Service::storeMessage(Message& message) {
 	ss << "New " << ((message.packetType == Message::TM) ? "TM" : "TC") << "["
 	   << std::hex
 	   << static_cast<int>(message.serviceType) << "," // Ignore-MISRA
-	   << static_cast<int>(message.messageType) // Ignore-MISRA
+	   << static_cast<int>(message.messageType)        // Ignore-MISRA
 	   << "] message! ";
 
 	for (unsigned int i = 0; i < message.dataSize; i++) {
 		ss << static_cast<int>(message.data[i]) << " "; // Ignore-MISRA
 	}
 
+
+	// Send data to YAMCS port
+	if constexpr (SendToYamcs) {
+		packetSender.sendPacketToYamcs(message);
+	}
 	LOG_DEBUG << ss.str();
 }
diff --git a/src/Platform/x86/Services/ParameterService.cpp b/src/Platform/x86/Services/ParameterService.cpp
index da7b4c439e937b854db079a4efd93bf972153c0f..268cfd279b2d9d773f34965643d9e30d30b63c70 100644
--- a/src/Platform/x86/Services/ParameterService.cpp
+++ b/src/Platform/x86/Services/ParameterService.cpp
@@ -1,8 +1,8 @@
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_PARAMETER
 
-#include "Services/ParameterService.hpp"
 #include "Parameters/PlatformParameters.hpp"
+#include "Services/ParameterService.hpp"
 
 void ParameterService::initializeParameterMap() {
 	parameters = {{static_cast<uint16_t>(0), PlatformParameters::parameter1},
@@ -10,4 +10,4 @@ void ParameterService::initializeParameterMap() {
 	              {static_cast<uint16_t>(2), PlatformParameters::parameter3}};
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Platform/x86/Services/ParameterStatisticsService.cpp b/src/Platform/x86/Services/ParameterStatisticsService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac6e9aa2e093bc9e3a72a26b89b8818cfabec395
--- /dev/null
+++ b/src/Platform/x86/Services/ParameterStatisticsService.cpp
@@ -0,0 +1,10 @@
+#include "Services/ParameterStatisticsService.hpp"
+#include "ECSS_Configuration.hpp"
+
+#ifdef SERVICE_PARAMETERSTATISTICS
+
+void ParameterStatisticsService::initializeStatisticsMap() {
+	statisticsMap = {};
+}
+
+#endif
diff --git a/src/Platform/x86/Services/TimeBasedSchedulingService.cpp b/src/Platform/x86/Services/TimeBasedSchedulingService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..86afc2bd2d8e0467d8cf9048821c285cab7b5284
--- /dev/null
+++ b/src/Platform/x86/Services/TimeBasedSchedulingService.cpp
@@ -0,0 +1,8 @@
+#include "ECSS_Configuration.hpp"
+#ifdef SERVICE_TIMESCHEDULING
+
+#include "Services/TimeBasedSchedulingService.hpp"
+
+void TimeBasedSchedulingService::notifyNewActivityAddition() {}
+
+#endif
\ No newline at end of file
diff --git a/src/Platform/x86/TimeGetter.cpp b/src/Platform/x86/TimeGetter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..acff1688c887152d17d5b09fa621fd86c807be62
--- /dev/null
+++ b/src/Platform/x86/TimeGetter.cpp
@@ -0,0 +1,15 @@
+#include "Helpers/TimeGetter.hpp"
+
+UTCTimestamp TimeGetter::getCurrentTimeUTC() {
+	time_t timeInSeconds = static_cast<time_t>(time(nullptr));
+	tm* UTCTimeStruct = gmtime(&timeInSeconds);
+	UTCTimestamp currentTime(UTCTimeStruct->tm_year, UTCTimeStruct->tm_mon,
+	                         UTCTimeStruct->tm_mday, UTCTimeStruct->tm_hour,
+	                         UTCTimeStruct->tm_min, UTCTimeStruct->tm_sec);
+	return currentTime;
+}
+
+Time::DefaultCUC TimeGetter::getCurrentTimeDefaultCUC() {
+	UTCTimestamp timeUTC = getCurrentTimeUTC();
+	return Time::DefaultCUC(timeUTC);
+}
diff --git a/src/Platform/x86/main.cpp b/src/Platform/x86/main.cpp
index 016647fda0cf1e2142123300802652a6b2899222..a2e0dc89c82dfa9c1bdbe4ba6968d9b9d6f6efd1 100644
--- a/src/Platform/x86/main.cpp
+++ b/src/Platform/x86/main.cpp
@@ -1,25 +1,25 @@
-#include <iostream>
 #include <Logger.hpp>
-#include <Time/UTCTimestamp.hpp>
 #include <Platform/x86/Helpers/UTCTimestamp.hpp>
+#include <Time/UTCTimestamp.hpp>
+#include <ctime>
+#include <iostream>
+#include "ErrorHandler.hpp"
 #include "Helpers/CRCHelper.hpp"
-#include "Services/TestService.hpp"
-#include "Services/ParameterService.hpp"
-#include "Services/RequestVerificationService.hpp"
-#include "Services/MemoryManagementService.hpp"
+#include "Helpers/Statistic.hpp"
+#include "Message.hpp"
+#include "MessageParser.hpp"
+#include "ServicePool.hpp"
+#include "Services/EventActionService.hpp"
 #include "Services/EventReportService.hpp"
 #include "Services/FunctionManagementService.hpp"
-#include "Services/EventActionService.hpp"
 #include "Services/LargePacketTransferService.hpp"
-#include "Services/TimeBasedSchedulingService.hpp"
+#include "Services/MemoryManagementService.hpp"
+#include "Services/ParameterService.hpp"
 #include "Services/ParameterStatisticsService.hpp"
-#include "Helpers/Statistic.hpp"
-#include "Message.hpp"
-#include "MessageParser.hpp"
-#include "ErrorHandler.hpp"
+#include "Services/RequestVerificationService.hpp"
+#include "Services/TestService.hpp"
+#include "Services/TimeBasedSchedulingService.hpp"
 #include "etl/String.hpp"
-#include "ServicePool.hpp"
-#include <ctime>
 
 int main() {
 	LOG_NOTICE << "ECSS Services test application";
@@ -55,19 +55,19 @@ int main() {
 	// Test code for reportParameter
 	Message sentPacket = Message(ParameterService::ServiceType, ParameterService::MessageType::ReportParameterValues,
 	                             Message::TC, 1); // application id is a dummy number (1)
-	sentPacket.appendUint16(2); // number of contained IDs
-	sentPacket.appendUint16(0); // first ID
-	sentPacket.appendUint16(1); // second ID
+	sentPacket.appendUint16(2);                   // number of contained IDs
+	sentPacket.appendUint16(0);                   // first ID
+	sentPacket.appendUint16(1);                   // second ID
 	paramService.reportParameters(sentPacket);
 
 	// Test code for setParameter
 	Message sentPacket2 = Message(ParameterService::ServiceType, ParameterService::MessageType::SetParameterValues,
 	                              Message::TC, 1); // application id is a dummy number (1)
-	sentPacket2.appendUint16(2); // number of contained IDs
-	sentPacket2.appendUint16(0); // first parameter ID
-	sentPacket2.appendUint32(63238); // settings for first parameter
-	sentPacket2.appendUint16(1); // 2nd parameter ID
-	sentPacket2.appendUint32(45823); // settings for 2nd parameter
+	sentPacket2.appendUint16(2);                   // number of contained IDs
+	sentPacket2.appendUint16(0);                   // first parameter ID
+	sentPacket2.appendUint32(63238);               // settings for first parameter
+	sentPacket2.appendUint16(1);                   // 2nd parameter ID
+	sentPacket2.appendUint32(45823);               // settings for 2nd parameter
 
 	paramService.setParameters(sentPacket2);
 	paramService.reportParameters(sentPacket);
@@ -84,9 +84,9 @@ int main() {
 	Message rcvPack = Message(MemoryManagementService::ServiceType,
 	                          MemoryManagementService::MessageType::DumpRawMemoryData, Message::TC, 1);
 	rcvPack.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID
-	rcvPack.appendUint16(3); // Iteration count
-	rcvPack.appendUint64(reinterpret_cast<uint64_t>(string)); // Start address
-	rcvPack.appendUint16(sizeof(string) / sizeof(string[0])); // Data read length
+	rcvPack.appendUint16(3);                                          // Iteration count
+	rcvPack.appendUint64(reinterpret_cast<uint64_t>(string));         // Start address
+	rcvPack.appendUint16(sizeof(string) / sizeof(string[0]));         // Data read length
 
 	rcvPack.appendUint64(reinterpret_cast<uint64_t>(anotherStr));
 	rcvPack.appendUint16(sizeof(anotherStr) / sizeof(anotherStr[0]));
@@ -100,21 +100,21 @@ int main() {
 
 	uint8_t data[2] = {'h', 'R'};
 	rcvPack.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID
-	rcvPack.appendUint16(2); // Iteration count
-	rcvPack.appendUint64(reinterpret_cast<uint64_t>(pStr)); // Start address
+	rcvPack.appendUint16(2);                                          // Iteration count
+	rcvPack.appendUint64(reinterpret_cast<uint64_t>(pStr));           // Start address
 	rcvPack.appendOctetString(String<2>(data, 2));
-	rcvPack.appendBits(16, CRCHelper::calculateCRC(data, 2)); // Append the CRC value
+	rcvPack.appendBits(16, CRCHelper::calculateCRC(data, 2));   // Append the CRC value
 	rcvPack.appendUint64(reinterpret_cast<uint64_t>(pStr + 1)); // Start address
 	rcvPack.appendOctetString(String<1>(data, 1));
 	rcvPack.appendBits(16, CRCHelper::calculateCRC(data, 1)); // Append the CRC value
-	memMangService.rawDataMemorySubservice.loadRawData(rcvPack);
+	memMangService.loadRawData(rcvPack);
 
 	rcvPack = Message(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::CheckRawMemoryData,
 	                  Message::TC, 1);
 
 	rcvPack.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID
-	rcvPack.appendUint16(2); // Iteration count
-	rcvPack.appendUint64(reinterpret_cast<uint64_t>(data)); // Start address
+	rcvPack.appendUint16(2);                                          // Iteration count
+	rcvPack.appendUint64(reinterpret_cast<uint64_t>(data));           // Start address
 	rcvPack.appendUint16(2);
 	rcvPack.appendUint64(reinterpret_cast<uint64_t>(data + 1)); // Start address
 	rcvPack.appendUint16(1);
@@ -245,7 +245,7 @@ int main() {
 	eventActionService.addEventActionDefinitions(eventActionDefinition7);
 
 	std::cout << "Status should be 000:";
-	for (auto& element : eventActionService.eventActionDefinitionMap) {
+	for (auto& element: eventActionService.eventActionDefinitionMap) {
 		std::cout << element.second.enabled;
 	}
 
@@ -264,7 +264,7 @@ int main() {
 
 	eventActionService.enableEventActionDefinitions(eventActionDefinition5);
 	std::cout << "\nStatus should be 111:";
-	for (auto& element : eventActionService.eventActionDefinitionMap) {
+	for (auto& element: eventActionService.eventActionDefinitionMap) {
 		std::cout << element.second.enabled;
 	}
 
@@ -282,7 +282,7 @@ int main() {
 	eventActionDefinition3.appendUint16(4);
 	eventActionService.disableEventActionDefinitions(eventActionDefinition3);
 	std::cout << "Status should be 000:";
-	for (auto& element : eventActionService.eventActionDefinitionMap) {
+	for (auto& element: eventActionService.eventActionDefinitionMap) {
 		std::cout << element.second.enabled;
 	}
 
@@ -327,7 +327,7 @@ int main() {
 	            TimeBasedSchedulingService::MessageType::EnableTimeBasedScheduleExecutionFunction, Message::TC, 1);
 	Message testMessage1(6, 5, Message::TC, 1);
 	Message testMessage2(4, 5, Message::TC, 1);
-	testMessage1.appendUint16(4253); // Append dummy data
+	testMessage1.appendUint16(4253);  // Append dummy data
 	testMessage2.appendUint16(45667); // Append dummy data
 
 	timeBasedSchedulingService.enableScheduleExecution(receivedMsg); // Enable the schedule
@@ -363,6 +363,8 @@ int main() {
 
 	LOG_NOTICE << "ECSS Services test complete";
 
+	ErrorHandler::reportInternalError(static_cast<ErrorHandler::InternalErrorType>(254));
+
 	std::cout << UTCTimestamp() << std::endl;
 	return 0;
 }
diff --git a/src/ServicePool.cpp b/src/ServicePool.cpp
index b8e7c963ca5af536baf4f0b52456a9432452bbb7..e36989475be54ea9444ef2959fc5deec6aa6942d 100644
--- a/src/ServicePool.cpp
+++ b/src/ServicePool.cpp
@@ -1,6 +1,6 @@
 #include "ServicePool.hpp"
 
-ServicePool Services = ServicePool();
+ServicePool Services = ServicePool(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 
 void ServicePool::reset() {
 	// Call the destructor
@@ -15,7 +15,7 @@ void ServicePool::reset() {
 
 uint16_t ServicePool::getAndUpdateMessageTypeCounter(uint8_t serviceType, uint8_t messageType) {
 	uint16_t key = (serviceType << 8U) | messageType; // Create the key of the map
-	return (messageTypeCounter[key])++; // Fetch and increase the value
+	return (messageTypeCounter[key])++;               // Fetch and increase the value
 }
 
 uint16_t ServicePool::getAndUpdatePacketSequenceCounter() {
diff --git a/src/Services/EventActionService.cpp b/src/Services/EventActionService.cpp
old mode 100644
new mode 100755
index 0963cf942b8a2dbd57a0a60fd972be37c78793a1..6fb59212dc078db140fbcc02d0aa9c891329ceb5
--- a/src/Services/EventActionService.cpp
+++ b/src/Services/EventActionService.cpp
@@ -1,191 +1,187 @@
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_EVENTACTION
 
-#include "Services/EventActionService.hpp"
 #include "Message.hpp"
 #include "MessageParser.hpp"
+#include "Services/EventActionService.hpp"
 
+EventActionService::EventActionDefinition::EventActionDefinition(uint16_t applicationID, uint16_t eventDefinitionID, Message& message)
+    : applicationID(applicationID), eventDefinitionID(eventDefinitionID), request(message.data + message.readPosition) {
+	message.readPosition += ECSSTCRequestStringSize;
+}
 
 void EventActionService::addEventActionDefinitions(Message& message) {
-	// TC[19,1]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction);
-	uint16_t applicationID = message.readEnum16();
-	uint16_t eventDefinitionID = message.readEnum16();
-	uint16_t eventActionDefinitionID = message.readEnum16();
-	bool canBeAdded = true;
-	if (eventActionDefinitionMap.find(eventDefinitionID) != eventActionDefinitionMap.end()) {
-		auto range = eventActionDefinitionMap.equal_range(eventDefinitionID);
-		for (auto& element = range.first; element != range.second; ++element) {
-			if (element->second.eventActionDefinitionID == eventActionDefinitionID) {
-				canBeAdded = false;
-				ErrorHandler::reportError(message, ErrorHandler::EventActionDefinitionIDExistsError);
+	if (!message.assertTC(ServiceType, MessageType::AddEventAction)) {
+		return;
+	}
+	uint8_t numberOfEventActionDefinitions = message.readUint8();
+	while (numberOfEventActionDefinitions-- != 0) {
+		uint16_t applicationID = message.readEnum16();
+		uint16_t eventDefinitionID = message.readEnum16();
+		bool canBeAdded = true;
+
+		for (auto& element: eventActionDefinitionMap) {
+			if (element.first == eventDefinitionID) {
+				if (element.second.enabled) {
+					canBeAdded = false;
+					ErrorHandler::reportError(message, ErrorHandler::EventActionEnabledError);
+				} else {
+					eventActionDefinitionMap.erase(eventDefinitionID);
+				}
+				break;
 			}
 		}
-	}
-
-	if ((message.dataSize - 6) > ECSSTCRequestStringSize) {
-		canBeAdded = false;
-		ErrorHandler::reportInternalError(ErrorHandler::MessageTooLarge);
-	}
-	if (canBeAdded) {
-		char data[ECSSTCRequestStringSize] = { 0 };
-		message.readString(data, message.dataSize - 6);
-		EventActionDefinition temp;
-		temp.enabled = false;
-		temp.applicationId = applicationID;
-		temp.eventDefinitionID = eventDefinitionID;
-		temp.eventActionDefinitionID = eventActionDefinitionID;
-		temp.request = String<ECSSTCRequestStringSize>(data);
-		if (eventActionDefinitionMap.size() == ECSSEventActionStructMapSize) {
-			ErrorHandler::reportError(message,ErrorHandler::EventActionDefinitionsMapIsFull);
-		} else {
-			eventActionDefinitionMap.insert(std::make_pair(eventDefinitionID, temp));
+		if (canBeAdded) {
+			if (eventActionDefinitionMap.size() == ECSSEventActionStructMapSize) {
+				ErrorHandler::reportError(message, ErrorHandler::EventActionDefinitionsMapIsFull);
+				continue;
+			}
+			EventActionDefinition temporaryEventActionDefinition(applicationID, eventDefinitionID, message);
+			eventActionDefinitionMap.insert(std::make_pair(eventDefinitionID, temporaryEventActionDefinition));
 		}
 	}
 }
 
 void EventActionService::deleteEventActionDefinitions(Message& message) {
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction);
-	uint16_t numberOfEventActionDefinitions = message.readUint16();
-	bool definitionIDexists = false;
-	for (uint16_t i = 0; i < numberOfEventActionDefinitions; i++) {
-		message.skipBytes(2);
+	if (!message.assertTC(ServiceType, MessageType::DeleteEventAction)) {
+		return;
+	}
+	uint8_t numberOfEventActionDefinitions = message.readUint8();
+	while (numberOfEventActionDefinitions-- != 0) {
+		uint16_t applicationID = message.readEnum16();
 		uint16_t eventDefinitionID = message.readEnum16();
-		uint16_t eventActionDefinitionID = message.readEnum16();
-		if (eventActionDefinitionMap.find(eventDefinitionID) != eventActionDefinitionMap.end()) {
-			auto range = eventActionDefinitionMap.equal_range(eventDefinitionID);
-			for (auto& element = range.first; element != range.second; ++element) {
-				if (element->second.eventActionDefinitionID == eventActionDefinitionID) {
-					definitionIDexists = true;
-					if (element->second.enabled) {
-						ErrorHandler::reportError(message, ErrorHandler::EventActionDeleteEnabledDefinitionError);
-					} else {
-						eventActionDefinitionMap.erase(element);
-					}
+		bool actionDefinitionExists = false;
+
+		for (auto& element: eventActionDefinitionMap) {
+			if (element.first == eventDefinitionID) {
+				actionDefinitionExists = true;
+				if (element.second.applicationID != applicationID) {
+					ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionError);
+				} else if (element.second.enabled) {
+					ErrorHandler::reportError(message, ErrorHandler::EventActionDeleteEnabledDefinitionError);
+				} else {
+					eventActionDefinitionMap.erase(eventActionDefinitionMap.find(eventDefinitionID));
 				}
+				break;
 			}
-			if (not definitionIDexists) {
-				ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionIDError);
-			}
-		} else {
-			ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventDefinitionError);
+		}
+		if (not actionDefinitionExists) {
+			ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionError);
 		}
 	}
 }
 
 void EventActionService::deleteAllEventActionDefinitions(Message& message) {
-	// TC[19,3]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::DeleteAllEventAction);
-
+	if (!message.assertTC(ServiceType, MessageType::DeleteAllEventAction)) {
+		return;
+	}
 	setEventActionFunctionStatus(false);
 	eventActionDefinitionMap.clear();
 }
 
 void EventActionService::enableEventActionDefinitions(Message& message) {
-	// TC[19,4]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction);
-	uint16_t numberOfEventActionDefinitions = message.readUint16();
+	if (!message.assertTC(ServiceType, MessageType::EnableEventAction)) {
+		return;
+	}
+	uint8_t numberOfEventActionDefinitions = message.readUint8();
 	if (numberOfEventActionDefinitions != 0U) {
-		for (uint16_t i = 0; i < numberOfEventActionDefinitions; i++) {
-			message.skipBytes(2); // Skips reading the application ID
+		while (numberOfEventActionDefinitions-- != 0) {
+			uint16_t applicationID = message.readEnum16();
 			uint16_t eventDefinitionID = message.readEnum16();
-			uint16_t eventActionDefinitionID = message.readEnum16();
-			if (eventActionDefinitionMap.find(eventDefinitionID) != eventActionDefinitionMap.end()) {
-				bool definitionIDexists = false;
-				auto range = eventActionDefinitionMap.equal_range(eventDefinitionID);
-				for (auto& element = range.first; element != range.second; ++element) {
-					if (element->second.eventActionDefinitionID == eventActionDefinitionID) {
-						element->second.enabled = true;
-						definitionIDexists = true;
-						break;
+			bool actionDefinitionExists = false;
+
+			for (auto& element: eventActionDefinitionMap) {
+				if (element.first == eventDefinitionID) {
+					actionDefinitionExists = true;
+					if (element.second.applicationID != applicationID) {
+						ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionError);
+					} else {
+						element.second.enabled = true;
 					}
+					break;
 				}
-				if (not definitionIDexists) {
-					ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionIDError);
-				}
-			} else {
-				ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventDefinitionError);
+			}
+			if (not actionDefinitionExists) {
+				ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionError);
 			}
 		}
 	} else {
-		for (auto& element : eventActionDefinitionMap) {
+		for (auto& element: eventActionDefinitionMap) {
 			element.second.enabled = true;
 		}
 	}
 }
 
 void EventActionService::disableEventActionDefinitions(Message& message) {
-	// TC[19,5]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction);
-	uint16_t numberOfEventActionDefinitions = message.readUint16();
+	if (!message.assertTC(ServiceType, MessageType::DisableEventAction)) {
+		return;
+	}
+	uint8_t numberOfEventActionDefinitions = message.readUint8();
 	if (numberOfEventActionDefinitions != 0U) {
-		for (uint16_t i = 0; i < numberOfEventActionDefinitions; i++) {
-			message.skipBytes(2); // Skips reading applicationID
+		while (numberOfEventActionDefinitions-- != 0) {
+			uint16_t applicationID = message.readEnum16();
 			uint16_t eventDefinitionID = message.readEnum16();
-			uint16_t eventActionDefinitionID = message.readEnum16();
-			if (eventActionDefinitionMap.find(eventDefinitionID) != eventActionDefinitionMap.end()) {
-				bool definitionIDexists = false;
-				auto range = eventActionDefinitionMap.equal_range(eventDefinitionID);
-				for (auto& element = range.first; element != range.second; ++element) {
-					if (element->second.eventActionDefinitionID == eventActionDefinitionID) {
-						element->second.enabled = false;
-						definitionIDexists = true;
+			bool actionDefinitionExists = false;
+
+			for (auto& element: eventActionDefinitionMap) {
+				if (element.first == eventDefinitionID) {
+					actionDefinitionExists = true;
+					if (element.second.applicationID != applicationID) {
+						ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionError);
+					} else {
+						element.second.enabled = false;
 					}
+					break;
 				}
-				if (not definitionIDexists) {
-					ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionIDError);
-				}
-			} else {
-				ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventDefinitionError);
+			}
+			if (not actionDefinitionExists) {
+				ErrorHandler::reportError(message, ErrorHandler::EventActionUnknownEventActionDefinitionError);
 			}
 		}
 	} else {
-		for (auto& element : eventActionDefinitionMap) {
+		for (auto& element: eventActionDefinitionMap) {
 			element.second.enabled = false;
 		}
 	}
 }
 
 void EventActionService::requestEventActionDefinitionStatus(Message& message) {
-	// TC[19,6]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::ReportStatusOfEachEventAction);
-
+	if (!message.assertTC(ServiceType, MessageType::ReportStatusOfEachEventAction)) {
+		return;
+	}
 	eventActionStatusReport();
 }
 
 void EventActionService::eventActionStatusReport() {
-	// TM[19,7]
 	Message report = createTM(EventActionStatusReport);
 	uint16_t count = eventActionDefinitionMap.size();
 	report.appendUint16(count);
-	for (const auto& element : eventActionDefinitionMap) {
-		report.appendEnum16(element.second.applicationId);
+	for (const auto& element: eventActionDefinitionMap) {
+		report.appendEnum16(element.second.applicationID);
 		report.appendEnum16(element.second.eventDefinitionID);
-		report.appendEnum16(element.second.eventActionDefinitionID);
 		report.appendBoolean(element.second.enabled);
 	}
 	storeMessage(report);
 }
 
 void EventActionService::enableEventActionFunction(Message& message) {
-	// TC[19,8]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::EnableEventActionFunction);
-
+	if (!message.assertTC(ServiceType, MessageType::EnableEventActionFunction)) {
+		return;
+	}
 	setEventActionFunctionStatus(true);
 }
 
 void EventActionService::disableEventActionFunction(Message& message) {
-	// TC[19,9]
-	message.assertTC(EventActionService::ServiceType, EventActionService::MessageType::DisableEventActionFunction);
-
+	if (!message.assertTC(ServiceType, MessageType::DisableEventActionFunction)) {
+		return;
+	}
 	setEventActionFunctionStatus(false);
 }
 
-// TODO: Should I use applicationID too?
-void EventActionService::executeAction(uint16_t eventID) {
+void EventActionService::executeAction(uint16_t eventDefinitionID) {
 	// Custom function
 	if (eventActionFunctionStatus) {
-		auto range = eventActionDefinitionMap.equal_range(eventID);
+		auto range = eventActionDefinitionMap.equal_range(eventDefinitionID);
 		for (auto& element = range.first; element != range.second; ++element) {
 			if (element->second.enabled) {
 				Message message = MessageParser::parseECSSTC(element->second.request);
@@ -215,7 +211,7 @@ void EventActionService::execute(Message& message) {
 		case ReportStatusOfEachEventAction:
 			requestEventActionDefinitionStatus(message);
 			break;
-		case EnableEventActionFunction :
+		case EnableEventActionFunction:
 			enableEventActionFunction(message);
 			break;
 		case DisableEventActionFunction:
diff --git a/src/Services/EventReportService.cpp b/src/Services/EventReportService.cpp
index 53dc18fb4d314d9a728d3f675a39cedd0253d7e0..5f2b23a4080ab397f0d0db21cb1b4daaed6a3979 100644
--- a/src/Services/EventReportService.cpp
+++ b/src/Services/EventReportService.cpp
@@ -1,8 +1,8 @@
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_EVENTREPORT
 
-#include <Services/EventReportService.hpp>
 #include <Services/EventActionService.hpp>
+#include <Services/EventReportService.hpp>
 #include "Message.hpp"
 
 /**
@@ -22,8 +22,7 @@ void EventReportService::informativeEventReport(Event eventID, const String<ECSS
 	}
 }
 
-void
-EventReportService::lowSeverityAnomalyReport(Event eventID, const String<ECSSEventDataAuxiliaryMaxSize>& data) {
+void EventReportService::lowSeverityAnomalyReport(Event eventID, const String<ECSSEventDataAuxiliaryMaxSize>& data) {
 	lowSeverityEventCount++;
 	// TM[5,2]
 	if (stateOfEvents[static_cast<uint16_t>(eventID)]) {
@@ -39,8 +38,7 @@ EventReportService::lowSeverityAnomalyReport(Event eventID, const String<ECSSEve
 	}
 }
 
-void
-EventReportService::mediumSeverityAnomalyReport(Event eventID, const String<ECSSEventDataAuxiliaryMaxSize>& data) {
+void EventReportService::mediumSeverityAnomalyReport(Event eventID, const String<ECSSEventDataAuxiliaryMaxSize>& data) {
 	mediumSeverityEventCount++;
 	// TM[5,3]
 	if (stateOfEvents[static_cast<uint16_t>(eventID)]) {
@@ -56,8 +54,7 @@ EventReportService::mediumSeverityAnomalyReport(Event eventID, const String<ECSS
 	}
 }
 
-void
-EventReportService::highSeverityAnomalyReport(Event eventID, const String<ECSSEventDataAuxiliaryMaxSize>& data) {
+void EventReportService::highSeverityAnomalyReport(Event eventID, const String<ECSSEventDataAuxiliaryMaxSize>& data) {
 	highSeverityEventCount++;
 	// TM[5,4]
 	if (stateOfEvents[static_cast<uint16_t>(eventID)]) {
@@ -75,19 +72,17 @@ EventReportService::highSeverityAnomalyReport(Event eventID, const String<ECSSEv
 
 void EventReportService::enableReportGeneration(Message message) {
 	// TC[5,5]
-	message.assertTC(EventReportService::ServiceType, EventReportService::MessageType::EnableReportGenerationOfEvents);
+	if (!message.assertTC(ServiceType, MessageType::EnableReportGenerationOfEvents)) {
+		return;
+	}
 
 	/**
 	 * @todo: Report an error if length > numberOfEvents
 	 */
 	uint16_t length = message.readUint16();
-	Event eventID[length];
-	for (uint16_t i = 0; i < length; i++) {
-		eventID[i] = static_cast<Event>(message.readEnum16());
-	}
 	if (length <= numberOfEvents) {
 		for (uint16_t i = 0; i < length; i++) {
-			stateOfEvents[static_cast<uint16_t>(eventID[i])] = true;
+			stateOfEvents[message.readEnum16()] = true;
 		}
 	}
 	disabledEventsCount = stateOfEvents.size() - stateOfEvents.count();
@@ -95,19 +90,17 @@ void EventReportService::enableReportGeneration(Message message) {
 
 void EventReportService::disableReportGeneration(Message message) {
 	// TC[5,6]
-	message.assertTC(EventReportService::ServiceType, EventReportService::MessageType::DisableReportGenerationOfEvents);
+	if (!message.assertTC(ServiceType, MessageType::DisableReportGenerationOfEvents)) {
+		return;
+	}
 
 	/**
 	 * @todo: Report an error if length > numberOfEvents
 	 */
 	uint16_t length = message.readUint16();
-	Event eventID[length];
-	for (uint16_t i = 0; i < length; i++) {
-		eventID[i] = static_cast<Event>(message.readEnum16());
-	}
 	if (length <= numberOfEvents) {
 		for (uint16_t i = 0; i < length; i++) {
-			stateOfEvents[static_cast<uint16_t>(eventID[i])] = false;
+			stateOfEvents[message.readEnum16()] = false;
 		}
 	}
 	disabledEventsCount = stateOfEvents.size() - stateOfEvents.count();
@@ -115,7 +108,9 @@ void EventReportService::disableReportGeneration(Message message) {
 
 void EventReportService::requestListOfDisabledEvents(Message message) {
 	// TC[5,7]
-	message.assertTC(EventReportService::ServiceType, EventReportService::MessageType::ReportListOfDisabledEvents);
+	if (!message.assertTC(ServiceType, MessageType::ReportListOfDisabledEvents)) {
+		return;
+	}
 
 	listOfDisabledEventsReport();
 }
diff --git a/src/Services/FunctionManagementService.cpp b/src/Services/FunctionManagementService.cpp
index 15361ff688031e211c11b637af0b229804760345..e299d0a5b82b654b1cf45f0d231b24e056d12b02 100644
--- a/src/Services/FunctionManagementService.cpp
+++ b/src/Services/FunctionManagementService.cpp
@@ -5,15 +5,13 @@
 
 void FunctionManagementService::call(Message& msg) {
 	msg.resetRead();
-	ErrorHandler::assertRequest(msg.packetType == Message::TC, msg,
-	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
-	ErrorHandler::assertRequest(msg.messageType == FunctionManagementService::MessageType::PerformFunction, msg,
-		ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
-	ErrorHandler::assertRequest(msg.serviceType == FunctionManagementService::ServiceType, msg,
-		ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
 
-	uint8_t funcName[ECSSFunctionNameLength] = { 0 }; // the function's name
-	uint8_t funcArgs[ECSSFunctionMaxArgLength] = { 0 }; // arguments for the function
+	if (!msg.assertTC(ServiceType, MessageType::PerformFunction)) {
+		return;
+	}
+
+	uint8_t funcName[ECSSFunctionNameLength] = {0};   // the function's name
+	uint8_t funcArgs[ECSSFunctionMaxArgLength] = {0}; // arguments for the function
 
 	msg.readString(funcName, ECSSFunctionNameLength);
 	msg.readString(funcArgs, ECSSFunctionMaxArgLength);
@@ -28,21 +26,20 @@ void FunctionManagementService::call(Message& msg) {
 	// locate the appropriate function pointer
 	String<ECSSFunctionNameLength> name(funcName);
 	FunctionMap::iterator iter = funcPtrIndex.find(name);
-	void (*selected)(String<ECSSFunctionMaxArgLength>);
 
-	if (iter != funcPtrIndex.end()) {
-		selected = *iter->second;
-	} else {
+	if (iter == funcPtrIndex.end()) {
 		ErrorHandler::reportError(msg, ErrorHandler::ExecutionStartErrorType::UnknownExecutionStartError);
 		return;
 	}
 
+	auto selected = *iter->second;
+
 	// execute the function if there are no obvious flaws (defined in the standard, pg.158)
 	selected(funcArgs);
 }
 
 void FunctionManagementService::include(String<ECSSFunctionNameLength> funcName,
-	void (* ptr)(String<ECSSFunctionMaxArgLength>)) {
+                                        void (*ptr)(String<ECSSFunctionMaxArgLength>)) {
 	if (not funcPtrIndex.full()) { // CAUTION: etl::map won't check by itself if it's full
 		// before attempting to insert a key-value pair, causing segmentation faults. Check first!
 		funcName.append(ECSSFunctionNameLength - funcName.length(), 0);
diff --git a/src/Services/HousekeepingService.cpp b/src/Services/HousekeepingService.cpp
index 35beaa2ab3163197ebd778e805a408c739beeaea..0a714e065f10a7101447559927a949397e28308a 100644
--- a/src/Services/HousekeepingService.cpp
+++ b/src/Services/HousekeepingService.cpp
@@ -2,16 +2,15 @@
 #include "ServicePool.hpp"
 
 void HousekeepingService::createHousekeepingReportStructure(Message& request) {
-	request.assertTC(ServiceType, MessageType::CreateHousekeepingReportStructure);
+	if (!request.assertTC(ServiceType, MessageType::CreateHousekeepingReportStructure)) {
+		return;
+	}
 
 	uint8_t idToCreate = request.readUint8();
-	if (housekeepingStructures.find(idToCreate) != housekeepingStructures.end()) {
-		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedAlreadyExistingStructure);
+	if (hasAlreadyExistingStructError(idToCreate, request)) {
 		return;
 	}
-	if (housekeepingStructures.size() >= ECSSMaxHousekeepingStructures) {
-		ErrorHandler::reportError(request,
-		                          ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfHousekeepingStructures);
+	if (hasExceededMaxNumOfHousekeepingStructsError(request)) {
 		return;
 	}
 	HousekeepingStructure newStructure;
@@ -23,8 +22,7 @@ void HousekeepingService::createHousekeepingReportStructure(Message& request) {
 
 	for (uint16_t i = 0; i < numOfSimplyCommutatedParams; i++) {
 		uint16_t newParamId = request.readUint16();
-		if (existsInVector(newStructure.simplyCommutatedParameterIds, newParamId)) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter);
+		if (hasAlreadyExistingParameterError(newStructure, newParamId, request)) {
 			continue;
 		}
 		newStructure.simplyCommutatedParameterIds.push_back(newParamId);
@@ -33,17 +31,17 @@ void HousekeepingService::createHousekeepingReportStructure(Message& request) {
 }
 
 void HousekeepingService::deleteHousekeepingReportStructure(Message& request) {
-	request.assertTC(ServiceType, MessageType::DeleteHousekeepingReportStructure);
+	if (!request.assertTC(ServiceType, MessageType::DeleteHousekeepingReportStructure)) {
+		return;
+	}
 	uint8_t numOfStructuresToDelete = request.readUint8();
 	for (uint8_t i = 0; i < numOfStructuresToDelete; i++) {
 		uint8_t structureId = request.readUint8();
-		if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+		if (hasNonExistingStructExecutionError(structureId, request)) {
 			continue;
 		}
-		if (housekeepingStructures.at(structureId).periodicGenerationActionStatus) {
-			ErrorHandler::reportError(request,
-			                          ErrorHandler::ExecutionStartErrorType::RequestedDeletionOfEnabledHousekeeping);
+
+		if (hasRequestedDeletionOfEnabledHousekeepingError(structureId, request)) {
 			continue;
 		}
 		housekeepingStructures.erase(structureId);
@@ -51,75 +49,80 @@ void HousekeepingService::deleteHousekeepingReportStructure(Message& request) {
 }
 
 void HousekeepingService::enablePeriodicHousekeepingParametersReport(Message& request) {
-	request.assertTC(ServiceType, MessageType::EnablePeriodicHousekeepingParametersReport);
+	if (!request.assertTC(ServiceType, MessageType::EnablePeriodicHousekeepingParametersReport)) {
+		return;
+	}
 
 	uint8_t numOfStructIds = request.readUint8();
 	for (uint8_t i = 0; i < numOfStructIds; i++) {
 		uint8_t structIdToEnable = request.readUint8();
-		if (housekeepingStructures.find(structIdToEnable) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::RequestedNonExistingStructure);
+		if (hasNonExistingStructError(structIdToEnable, request)) {
 			continue;
 		}
-		housekeepingStructures.at(structIdToEnable).periodicGenerationActionStatus = true;
+		setPeriodicGenerationActionStatus(structIdToEnable, true);
 	}
 }
 
 void HousekeepingService::disablePeriodicHousekeepingParametersReport(Message& request) {
-	request.assertTC(ServiceType, MessageType::DisablePeriodicHousekeepingParametersReport);
+	if (!request.assertTC(ServiceType, MessageType::DisablePeriodicHousekeepingParametersReport)) {
+		return;
+	}
 
 	uint8_t numOfStructIds = request.readUint8();
 	for (uint8_t i = 0; i < numOfStructIds; i++) {
 		uint8_t structIdToDisable = request.readUint8();
-		if (housekeepingStructures.find(structIdToDisable) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::RequestedNonExistingStructure);
+		if (hasNonExistingStructError(structIdToDisable, request)) {
 			continue;
 		}
-		housekeepingStructures.at(structIdToDisable).periodicGenerationActionStatus = false;
+		setPeriodicGenerationActionStatus(structIdToDisable, false);
 	}
 }
 
 void HousekeepingService::reportHousekeepingStructures(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportHousekeepingStructures);
+	if (!request.assertTC(ServiceType, MessageType::ReportHousekeepingStructures)) {
+		return;
+	}
 
 	uint8_t numOfStructsToReport = request.readUint8();
 	for (uint8_t i = 0; i < numOfStructsToReport; i++) {
 		uint8_t structureId = request.readUint8();
-		if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+		if (hasNonExistingStructExecutionError(structureId, request)) {
 			continue;
 		}
+
 		housekeepingStructureReport(structureId);
 	}
 }
 
 void HousekeepingService::housekeepingStructureReport(uint8_t structIdToReport) {
 	auto housekeepingStructure = housekeepingStructures.find(structIdToReport);
-	if (housekeepingStructure == housekeepingStructures.end()) {
-		ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::NonExistentHousekeeping);
+	if (hasNonExistingStructInternalError(structIdToReport)) {
 		return;
 	}
-	Message structReport(ServiceType, MessageType::HousekeepingStructuresReport, Message::TM, 1);
+	Message structReport = createTM(MessageType::HousekeepingStructuresReport);
 	structReport.appendUint8(structIdToReport);
 
 	structReport.appendBoolean(housekeepingStructure->second.periodicGenerationActionStatus);
 	structReport.appendUint32(housekeepingStructure->second.collectionInterval);
 	structReport.appendUint16(housekeepingStructure->second.simplyCommutatedParameterIds.size());
 
-	for (auto parameterId : housekeepingStructure->second.simplyCommutatedParameterIds) {
+	for (auto parameterId: housekeepingStructure->second.simplyCommutatedParameterIds) {
 		structReport.appendUint16(parameterId);
 	}
 	storeMessage(structReport);
 }
 
 void HousekeepingService::housekeepingParametersReport(uint8_t structureId) {
-	if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) {
-		ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::NonExistentHousekeeping);
+	if (hasNonExistingStructInternalError(structureId)) {
 		return;
 	}
-	Message housekeepingReport(ServiceType, MessageType::HousekeepingParametersReport, Message::TM, 1);
+
+	auto& housekeepingStructure = getStruct(structureId)->get();
+
+	Message housekeepingReport = createTM(MessageType::HousekeepingParametersReport);
 
 	housekeepingReport.appendUint8(structureId);
-	for (auto id : housekeepingStructures.at(structureId).simplyCommutatedParameterIds) {
+	for (auto id: housekeepingStructure.simplyCommutatedParameterIds) {
 		if (auto parameter = Services.parameterManagement.getParameter(id)) {
 			parameter->get().appendValueToMessage(housekeepingReport);
 		}
@@ -128,38 +131,38 @@ void HousekeepingService::housekeepingParametersReport(uint8_t structureId) {
 }
 
 void HousekeepingService::generateOneShotHousekeepingReport(Message& request) {
-	request.assertTC(ServiceType, MessageType::GenerateOneShotHousekeepingReport);
+	if (!request.assertTC(ServiceType, MessageType::GenerateOneShotHousekeepingReport)) {
+		return;
+	}
 
 	uint8_t numOfStructsToReport = request.readUint8();
 	for (uint8_t i = 0; i < numOfStructsToReport; i++) {
 		uint8_t structureId = request.readUint8();
-		if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+		if (hasNonExistingStructExecutionError(structureId, request)) {
 			continue;
 		}
+
 		housekeepingParametersReport(structureId);
 	}
 }
 
 void HousekeepingService::appendParametersToHousekeepingStructure(Message& request) {
-	request.assertTC(ServiceType, MessageType::AppendParametersToHousekeepingStructure);
+	if (!request.assertTC(ServiceType, MessageType::AppendParametersToHousekeepingStructure)) {
+		return;
+	}
 
 	uint8_t targetStructId = request.readUint8();
-	if (housekeepingStructures.find(targetStructId) == housekeepingStructures.end()) {
-		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+	if (hasNonExistingStructExecutionError(targetStructId, request)) {
 		return;
 	}
-	auto& housekeepingStructure = housekeepingStructures.at(targetStructId);
-	if (housekeepingStructure.periodicGenerationActionStatus) {
-		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedAppendToEnabledHousekeeping);
+	auto& housekeepingStructure = getStruct(targetStructId)->get();
+	if (hasRequestedAppendToEnabledHousekeepingError(housekeepingStructure, request)) {
 		return;
 	}
 	uint16_t numOfSimplyCommutatedParameters = request.readUint16();
 
 	for (uint16_t i = 0; i < numOfSimplyCommutatedParameters; i++) {
-		if (housekeepingStructure.simplyCommutatedParameterIds.size() >= ECSSMaxSimplyCommutatedParameters) {
-			ErrorHandler::reportError(
-			    request, ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters);
+		if (hasExceededMaxNumOfSimplyCommutatedParamsError(housekeepingStructure, request)) {
 			return;
 		}
 		uint16_t newParamId = request.readUint16();
@@ -167,8 +170,7 @@ void HousekeepingService::appendParametersToHousekeepingStructure(Message& reque
 			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::GetNonExistingParameter);
 			continue;
 		}
-		if (existsInVector(housekeepingStructure.simplyCommutatedParameterIds, newParamId)) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter);
+		if (hasAlreadyExistingParameterError(housekeepingStructure, newParamId, request)) {
 			continue;
 		}
 		housekeepingStructure.simplyCommutatedParameterIds.push_back(newParamId);
@@ -176,40 +178,42 @@ void HousekeepingService::appendParametersToHousekeepingStructure(Message& reque
 }
 
 void HousekeepingService::modifyCollectionIntervalOfStructures(Message& request) {
-	request.assertTC(ServiceType, MessageType::ModifyCollectionIntervalOfStructures);
+	if (!request.assertTC(ServiceType, MessageType::ModifyCollectionIntervalOfStructures)) {
+		return;
+	}
 
 	uint8_t numOfTargetStructs = request.readUint8();
 	for (uint8_t i = 0; i < numOfTargetStructs; i++) {
 		uint8_t targetStructId = request.readUint8();
 		uint32_t newCollectionInterval = request.readUint32();
-		if (housekeepingStructures.find(targetStructId) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+		if (hasNonExistingStructExecutionError(targetStructId, request)) {
 			continue;
 		}
-		housekeepingStructures.at(targetStructId).collectionInterval = newCollectionInterval;
+		setCollectionInterval(targetStructId, newCollectionInterval);
 	}
 }
 
 void HousekeepingService::reportHousekeepingPeriodicProperties(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportHousekeepingPeriodicProperties);
+	if (!request.assertTC(ServiceType, MessageType::ReportHousekeepingPeriodicProperties)) {
+		return;
+	}
 
 	uint8_t numOfValidIds = 0;
 	uint8_t numOfStructIds = request.readUint8();
 	for (uint8_t i = 0; i < numOfStructIds; i++) {
 		uint8_t structIdToReport = request.readUint8();
-		if (housekeepingStructures.find(structIdToReport) != housekeepingStructures.end()) {
+		if (structExists(structIdToReport)) {
 			numOfValidIds++;
 		}
 	}
-	Message periodicPropertiesReport(ServiceType, MessageType::HousekeepingPeriodicPropertiesReport, Message::TM, 1);
+	Message periodicPropertiesReport = createTM(MessageType::HousekeepingPeriodicPropertiesReport);
 	periodicPropertiesReport.appendUint8(numOfValidIds);
 	request.resetRead();
 	request.readUint8();
 
 	for (uint8_t i = 0; i < numOfStructIds; i++) {
 		uint8_t structIdToReport = request.readUint8();
-		if (housekeepingStructures.find(structIdToReport) == housekeepingStructures.end()) {
-			ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+		if (hasNonExistingStructExecutionError(structIdToReport, request)) {
 			continue;
 		}
 		appendPeriodicPropertiesToMessage(periodicPropertiesReport, structIdToReport);
@@ -219,8 +223,8 @@ void HousekeepingService::reportHousekeepingPeriodicProperties(Message& request)
 
 void HousekeepingService::appendPeriodicPropertiesToMessage(Message& report, uint8_t structureId) {
 	report.appendUint8(structureId);
-	report.appendBoolean(housekeepingStructures.at(structureId).periodicGenerationActionStatus);
-	report.appendUint32(housekeepingStructures.at(structureId).collectionInterval);
+	report.appendBoolean(getPeriodicGenerationActionStatus(structureId));
+	report.appendUint32(getCollectionInterval(structureId));
 }
 
 void HousekeepingService::execute(Message& message) {
@@ -262,25 +266,99 @@ bool HousekeepingService::existsInVector(const etl::vector<uint16_t, ECSSMaxSimp
 
 uint32_t
 HousekeepingService::reportPendingStructures(uint32_t currentTime, uint32_t previousTime, uint32_t expectedDelay) {
-    uint32_t nextCollection = std::numeric_limits<uint32_t>::max();
-
-    for (auto &housekeepingStructure: housekeepingStructures) {
-        if (housekeepingStructure.second.collectionInterval == 0) {
-            housekeepingParametersReport(housekeepingStructure.second.structureId);
-            nextCollection = 0;
-            continue;
-        }
-        if (currentTime != 0 and (currentTime % housekeepingStructure.second.collectionInterval == 0 or
-                                  (previousTime + expectedDelay) % housekeepingStructure.second.collectionInterval ==
-                                  0)) {
-            housekeepingParametersReport(housekeepingStructure.second.structureId);
-        }
-        uint32_t structureTimeToCollection = housekeepingStructure.second.collectionInterval -
-                                             currentTime % housekeepingStructure.second.collectionInterval;
-        if (nextCollection > structureTimeToCollection) {
-            nextCollection = structureTimeToCollection;
-        }
-    }
-
-    return nextCollection;
+	uint32_t nextCollection = std::numeric_limits<uint32_t>::max();
+
+	for (auto& housekeepingStructure: housekeepingStructures) {
+		if (!housekeepingStructure.second.periodicGenerationActionStatus) {
+			continue;
+		}
+		if (housekeepingStructure.second.collectionInterval == 0) {
+			housekeepingParametersReport(housekeepingStructure.second.structureId);
+			nextCollection = 0;
+			continue;
+		}
+		if (currentTime != 0 and (currentTime % housekeepingStructure.second.collectionInterval == 0 or
+		                          (previousTime + expectedDelay) % housekeepingStructure.second.collectionInterval ==
+		                              0)) {
+			housekeepingParametersReport(housekeepingStructure.second.structureId);
+		}
+		uint32_t structureTimeToCollection = housekeepingStructure.second.collectionInterval -
+		                                     currentTime % housekeepingStructure.second.collectionInterval;
+		if (nextCollection > structureTimeToCollection) {
+			nextCollection = structureTimeToCollection;
+		}
+	}
+
+	return nextCollection;
+}
+
+bool HousekeepingService::hasNonExistingStructExecutionError(uint8_t id, Message& req) {
+	if (!structExists(id)) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure);
+		return true;
+	}
+	return false;
+}
+
+bool HousekeepingService::hasNonExistingStructError(uint8_t id, Message& req) {
+	if (!structExists(id)) {
+		ErrorHandler::reportError(req, ErrorHandler::RequestedNonExistingStructure);
+		return true;
+	}
+	return false;
+}
+
+bool HousekeepingService::hasNonExistingStructInternalError(uint8_t id) {
+	if (!structExists(id)) {
+		ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::NonExistentHousekeeping);
+		return true;
+	}
+	return false;
+}
+bool HousekeepingService::hasAlreadyExistingParameterError(HousekeepingStructure& housekeepingStruct, uint8_t id, Message& req) {
+	if (existsInVector(housekeepingStruct.simplyCommutatedParameterIds, id)) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter);
+		return true;
+	}
+	return false;
 }
+
+bool HousekeepingService::hasAlreadyExistingStructError(uint8_t id, Message& req) {
+	if (structExists(id)) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedAlreadyExistingStructure);
+		return true;
+	}
+	return false;
+}
+
+bool HousekeepingService::hasExceededMaxNumOfHousekeepingStructsError(Message& req) {
+	if (housekeepingStructures.size() >= ECSSMaxHousekeepingStructures) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfHousekeepingStructures);
+		return true;
+	}
+	return false;
+}
+
+bool HousekeepingService::hasRequestedAppendToEnabledHousekeepingError(HousekeepingStructure& housekeepingStruct, Message& req) {
+	if (housekeepingStruct.periodicGenerationActionStatus) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedAppendToEnabledHousekeeping);
+		return true;
+	}
+	return false;
+}
+
+bool HousekeepingService::hasRequestedDeletionOfEnabledHousekeepingError(uint8_t id, Message& req) {
+	if (getPeriodicGenerationActionStatus(id)) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedDeletionOfEnabledHousekeeping);
+		return true;
+	}
+	return false;
+}
+
+bool HousekeepingService::hasExceededMaxNumOfSimplyCommutatedParamsError(HousekeepingStructure& housekeepingStruct, Message& req) {
+	if (housekeepingStruct.simplyCommutatedParameterIds.size() >= ECSSMaxSimplyCommutatedParameters) {
+		ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters);
+		return true;
+	}
+	return false;
+}
\ No newline at end of file
diff --git a/src/Services/LargePacketTransferService.cpp b/src/Services/LargePacketTransferService.cpp
index 03bebbcd4d9df1b8df3b39d6552bcfb174420a80..b96c03aed3d886f475a08d27daeb90839f5a7975 100644
--- a/src/Services/LargePacketTransferService.cpp
+++ b/src/Services/LargePacketTransferService.cpp
@@ -2,58 +2,52 @@
 #ifdef SERVICE_LARGEPACKET
 
 #include <Services/LargePacketTransferService.hpp>
-#include "Message.hpp"
 #include <etl/String.hpp>
+#include "Message.hpp"
 
 void LargePacketTransferService::firstDownlinkPartReport(uint16_t largeMessageTransactionIdentifier,
                                                          uint16_t partSequenceNumber,
                                                          const String<ECSSMaxFixedOctetStringSize>& string) {
-	// TM[13,1]
-
 	Message report = createTM(LargePacketTransferService::MessageType::FirstDownlinkPartReport);
 	report.appendUint16(largeMessageTransactionIdentifier); // large message transaction identifier
-	report.appendUint16(partSequenceNumber); // part sequence number
-	report.appendOctetString(string); // fixed octet-string
+	report.appendUint16(partSequenceNumber);                // part sequence number
+	report.appendOctetString(string);                       // fixed octet-string
 	storeMessage(report);
 }
 
 void LargePacketTransferService::intermediateDownlinkPartReport(
     uint16_t largeMessageTransactionIdentifier, uint16_t partSequenceNumber,
     const String<ECSSMaxFixedOctetStringSize>& string) {
-	// TM[13,2]
+
 	Message report = createTM(LargePacketTransferService::MessageType::InternalDownlinkPartReport);
 	report.appendUint16(largeMessageTransactionIdentifier); // large message transaction identifier
-	report.appendUint16(partSequenceNumber); // part sequence number
-	report.appendOctetString(string); // fixed octet-string
+	report.appendUint16(partSequenceNumber);                // part sequence number
+	report.appendOctetString(string);                       // fixed octet-string
 	storeMessage(report);
 }
 
 void LargePacketTransferService::lastDownlinkPartReport(uint16_t largeMessageTransactionIdentifier,
                                                         uint16_t partSequenceNumber,
                                                         const String<ECSSMaxFixedOctetStringSize>& string) {
-	// TM[13,3]
 	Message report = createTM(LargePacketTransferService::MessageType::LastDownlinkPartReport);
 	report.appendUint16(largeMessageTransactionIdentifier); // large message transaction identifier
-	report.appendUint16(partSequenceNumber); // part sequence number
-	report.appendOctetString(string); // fixed octet-string
+	report.appendUint16(partSequenceNumber);                // part sequence number
+	report.appendOctetString(string);                       // fixed octet-string
 	storeMessage(report);
 }
 
 String<ECSSMaxFixedOctetStringSize>
 LargePacketTransferService::firstUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string) {
-	// TC[13,9]
 	return string;
 }
 
 String<ECSSMaxFixedOctetStringSize>
 LargePacketTransferService::intermediateUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string) {
-	// TC[13,10]
 	return string;
 }
 
 String<ECSSMaxFixedOctetStringSize>
 LargePacketTransferService::lastUplinkPart(const String<ECSSMaxFixedOctetStringSize>& string) {
-	// TC[13, 11]
 	return string;
 }
 
@@ -61,19 +55,19 @@ void LargePacketTransferService::split(Message& message, uint16_t largeMessageTr
 	//TODO: Should this be uint32?
 	uint16_t size = message.dataSize;
 	uint16_t positionCounter = 0;
-	uint16_t parts = (size/ECSSMaxFixedOctetStringSize) + 1;
+	uint16_t parts = (size / ECSSMaxFixedOctetStringSize) + 1;
 	String<ECSSMaxFixedOctetStringSize> stringPart("");
 	uint8_t dataPart[ECSSMaxFixedOctetStringSize];
 
-	for (uint16_t i = 0; i < ECSSMaxFixedOctetStringSize; i++){
+	for (uint16_t i = 0; i < ECSSMaxFixedOctetStringSize; i++) {
 		dataPart[i] = message.data[positionCounter];
 		positionCounter++;
 	}
 	stringPart = dataPart;
 	firstDownlinkPartReport(largeMessageTransactionIdentifier, 0, stringPart);
 
-	for (uint16_t part = 1; part < (parts - 1U); part++){
-		for (uint16_t i = 0; i < ECSSMaxFixedOctetStringSize; i++){
+	for (uint16_t part = 1; part < (parts - 1U); part++) {
+		for (uint16_t i = 0; i < ECSSMaxFixedOctetStringSize; i++) {
 			dataPart[i] = message.data[positionCounter];
 			positionCounter++;
 		}
@@ -81,8 +75,8 @@ void LargePacketTransferService::split(Message& message, uint16_t largeMessageTr
 		intermediateDownlinkPartReport(largeMessageTransactionIdentifier, part, stringPart);
 	}
 
-	for (uint16_t i = 0; i < ECSSMaxFixedOctetStringSize; i++){
-		if (message.dataSize == positionCounter){
+	for (uint16_t i = 0; i < ECSSMaxFixedOctetStringSize; i++) {
+		if (message.dataSize == positionCounter) {
 			dataPart[i] = 0; // To prevent from filling the rest of the String with garbage info
 		}
 		dataPart[i] = message.data[positionCounter];
diff --git a/src/Services/MemoryManagementService.cpp b/src/Services/MemoryManagementService.cpp
index db821cbfb7a531045774856682d0ef72576179d6..fba8b0e0315d3f6d5c4219c70a63ea956abe0c05 100644
--- a/src/Services/MemoryManagementService.cpp
+++ b/src/Services/MemoryManagementService.cpp
@@ -1,11 +1,10 @@
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_MEMORY
 
-#include "Services/MemoryManagementService.hpp"
 #include <cerrno>
 #include <etl/String.hpp>
+#include "Services/MemoryManagementService.hpp"
 
-// Define the constructors for the classes
 MemoryManagementService::MemoryManagementService() : rawDataMemorySubservice(*this) {
 	serviceType = MemoryManagementService::ServiceType;
 }
@@ -13,8 +12,7 @@ MemoryManagementService::MemoryManagementService() : rawDataMemorySubservice(*th
 MemoryManagementService::RawDataMemoryManagement::RawDataMemoryManagement(MemoryManagementService& parent)
     : mainService(parent) {}
 
-// Function declarations for the raw data memory management subservice
-void MemoryManagementService::RawDataMemoryManagement::loadRawData(Message& request) {
+void MemoryManagementService::loadRawData(Message& request) {
 	/**
 	 * Bear in mind that there is currently no error checking for invalid parameters.
 	 * A future version will include error checking and the corresponding error report/notification,
@@ -23,149 +21,131 @@ void MemoryManagementService::RawDataMemoryManagement::loadRawData(Message& requ
 	 * @todo Add error checking and reporting for the parameters
 	 * @todo Add failure reporting
 	 */
-	// Check if we have the correct packet
 	request.assertTC(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::LoadRawMemoryDataAreas);
-
-	// Read the memory ID from the request
 	auto memoryID = MemoryManagementService::MemoryID(request.readEnum8());
 
-	// Check for a valid memory ID first
-	if (mainService.memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) {
-		// Variable declaration
-		uint8_t readData[ECSSMaxStringSize]; // Preallocate the array
-		uint16_t iterationCount = request.readUint16(); // Get the iteration count
-
-		if (memoryID == MemoryManagementService::MemoryID::FLASH) {
-			// todo: Define FLASH specific access code when we transfer to embedded
-		} else {
-			for (std::size_t j = 0; j < iterationCount; j++) {
-				uint64_t startAddress = request.readUint64(); // Start address of the memory
-				uint16_t dataLength = request.readOctetString(readData); // Data length to load
-				uint16_t checksum = request.readBits(16); // Get the CRC checksum from the message
-
-				// Continue only if the checksum passes
-				if (mainService.dataValidator(readData, checksum, dataLength)) {
-					if (mainService.addressValidator(memoryID, startAddress) &&
-					    mainService.addressValidator(memoryID, startAddress + dataLength)) {
-						for (std::size_t i = 0; i < dataLength; i++) {
-							*(reinterpret_cast<uint8_t*>(startAddress) + i) = readData[i];
-						}
-
-						// Read the loaded data for checksum validation and perform a check
-						for (std::size_t i = 0; i < dataLength; i++) {
-							readData[i] = *(reinterpret_cast<uint8_t*>(startAddress) + i);
-						}
-						if (checksum != CRCHelper::calculateCRC(readData, dataLength)) {
-							ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed);
-						}
-					} else {
-						ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed);
-					}
-				} else {
-					ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed);
-					continue; // Continue to the next command
-				}
+	if (!memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) {
+		// TODO: Send a failed start of execution
+		return;
+	}
+
+	uint8_t readData[ECSSMaxStringSize];
+	uint16_t iterationCount = request.readUint16();
+
+	if (memoryID == MemoryManagementService::MemoryID::FLASH_MEMORY) {
+		// TODO: Define FLASH specific access code when we transfer to embedded
+	} else {
+		for (std::size_t j = 0; j < iterationCount; j++) {
+			uint64_t startAddress = request.readUint64();
+			uint16_t dataLength = request.readOctetString(readData);
+			uint16_t checksum = request.readBits(16);
+
+			if (!dataValidator(readData, checksum, dataLength)) {
+				ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed);
+				continue;
+			}
+
+			if (!addressValidator(memoryID, startAddress) ||
+			    !addressValidator(memoryID, startAddress + dataLength)) {
+				ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed);
+				continue;
+			}
+
+			for (std::size_t i = 0; i < dataLength; i++) {
+				*(reinterpret_cast<uint8_t*>(startAddress) + i) = readData[i];
+			}
+
+			for (std::size_t i = 0; i < dataLength; i++) {
+				readData[i] = *(reinterpret_cast<uint8_t*>(startAddress) + i);
+			}
+
+			if (checksum != CRCHelper::calculateCRC(readData, dataLength)) {
+				ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed);
 			}
 		}
-	} else {
-		// todo: Send a failed start of execution
 	}
 }
 
 void MemoryManagementService::RawDataMemoryManagement::dumpRawData(Message& request) {
-	// Check if we have the correct packet
-	request.assertTC(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::DumpRawMemoryData);
+	if (!request.assertTC(ServiceType, MessageType::DumpRawMemoryData)) {
+		return;
+	}
 
-	// Create the report message object of telemetry message subtype 6
 	Message report = mainService.createTM(MemoryManagementService::MessageType::DumpRawMemoryDataReport);
-	uint8_t memoryID = request.readEnum8(); // Read the memory ID from the request
+	uint8_t memoryID = request.readEnum8();
 
-	// Check for a valid memory ID first
-	if (mainService.memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) {
-		// Variable declaration
-		uint8_t readData[ECSSMaxStringSize]; // Preallocate the array
-		uint16_t iterationCount = request.readUint16(); // Get the iteration count
+	if (memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) {
+		uint8_t readData[ECSSMaxStringSize];
+		uint16_t iterationCount = request.readUint16();
 
-		// Append the data to report message
-		report.appendEnum8(memoryID); // Memory ID
-		report.appendUint16(iterationCount); // Iteration count
+		report.appendEnum8(memoryID);
+		report.appendUint16(iterationCount);
 
-		// Iterate N times, as specified in the command message
 		for (std::size_t j = 0; j < iterationCount; j++) {
-			uint64_t startAddress = request.readUint64(); // Data length to read
-			uint16_t readLength = request.readUint16(); // Start address for the memory read
+			uint64_t startAddress = request.readUint64();
+			uint16_t readLength = request.readUint16();
 
-			// Read memory data, an octet at a time, checking for a valid address first
-			if (mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress) &&
-			    mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress + readLength)) {
+			if (addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress) &&
+			    addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress + readLength)) {
 				for (std::size_t i = 0; i < readLength; i++) {
 					readData[i] = *(reinterpret_cast<uint8_t*>(startAddress) + i);
 				}
 
-				// This part is repeated N-times (N = iteration count)
-				report.appendUint64(startAddress); // Start address
-				report.appendOctetString(String<1024>(readData, readLength)); // Save the
-				// read data
+				report.appendUint64(startAddress);
+				report.appendOctetString(String<1024>(readData, readLength));
 				report.appendBits(16, CRCHelper::calculateCRC(readData, readLength));
 			} else {
 				ErrorHandler::reportError(request, ErrorHandler::AddressOutOfRange);
 			}
 		}
 
-		mainService.storeMessage(report); // Save the report message
-		request.resetRead(); // Reset the reading count
+		mainService.storeMessage(report);
+		request.resetRead();
 	} else {
-		// todo: Send a failed start of execution
+		// TODO: Send a failed start of execution
 	}
 }
 
 void MemoryManagementService::RawDataMemoryManagement::checkRawData(Message& request) {
-	// Check if we have the correct packet
-	request.assertTC(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::CheckRawMemoryData);
+	if (!request.assertTC(ServiceType, MessageType::CheckRawMemoryData)) {
+		return;
+	}
 
-	// Create the report message object of telemetry message subtype 10
 	Message report = mainService.createTM(MemoryManagementService::MessageType::CheckRawMemoryDataReport);
-	uint8_t memoryID = request.readEnum8(); // Read the memory ID from the request
+	uint8_t memoryID = request.readEnum8();
 
-	if (mainService.memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) {
-		// Variable declaration
-		uint8_t readData[ECSSMaxStringSize]; // Preallocate the array
-		uint16_t iterationCount = request.readUint16(); // Get the iteration count
+	if (memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) {
+		uint8_t readData[ECSSMaxStringSize];
+		uint16_t iterationCount = request.readUint16();
 
-		// Append the data to report message
-		report.appendEnum8(memoryID); // Memory ID
-		report.appendUint16(iterationCount); // Iteration count
+		report.appendEnum8(memoryID);
+		report.appendUint16(iterationCount);
 
-		// Iterate N times, as specified in the command message
 		for (std::size_t j = 0; j < iterationCount; j++) {
-			uint64_t startAddress = request.readUint64(); // Data length to read
-			uint16_t readLength = request.readUint16(); // Start address for the memory read
+			uint64_t startAddress = request.readUint64();
+			uint16_t readLength = request.readUint16();
 
-			// Check whether the first and the last addresses are within the limits
-			if (mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress) &&
-			    mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress + readLength)) {
-				// Read memory data and save them for checksum calculation
+			if (addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress) &&
+			    addressValidator(MemoryManagementService::MemoryID(memoryID), startAddress + readLength)) {
 				for (std::size_t i = 0; i < readLength; i++) {
 					readData[i] = *(reinterpret_cast<uint8_t*>(startAddress) + i);
 				}
 
-				// This part is repeated N-times (N = iteration count)
-				report.appendUint64(startAddress); // Start address
-				report.appendUint16(readLength); // Save the read data
-				report.appendBits(16, CRCHelper::calculateCRC(readData, readLength)); // Append CRC
+				report.appendUint64(startAddress);
+				report.appendUint16(readLength);
+				report.appendBits(16, CRCHelper::calculateCRC(readData, readLength));
 			} else {
 				ErrorHandler::reportError(request, ErrorHandler::AddressOutOfRange);
 			}
 		}
 
-		mainService.storeMessage(report); // Save the report message
-		request.resetRead(); // Reset the reading count
+		mainService.storeMessage(report);
+		request.resetRead();
 	} else {
-		// todo: Send a failed start of execution report
+		// TODO: Send a failed start of execution report
 	}
 }
 
-// Private function declaration section
 bool MemoryManagementService::addressValidator(MemoryManagementService::MemoryID memId, uint64_t address) {
 	bool validIndicator = false;
 
@@ -195,14 +175,14 @@ bool MemoryManagementService::addressValidator(MemoryManagementService::MemoryID
 				validIndicator = true;
 			}
 			break;
-		case MemoryManagementService::MemoryID::FLASH:
+		case MemoryManagementService::MemoryID::FLASH_MEMORY:
 			if ((address >= FlashLowerLim) && (address <= FlashUpperLim)) {
 				validIndicator = true;
 			}
 			break;
 
 		default:
-			validIndicator = true; // todo: Implemented so addresses from PC can be read. Remove.
+			validIndicator = true; // TODO: Implemented so addresses from PC can be read. Remove.
 			break;
 	}
 
@@ -215,7 +195,7 @@ inline bool MemoryManagementService::memoryIdValidator(MemoryManagementService::
 	       (memId == MemoryManagementService::MemoryID::RAM_D3) ||
 	       (memId == MemoryManagementService::MemoryID::DTCMRAM) ||
 	       (memId == MemoryManagementService::MemoryID::ITCMRAM) ||
-	       (memId == MemoryManagementService::MemoryID::FLASH) ||
+	       (memId == MemoryManagementService::MemoryID::FLASH_MEMORY) ||
 	       (memId == MemoryManagementService::MemoryID::EXTERNAL);
 }
 
@@ -226,7 +206,7 @@ inline bool MemoryManagementService::dataValidator(const uint8_t* data, uint16_t
 void MemoryManagementService::execute(Message& message) {
 	switch (message.messageType) {
 		case LoadRawMemoryDataAreas:
-			rawDataMemorySubservice.loadRawData(message);
+			loadRawData(message);
 			break;
 		case DumpRawMemoryData:
 			rawDataMemorySubservice.dumpRawData(message);
diff --git a/src/Services/OnBoardMonitoringService.cpp b/src/Services/OnBoardMonitoringService.cpp
index f644546db72bc8f8bfc59ec14352064893258cb1..06bbefd252acb63ff82d6af5d5f76160b5137f92 100644
--- a/src/Services/OnBoardMonitoringService.cpp
+++ b/src/Services/OnBoardMonitoringService.cpp
@@ -5,7 +5,9 @@
 #include "etl/map.h"
 
 void OnBoardMonitoringService::enableParameterMonitoringDefinitions(Message& message) {
-	message.assertTC(ServiceType, EnableParameterMonitoringDefinitions);
+	if (!message.assertTC(ServiceType, EnableParameterMonitoringDefinitions)) {
+		return;
+	}
 
 	uint16_t numberOfPMONDefinitions = message.readUint16();
 	for (uint16_t i = 0; i < numberOfPMONDefinitions; i++) {
@@ -22,7 +24,9 @@ void OnBoardMonitoringService::enableParameterMonitoringDefinitions(Message& mes
 }
 
 void OnBoardMonitoringService::disableParameterMonitoringDefinitions(Message& message) {
-	message.assertTC(ServiceType, DisableParameterMonitoringDefinitions);
+	if (!message.assertTC(ServiceType, DisableParameterMonitoringDefinitions)) {
+		return;
+	}
 
 	uint16_t numberOfPMONDefinitions = message.readUint16();
 	for (uint16_t i = 0; i < numberOfPMONDefinitions; i++) {
@@ -39,12 +43,16 @@ void OnBoardMonitoringService::disableParameterMonitoringDefinitions(Message& me
 }
 
 void OnBoardMonitoringService::changeMaximumTransitionReportingDelay(Message& message) {
-	message.assertTC(ServiceType, ChangeMaximumTransitionReportingDelay);
+	if (!message.assertTC(ServiceType, ChangeMaximumTransitionReportingDelay)) {
+		return;
+	}
 	maximumTransitionReportingDelay = message.readUint16();
 }
 
 void OnBoardMonitoringService::deleteAllParameterMonitoringDefinitions(Message& message) {
-	message.assertTC(ServiceType, DeleteAllParameterMonitoringDefinitions);
+	if (!message.assertTC(ServiceType, DeleteAllParameterMonitoringDefinitions)) {
+		return;
+	}
 	if (parameterMonitoringFunctionStatus) {
 		ErrorHandler::reportError(
 		    message, ErrorHandler::ExecutionStartErrorType::InvalidRequestToDeleteAllParameterMonitoringDefinitions);
diff --git a/src/Services/ParameterService.cpp b/src/Services/ParameterService.cpp
index 417debf669c2e5d6bad761917138a21850e57611..60ebd04c1c9e66647eb2e4a617a1a68e50839945 100644
--- a/src/Services/ParameterService.cpp
+++ b/src/Services/ParameterService.cpp
@@ -1,21 +1,16 @@
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_PARAMETER
 
-#include "Services/ParameterService.hpp"
 #include "Helpers/Parameter.hpp"
+#include "Services/ParameterService.hpp"
 
 
 void ParameterService::reportParameters(Message& paramIds) {
-	// TM[20,2]
-	Message parameterReport(ParameterService::ServiceType, ParameterService::MessageType::ParameterValuesReport,
-	                        Message::TM, 1);
 
-	ErrorHandler::assertRequest(paramIds.packetType == Message::TC, paramIds,
-	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
-	ErrorHandler::assertRequest(paramIds.messageType == ParameterService::MessageType::ReportParameterValues, paramIds,
-	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
-	ErrorHandler::assertRequest(paramIds.serviceType == ParameterService::ServiceType, paramIds,
-	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
+	if (!paramIds.assertTC(ServiceType, ReportParameterValues)) {
+		return;
+	}
+	Message parameterReport = createTM(ParameterValuesReport);
 
 	uint16_t numOfIds = paramIds.readUint16();
 	uint16_t numberOfValidIds = 0;
@@ -30,35 +25,33 @@ void ParameterService::reportParameters(Message& paramIds) {
 	numOfIds = paramIds.readUint16();
 	for (uint16_t i = 0; i < numOfIds; i++) {
 		uint16_t currId = paramIds.readUint16();
-		if (auto parameter = getParameter(currId)) {
-			parameterReport.appendUint16(currId);
-			parameter->get().appendValueToMessage(parameterReport);
-		} else {
+		auto parameter = getParameter(currId);
+		if (!parameter) {
 			ErrorHandler::reportError(paramIds, ErrorHandler::GetNonExistingParameter);
+			continue;
 		}
+		parameterReport.appendUint16(currId);
+		parameter->get().appendValueToMessage(parameterReport);
 	}
 
 	storeMessage(parameterReport);
 }
 
-void ParameterService::setParameters(Message& newParamValues) {
-	ErrorHandler::assertRequest(newParamValues.packetType == Message::TC, newParamValues,
-	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
-	ErrorHandler::assertRequest(newParamValues.messageType == ParameterService::MessageType::SetParameterValues,
-	                            newParamValues, ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
-	ErrorHandler::assertRequest(newParamValues.serviceType == ParameterService::ServiceType, newParamValues,
-	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
+void ParameterService::setParameters(Message& newParamValues) const {
+	if (!newParamValues.assertTC(ServiceType, MessageType::SetParameterValues)) {
+		return;
+	}
 
 	uint16_t numOfIds = newParamValues.readUint16();
 
 	for (uint16_t i = 0; i < numOfIds; i++) {
 		uint16_t currId = newParamValues.readUint16();
-		if (auto parameter = getParameter(currId)) {
-			parameter->get().setValueFromMessage(newParamValues);
-		} else {
+		auto parameter = getParameter(currId);
+		if (!parameter) {
 			ErrorHandler::reportError(newParamValues, ErrorHandler::SetNonExistingParameter);
 			break; // Setting next parameters is impossible, since the size of value to be read is unknown
 		}
+		parameter->get().setValueFromMessage(newParamValues);
 	}
 }
 
diff --git a/src/Services/ParameterStatisticsService.cpp b/src/Services/ParameterStatisticsService.cpp
index 432be671a3356fcf071d53f632aa2ad5b582cf9e..6bcfc9b489bc5195bec737dfbbd86fc413d2b42a 100644
--- a/src/Services/ParameterStatisticsService.cpp
+++ b/src/Services/ParameterStatisticsService.cpp
@@ -1,32 +1,40 @@
-#include <iostream>
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_PARAMETER
-#include "Services/ParameterStatisticsService.hpp"
 #include "ServicePool.hpp"
+#include "Services/ParameterStatisticsService.hpp"
+
+ParameterStatisticsService::ParameterStatisticsService() : evaluationStartTime(TimeGetter::getCurrentTimeDefaultCUC()) {
+	initializeStatisticsMap();
+	serviceType = ServiceType;
+}
 
 void ParameterStatisticsService::reportParameterStatistics(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportParameterStatistics);
+	if (!request.assertTC(ServiceType, MessageType::ReportParameterStatistics)) {
+		return;
+	}
 	parameterStatisticsReport();
 
-	// TODO: append start time and end time to the report
+	if (hasAutomaticStatisticsReset or request.readBoolean()) {
+		resetParameterStatistics();
+	}
+}
+
+void ParameterStatisticsService::reportParameterStatistics(bool reset) {
+	parameterStatisticsReport();
 
-	if (hasAutomaticStatisticsReset) {
+	if (hasAutomaticStatisticsReset or reset) {
 		resetParameterStatistics();
-	} else {
-		bool resetFlagValue = request.readBoolean();
-		if (resetFlagValue) {
-			resetParameterStatistics();
-		}
 	}
 }
 
 void ParameterStatisticsService::parameterStatisticsReport() {
-	Message report(ServiceType, MessageType::ParameterStatisticsReport, Message::TM, 1);
-	report.appendUint16(1); // Dummy value for start and end time, will change in the end
-	report.appendUint16(1);
-	uint16_t numOfValidParameters = 0;
+	Message report = createTM(ParameterStatisticsReport);
+	report.append(evaluationStartTime);
+	auto evaluationStopTime = TimeGetter::getCurrentTimeDefaultCUC();
+	report.append(evaluationStopTime);
 
-	for (auto& currentStatistic : statisticsMap) {
+	uint16_t numOfValidParameters = 0;
+	for (auto& currentStatistic: statisticsMap) {
 		uint16_t numOfSamples = currentStatistic.second.sampleCounter;
 		if (numOfSamples == 0) {
 			continue;
@@ -35,7 +43,7 @@ void ParameterStatisticsService::parameterStatisticsReport() {
 	}
 	report.appendUint16(numOfValidParameters);
 
-	for (auto& currentStatistic : statisticsMap) {
+	for (auto& currentStatistic: statisticsMap) {
 		uint16_t currentId = currentStatistic.first;
 		uint16_t numOfSamples = currentStatistic.second.sampleCounter;
 		if (numOfSamples == 0) {
@@ -49,16 +57,17 @@ void ParameterStatisticsService::parameterStatisticsReport() {
 }
 
 void ParameterStatisticsService::resetParameterStatistics(Message& request) {
-	request.assertTC(ServiceType, MessageType::ResetParameterStatistics);
+	if (!request.assertTC(ServiceType, MessageType::ResetParameterStatistics)) {
+		return;
+	}
 	resetParameterStatistics();
 }
 
 void ParameterStatisticsService::resetParameterStatistics() {
-	// TODO: Stop the evaluation of parameter statistics
-	for (auto& it : statisticsMap) {
+	for (auto& it: statisticsMap) {
 		it.second.resetStatistics();
 	}
-	// TODO: Restart the evaluation of parameter statistics
+	evaluationStartTime = TimeGetter::getCurrentTimeDefaultCUC();
 }
 
 void ParameterStatisticsService::enablePeriodicStatisticsReporting(Message& request) {
@@ -68,7 +77,9 @@ void ParameterStatisticsService::enablePeriodicStatisticsReporting(Message& requ
 	 */
 	uint16_t SAMPLING_PARAMETER_INTERVAL = 5;
 
-	request.assertTC(ServiceType, MessageType::EnablePeriodicParameterReporting);
+	if (!request.assertTC(ServiceType, MessageType::EnablePeriodicParameterReporting)) {
+		return;
+	}
 
 	uint16_t timeInterval = request.readUint16();
 	if (timeInterval < SAMPLING_PARAMETER_INTERVAL) {
@@ -76,18 +87,22 @@ void ParameterStatisticsService::enablePeriodicStatisticsReporting(Message& requ
 		return;
 	}
 	periodicStatisticsReportingStatus = true;
-	reportingInterval = timeInterval;
+	reportingIntervalMs = timeInterval;
 }
 
 void ParameterStatisticsService::disablePeriodicStatisticsReporting(Message& request) {
-	request.assertTC(ServiceType, MessageType::DisablePeriodicParameterReporting);
+	if (!request.assertTC(ServiceType, MessageType::DisablePeriodicParameterReporting)) {
+		return;
+	}
 
 	periodicStatisticsReportingStatus = false;
-	reportingInterval = 0;
+	reportingIntervalMs = 0;
 }
 
 void ParameterStatisticsService::addOrUpdateStatisticsDefinitions(Message& request) {
-	request.assertTC(ServiceType, MessageType::AddOrUpdateParameterStatisticsDefinitions);
+	if (!request.assertTC(ServiceType, MessageType::AddOrUpdateParameterStatisticsDefinitions)) {
+		return;
+	}
 
 	uint16_t numOfIds = request.readUint16();
 	for (uint16_t i = 0; i < numOfIds; i++) {
@@ -103,7 +118,7 @@ void ParameterStatisticsService::addOrUpdateStatisticsDefinitions(Message& reque
 		uint16_t interval = 0;
 		if (supportsSamplingInterval) {
 			interval = request.readUint16();
-			if (interval < reportingInterval) {
+			if (interval < reportingIntervalMs) {
 				ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::InvalidSamplingRateError);
 				continue;
 			}
@@ -130,7 +145,9 @@ void ParameterStatisticsService::addOrUpdateStatisticsDefinitions(Message& reque
 }
 
 void ParameterStatisticsService::deleteStatisticsDefinitions(Message& request) {
-	request.assertTC(ServiceType, MessageType::DeleteParameterStatisticsDefinitions);
+	if (!request.assertTC(ServiceType, MessageType::DeleteParameterStatisticsDefinitions)) {
+		return;
+	}
 
 	uint16_t numOfIds = request.readUint16();
 	if (numOfIds == 0) {
@@ -152,21 +169,23 @@ void ParameterStatisticsService::deleteStatisticsDefinitions(Message& request) {
 }
 
 void ParameterStatisticsService::reportStatisticsDefinitions(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportParameterStatisticsDefinitions);
+	if (!request.assertTC(ServiceType, MessageType::ReportParameterStatisticsDefinitions)) {
+		return;
+	}
 	statisticsDefinitionsReport();
 }
 
 void ParameterStatisticsService::statisticsDefinitionsReport() {
-	Message definitionsReport(ServiceType, MessageType::ParameterStatisticsDefinitionsReport, Message::TM, 1);
+	Message definitionsReport = createTM(ParameterStatisticsDefinitionsReport);
 
-	uint16_t currentReportingInterval = 0;
+	uint16_t currentReportingIntervalMs = 0;
 	if (periodicStatisticsReportingStatus) {
-		currentReportingInterval = reportingInterval;
+		currentReportingIntervalMs = reportingIntervalMs;
 	}
-	definitionsReport.appendUint16(currentReportingInterval);
+	definitionsReport.appendUint16(currentReportingIntervalMs);
 	definitionsReport.appendUint16(statisticsMap.size());
 
-	for (auto& currentParam : statisticsMap) {
+	for (auto& currentParam: statisticsMap) {
 		uint16_t currentId = currentParam.first;
 		uint16_t samplingInterval = currentParam.second.selfSamplingInterval;
 		definitionsReport.appendUint16(currentId);
diff --git a/src/Services/RealTimeForwardingControlService.cpp b/src/Services/RealTimeForwardingControlService.cpp
index 2ca94a03289880696d9663881d71ae22a43fa067..a23d4990969b6a9ce7905469f4d7d40677497ca0 100644
--- a/src/Services/RealTimeForwardingControlService.cpp
+++ b/src/Services/RealTimeForwardingControlService.cpp
@@ -2,14 +2,14 @@
 #include <iostream>
 
 void RealTimeForwardingControlService::addAllReportsOfApplication(uint8_t applicationID) {
-	for (auto& service: AllMessageTypes::messagesOfService) {
+	for (const auto& service: AllMessageTypes::MessagesOfService) {
 		uint8_t serviceType = service.first;
 		addAllReportsOfService(applicationID, serviceType);
 	}
 }
 
 void RealTimeForwardingControlService::addAllReportsOfService(uint8_t applicationID, uint8_t serviceType) {
-	for (auto& messageType: AllMessageTypes::messagesOfService[serviceType]) {
+	for (const auto& messageType: AllMessageTypes::MessagesOfService.at(serviceType)) {
 		auto appServicePair = std::make_pair(applicationID, serviceType);
 		applicationProcessConfiguration.definitions[appServicePair].push_back(messageType);
 	}
@@ -18,7 +18,7 @@ void RealTimeForwardingControlService::addAllReportsOfService(uint8_t applicatio
 uint8_t RealTimeForwardingControlService::countServicesOfApplication(uint8_t applicationID) {
 	uint8_t serviceCounter = 0;
 	for (auto& definition: applicationProcessConfiguration.definitions) {
-		auto& pair = definition.first;
+		const auto& pair = definition.first;
 		if (pair.first == applicationID) {
 			serviceCounter++;
 		}
@@ -79,7 +79,7 @@ bool RealTimeForwardingControlService::checkService(Message& request, uint8_t ap
 
 bool RealTimeForwardingControlService::maxReportTypesReached(Message& request, uint8_t applicationID,
                                                              uint8_t serviceType) {
-	if (countReportsOfService(applicationID, serviceType) >= AllMessageTypes::messagesOfService[serviceType].size()) {
+	if (countReportsOfService(applicationID, serviceType) >= AllMessageTypes::MessagesOfService.at(serviceType).size()) {
 		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached);
 		return true;
 	}
@@ -88,11 +88,8 @@ bool RealTimeForwardingControlService::maxReportTypesReached(Message& request, u
 
 bool RealTimeForwardingControlService::checkMessage(Message& request, uint8_t applicationID, uint8_t serviceType,
                                                     uint8_t messageType) {
-	if (maxReportTypesReached(request, applicationID, serviceType) or
-	    reportExistsInAppProcessConfiguration(applicationID, serviceType, messageType)) {
-		return false;
-	}
-	return true;
+	return !maxReportTypesReached(request, applicationID, serviceType) and
+	       !reportExistsInAppProcessConfiguration(applicationID, serviceType, messageType);
 }
 
 bool RealTimeForwardingControlService::reportExistsInAppProcessConfiguration(uint8_t applicationID, uint8_t serviceType,
@@ -103,7 +100,9 @@ bool RealTimeForwardingControlService::reportExistsInAppProcessConfiguration(uin
 }
 
 void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(Message& request) {
-	request.assertTC(ServiceType, MessageType::AddReportTypesToAppProcessConfiguration);
+	if (!request.assertTC(ServiceType, MessageType::AddReportTypesToAppProcessConfiguration)) {
+		return;
+	}
 	uint8_t numOfApplications = request.readUint8();
 
 	for (uint8_t i = 0; i < numOfApplications; i++) {
diff --git a/src/Services/RequestVerificationService.cpp b/src/Services/RequestVerificationService.cpp
index 33546c778b51a0d57832080b7acc3a4e86e6832f..42b0ab05393ad17563d100804c32198c3095b1c8 100644
--- a/src/Services/RequestVerificationService.cpp
+++ b/src/Services/RequestVerificationService.cpp
@@ -8,11 +8,11 @@ void RequestVerificationService::successAcceptanceVerification(const Message& re
 
 	Message report = createTM(RequestVerificationService::MessageType::SuccessfulAcceptanceReport);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
 
 	storeMessage(report);
@@ -24,13 +24,13 @@ void RequestVerificationService::failAcceptanceVerification(const Message& reque
 
 	Message report = createTM(RequestVerificationService::MessageType::FailedAcceptanceReport);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
-	report.appendEnum16(errorCode); // error code
+	report.appendEnum16(errorCode);                     // error code
 
 	storeMessage(report);
 }
@@ -40,11 +40,11 @@ void RequestVerificationService::successStartExecutionVerification(const Message
 
 	Message report = createTM(RequestVerificationService::MessageType::SuccessfulStartOfExecution);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
 
 	storeMessage(report);
@@ -56,13 +56,13 @@ void RequestVerificationService::failStartExecutionVerification(const Message& r
 
 	Message report = createTM(RequestVerificationService::MessageType::FailedStartOfExecution);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
-	report.appendEnum16(errorCode); // error code
+	report.appendEnum16(errorCode);                     // error code
 
 	storeMessage(report);
 }
@@ -72,13 +72,13 @@ void RequestVerificationService::successProgressExecutionVerification(const Mess
 
 	Message report = createTM(RequestVerificationService::MessageType::SuccessfulProgressOfExecution);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
-	report.appendByte(stepID); // step ID
+	report.appendByte(stepID);                          // step ID
 
 	storeMessage(report);
 }
@@ -90,14 +90,14 @@ void RequestVerificationService::failProgressExecutionVerification(const Message
 
 	Message report = createTM(RequestVerificationService::MessageType::FailedProgressOfExecution);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
-	report.appendByte(stepID); // step ID
-	report.appendEnum16(errorCode); // error code
+	report.appendByte(stepID);                          // step ID
+	report.appendEnum16(errorCode);                     // error code
 
 	storeMessage(report);
 }
@@ -107,11 +107,11 @@ void RequestVerificationService::successCompletionExecutionVerification(const Me
 
 	Message report = createTM(RequestVerificationService::MessageType::SuccessfulCompletionOfExecution);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
 
 	storeMessage(report);
@@ -123,13 +123,13 @@ void RequestVerificationService::failCompletionExecutionVerification(
 
 	Message report = createTM(RequestVerificationService::MessageType::FailedCompletionOfExecution);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
-	report.appendEnum16(errorCode); // error code
+	report.appendEnum16(errorCode);                     // error code
 
 	storeMessage(report);
 }
@@ -140,13 +140,13 @@ void RequestVerificationService::failRoutingVerification(const Message& request,
 
 	Message report = createTM(RequestVerificationService::MessageType::FailedRoutingReport);
 
-	report.appendEnumerated(3, CCSDSPacketVersion); // packet version number
-	report.appendEnumerated(1, request.packetType); // packet type
-	report.appendBits(1, 1); // secondary header flag
+	report.appendEnumerated(3, CCSDSPacketVersion);     // packet version number
+	report.appendEnumerated(1, request.packetType);     // packet type
+	report.appendBits(1, 1);                            // secondary header flag
 	report.appendEnumerated(11, request.applicationId); // application process ID
-	report.appendEnumerated(2, ECSSSequenceFlags); // sequence flags
+	report.appendEnumerated(2, ECSSSequenceFlags);      // sequence flags
 	report.appendBits(14, request.packetSequenceCount); // packet sequence count
-	report.appendEnum16(errorCode); // error code
+	report.appendEnum16(errorCode);                     // error code
 
 	storeMessage(report);
 }
diff --git a/src/Services/StorageAndRetrievalService.cpp b/src/Services/StorageAndRetrievalService.cpp
index 23f06f48b380f5359ed367787e32a95a057ab27c..2b9e1d8cfdc6cef4c585cd5f9e6198aa273e929f 100644
--- a/src/Services/StorageAndRetrievalService.cpp
+++ b/src/Services/StorageAndRetrievalService.cpp
@@ -25,7 +25,7 @@ void StorageAndRetrievalService::copyFromTagToTag(Message& request) {
 		return;
 	}
 
-	for (auto& packet : packetStores[fromPacketStoreId].storedTelemetryPackets) {
+	for (auto& packet: packetStores[fromPacketStoreId].storedTelemetryPackets) {
 		if (packet.first < startTime) {
 			continue;
 		}
@@ -46,7 +46,7 @@ void StorageAndRetrievalService::copyAfterTimeTag(Message& request) {
 		return;
 	}
 
-	for (auto& packet : packetStores[fromPacketStoreId].storedTelemetryPackets) {
+	for (auto& packet: packetStores[fromPacketStoreId].storedTelemetryPackets) {
 		if (packet.first < startTime) {
 			continue;
 		}
@@ -64,7 +64,7 @@ void StorageAndRetrievalService::copyBeforeTimeTag(Message& request) {
 		return;
 	}
 
-	for (auto& packet : packetStores[fromPacketStoreId].storedTelemetryPackets) {
+	for (auto& packet: packetStores[fromPacketStoreId].storedTelemetryPackets) {
 		if (packet.first > endTime) {
 			break;
 		}
@@ -159,7 +159,7 @@ void StorageAndRetrievalService::createContentSummary(Message& report,
 
 	report.appendUint32(packetStores[packetStoreId].openRetrievalStartTimeTag);
 
-	auto filledPercentage1 = static_cast<uint16_t>(packetStores[packetStoreId].storedTelemetryPackets.size() * 100.0f /
+	auto filledPercentage1 = static_cast<uint16_t>(static_cast<float>(packetStores[packetStoreId].storedTelemetryPackets.size()) * 100 /
 	                                               ECSSMaxPacketStoreSize);
 	report.appendUint16(filledPercentage1);
 
@@ -169,7 +169,7 @@ void StorageAndRetrievalService::createContentSummary(Message& report,
 	    std::end(packetStores[packetStoreId].storedTelemetryPackets), [this, &packetStoreId](auto packet) {
 		    return packet.first >= packetStores[packetStoreId].openRetrievalStartTimeTag;
 	    });
-	auto filledPercentage2 = static_cast<uint16_t>(numOfPacketsToBeTransferred * 100.0f / ECSSMaxPacketStoreSize);
+	auto filledPercentage2 = static_cast<uint16_t>(static_cast<float>(numOfPacketsToBeTransferred) * 100 / ECSSMaxPacketStoreSize);
 	report.appendUint16(filledPercentage2);
 }
 
@@ -217,9 +217,7 @@ uint16_t StorageAndRetrievalService::currentNumberOfPacketStores() {
 
 PacketStore& StorageAndRetrievalService::getPacketStore(const String<ECSSPacketStoreIdSize>& packetStoreId) {
 	auto packetStore = packetStores.find(packetStoreId);
-	if (packetStore == packetStores.end()) {
-		assert(ErrorHandler::ExecutionStartErrorType::NonExistingPacketStore);
-	}
+	ASSERT_INTERNAL(packetStore != packetStores.end(), ErrorHandler::InternalErrorType::ElementNotInArray);
 	return packetStore->second;
 }
 
@@ -231,7 +229,7 @@ void StorageAndRetrievalService::executeOnPacketStores(Message& request,
                                                        const std::function<void(PacketStore&)>& function) {
 	uint16_t numOfPacketStores = request.readUint16();
 	if (numOfPacketStores == 0) {
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			function(packetStore.second);
 		}
 		return;
@@ -249,19 +247,25 @@ void StorageAndRetrievalService::executeOnPacketStores(Message& request,
 }
 
 void StorageAndRetrievalService::enableStorageFunction(Message& request) {
-	request.assertTC(ServiceType, MessageType::EnableStorageInPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::EnableStorageInPacketStores)) {
+		return;
+	}
 
 	executeOnPacketStores(request, [](PacketStore& p) { p.storageStatus = true; });
 }
 
 void StorageAndRetrievalService::disableStorageFunction(Message& request) {
-	request.assertTC(ServiceType, MessageType::DisableStorageInPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::DisableStorageInPacketStores)) {
+		return;
+	}
 
 	executeOnPacketStores(request, [](PacketStore& p) { p.storageStatus = false; });
 }
 
 void StorageAndRetrievalService::startByTimeRangeRetrieval(Message& request) {
-	request.assertTC(ServiceType, MessageType::StartByTimeRangeRetrieval);
+	if (!request.assertTC(ServiceType, MessageType::StartByTimeRangeRetrieval)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	bool errorFlag = false;
@@ -290,13 +294,15 @@ void StorageAndRetrievalService::startByTimeRangeRetrieval(Message& request) {
 }
 
 void StorageAndRetrievalService::deletePacketStoreContent(Message& request) {
-	request.assertTC(ServiceType, MessageType::DeletePacketStoreContent);
+	if (!request.assertTC(ServiceType, MessageType::DeletePacketStoreContent)) {
+		return;
+	}
 
 	uint32_t timeLimit = request.readUint32(); // todo: decide the time-format
 	uint16_t numOfPacketStores = request.readUint16();
 
 	if (numOfPacketStores == 0) {
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			if (packetStore.second.byTimeRangeRetrievalStatus) {
 				ErrorHandler::reportError(
 				    request, ErrorHandler::ExecutionStartErrorType::SetPacketStoreWithByTimeRangeRetrieval);
@@ -332,14 +338,16 @@ void StorageAndRetrievalService::deletePacketStoreContent(Message& request) {
 }
 
 void StorageAndRetrievalService::packetStoreContentSummaryReport(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportContentSummaryOfPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::ReportContentSummaryOfPacketStores)) {
+		return;
+	}
 
-	Message report(ServiceType, MessageType::PacketStoreContentSummaryReport, Message::TM, 1);
+	Message report = createTM(PacketStoreContentSummaryReport);
 	uint16_t numOfPacketStores = request.readUint16();
 
 	if (numOfPacketStores == 0) {
 		report.appendUint16(packetStores.size());
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			auto packetStoreId = packetStore.first;
 			report.appendString(packetStoreId);
 			createContentSummary(report, packetStoreId);
@@ -371,7 +379,9 @@ void StorageAndRetrievalService::packetStoreContentSummaryReport(Message& reques
 }
 
 void StorageAndRetrievalService::changeOpenRetrievalStartTimeTag(Message& request) {
-	request.assertTC(ServiceType, MessageType::ChangeOpenRetrievalStartingTime);
+	if (!request.assertTC(ServiceType, MessageType::ChangeOpenRetrievalStartingTime)) {
+		return;
+	}
 
 	uint32_t newStartTimeTag = request.readUint32();
 	/**
@@ -379,7 +389,7 @@ void StorageAndRetrievalService::changeOpenRetrievalStartTimeTag(Message& reques
 	 */
 	uint16_t numOfPacketStores = request.readUint16();
 	if (numOfPacketStores == 0) {
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			if (packetStore.second.openRetrievalStatus == PacketStore::InProgress) {
 				ErrorHandler::reportError(
 				    request, ErrorHandler::ExecutionStartErrorType::SetPacketStoreWithOpenRetrievalInProgress);
@@ -406,11 +416,13 @@ void StorageAndRetrievalService::changeOpenRetrievalStartTimeTag(Message& reques
 }
 
 void StorageAndRetrievalService::resumeOpenRetrievalOfPacketStores(Message& request) {
-	request.assertTC(ServiceType, MessageType::ResumeOpenRetrievalOfPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::ResumeOpenRetrievalOfPacketStores)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	if (numOfPacketStores == 0) {
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			if (packetStore.second.byTimeRangeRetrievalStatus) {
 				ErrorHandler::reportError(
 				    request, ErrorHandler::ExecutionStartErrorType::SetPacketStoreWithByTimeRangeRetrieval);
@@ -437,11 +449,13 @@ void StorageAndRetrievalService::resumeOpenRetrievalOfPacketStores(Message& requ
 }
 
 void StorageAndRetrievalService::suspendOpenRetrievalOfPacketStores(Message& request) {
-	request.assertTC(ServiceType, MessageType::SuspendOpenRetrievalOfPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::SuspendOpenRetrievalOfPacketStores)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	if (numOfPacketStores == 0) {
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			packetStore.second.openRetrievalStatus = PacketStore::Suspended;
 		}
 		return;
@@ -457,11 +471,13 @@ void StorageAndRetrievalService::suspendOpenRetrievalOfPacketStores(Message& req
 }
 
 void StorageAndRetrievalService::abortByTimeRangeRetrieval(Message& request) {
-	request.assertTC(ServiceType, MessageType::AbortByTimeRangeRetrieval);
+	if (!request.assertTC(ServiceType, MessageType::AbortByTimeRangeRetrieval)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	if (numOfPacketStores == 0) {
-		for (auto& packetStore : packetStores) {
+		for (auto& packetStore: packetStores) {
 			packetStore.second.byTimeRangeRetrievalStatus = false;
 		}
 		return;
@@ -477,11 +493,13 @@ void StorageAndRetrievalService::abortByTimeRangeRetrieval(Message& request) {
 }
 
 void StorageAndRetrievalService::packetStoresStatusReport(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportStatusOfPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::ReportStatusOfPacketStores)) {
+		return;
+	}
 
-	Message report(ServiceType, MessageType::PacketStoresStatusReport, Message::TM, 1);
+	Message report = createTM(PacketStoresStatusReport);
 	report.appendUint16(packetStores.size());
-	for (auto& packetStore : packetStores) {
+	for (auto& packetStore: packetStores) {
 		auto packetStoreId = packetStore.first;
 		report.appendString(packetStoreId);
 		report.appendBoolean(packetStore.second.storageStatus);
@@ -492,7 +510,9 @@ void StorageAndRetrievalService::packetStoresStatusReport(Message& request) {
 }
 
 void StorageAndRetrievalService::createPacketStores(Message& request) {
-	request.assertTC(ServiceType, MessageType::CreatePacketStores);
+	if (!request.assertTC(ServiceType, MessageType::CreatePacketStores)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	for (uint16_t i = 0; i < numOfPacketStores; i++) {
@@ -529,13 +549,15 @@ void StorageAndRetrievalService::createPacketStores(Message& request) {
 }
 
 void StorageAndRetrievalService::deletePacketStores(Message& request) {
-	request.assertTC(ServiceType, MessageType::DeletePacketStores);
+	if (!request.assertTC(ServiceType, MessageType::DeletePacketStores)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	if (numOfPacketStores == 0) {
-		int numOfPacketStoresToDelete = 0;
-		etl::string<ECSSPacketStoreIdSize> packetStoresToDelete[packetStores.size()];
-		for (auto& packetStore : packetStores) {
+		uint16_t numOfPacketStoresToDelete = 0;
+		etl::string<ECSSPacketStoreIdSize> packetStoresToDelete[ECSSMaxPacketStores];
+		for (auto& packetStore: packetStores) {
 			if (packetStore.second.storageStatus) {
 				ErrorHandler::reportError(
 				    request, ErrorHandler::ExecutionStartErrorType::DeletionOfPacketStoreWithStorageStatusEnabled);
@@ -592,11 +614,13 @@ void StorageAndRetrievalService::deletePacketStores(Message& request) {
 }
 
 void StorageAndRetrievalService::packetStoreConfigurationReport(Message& request) {
-	request.assertTC(ServiceType, MessageType::ReportConfigurationOfPacketStores);
+	if (!request.assertTC(ServiceType, MessageType::ReportConfigurationOfPacketStores)) {
+		return;
+	}
+	Message report = createTM(PacketStoreConfigurationReport);
 
-	Message report(ServiceType, MessageType::PacketStoreConfigurationReport, Message::TM, 1);
 	report.appendUint16(packetStores.size());
-	for (auto& packetStore : packetStores) {
+	for (auto& packetStore: packetStores) {
 		auto packetStoreId = packetStore.first;
 		report.appendString(packetStoreId);
 		report.appendUint16(packetStore.second.sizeInBytes);
@@ -608,7 +632,9 @@ void StorageAndRetrievalService::packetStoreConfigurationReport(Message& request
 }
 
 void StorageAndRetrievalService::copyPacketsInTimeWindow(Message& request) {
-	request.assertTC(ServiceType, MessageType::CopyPacketsInTimeWindow);
+	if (!request.assertTC(ServiceType, MessageType::CopyPacketsInTimeWindow)) {
+		return;
+	}
 
 	uint8_t typeOfTimeWindow = request.readEnum8();
 	switch (typeOfTimeWindow) {
@@ -628,7 +654,9 @@ void StorageAndRetrievalService::copyPacketsInTimeWindow(Message& request) {
 }
 
 void StorageAndRetrievalService::resizePacketStores(Message& request) {
-	request.assertTC(ServiceType, MessageType::ResizePacketStores);
+	if (!request.assertTC(ServiceType, MessageType::ResizePacketStores)) {
+		return;
+	}
 
 	uint16_t numOfPacketStores = request.readUint16();
 	for (uint16_t i = 0; i < numOfPacketStores; i++) {
@@ -664,7 +692,9 @@ void StorageAndRetrievalService::resizePacketStores(Message& request) {
 }
 
 void StorageAndRetrievalService::changeTypeToCircular(Message& request) {
-	request.assertTC(ServiceType, MessageType::ChangeTypeToCircular);
+	if (!request.assertTC(ServiceType, MessageType::ChangeTypeToCircular)) {
+		return;
+	}
 
 	auto idToChange = readPacketStoreId(request);
 	if (packetStores.find(idToChange) == packetStores.end()) {
@@ -692,7 +722,9 @@ void StorageAndRetrievalService::changeTypeToCircular(Message& request) {
 }
 
 void StorageAndRetrievalService::changeTypeToBounded(Message& request) {
-	request.assertTC(ServiceType, MessageType::ChangeTypeToBounded);
+	if (!request.assertTC(ServiceType, MessageType::ChangeTypeToBounded)) {
+		return;
+	}
 
 	auto idToChange = readPacketStoreId(request);
 	if (packetStores.find(idToChange) == packetStores.end()) {
@@ -720,7 +752,9 @@ void StorageAndRetrievalService::changeTypeToBounded(Message& request) {
 }
 
 void StorageAndRetrievalService::changeVirtualChannel(Message& request) {
-	request.assertTC(ServiceType, MessageType::ChangeVirtualChannel);
+	if (!request.assertTC(ServiceType, MessageType::ChangeVirtualChannel)) {
+		return;
+	}
 
 	auto idToChange = readPacketStoreId(request);
 	uint8_t virtualChannel = request.readUint8();
diff --git a/src/Services/TestService.cpp b/src/Services/TestService.cpp
index 93c1ebeed096ba0197428622e4417985925a0a66..e6dbc7e3fac8c9482dd2d1784e9eecfed7becf99 100644
--- a/src/Services/TestService.cpp
+++ b/src/Services/TestService.cpp
@@ -1,23 +1,32 @@
 #include "ECSS_Configuration.hpp"
 #ifdef SERVICE_TEST
 
+#include "ServicePool.hpp"
 #include "Services/TestService.hpp"
 
 void TestService::areYouAlive(Message& request) {
-	request.assertTC(TestService::ServiceType, TestService::MessageType::AreYouAliveTest);
-	// TM[17,2] are-you-alive connection test report
-	Message report = createTM(TestService::MessageType::AreYouAliveTestReport);
+	if (!request.assertTC(TestService::ServiceType, TestService::MessageType::AreYouAliveTest)) {
+		return;
+	}
+	areYouAliveReport();
+}
 
+void TestService::areYouAliveReport() {
+	Message report = createTM(TestService::MessageType::AreYouAliveTestReport);
 	storeMessage(report);
 }
 
 void TestService::onBoardConnection(Message& request) {
-	request.assertTC(TestService::ServiceType, TestService::MessageType::OnBoardConnectionTest);
-	// TM[17,4] on-board connection test report
-	Message report = createTM(TestService::MessageType::OnBoardConnectionTestReport);
+	if (!request.assertTC(TestService::ServiceType, TestService::MessageType::OnBoardConnectionTest)) {
+		return;
+	}
+	uint16_t applicationProcessId = request.readUint16();
+	onBoardConnectionReport(applicationProcessId);
+}
 
-	report.appendUint16(request.readUint16());
-	// just print it on the screen
+void TestService::onBoardConnectionReport(uint16_t applicationProcessId) {
+	Message report = createTM(TestService::MessageType::OnBoardConnectionTestReport);
+	report.appendUint16(applicationProcessId);
 	storeMessage(report);
 }
 
diff --git a/src/Services/TimeBasedSchedulingService.cpp b/src/Services/TimeBasedSchedulingService.cpp
index b88f46a48db0c5d1aa5ba79cc15d95bd54005451..f5d2efc29226aac7d038fbefddb72aa738a9d064 100644
--- a/src/Services/TimeBasedSchedulingService.cpp
+++ b/src/Services/TimeBasedSchedulingService.cpp
@@ -7,55 +7,65 @@ TimeBasedSchedulingService::TimeBasedSchedulingService() {
 	serviceType = TimeBasedSchedulingService::ServiceType;
 }
 
-void TimeBasedSchedulingService::enableScheduleExecution(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::EnableTimeBasedScheduleExecutionFunction);
+Time::DefaultCUC TimeBasedSchedulingService::executeScheduledActivity(Time::DefaultCUC currentTime) {
+	if (currentTime >= scheduledActivities.front().requestReleaseTime && !scheduledActivities.empty()) {
+		if (scheduledActivities.front().requestID.applicationID == ApplicationId) {
+			MessageParser::execute(scheduledActivities.front().request);
+		}
+		scheduledActivities.pop_front();
+	}
+
+	if (!scheduledActivities.empty()) {
+		return scheduledActivities.front().requestReleaseTime;
+	} else {
+		return Time::DefaultCUC::max();
+	}
+}
 
-	executionFunctionStatus = true; // Enable the service
+void TimeBasedSchedulingService::enableScheduleExecution(Message& request) {
+	if (!request.assertTC(ServiceType, MessageType::EnableTimeBasedScheduleExecutionFunction)) {
+		return;
+	}
+	executionFunctionStatus = true;
 }
 
 void TimeBasedSchedulingService::disableScheduleExecution(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::DisableTimeBasedScheduleExecutionFunction);
-
-	executionFunctionStatus = false; // Disable the service
+	if (!request.assertTC(ServiceType, MessageType::DisableTimeBasedScheduleExecutionFunction)) {
+		return;
+	}
+	executionFunctionStatus = false;
 }
 
 void TimeBasedSchedulingService::resetSchedule(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::ResetTimeBasedSchedule);
-
-	executionFunctionStatus = false; // Disable the service
-	scheduledActivities.clear(); // Delete all scheduled activities
+	if (!request.assertTC(ServiceType, MessageType::ResetTimeBasedSchedule)) {
+		return;
+	}
+	executionFunctionStatus = false;
+	scheduledActivities.clear();
 	// todo: Add resetting for sub-schedules and groups, if defined
 }
 
 void TimeBasedSchedulingService::insertActivities(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::InsertActivities);
+	if (!request.assertTC(ServiceType, MessageType::InsertActivities)) {
+		return;
+	}
 
 	// todo: Get the sub-schedule ID if they are implemented
-	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	uint16_t iterationCount = request.readUint16();
 	while (iterationCount-- != 0) {
 		// todo: Get the group ID first, if groups are used
-		uint32_t currentTime = TimeGetter::getSeconds(); // Get the current system time
+		Time::DefaultCUC currentTime = TimeGetter::getCurrentTimeDefaultCUC();
 
-		uint32_t releaseTime = request.readUint32(); // Get the specified release time
+		Time::DefaultCUC releaseTime = request.readDefaultCUCTimeStamp();
 		if ((scheduledActivities.available() == 0) || (releaseTime < (currentTime + ECSSTimeMarginForActivation))) {
 			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 			request.skipBytes(ECSSTCRequestStringSize);
 		} else {
-			// Get the TC packet request
 			uint8_t requestData[ECSSTCRequestStringSize] = {0};
 			request.readString(requestData, ECSSTCRequestStringSize);
 			Message receivedTCPacket = MessageParser::parseECSSTC(requestData);
-			ScheduledActivity newActivity; // Create the new activity
+			ScheduledActivity newActivity;
 
-			// Assign the attributes to the newly created activity
 			newActivity.request = receivedTCPacket;
 			newActivity.requestReleaseTime = releaseTime;
 
@@ -63,95 +73,89 @@ void TimeBasedSchedulingService::insertActivities(Message& request) {
 			newActivity.requestID.applicationID = request.applicationId;
 			newActivity.requestID.sequenceCount = request.packetSequenceCount;
 
-			scheduledActivities.push_back(newActivity); // Insert the new activities
+			scheduledActivities.push_back(newActivity);
 		}
 	}
-	sortActivitiesReleaseTime(scheduledActivities); // Sort activities by their release time
+	sortActivitiesReleaseTime(scheduledActivities);
+	notifyNewActivityAddition();
 }
 
 void TimeBasedSchedulingService::timeShiftAllActivities(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::TimeShiftALlScheduledActivities);
+	if (!request.assertTC(ServiceType, MessageType::TimeShiftALlScheduledActivities)) {
+		return;
+	}
 
-	uint32_t current_time = TimeGetter::getSeconds(); // Get the current system time
+	Time::DefaultCUC current_time = TimeGetter::getCurrentTimeDefaultCUC();
 
-	// Find the earliest release time. It will be the first element of the iterator pair
 	const auto releaseTimes =
 	    etl::minmax_element(scheduledActivities.begin(), scheduledActivities.end(),
 	                        [](ScheduledActivity const& leftSide, ScheduledActivity const& rightSide) {
 		                        return leftSide.requestReleaseTime < rightSide.requestReleaseTime;
 	                        });
 	// todo: Define what the time format is going to be
-	int32_t relativeOffset = request.readSint32(); // Get the relative offset
-	if ((releaseTimes.first->requestReleaseTime + relativeOffset) < (current_time + ECSSTimeMarginForActivation)) {
-		// Report the error
+	Time::RelativeTime relativeOffset = request.readRelativeTime();
+	if ((releaseTimes.first->requestReleaseTime + std::chrono::seconds(relativeOffset)) < (current_time + ECSSTimeMarginForActivation)) {
 		ErrorHandler::reportError(request, ErrorHandler::SubServiceExecutionStartError);
-	} else {
-		for (auto& activity : scheduledActivities) {
-			activity.requestReleaseTime += relativeOffset; // Time shift each activity
-		}
+		return;
+	}
+	for (auto& activity: scheduledActivities) {
+		activity.requestReleaseTime += std::chrono::seconds(relativeOffset);
 	}
 }
 
 void TimeBasedSchedulingService::timeShiftActivitiesByID(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::TimeShiftActivitiesById);
+	if (!request.assertTC(ServiceType, MessageType::TimeShiftActivitiesById)) {
+		return;
+	}
 
-	uint32_t current_time = TimeGetter::getSeconds(); // Get the current system time
+	Time::DefaultCUC current_time = TimeGetter::getCurrentTimeDefaultCUC();
 
-	int32_t relativeOffset = request.readSint32(); // Get the offset first
-	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	auto relativeOffset = std::chrono::seconds(request.readRelativeTime());
+	uint16_t iterationCount = request.readUint16();
 	while (iterationCount-- != 0) {
-		// Parse the request ID
-		RequestID receivedRequestID; // Save the received request ID
-		receivedRequestID.sourceID = request.readUint8(); // Get the source ID
-		receivedRequestID.applicationID = request.readUint16(); // Get the application ID
-		receivedRequestID.sequenceCount = request.readUint16(); // Get the sequence count
+		RequestID receivedRequestID;
+		receivedRequestID.sourceID = request.readUint8();
+		receivedRequestID.applicationID = request.readUint16();
+		receivedRequestID.sequenceCount = request.readUint16();
 
-		// Try to find the activity with the requested request ID
 		auto requestIDMatch = etl::find_if_not(scheduledActivities.begin(), scheduledActivities.end(),
 		                                       [&receivedRequestID](ScheduledActivity const& currentElement) {
 			                                       return receivedRequestID != currentElement.requestID;
 		                                       });
 
 		if (requestIDMatch != scheduledActivities.end()) {
-			// If the relative offset does not meet the restrictions issue an error
 			if ((requestIDMatch->requestReleaseTime + relativeOffset) <
 			    (current_time + ECSSTimeMarginForActivation)) {
 				ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 			} else {
-				requestIDMatch->requestReleaseTime += relativeOffset; // Add the time offset
+				requestIDMatch->requestReleaseTime += relativeOffset;
 			}
 		} else {
 			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 		}
 	}
-	sortActivitiesReleaseTime(scheduledActivities); // Sort activities by their release time
+	sortActivitiesReleaseTime(scheduledActivities);
 }
 
 void TimeBasedSchedulingService::deleteActivitiesByID(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::DeleteActivitiesById);
+	if (!request.assertTC(ServiceType, MessageType::DeleteActivitiesById)) {
+		return;
+	}
 
-	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	uint16_t iterationCount = request.readUint16();
 	while (iterationCount-- != 0) {
-		// Parse the request ID
-		RequestID receivedRequestID; // Save the received request ID
-		receivedRequestID.sourceID = request.readUint8(); // Get the source ID
-		receivedRequestID.applicationID = request.readUint16(); // Get the application ID
-		receivedRequestID.sequenceCount = request.readUint16(); // Get the sequence count
+		RequestID receivedRequestID;
+		receivedRequestID.sourceID = request.readUint8();
+		receivedRequestID.applicationID = request.readUint16();
+		receivedRequestID.sequenceCount = request.readUint16();
 
-		// Try to find the activity with the requested request ID
 		const auto requestIDMatch = etl::find_if_not(scheduledActivities.begin(), scheduledActivities.end(),
 		                                             [&receivedRequestID](ScheduledActivity const& currentElement) {
 			                                             return receivedRequestID != currentElement.requestID;
 		                                             });
 
 		if (requestIDMatch != scheduledActivities.end()) {
-			scheduledActivities.erase(requestIDMatch); // Delete activity from the schedule
+			scheduledActivities.erase(requestIDMatch);
 		} else {
 			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 		}
@@ -159,82 +163,70 @@ void TimeBasedSchedulingService::deleteActivitiesByID(Message& request) {
 }
 
 void TimeBasedSchedulingService::detailReportAllActivities(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::DetailReportAllScheduledActivities);
+	if (!request.assertTC(ServiceType, MessageType::DetailReportAllScheduledActivities)) {
+		return;
+	}
 
-	// Create the report message object of telemetry message subtype 10 for each activity
-	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduleReportById);
-	report.appendUint16(static_cast<uint16_t>(scheduledActivities.size()));
+	timeBasedScheduleDetailReport(scheduledActivities);
+}
 
-	for (auto& activity : scheduledActivities) {
-		// todo: append sub-schedule and group ID if they are defined
+void TimeBasedSchedulingService::timeBasedScheduleDetailReport(const etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities>& listOfActivities) {
+	// todo: append sub-schedule and group ID if they are defined
+	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduleReportById);
+	report.appendUint16(static_cast<uint16_t>(listOfActivities.size()));
 
-		report.appendUint32(activity.requestReleaseTime);
+	for (const auto& activity: listOfActivities) {
+		report.appendDefaultCUCTimeStamp(activity.requestReleaseTime); // todo: Replace with the time parser
 		report.appendString(MessageParser::composeECSS(activity.request));
 	}
-	storeMessage(report); // Save the report
+	storeMessage(report);
 }
 
 void TimeBasedSchedulingService::detailReportActivitiesByID(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::DetailReportActivitiesById);
+	if (!request.assertTC(ServiceType, MessageType::DetailReportActivitiesById)) {
+		return;
+	}
 
-	// Create the report message object of telemetry message subtype 10 for each activity
-	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduleReportById);
 	etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities> matchedActivities;
 
-	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	uint16_t iterationCount = request.readUint16();
 	while (iterationCount-- != 0) {
-		// Parse the request ID
-		RequestID receivedRequestID; // Save the received request ID
-		receivedRequestID.sourceID = request.readUint8(); // Get the source ID
-		receivedRequestID.applicationID = request.readUint16(); // Get the application ID
-		receivedRequestID.sequenceCount = request.readUint16(); // Get the sequence count
+		RequestID receivedRequestID;
+		receivedRequestID.sourceID = request.readUint8();
+		receivedRequestID.applicationID = request.readUint16();
+		receivedRequestID.sequenceCount = request.readUint16();
 
-		// Try to find the activity with the requested request ID
 		const auto requestIDMatch = etl::find_if_not(scheduledActivities.begin(), scheduledActivities.end(),
 		                                             [&receivedRequestID](ScheduledActivity const& currentElement) {
 			                                             return receivedRequestID != currentElement.requestID;
 		                                             });
 
 		if (requestIDMatch != scheduledActivities.end()) {
-			matchedActivities.push_back(*requestIDMatch); // Save the matched activity
+			matchedActivities.push_back(*requestIDMatch);
 		} else {
 			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 		}
 	}
 
-	sortActivitiesReleaseTime(matchedActivities); // Sort activities by their release time
+	sortActivitiesReleaseTime(matchedActivities);
 
-	// todo: append sub-schedule and group ID if they are defined
-	report.appendUint16(static_cast<uint16_t>(matchedActivities.size()));
-	for (auto& match : matchedActivities) {
-		report.appendUint32(match.requestReleaseTime); // todo: Replace with the time parser
-		report.appendString(MessageParser::composeECSS(match.request));
-	}
-	storeMessage(report); // Save the report
+	timeBasedScheduleDetailReport(matchedActivities);
 }
 
 void TimeBasedSchedulingService::summaryReportActivitiesByID(Message& request) {
-	// Check if the correct packet is being processed
-	assert(request.serviceType == TimeBasedSchedulingService::ServiceType);
-	assert(request.messageType == TimeBasedSchedulingService::MessageType::ActivitiesSummaryReportById);
+	if (!request.assertTC(ServiceType, MessageType::ActivitiesSummaryReportById)) {
+		return;
+	}
 
-	// Create the report message object of telemetry message subtype 13 for each activity
-	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduledSummaryReport);
 	etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities> matchedActivities;
 
-	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	uint16_t iterationCount = request.readUint16();
 	while (iterationCount-- != 0) {
-		// Parse the request ID
-		RequestID receivedRequestID; // Save the received request ID
-		receivedRequestID.sourceID = request.readUint8(); // Get the source ID
-		receivedRequestID.applicationID = request.readUint16(); // Get the application ID
-		receivedRequestID.sequenceCount = request.readUint16(); // Get the sequence count
+		RequestID receivedRequestID;
+		receivedRequestID.sourceID = request.readUint8();
+		receivedRequestID.applicationID = request.readUint16();
+		receivedRequestID.sequenceCount = request.readUint16();
 
-		// Try to find the activity with the requested request ID
 		auto requestIDMatch = etl::find_if_not(scheduledActivities.begin(), scheduledActivities.end(),
 		                                       [&receivedRequestID](ScheduledActivity const& currentElement) {
 			                                       return receivedRequestID != currentElement.requestID;
@@ -246,18 +238,24 @@ void TimeBasedSchedulingService::summaryReportActivitiesByID(Message& request) {
 			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 		}
 	}
-	sortActivitiesReleaseTime(matchedActivities); // Sort activities by their release time
+	sortActivitiesReleaseTime(matchedActivities);
+
+	timeBasedScheduleSummaryReport(matchedActivities);
+}
+
+void TimeBasedSchedulingService::timeBasedScheduleSummaryReport(const etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities>& listOfActivities) {
+	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduledSummaryReport);
 
 	// todo: append sub-schedule and group ID if they are defined
-	report.appendUint16(static_cast<uint16_t>(matchedActivities.size()));
-	for (auto& match : matchedActivities) {
+	report.appendUint16(static_cast<uint16_t>(listOfActivities.size()));
+	for (const auto& match: listOfActivities) {
 		// todo: append sub-schedule and group ID if they are defined
-		report.appendUint32(match.requestReleaseTime);
+		report.appendDefaultCUCTimeStamp(match.requestReleaseTime);
 		report.appendUint8(match.requestID.sourceID);
 		report.appendUint16(match.requestID.applicationID);
 		report.appendUint16(match.requestID.sequenceCount);
 	}
-	storeMessage(report); // Save the report
+	storeMessage(report);
 }
 
 void TimeBasedSchedulingService::execute(Message& message) {
diff --git a/src/Time/UTCTimestamp.cpp b/src/Time/UTCTimestamp.cpp
index 072d6b67ff32e1db02d1a835a6ae61c3d43d9a1f..f534455f81b67ed19d8fa4bb4267a66324caa401 100644
--- a/src/Time/UTCTimestamp.cpp
+++ b/src/Time/UTCTimestamp.cpp
@@ -131,3 +131,33 @@ bool UTCTimestamp::operator<=(const UTCTimestamp& Date) const {
 bool UTCTimestamp::operator>=(const UTCTimestamp& Date) const {
 	return ((*this > Date) || (*this == Date));
 }
+void UTCTimestamp::repair() {
+	using namespace Time;
+
+	if (second > Time::SecondsPerMinute) {
+		second -= Time::SecondsPerMinute;
+		minute++;
+	}
+
+	const auto MinutesPerHour = SecondsPerHour / SecondsPerMinute;
+	if (minute >= MinutesPerHour) {
+		minute -= MinutesPerHour;
+		hour++;
+	}
+
+	const auto HoursPerDay = SecondsPerDay / SecondsPerHour;
+	if (hour >= HoursPerDay) {
+		hour -= HoursPerDay;
+		day++;
+	}
+
+	if (day > daysOfMonth()) {
+		day -= daysOfMonth();
+		month++;
+	}
+
+	if (month > MonthsPerYear) {
+		month -= MonthsPerYear;
+		year++;
+	}
+}
diff --git a/test/ErrorHandler.cpp b/test/ErrorHandlerTests.cpp
similarity index 99%
rename from test/ErrorHandler.cpp
rename to test/ErrorHandlerTests.cpp
index 2db17bf40a7f120fa9e8e6b86e8df02c3d815d04..b5924e1803e5af7119fb87877085a92390103bd9 100644
--- a/test/ErrorHandler.cpp
+++ b/test/ErrorHandlerTests.cpp
@@ -1,7 +1,7 @@
-#include <catch2/catch.hpp>
 #include <ErrorHandler.hpp>
-#include "Services/ServiceTests.hpp"
+#include <catch2/catch_all.hpp>
 #include "Services/RequestVerificationService.hpp"
+#include "Services/ServiceTests.hpp"
 
 TEST_CASE("Error: Failed Acceptance", "[errors]") {
 	Message failedMessage(38, 32, Message::TC, 47);
diff --git a/test/Helpers/CRCHelper.cpp b/test/Helpers/CRCHelperTests.cpp
similarity index 83%
rename from test/Helpers/CRCHelper.cpp
rename to test/Helpers/CRCHelperTests.cpp
index 5988eb3ee1be035397b87530493ef7d9e7b8526a..7d94c4f838bd26741a4556df41340f2e9b0289f4 100644
--- a/test/Helpers/CRCHelper.cpp
+++ b/test/Helpers/CRCHelperTests.cpp
@@ -1,11 +1,11 @@
-#include "catch2/catch.hpp"
 #include "Helpers/CRCHelper.hpp"
+#include "catch2/catch_all.hpp"
 
 TEST_CASE("CRC calculation - Basic String tests") {
-	CHECK(CRCHelper::calculateCRC((uint8_t*)"Raccoon Squad!", 14) == 0x08FC);
-	CHECK(CRCHelper::calculateCRC((uint8_t*)"ASAT", 4) == 0xBFFA);
-	CHECK(CRCHelper::calculateCRC((uint8_t*)"All your space are belong to us", 31) == 0x545F);
-	CHECK(CRCHelper::calculateCRC((uint8_t*)"SPAAAAAAAAACE!", 14) == 0xB441);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "Raccoon Squad!", 14) == 0x08FC);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "ASAT", 4) == 0xBFFA);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "All your space are belong to us", 31) == 0x545F);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "SPAAAAAAAAACE!", 14) == 0xB441);
 }
 
 TEST_CASE("CRC calculation - Basic byte tests") {
diff --git a/test/Helpers/PacketStore.cpp b/test/Helpers/PacketStoreTests.cpp
similarity index 96%
rename from test/Helpers/PacketStore.cpp
rename to test/Helpers/PacketStoreTests.cpp
index 072303a5b3d8a4c5e92316eb3a446b9ff6e5eb21..ea50e7ed93db25c9ba3b2821975780a80cf8edab 100644
--- a/test/Helpers/PacketStore.cpp
+++ b/test/Helpers/PacketStoreTests.cpp
@@ -1,5 +1,5 @@
 #include "Helpers/PacketStore.hpp"
-#include "catch2/catch.hpp"
+#include "catch2/catch_all.hpp"
 
 TEST_CASE("Counting a packet store's size in bytes") {
 	SECTION("Correct counting of size in bytes") {
diff --git a/test/Helpers/PlatformParameters.cpp b/test/Helpers/PlatformParameters.cpp
index adccb72716c9eb5979d953c3f97a1ba63858335b..833254a181d9b51481cd59923aba9cc2d12b41d1 100644
--- a/test/Helpers/PlatformParameters.cpp
+++ b/test/Helpers/PlatformParameters.cpp
@@ -1,7 +1,7 @@
 #include "Platform/x86/Parameters/PlatformParameters.hpp"
-#include "catch2/catch.hpp"
 #include "../Services/ServiceTests.hpp"
 #include "ECSS_Definitions.hpp"
+#include "catch2/catch_all.hpp"
 
 TEST_CASE("Getting a reference of a parameter") {
 	SECTION("Valid parameter requested") {
diff --git a/test/Helpers/Statistic.cpp b/test/Helpers/StatisticTests.cpp
similarity index 78%
rename from test/Helpers/Statistic.cpp
rename to test/Helpers/StatisticTests.cpp
index 5db84a3876685ace98f57408b009d48e4eb8fb3f..5fb8a3e8dd1b93ec2a72cd3f1adcdd0a68f53b22 100644
--- a/test/Helpers/Statistic.cpp
+++ b/test/Helpers/StatisticTests.cpp
@@ -1,6 +1,6 @@
 #include "Helpers/Statistic.hpp"
 #include "Services/ParameterStatisticsService.hpp"
-#include "catch2/catch.hpp"
+#include "catch2/catch_all.hpp"
 
 TEST_CASE("Statistics updating function") {
 	SECTION("values in one by one") {
@@ -17,25 +17,25 @@ TEST_CASE("Statistics updating function") {
 		stat1.updateStatistics(value);
 		CHECK(stat1.max == 3.24);
 		CHECK(stat1.min == 1.3);
-		CHECK(stat1.mean == Approx(2.27).epsilon(0.01));
+		CHECK(stat1.mean == Catch::Approx(2.27).epsilon(0.01));
 
 		value = 5.8;
 		stat1.updateStatistics(value);
 		CHECK(stat1.max == 5.8);
 		CHECK(stat1.min == 1.3);
-		CHECK(stat1.mean == Approx(3.446).epsilon(0.001));
+		CHECK(stat1.mean == Catch::Approx(3.446).epsilon(0.001));
 	}
 
 	SECTION("Multiple consecutive values") {
 		double values[10] = {8.3001, 2.3, 6.4, 1.1, 8.35, 3.4, 6, 8.31, 4.7, 1.09};
 		Statistic stat;
 		CHECK(stat.statisticsAreInitialized());
-		for (auto& value : values) {
+		for (auto& value: values) {
 			stat.updateStatistics(value);
 		}
 		CHECK(stat.max == 8.35);
 		CHECK(stat.min == 1.09);
-		CHECK(stat.mean == Approx(4.99501).epsilon(0.00001));
+		CHECK(stat.mean == Catch::Approx(4.99501).epsilon(0.00001));
 	}
 }
 
@@ -46,17 +46,17 @@ TEST_CASE("Appending of statistics to message") {
 		double values[10] = {8.3001, 2.3, 6.4, 1.1, 8.35, 3.4, 6, 8.31, 4.7, 1.09};
 		Statistic stat;
 		CHECK(stat.statisticsAreInitialized());
-		for (auto& value : values) {
+		for (auto& value: values) {
 			stat.updateStatistics(value);
 		}
 		stat.appendStatisticsToMessage(report);
 
 		REQUIRE(report.readFloat() == 8.35f);
-		REQUIRE(report.readUint32() == 0); // No CUC integration yet
+		REQUIRE(report.readUint32() == 86769000);   // dummy time value
 		REQUIRE(report.readFloat() == 1.09f);
-		REQUIRE(report.readUint32() == 0);
-		REQUIRE(report.readFloat() == Approx(4.99501).epsilon(0.00001));
-		REQUIRE(report.readFloat() == Approx(2.76527).epsilon(0.00001));
+		REQUIRE(report.readUint32() == 86769000);
+		REQUIRE(report.readFloat() == Catch::Approx(4.99501).epsilon(0.00001));
+		REQUIRE(report.readFloat() == Catch::Approx(2.76527).epsilon(0.00001));
 	}
 }
 
@@ -74,11 +74,11 @@ TEST_CASE("Reset statistics") {
 		double values[10] = {8.3001, 2.3, 6.4, 1.1, 8.35, 3.4, 6, 8.31, 4.7, 1.09};
 		Statistic stat;
 		CHECK(stat.statisticsAreInitialized());
-		for (auto& value : values) {
+		for (auto& value: values) {
 			stat.updateStatistics(value);
 		}
 		CHECK(not stat.statisticsAreInitialized());
 		stat.resetStatistics();
 		REQUIRE(stat.statisticsAreInitialized());
 	}
-}
\ No newline at end of file
+}
diff --git a/test/MessageParser.cpp b/test/MessageParserTests.cpp
similarity index 59%
rename from test/MessageParser.cpp
rename to test/MessageParserTests.cpp
index 93cfa695a26cb1a97455db4c6e6ddf4310ec98c5..b513b90945df366054584b45e5579207100bd89e 100644
--- a/test/MessageParser.cpp
+++ b/test/MessageParserTests.cpp
@@ -1,8 +1,9 @@
-#include <catch2/catch.hpp>
+#include "MessageParser.hpp"
 #include <Message.hpp>
+#include <catch2/catch_all.hpp>
 #include <cstring>
 #include "Helpers/CRCHelper.hpp"
-#include "MessageParser.hpp"
+#include "Helpers/TimeGetter.hpp"
 
 TEST_CASE("TC message parsing", "[MessageParser]") {
 	uint8_t packet[] = {0x18, 0x07, 0xe0, 0x07, 0x00, 0x0a, 0x20, 0x81, 0x1f, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f};
@@ -18,8 +19,8 @@ TEST_CASE("TC message parsing", "[MessageParser]") {
 }
 
 TEST_CASE("TC Message parsing into a string", "[MessageParser]") {
-	uint8_t wantedPacket[] = {0x18, 0x07, 0xe0, 0x07, 0x00, 0x0a, 0x20, 0x81,
-	                          0x1f, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f};
+	uint8_t wantedPacket[] = {0x18, 0x07, 0xe0, 0x07, 0x00, 0x09, 0x20, 0x81,
+	                          0x1f, 0x00, 0x07, 0x68, 0x65, 0x6c, 0x6c, 0x6f};
 
 	Message message;
 	message.packetType = Message::TC;
@@ -43,13 +44,20 @@ TEST_CASE("TC Message parsing into a string", "[MessageParser]") {
 	CHECK(createdPacket.size() == 16);
 	CHECK((createdPacket == String<16>(wantedPacket)));
 #endif
+
 }
 
 TEST_CASE("TM message parsing", "[MessageParser]") {
-	uint8_t packet[] = {0x08, 0x02, 0xc0, 0x4d, 0x00, 0x0c, 0x20, 0x16, 0x11,
-	                    0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x68, 0x69};
+	uint8_t packet[] = {0x08, 0x02, 0xc0, 0x4d, 0x00, 0x12, 0x20, 0x16,
+	                    0x11,0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,
+	                    0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x68, 0x69};
+	uint32_t time = TimeGetter::getCurrentTimeDefaultCUC().formatAsBytes();
+	packet[13] = (time >> 24) & 0xFF;
+	packet[14] = (time >> 16) & 0xFF;
+	packet[15] = (time >> 8) & 0xFF;
+	packet[16] = (time) & 0xFF;
 
-	Message message = MessageParser::parse(packet, 18);
+	Message message = MessageParser::parse(packet, 24);
 	CHECK(message.packetType == Message::TM);
 	CHECK(message.applicationId == 2);
 	CHECK(message.packetSequenceCount == 77);
@@ -57,11 +65,23 @@ TEST_CASE("TM message parsing", "[MessageParser]") {
 	CHECK(message.serviceType == 22);
 	CHECK(message.messageType == 17);
 	CHECK(memcmp(message.data, "hellohi", 7) == 0);
+
+	// Add ECSS and CCSDS header
+	String<CCSDSMaxMessageSize> createdPacket = MessageParser::compose(message);
+	uint32_t messageTime =  (createdPacket[16] & 0xFF) | ((createdPacket[15] & 0xFF ) << 8) | ((createdPacket[14] & 0xFF) << 16) | ((createdPacket[13] & 0xFF ) << 24);
+	CHECK(messageTime == time);
+
 }
 
 TEST_CASE("TM Message parsing into a string", "[MessageParser]") {
-	uint8_t wantedPacket[] = {0x08, 0x02, 0xc0, 0x4d, 0x00, 0x0c, 0x20, 0x16, 0x11,
-	                          0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x68, 0x69};
+	uint8_t wantedPacket[] = {0x08, 0x02, 0xc0, 0x4d, 0x00, 0x11, 0x20, 0x16,
+	                          0x11,0x00, 0x00,0x00, 0x02,0x00, 0x00,0x00,
+	                          0x00, 0x68,0x65, 0x6c, 0x6c, 0x6f, 0x68, 0x69};
+	uint32_t time = TimeGetter::getCurrentTimeDefaultCUC().formatAsBytes();
+	wantedPacket[13] = (time >> 24) & 0xFF;
+	wantedPacket[14] = (time >> 16) & 0xFF;
+	wantedPacket[15] = (time >> 8) & 0xFF;
+	wantedPacket[16] = (time) & 0xFF;
 
 	Message message;
 	message.packetType = Message::TM;
@@ -75,14 +95,14 @@ TEST_CASE("TM Message parsing into a string", "[MessageParser]") {
 	String<CCSDSMaxMessageSize> createdPacket = MessageParser::compose(message);
 
 #if ECSS_CRC_INCLUDED
-	CHECK(createdPacket.size() == 20);
-	CHECK(memcmp(createdPacket.data(), wantedPacket, 18) == 0);
+	CHECK(createdPacket.size() == 26);
+	CHECK(memcmp(createdPacket.data(), wantedPacket, 24) == 0);
 
 	const uint8_t* packet = reinterpret_cast<uint8_t*>(&createdPacket.data()[0]);
-	uint8_t crc_verification = CRCHelper::validateCRC(packet, 20);
+	uint8_t crc_verification = CRCHelper::validateCRC(packet, 26);
 	CHECK(crc_verification == 0);
 #else
-	CHECK(createdPacket.size() == 18);
-	CHECK((createdPacket == String<18>(wantedPacket)));
+	CHECK(createdPacket.size() == 24);
+	CHECK((createdPacket == String<24>(wantedPacket)));
 #endif
 }
diff --git a/test/Message.cpp b/test/MessageTests.cpp
similarity index 76%
rename from test/Message.cpp
rename to test/MessageTests.cpp
index 84a0c58d2fe440b0aa5d7c1918a3608581d8145d..840d3e2eda157742842af5e106ef7b252afc1471 100644
--- a/test/Message.cpp
+++ b/test/MessageTests.cpp
@@ -1,8 +1,8 @@
-#include <catch2/catch.hpp>
 #include <Message.hpp>
 #include <ServicePool.hpp>
-#include "etl/String.hpp"
+#include <catch2/catch_all.hpp>
 #include "Services/EventReportService.hpp"
+#include "etl/String.hpp"
 
 TEST_CASE("Message is usable", "[message]") {
 	Message message(EventReportService::ServiceType, 17, Message::TC, 3);
@@ -94,15 +94,13 @@ TEST_CASE("Requirement 7.3.3 (Enumerated)", "[message][ecss]") {
 TEST_CASE("Requirement 7.3.4 (Unsigned integer)", "[message][ecss]") {
 	Message message(0, 0, Message::TC, 0);
 
-	message.append<char>(110);
 	message.append<uint8_t>(230);
 	message.append<uint16_t>(15933);
 	message.append<uint32_t>(2000001);
 	message.append<uint64_t>(12446744073709551615ULL);
 
-	REQUIRE(message.dataSize == 1 + 1 + 2 + 4 + 8);
+	REQUIRE(message.dataSize == 1 + 2 + 4 + 8);
 
-	CHECK(message.read<char>() == 110);
 	CHECK(message.read<uint8_t>() == 230);
 	CHECK(message.read<uint16_t>() == 15933);
 	CHECK(message.read<uint32_t>() == 2000001);
@@ -115,8 +113,8 @@ TEST_CASE("Requirement 7.3.4 (Unsigned integer)", "[message][ecss]") {
 		 * processors store data in little endian format. As a result, special care needs to be
 		 * taken for compliance.
 		 */
-		CHECK(message.data[2] == 0x3e);
-		CHECK(message.data[3] == 0x3d);
+		CHECK(message.data[1] == 0x3e);
+		CHECK(message.data[2] == 0x3d);
 	}
 }
 
@@ -163,7 +161,54 @@ TEST_CASE("Test appending double") {
 
 	REQUIRE(message.dataSize == 8);
 
-	CHECK(message.read<double>() == Approx(2.324).epsilon(0.0001));
+	CHECK(message.read<double>() == Catch::Approx(2.324).epsilon(0.0001));
+}
+
+TEST_CASE("Test appending offset") {
+	Message message(0, 0, Message::TC, 0);
+	message.append<Time::RelativeTime>(555);
+
+	REQUIRE(message.dataSize == 8);
+
+	CHECK(message.read<Time::RelativeTime>() == 555);
+}
+
+TEST_CASE("Test appending a CUC timestamp") {
+	using namespace Time;
+
+	SECTION("Test 1") {
+		auto timeCUC = TimeGetter::getCurrentTimeDefaultCUC();
+		REQUIRE(timeCUC.formatAsBytes() == 86769000);
+
+		Message message(0, 0, Message::TC, 0);
+		message.appendDefaultCUCTimeStamp(timeCUC);
+
+		REQUIRE(message.readUint32() == 86769000);
+	}
+
+	SECTION("Test 2") {
+		DefaultCUC timeCUC(34511_t);
+
+		Message message(0, 0, Message::TC, 0);
+		message.appendDefaultCUCTimeStamp(timeCUC);
+
+		REQUIRE(message.readUint32() == 34511);
+	}
+}
+
+TEST_CASE("Test reading a custom CUC timestamp") {
+	using namespace Time;
+	/**
+ 	* Append a custom CUC Time Stamp to a message object and check if is it read corretly
+ 	*/
+	DefaultCUC timeCUC(34511_t);
+
+	Message message(0, 0, Message::TC, 0);
+	message.appendDefaultCUCTimeStamp(timeCUC);
+
+	auto returnTimeCUC = message.readDefaultCUCTimeStamp();
+
+	REQUIRE(returnTimeCUC.formatAsBytes() == 34511);
 }
 
 TEST_CASE("Requirement 7.3.8 (Octet-string)", "[message][ecss]") {
@@ -350,3 +395,64 @@ TEST_CASE("Packet sequence counter", "[message]") {
 		CHECK(message2.packetSequenceCount == 0);
 	}
 }
+
+TEST_CASE("Storing and retrieving enums in Messages") {
+	enum ActiveBus : uint8_t {
+		Main = 0x0,
+		Redundant = 0x1
+	};
+
+	SECTION("Using Enums in parameters") {
+		auto parameter1 = Parameter<ActiveBus>(Redundant);
+		auto parameter2 = Parameter<ActiveBus>(Main);
+		Message message;
+
+		parameter1.appendValueToMessage(message);
+		parameter2.setValueFromMessage(message);
+
+		CHECK(parameter1.getValue() == parameter2.getValue());
+	}
+
+	SECTION("Using Enums in variables") {
+		ActiveBus variable1 = Redundant;
+		ActiveBus variable2 = Main;
+		Message message;
+
+		message.append(variable1);
+		variable2 = message.read<ActiveBus>();
+
+		CHECK(variable1 == variable2);
+	}
+
+	SECTION("Another type of enum") {
+		enum Numbers : uint64_t {
+			First = 1577829600,
+			Second = 1667045679
+		};
+
+		auto parameter1 = Parameter<Numbers>(First);
+		auto parameter2 = Parameter<Numbers>(Second);
+		Message message;
+
+		parameter1.appendValueToMessage(message);
+		parameter2.setValueFromMessage(message);
+
+		CHECK(parameter1.getValue() == parameter2.getValue());
+	}
+
+		SECTION("Another type of enum") {
+		enum MemoryPartitionUsed : bool {
+			first = false,
+			second = true
+		};
+
+		auto parameter3 = Parameter<MemoryPartitionUsed>(first);
+		auto parameter4 = Parameter<MemoryPartitionUsed>(second);
+		Message message;
+
+		parameter3.appendValueToMessage(message);
+		parameter4.setValueFromMessage(message);
+
+		CHECK(parameter3.getValue() == parameter4.getValue());
+	}
+}
diff --git a/test/Parameters/LazyParameterTests.cpp b/test/Parameters/LazyParameterTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ef291663fc136290ead8f9588aa1cc5c60524ee8
--- /dev/null
+++ b/test/Parameters/LazyParameterTests.cpp
@@ -0,0 +1,85 @@
+#include "../Services/ServiceTests.hpp"
+#include "Helpers/LazyParameter.hpp"
+#include "Message.hpp"
+#include "catch2/catch_all.hpp"
+
+TEST_CASE("Lazy Parameter: Getter") {
+	LazyParameter<uint32_t> parameter;
+	CHECK(parameter.getValue().has_value() == false);
+
+	parameter.setGetter([]() -> auto{
+		static uint32_t value = 99100;
+		return value++;
+	});
+
+	CHECK(parameter.getValue().value() == 99100);
+	CHECK(parameter.getValue().value() == 99101);
+	CHECK(parameter.getValueAsDouble() == 99102);
+
+	parameter.unsetGetter();
+
+	CHECK(parameter.getValue().has_value() == false);
+	CHECK(parameter.getValueAsDouble() == 0);
+}
+
+TEST_CASE("Lazy Parameter: Messages") {
+	const int16_t fallback = -1;
+	const int16_t value = 42;
+
+	LazyParameter<int16_t> parameter(
+	    []() -> auto{
+		    return value;
+	    },
+	    fallback);
+
+	SECTION("Getter works") {
+		Message message(0, 0, Message::TC);
+		parameter.appendValueToMessage(message);
+
+		CHECK(message.dataSize == 2);
+		CHECK(message.readSint16() == value);
+		CHECK(ServiceTests::hasNoErrors());
+	}
+
+	SECTION("Getter broken") {
+		parameter.unsetGetter();
+
+		Message message(0, 0, Message::TC);
+		parameter.appendValueToMessage(message);
+
+		CHECK(message.dataSize == 2);
+		CHECK(message.readSint16() == fallback);
+		CHECK(ServiceTests::thrownError(ErrorHandler::ParameterValueMissing));
+	}
+
+	SECTION("Attempt to write") {
+		Message message(0, 0, Message::TC);
+		message.appendSint16(99);
+		message.appendSint16(100);
+
+		parameter.setValueFromMessage(message);
+		CHECK(ServiceTests::thrownError(ErrorHandler::ParameterReadOnly));
+
+		// Make sure that the appropriate amount of bytes has been skipped
+		CHECK(message.readSint16() == 100);
+	}
+}
+
+TEST_CASE("Lazy Parameter: Complex Types") {
+	using namespace Time;
+
+	LazyParameter<Time::DefaultCUC> parameter(Time::DefaultCUC(100_t));
+
+	SECTION("Default value") {
+		CHECK(parameter.getValue().has_value() == false);
+	}
+
+	SECTION("Set value") {
+		parameter.setGetter([]() -> Time::DefaultCUC {
+			return Time::DefaultCUC(200_t);
+		});
+
+		CHECK(parameter.getValue().value() == Time::DefaultCUC{200_t});
+		CHECK(parameter.getValueAsDouble() == 0);
+	}
+}
diff --git a/test/Parameters/NotifyParameterTests.cpp b/test/Parameters/NotifyParameterTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4950f7680e2ac53185632cda60247624f187dcf0
--- /dev/null
+++ b/test/Parameters/NotifyParameterTests.cpp
@@ -0,0 +1,63 @@
+#include "Helpers/NotifyParameter.hpp"
+#include "Message.hpp"
+#include "catch2/catch_all.hpp"
+
+TEST_CASE("Notify Parameter: Notifier") {
+	int counter = 0;
+
+	NotifyParameter<uint32_t> parameter(0);
+
+	SECTION("Notifier not set") {
+		parameter.setValueLoudly(1);
+		CHECK(counter == 0);
+	}
+
+	parameter.setNotifier([&counter](auto) -> auto{
+		counter++;
+	});
+	CHECK(counter == 1);
+
+	parameter.setValueLoudly(2);
+	CHECK(counter == 2);
+
+	parameter.setValueLoudly(2);
+	CHECK(counter == 3);
+
+	parameter.unsetNotifier();
+	parameter.setValueLoudly(3);
+	CHECK(counter == 3);
+}
+
+TEST_CASE("Notify Parameter: Messages") {
+	int16_t storage;
+
+	NotifyParameter<uint32_t> parameter(
+	    0, [&storage](auto v) -> auto{
+		    storage = v;
+	    });
+
+	Message message(0, 0, Message::TC);
+	message.appendUint32(184);
+
+	parameter.setValueFromMessage(message);
+
+	CHECK(storage == 184);
+}
+
+TEST_CASE("Notify Parameter: Extra functionality") {
+	int counter = 0;
+
+	NotifyParameter<uint32_t> parameter(0);
+	auto notifier = [&counter](auto) -> auto{
+		counter++;
+	};
+
+	parameter.setNotifier(notifier);
+	CHECK(counter == 1);
+
+	parameter.setNotifier(notifier, false);
+	CHECK(counter == 1);
+
+	parameter.notify();
+	CHECK(counter == 2);
+}
\ No newline at end of file
diff --git a/test/Services/Parameter.cpp b/test/Parameters/ParameterTests.cpp
similarity index 85%
rename from test/Services/Parameter.cpp
rename to test/Parameters/ParameterTests.cpp
index 10c47ac78cebf73604199fa4aa3c4c56e6ee6fe0..d7b373f1289734445ccad5d589e2bfb4b791950e 100644
--- a/test/Services/Parameter.cpp
+++ b/test/Parameters/ParameterTests.cpp
@@ -1,8 +1,8 @@
-#include <iostream>
-#include "catch2/catch.hpp"
 #include "Helpers/Parameter.hpp"
-#include "Services/ParameterService.hpp"
+#include <iostream>
 #include "Message.hpp"
+#include "Services/ParameterService.hpp"
+#include "catch2/catch_all.hpp"
 
 TEST_CASE("Parameter Append") {
 	SECTION("Check correct appending") {
@@ -49,24 +49,24 @@ TEST_CASE("Get value as double") {
 		auto parameter1 = Parameter<uint8_t>(7);
 		uint8_t value = 13;
 		parameter1.setValue(value);
-		CHECK(parameter1.getValueAsDouble() == Approx(13.0).epsilon(0.1));
+		CHECK(parameter1.getValueAsDouble() == Catch::Approx(13.0).epsilon(0.1));
 	}
 	SECTION("uint16 to double") {
 		auto parameter2 = Parameter<uint32_t>(8);
 		uint16_t value = 264;
 		parameter2.setValue(value);
-		CHECK(parameter2.getValueAsDouble() == Approx(264.0).epsilon(0.1));
+		CHECK(parameter2.getValueAsDouble() == Catch::Approx(264.0).epsilon(0.1));
 	}
 	SECTION("uint32 to double") {
 		auto parameter3 = Parameter<uint32_t>(9);
 		uint32_t value = 544;
 		parameter3.setValue(value);
-		CHECK(parameter3.getValueAsDouble() == Approx(544.0).epsilon(0.1));
+		CHECK(parameter3.getValueAsDouble() == Catch::Approx(544.0).epsilon(0.1));
 	}
 	SECTION("float to double") {
 		auto parameter4 = Parameter<float>(10);
 		float value = 14.237;
 		parameter4.setValue(value);
-		CHECK(parameter4.getValueAsDouble() == Approx(14.237).epsilon(0.001));
+		CHECK(parameter4.getValueAsDouble() == Catch::Approx(14.237).epsilon(0.001));
 	}
 }
diff --git a/test/Services/DummyService.cpp b/test/Services/DummyService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff3549355b8386514e84f8cedafd7bbc937ecccf
--- /dev/null
+++ b/test/Services/DummyService.cpp
@@ -0,0 +1,17 @@
+#include "Services/DummyService.hpp"
+#include <catch2/catch_all.hpp>
+#include "ServicePool.hpp"
+#include "ServiceTests.hpp"
+
+DummyService& dummyService = Services.dummyService;
+
+TEST_CASE("Log string as message TM[128, 128]", "[service][st128]") {
+	etl::string<LOGGER_MAX_MESSAGE_SIZE> log = "An amazing log that is very informative";
+	dummyService.logAsECSSMessage(log);
+	Message report = ServiceTests::get(0);
+	CHECK(report.serviceType == DummyService::ServiceType);
+	CHECK(report.messageType == DummyService::MessageType::LogString);
+	char logOutput[39];
+	report.readString(logOutput, 39);
+	CHECK(memcmp(logOutput, "An amazing log that is very informative", 39) == 0);
+}
diff --git a/test/Services/EventActionService.cpp b/test/Services/EventActionService.cpp
deleted file mode 100644
index 0d26065c77360f45dca03f13f0f1fe842064aa2c..0000000000000000000000000000000000000000
--- a/test/Services/EventActionService.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-#include <catch2/catch.hpp>
-#include <Services/EventActionService.hpp>
-#include <Message.hpp>
-#include "ServiceTests.hpp"
-#include <etl/String.hpp>
-#include <cstring>
-#include <ServicePool.hpp>
-
-EventActionService& eventActionService = Services.eventAction;
-
-TEST_CASE("Add event-action definitions TC[19,1]", "[service][st19]") {
-	
-	// Add a message that is too large to check for the corresponding error
-	Message message(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message.appendEnum16(0);
-	message.appendEnum16(1);
-	message.appendEnum16(1);
-	String<128> data = "0123456789012345678901234567890123456789012345678901234567890123456789";
-	message.appendString(data);
-
-	MessageParser::execute(message);
-	CHECK(ServiceTests::thrownError(ErrorHandler::MessageTooLarge));
-	CHECK(ServiceTests::countErrors() == 1);
-
-	// Add an event-action definition to check if the values are inserted correctly
-	Message message1(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message1.appendEnum16(0);
-	message1.appendEnum16(2);
-	message1.appendEnum16(1);
-	data = "01234";
-	message1.appendString(data);
-	MessageParser::execute(message1);
-
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(2)->second.applicationId == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(2)->second.eventDefinitionID == 2);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(2)->second.enabled == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(2)->second.request.compare(data) == 0);
-
-	// Add a second event-action definition
-	Message message2(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message2.appendEnum16(1);
-	message2.appendEnum16(3);
-	message2.appendEnum16(1);
-	data = "456";
-	message2.appendString(data);
-	MessageParser::execute(message2);
-
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(3)->second.applicationId == 1);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(3)->second.eventDefinitionID == 3);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(3)->second.enabled == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(3)->second.request.compare(data) == 0);
-
-	// Adding the same message to check for error
-	Message message3(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message3.appendEnum16(1);
-	message3.appendEnum16(3);
-	message3.appendEnum16(1);
-	data = "456";
-	message3.appendString(data);
-	MessageParser::execute(message3);
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionDefinitionIDExistsError));
-	CHECK(ServiceTests::countErrors() == 2);
-}
-
-TEST_CASE("Delete event-action definitions TC[19,2]", "[service][st19]") {
-
-	// Add messages for the purpose of deleting them
-	Message message0(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message0.appendEnum16(1);
-	message0.appendEnum16(0);
-	message0.appendEnum16(1);
-	String<64> data = "0";
-	message0.appendString(data);
-	MessageParser::execute(message0);
-
-	Message message1(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	data = "1";
-	message1.appendString(data);
-	MessageParser::execute(message1);
-
-	Message message2(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message2.appendEnum16(1);
-	message2.appendEnum16(2);
-	message2.appendEnum16(1);
-	data = "2";
-	message2.appendString(data);
-	MessageParser::execute(message2);
-
-	Message message5(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
-	message5.appendUint16(1);
-	message5.appendEnum16(1);
-	message5.appendEnum16(2);
-	message5.appendEnum16(1);
-	MessageParser::execute(message5);
-
-	// Checking the values after deleting some definitions
-
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.applicationId == 1);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.eventDefinitionID == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.request.compare("0") == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.enabled == 0);
-
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.applicationId == 1);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.eventDefinitionID == 1);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.request.compare("1") == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.enabled == 0);
-
-	CHECK(eventActionService.eventActionDefinitionMap.find(2) == eventActionService.eventActionDefinitionMap.end());
-
-	// Enabling a definition to check for errors in the case of an attempt to delete it
-	Message message8(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
-	message8.appendUint16(1);
-	message8.appendEnum16(1);
-	message8.appendEnum16(1);
-	message8.appendEnum16(1);
-	MessageParser::execute(message8);
-
-	Message message6(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
-	message6.appendUint16(1);
-	message6.appendEnum16(1);
-	message6.appendEnum16(1);
-	message6.appendEnum16(1);
-	MessageParser::execute(message6);
-
-	// Checking for errors in the case mentioned above
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionDeleteEnabledDefinitionError));
-	CHECK(ServiceTests::countErrors() == 1);
-
-	// Checking for errors in the case of an unknown definition
-	Message message7(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
-	message7.appendUint16(1);
-	message7.appendEnum16(1);
-	message7.appendEnum16(10);
-	message7.appendEnum16(1);
-	MessageParser::execute(message7);
-
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventDefinitionError));
-	CHECK(ServiceTests::countErrors() == 2);
-
-	Message message9(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
-	message9.appendUint16(1);
-	message9.appendEnum16(1);
-	message9.appendEnum16(1);
-	message9.appendEnum16(10);
-	MessageParser::execute(message9);
-
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionIDError));
-	CHECK(ServiceTests::countErrors() == 3);
-}
-
-TEST_CASE("Delete all event-action definitions TC[19,3]", "[service][st19]") {
-
-	// Adding event action definitions to delete them later
-	Message message0(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message0.appendEnum16(1);
-	message0.appendEnum16(0);
-	message0.appendEnum16(1);
-	String<64> data = "0";
-	message0.appendString(data);
-	MessageParser::execute(message0);
-
-	Message message1(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	data = "1";
-	message1.appendString(data);
-	MessageParser::execute(message1);
-
-	Message message2(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message2.appendEnum16(1);
-	message2.appendEnum16(2);
-	message2.appendEnum16(1);
-	data = "2";
-	message2.appendString(data);
-	MessageParser::execute(message2);
-
-	Message message3(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message3.appendEnum16(1);
-	message3.appendEnum16(3);
-	message3.appendEnum16(1);
-	data = "3";
-	message3.appendString(data);
-	MessageParser::execute(message3);
-
-	Message message4(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message4.appendEnum16(1);
-	message4.appendEnum16(4);
-	message4.appendEnum16(1);
-	data = "4";
-	message4.appendString(data);
-	MessageParser::execute(message4);
-
-	Message message(EventActionService::ServiceType, EventActionService::MessageType::DeleteAllEventAction, Message::TC, 0);
-	MessageParser::execute(message);
-
-	// Checking the content of the map
-	for (int i = 0; i < 256; i++){
-		CHECK(eventActionService.eventActionDefinitionMap.find(i) == eventActionService.eventActionDefinitionMap.end());
-	}
-}
-
-TEST_CASE("Enable event-action definitions TC[19,4]", "[service][st19]") {
-
-	// Adding event action definitions to enable them
-	Message message0(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message0.appendEnum16(1);
-	message0.appendEnum16(0);
-	message0.appendEnum16(1);
-	String<64> data = "0";
-	message0.appendString(data);
-	MessageParser::execute(message0);
-
-	Message message1(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	data = "00";
-	message1.appendString(data);
-	MessageParser::execute(message1);
-
-	// Checking their enabled status
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.enabled == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.enabled == 0);
-
-	// Creating a message to enable the previous messages
-	Message message3(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
-	message3.appendUint16(2);
-	message3.appendEnum16(1);
-	message3.appendEnum16(0);
-	message3.appendEnum16(1);
-	message3.appendEnum16(1);
-	message3.appendEnum16(1);
-	message3.appendEnum16(1);
-	MessageParser::execute(message3);
-
-	// Checking if the messages are enabled
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.enabled == 1);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.enabled == 1);
-
-	// Checking for errors in the case of an attempt to enable an unknown definition
-	Message message7(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
-	message7.appendUint16(1);
-	message7.appendEnum16(1);
-	message7.appendEnum16(6);
-	MessageParser::execute(message7);
-
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventDefinitionError));
-	CHECK(ServiceTests::countErrors() == 1);
-
-	// Checking for errors in the case of an attempt to enable an unknown definition
-	Message message8(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
-	message8.appendUint16(1);
-	message8.appendEnum16(1);
-	message8.appendEnum16(1);
-	message8.appendEnum16(10);
-	MessageParser::execute(message8);
-
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionIDError));
-	CHECK(ServiceTests::countErrors() == 2);
-}
-
-TEST_CASE("Disable event-action definitions TC[19,5]", "[service][st19]") {
-
-	// Adding event action definitions to enable them
-	Message message0(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message0.appendEnum16(1);
-	message0.appendEnum16(0);
-	message0.appendEnum16(1);
-	String<64> data = "0";
-	message0.appendString(data);
-	MessageParser::execute(message0);
-
-	Message message1(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	message1.appendEnum16(1);
-	data = "00";
-	message1.appendString(data);
-	MessageParser::execute(message1);
-
-	// Checking their enabled status
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.enabled == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.enabled == 0);
-
-	// Creating a message to enable the previous messages
-	Message message3(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
-	message3.appendUint16(2);
-	message3.appendEnum16(1);
-	message3.appendEnum16(0);
-	message3.appendEnum16(1);
-	message3.appendEnum16(1);
-	message3.appendEnum16(1);
-	message3.appendEnum16(1);
-	MessageParser::execute(message3);
-
-	// Checking if the messages are enabled
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.enabled == 1);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.enabled == 1);
-
-	// Creating a message to enable the previous messages
-	Message message4(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
-	message4.appendUint16(2);
-	message4.appendEnum16(1);
-	message4.appendEnum16(0);
-	message4.appendEnum16(1);
-	message4.appendEnum16(1);
-	message4.appendEnum16(1);
-	message4.appendEnum16(1);
-	MessageParser::execute(message4);
-
-	// Checking if the messages are enabled
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(0)->second.enabled == 0);
-	CHECK(eventActionService.eventActionDefinitionMap.lower_bound(1)->second.enabled == 0);
-
-	// Checking for errors in the case of an attempt to enable an unknown definition
-	Message message7(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
-	message7.appendUint16(1);
-	message7.appendEnum16(1);
-	message7.appendEnum16(6);
-	MessageParser::execute(message7);
-
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventDefinitionError));
-	CHECK(ServiceTests::countErrors() == 1);
-
-	// Checking for errors in the case of an attempt to enable an unknown definition
-	Message message8(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
-	message8.appendUint16(1);
-	message8.appendEnum16(1);
-	message8.appendEnum16(1);
-	message8.appendEnum16(10);
-	MessageParser::execute(message8);
-
-	CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionIDError));
-	CHECK(ServiceTests::countErrors() == 2);
-}
-
-TEST_CASE("Request event-action definition status TC[19,6]", "[service][st19]") {
-
-	// Creating a request for a report on the event action definitions
-	Message message(EventActionService::ServiceType, EventActionService::MessageType::ReportStatusOfEachEventAction, Message::TC, 0);
-	MessageParser::execute(message);
-	REQUIRE(ServiceTests::hasOneMessage());
-
-	// Checking that the report was made
-	Message report = ServiceTests::get(0);
-	CHECK(report.messageType == 7);
-}
-
-TEST_CASE("Event-action status report TM[19,7]", "[service][st19]") {
-
-	// Adding event-action definitions to report them
-	Message message0(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message0.appendEnum16(1);
-	message0.appendEnum16(0);
-	message0.appendEnum16(1);
-	String<64> data = "0";
-	message0.appendString(data);
-	MessageParser::execute(message0);
-
-	Message message1(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
-	message1.appendEnum16(1);
-	message1.appendEnum16(2);
-	message1.appendEnum16(1);
-	data = "2";
-	message1.appendString(data);
-	MessageParser::execute(message1);
-
-	// Enablilng one of the two
-	Message message2(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
-	message2.appendUint16(1);
-	message2.appendEnum16(1);
-	message2.appendEnum16(0);
-	message2.appendEnum16(1);
-	eventActionService.enableEventActionDefinitions(message2);
-
-	eventActionService.eventActionStatusReport();
-	REQUIRE(ServiceTests::hasOneMessage());
-
-	// Checking the contents of the report
-	Message report = ServiceTests::get(0);
-	CHECK(report.readUint16() == 2);
-	CHECK(report.readEnum16() == 1);
-	CHECK(report.readEnum16() == 0);
-	CHECK(report.readEnum16() == 1);
-	CHECK(report.readBoolean() == 1);
-	CHECK(report.readEnum16() == 1);
-	CHECK(report.readEnum16() == 2);
-	CHECK(report.readEnum16() == 1);
-	CHECK(report.readBoolean() == 0);
-}
-
-TEST_CASE("Enable event-action function TC[19,8]", "[service][st19]") {
-
-	// A message to enable event action function
-
-	Message message(EventActionService::ServiceType, EventActionService::MessageType::EnableEventActionFunction, Message::TC, 0);
-	eventActionService.enableEventActionFunction(message);
-	CHECK(eventActionService.getEventActionFunctionStatus());
-}
-
-TEST_CASE("Disable event-action function TC[19,9]", "[service][st19]") {
-
-	// A message to disable event action function
-	Message message(EventActionService::ServiceType, EventActionService::MessageType::DisableEventActionFunction, Message::TC, 0);
-	eventActionService.disableEventActionFunction(message);
-	CHECK(eventActionService.getEventActionFunctionStatus() == false);
-}
-
-TEST_CASE("Execute a TC request", "[service][st19]"){
-
-}
diff --git a/test/Services/EventActionServiceTests.cpp b/test/Services/EventActionServiceTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b2365af7905526c060a8bde494a603e1266ceff
--- /dev/null
+++ b/test/Services/EventActionServiceTests.cpp
@@ -0,0 +1,534 @@
+#include <Message.hpp>
+#include <ServicePool.hpp>
+#include <Services/EventActionService.hpp>
+#include <catch2/catch_all.hpp>
+#include <etl/String.hpp>
+#include "ServiceTests.hpp"
+
+EventActionService& eventActionService = Services.eventAction;
+
+/**
+ * Initializes 9 Event Action Definitions with eventDefinitionIDs = {0, 4, 2, 12, 1, 5, 8, 23, 3}
+ */
+void initializeEventActionDefinitions() {
+	Message addDefinitions(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+	uint8_t numberOfEventActionDefinitions = 9;
+	uint16_t applicationIDs[] = {1, 0, 1, 0, 0, 2, 0, 1, 0};
+	uint16_t eventDefinitionIDs[] = {0, 4, 2, 12, 1, 5, 8, 23, 3};
+	String<ECSSTCRequestStringSize> data[] = {"\0", "1", "\0", "3", "4", "5", "6", "7", "8"};
+	addDefinitions.appendUint8(numberOfEventActionDefinitions);
+	for (auto i = 0; i < numberOfEventActionDefinitions; i++) {
+		addDefinitions.appendEnum16(applicationIDs[i]);
+		addDefinitions.appendEnum16(eventDefinitionIDs[i]);
+		addDefinitions.appendFixedString(data[i]);
+	}
+	MessageParser::execute(addDefinitions);
+
+	REQUIRE(eventActionService.eventActionDefinitionMap.size() == 9);
+	for (auto i = 0; i < numberOfEventActionDefinitions; i++) {
+		REQUIRE(eventActionService.eventActionDefinitionMap.find(eventDefinitionIDs[i]) != eventActionService.eventActionDefinitionMap.end());
+	}
+}
+
+TEST_CASE("Add event-action definitions TC[19,1]", "[service][st19]") {
+	SECTION("Add an event-action definition to check if the values are inserted correctly") {
+		Message addDefinition(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinition.appendUint8(1);
+		addDefinition.appendEnum16(0);
+		addDefinition.appendEnum16(2);
+		String<ECSSTCRequestStringSize> data = "12345abcdefg";
+		addDefinition.appendFixedString(data);
+		MessageParser::execute(addDefinition);
+
+		auto element = eventActionService.eventActionDefinitionMap.find(2);
+		CHECK(element->second.applicationID == 0);
+		CHECK(element->second.eventDefinitionID == 2);
+		CHECK(!element->second.enabled);
+		for (auto i = 0; i < data.size(); ++i) {
+			CHECK(data[i] == element->second.request[i]);
+		}
+	}
+
+	SECTION("Adding multiple event-action definitions for different events") {
+		Message addDefinitions(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		uint8_t numberOfEventActionDefinitions = 3;
+		uint16_t applicationIDs[] = {0, 1, 2};
+		uint16_t eventDefinitionIDs[] = {3, 5, 4};
+		String<ECSSTCRequestStringSize> dataArray[] = {"123", "456", "789"};
+		addDefinitions.appendUint8(numberOfEventActionDefinitions);
+		for (auto i = 0; i < numberOfEventActionDefinitions; i++) {
+			addDefinitions.appendEnum16(applicationIDs[i]);
+			addDefinitions.appendEnum16(eventDefinitionIDs[i]);
+			addDefinitions.appendFixedString(dataArray[i]);
+		}
+		MessageParser::execute(addDefinitions);
+
+		for (auto i = 0; i < numberOfEventActionDefinitions; i++) {
+			auto element = eventActionService.eventActionDefinitionMap.find(eventDefinitionIDs[i]);
+			CHECK(element->second.applicationID == applicationIDs[i]);
+			CHECK(element->second.eventDefinitionID == eventDefinitionIDs[i]);
+			CHECK(element->second.request.substr(0, 3) == dataArray[i]);
+			CHECK(!element->second.enabled);
+			CHECK(element->second.request.size() == ECSSTCRequestStringSize);
+		}
+
+		eventActionService.eventActionDefinitionMap.clear();
+		ServiceTests::reset();
+	}
+
+	SECTION("Add an event definition ID that already exists") {
+		Message addDefinitions(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinitions.appendUint8(2);
+		addDefinitions.appendEnum16(1);
+		addDefinitions.appendEnum16(3);
+		String<ECSSTCRequestStringSize> data = "123";
+		addDefinitions.appendFixedString(data);
+		addDefinitions.appendEnum16(6);
+		addDefinitions.appendEnum16(3);
+		data = "123";
+		addDefinitions.appendFixedString(data);
+		MessageParser::execute(addDefinitions);
+
+		addDefinitions.appendUint8(1);
+		addDefinitions.appendEnum16(3);
+		addDefinitions.appendEnum16(3);
+		data = "234";
+		addDefinitions.appendFixedString(data);
+		MessageParser::execute(addDefinitions);
+
+		auto element = eventActionService.eventActionDefinitionMap.find(3);
+		CHECK(element->second.applicationID == 3);
+		CHECK(element->second.request.substr(0, 3) == data);
+
+
+		eventActionService.eventActionDefinitionMap.clear();
+		ServiceTests::reset();
+	}
+
+	SECTION("Add an event action definition that is already enabled") {
+		Message addDefinitions(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinitions.appendUint8(1);
+		addDefinitions.appendEnum16(0);
+		addDefinitions.appendEnum16(3);
+		String<ECSSTCRequestStringSize> data = "456";
+		addDefinitions.appendFixedString(data);
+		MessageParser::execute(addDefinitions);
+
+		Message enableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+
+		enableDefinitions.appendUint8(1);
+		enableDefinitions.appendEnum16(0);
+		enableDefinitions.appendEnum16(3);
+		MessageParser::execute(enableDefinitions);
+
+		addDefinitions.appendUint8(1);
+		addDefinitions.appendEnum16(5);
+		addDefinitions.appendEnum16(3);
+		data = "456";
+		addDefinitions.appendFixedString(data);
+		MessageParser::execute(addDefinitions);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionEnabledError));
+		CHECK(ServiceTests::countErrors() == 1);
+
+		eventActionService.eventActionDefinitionMap.clear();
+		ServiceTests::reset();
+	}
+
+	SECTION("Add an event-action definition when the eventActionDefinitionMap is full") {
+		Message message(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		String<ECSSTCRequestStringSize> data = "123";
+		message.appendFixedString(data);
+		uint16_t applicationID = 257;
+
+		for (uint16_t eventDefinitionID = 0; eventDefinitionID < 100; ++eventDefinitionID) {
+			EventActionService::EventActionDefinition temp(--applicationID, eventDefinitionID, message);
+			eventActionService.eventActionDefinitionMap.insert(std::make_pair(eventDefinitionID, temp));
+			message.resetRead();
+		}
+
+		Message addDefinitions(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinitions.appendUint8(2);
+		addDefinitions.appendEnum16(1);
+		addDefinitions.appendEnum16(100);
+		addDefinitions.appendEnum16(0);
+		addDefinitions.appendEnum16(101);
+		addDefinitions.appendFixedString(data);
+		MessageParser::execute(addDefinitions);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionDefinitionsMapIsFull));
+		CHECK(ServiceTests::countErrors() == 2);
+		eventActionService.eventActionDefinitionMap.clear();
+	}
+}
+
+TEST_CASE("Enable event-action definitions TC[19,4]", "[service][st19]") {
+	SECTION("Simple enable some event-action definitions") {
+		initializeEventActionDefinitions();
+
+		auto element = eventActionService.eventActionDefinitionMap.find(4);
+		REQUIRE(!element->second.enabled);
+		REQUIRE(!eventActionService.eventActionDefinitionMap.find(1)->second.enabled);
+
+		Message enableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinitions.appendUint8(3);
+		enableDefinitions.appendEnum16(0);
+		enableDefinitions.appendEnum16(4);
+		enableDefinitions.appendEnum16(1);
+		enableDefinitions.appendEnum16(2);
+		enableDefinitions.appendEnum16(0);
+		enableDefinitions.appendEnum16(1);
+		MessageParser::execute(enableDefinitions);
+
+		CHECK(element->second.enabled);
+		CHECK(eventActionService.eventActionDefinitionMap.find(1)->second.enabled);
+	}
+
+	SECTION("Trying to enable an unknown definition") {
+		Message enableDefinition(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinition.appendUint8(1);
+		enableDefinition.appendUint16(1);
+		enableDefinition.appendEnum16(7);
+		MessageParser::execute(enableDefinition);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionError));
+		CHECK(ServiceTests::countErrors() == 1);
+	}
+
+	SECTION("Trying to enable an existing event-action definition with the wrong event definition ID") {
+		Message enableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinitions.appendUint8(2);
+		enableDefinitions.appendEnum16(1);
+		enableDefinitions.appendEnum16(4);
+		enableDefinitions.appendEnum16(1);
+		enableDefinitions.appendEnum16(3);
+		MessageParser::execute(enableDefinitions);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionError));
+		CHECK(ServiceTests::countErrors() == 2);
+
+		eventActionService.eventActionDefinitionMap.clear();
+	}
+
+	SECTION("Enable all event action definitions") {
+		initializeEventActionDefinitions();
+
+		Message enableAllDefinitions(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableAllDefinitions.appendUint8(0);
+		MessageParser::execute(enableAllDefinitions);
+
+		for (const auto& iterator: eventActionService.eventActionDefinitionMap) {
+			CHECK(iterator.second.enabled);
+		}
+
+		eventActionService.eventActionDefinitionMap.clear();
+	}
+}
+
+TEST_CASE("Delete event-action definitions TC[19,2]", "[service][st19]") {
+	SECTION("Delete an event-action definition") {
+		initializeEventActionDefinitions();
+
+		Message deleteDefinition(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
+		deleteDefinition.appendUint8(2);
+		deleteDefinition.appendEnum16(1);
+		deleteDefinition.appendEnum16(2);
+		deleteDefinition.appendEnum16(2);
+		deleteDefinition.appendEnum16(5);
+		MessageParser::execute(deleteDefinition);
+
+		REQUIRE(eventActionService.eventActionDefinitionMap.count(0) == 1);
+		REQUIRE(eventActionService.eventActionDefinitionMap.count(2) == 0);
+		REQUIRE(eventActionService.eventActionDefinitionMap.count(1) == 1);
+		REQUIRE(eventActionService.eventActionDefinitionMap.count(5) == 0);
+	}
+
+	SECTION("Trying to delete an enabled event-action definition") {
+		Message enableDefinition(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinition.appendUint8(1);
+		enableDefinition.appendEnum16(0);
+		enableDefinition.appendEnum16(1);
+		MessageParser::execute(enableDefinition);
+
+		Message deleteDefinition(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
+		deleteDefinition.appendUint8(1);
+		deleteDefinition.appendEnum16(0);
+		deleteDefinition.appendEnum16(1);
+		MessageParser::execute(deleteDefinition);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionDeleteEnabledDefinitionError));
+		CHECK(ServiceTests::countErrors() == 1);
+	}
+
+	SECTION("Trying to delete an unknown event-action definition") {
+		Message deleteDefinition(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
+		deleteDefinition.appendUint8(1);
+		deleteDefinition.appendEnum16(1);
+		deleteDefinition.appendEnum16(8);
+		MessageParser::execute(deleteDefinition);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionError));
+		CHECK(ServiceTests::countErrors() == 1);
+	}
+
+	SECTION("Trying to delete an existing event-action definition with the wrong event definition ID") {
+		Message deleteDefinition(EventActionService::ServiceType, EventActionService::MessageType::DeleteEventAction, Message::TC, 0);
+		deleteDefinition.appendUint8(2);
+		deleteDefinition.appendEnum16(0);
+		deleteDefinition.appendEnum16(0);
+		deleteDefinition.appendEnum16(0);
+		deleteDefinition.appendEnum16(5);
+		MessageParser::execute(deleteDefinition);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionError));
+		CHECK(ServiceTests::countErrors() == 2);
+
+		eventActionService.eventActionDefinitionMap.clear();
+	}
+}
+
+TEST_CASE("Delete all event-action definitions TC[19,3]", "[service][st19]") {
+	initializeEventActionDefinitions();
+
+	REQUIRE(eventActionService.eventActionDefinitionMap.size() == 9);
+
+	Message deleteAllDefinitions(EventActionService::ServiceType, EventActionService::MessageType::DeleteAllEventAction, Message::TC, 0);
+	MessageParser::execute(deleteAllDefinitions);
+
+	CHECK(eventActionService.eventActionDefinitionMap.empty());
+}
+
+TEST_CASE("Disable event-action definitions TC[19,5]", "[service][st19]") {
+	SECTION("Simple disable some event-action definitions") {
+		initializeEventActionDefinitions();
+
+		Message enableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinitions.appendUint8(4);
+		enableDefinitions.appendEnum16(0);
+		enableDefinitions.appendEnum16(4);
+		enableDefinitions.appendEnum16(1);
+		enableDefinitions.appendEnum16(2);
+		enableDefinitions.appendEnum16(0);
+		enableDefinitions.appendEnum16(1);
+		enableDefinitions.appendEnum16(1);
+		enableDefinitions.appendEnum16(23);
+		MessageParser::execute(enableDefinitions);
+
+		auto range = eventActionService.eventActionDefinitionMap.find(4);
+		REQUIRE(range->second.enabled);
+		REQUIRE(eventActionService.eventActionDefinitionMap.find(1)->second.enabled);
+
+		Message disableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
+		disableDefinitions.appendUint8(4);
+		disableDefinitions.appendEnum16(0);
+		disableDefinitions.appendEnum16(4);
+		disableDefinitions.appendEnum16(2);
+		disableDefinitions.appendEnum16(5);
+		disableDefinitions.appendEnum16(1);
+		disableDefinitions.appendEnum16(2);
+		disableDefinitions.appendEnum16(0);
+		disableDefinitions.appendEnum16(1);
+		MessageParser::execute(disableDefinitions);
+
+		CHECK(!range->second.enabled);
+		CHECK(!eventActionService.eventActionDefinitionMap.find(5)->second.enabled);
+		CHECK(!eventActionService.eventActionDefinitionMap.find(1)->second.enabled);
+	}
+
+	SECTION("Trying to disable unknown definitions") {
+		Message disableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
+		disableDefinitions.appendUint8(2);
+		disableDefinitions.appendUint16(1);
+		disableDefinitions.appendEnum16(6);
+		disableDefinitions.appendUint16(0);
+		disableDefinitions.appendEnum16(13);
+		MessageParser::execute(disableDefinitions);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionError));
+		CHECK(ServiceTests::countErrors() == 2);
+	}
+
+	SECTION("Trying to disable an existing event-action definition with the wrong event definition ID") {
+		Message disableDefinitions(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
+		disableDefinitions.appendUint8(2);
+		disableDefinitions.appendEnum16(1);
+		disableDefinitions.appendEnum16(5);
+		disableDefinitions.appendEnum16(0);
+		disableDefinitions.appendEnum16(5);
+		MessageParser::execute(disableDefinitions);
+
+		CHECK(ServiceTests::thrownError(ErrorHandler::EventActionUnknownEventActionDefinitionError));
+		CHECK(ServiceTests::countErrors() == 2);
+	}
+
+	SECTION("Disable all event action definitions") {
+		REQUIRE(!eventActionService.eventActionDefinitionMap.empty());
+
+		Message enableAllDefinitions(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableAllDefinitions.appendUint8(0);
+		MessageParser::execute(enableAllDefinitions);
+
+		Message disableAllDefinitions(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
+		disableAllDefinitions.appendUint8(0);
+		MessageParser::execute(disableAllDefinitions);
+
+		for (const auto& iterator: eventActionService.eventActionDefinitionMap) {
+			CHECK(!iterator.second.enabled);
+		}
+	}
+}
+
+TEST_CASE("Request event-action definition status TC[19,6]", "[service][st19]") {
+	Message statusRequest(EventActionService::ServiceType, EventActionService::MessageType::ReportStatusOfEachEventAction, Message::TC, 0);
+	MessageParser::execute(statusRequest);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message report = ServiceTests::get(0);
+	CHECK(report.messageType == 7);
+}
+
+TEST_CASE("Event-action status report TM[19,7]", "[service][st19]") {
+	Message addDefinitions(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+	addDefinitions.appendUint8(2);
+	addDefinitions.appendEnum16(1);
+	addDefinitions.appendEnum16(0);
+	String<ECSSTCRequestStringSize> data = "0";
+	addDefinitions.appendFixedString(data);
+	addDefinitions.appendEnum16(1);
+	addDefinitions.appendEnum16(2);
+	data = "2";
+	addDefinitions.appendFixedString(data);
+	MessageParser::execute(addDefinitions);
+
+	Message enableDefinition(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC,
+	                         0);
+	enableDefinition.appendUint8(1);
+	enableDefinition.appendEnum16(1);
+	enableDefinition.appendEnum16(0);
+	MessageParser::execute(enableDefinition);
+
+	eventActionService.eventActionStatusReport();
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message report = ServiceTests::get(0);
+	CHECK(report.readUint16() == 2);
+	CHECK(report.readEnum16() == 1);
+	CHECK(report.readEnum16() == 0);
+	CHECK(report.readBoolean() == 1);
+	CHECK(report.readEnum16() == 1);
+	CHECK(report.readEnum16() == 2);
+	CHECK(report.readBoolean() == 0);
+}
+
+TEST_CASE("Enable event-action function TC[19,8]", "[service][st19]") {
+	Message message(EventActionService::ServiceType, EventActionService::MessageType::EnableEventActionFunction, Message::TC, 0);
+	eventActionService.enableEventActionFunction(message);
+	CHECK(eventActionService.getEventActionFunctionStatus());
+}
+
+TEST_CASE("Disable event-action function TC[19,9]", "[service][st19]") {
+	Message message(EventActionService::ServiceType, EventActionService::MessageType::DisableEventActionFunction, Message::TC, 0);
+	eventActionService.disableEventActionFunction(message);
+	CHECK(eventActionService.getEventActionFunctionStatus() == false);
+}
+
+TEST_CASE("Execute a TC request", "[service][st19]") {
+	SECTION("Action: Disable event-action definition") {
+		Message addDefinition(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinition.appendUint8(1);
+		addDefinition.appendEnum16(0);
+		addDefinition.appendEnum16(15);
+
+		Message messageToBeExecuted(EventActionService::ServiceType, EventActionService::MessageType::DisableEventAction, Message::TC, 0);
+		messageToBeExecuted.appendUint8(1);
+		messageToBeExecuted.appendEnum16(0);
+		messageToBeExecuted.appendEnum16(15);
+		addDefinition.appendMessage(messageToBeExecuted, ECSSTCRequestStringSize);
+		MessageParser::execute(addDefinition);
+
+		Message enableDefinition(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinition.appendUint8(1);
+		enableDefinition.appendEnum16(0);
+		enableDefinition.appendEnum16(15);
+		MessageParser::execute(enableDefinition);
+		CHECK(eventActionService.eventActionDefinitionMap.find(15)->second.enabled);
+
+		Message enableFunction(EventActionService::ServiceType, EventActionService::MessageType::EnableEventActionFunction, Message::TC, 0);
+		eventActionService.enableEventActionFunction(enableFunction);
+		REQUIRE(eventActionService.getEventActionFunctionStatus());
+
+		eventActionService.executeAction(15);
+
+		CHECK(!eventActionService.eventActionDefinitionMap.find(15)->second.enabled);
+		CHECK(ServiceTests::countErrors() == 0);
+
+		ServiceTests::reset();
+	}
+
+	SECTION("Action: Add event-action definition") {
+		Message addDefinition(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinition.appendUint8(1);
+		addDefinition.appendEnum16(0);
+		addDefinition.appendEnum16(9);
+
+		Message messageToBeExecuted(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		messageToBeExecuted.appendUint8(1);
+		messageToBeExecuted.appendEnum16(0);
+		messageToBeExecuted.appendEnum16(74);
+		String<ECSSTCRequestStringSize> data = "12345";
+		messageToBeExecuted.appendString(data);
+		addDefinition.appendMessage(messageToBeExecuted, ECSSTCRequestStringSize);
+
+		MessageParser::execute(addDefinition);
+
+		Message enableDefinition(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinition.appendUint8(1);
+		enableDefinition.appendEnum16(0);
+		enableDefinition.appendEnum16(9);
+		MessageParser::execute(enableDefinition);
+
+		eventActionService.executeAction(9);
+
+		auto element = eventActionService.eventActionDefinitionMap.find(74);
+		CHECK(element->second.applicationID == 0);
+		CHECK(element->second.eventDefinitionID == 74);
+		CHECK(!element->second.enabled);
+		CHECK(element->second.request.size() == ECSSTCRequestStringSize);
+	}
+
+	SECTION("Action: ParameterService::ReportParameterValues") {
+		Message addDefinition(EventActionService::ServiceType, EventActionService::MessageType::AddEventAction, Message::TC, 0);
+		addDefinition.appendUint8(1);
+		addDefinition.appendEnum16(0);
+		addDefinition.appendEnum16(10);
+
+		Message TCToBeExecuted = Message(ParameterService::ServiceType, ParameterService::MessageType::ReportParameterValues,
+		                                 Message::TC, 1);
+		TCToBeExecuted.appendUint16(3);
+		TCToBeExecuted.appendUint16(0);
+		TCToBeExecuted.appendUint16(1);
+		TCToBeExecuted.appendUint16(2);
+		addDefinition.appendMessage(TCToBeExecuted, ECSSTCRequestStringSize);
+
+		MessageParser::execute(addDefinition);
+
+		Message enableDefinition(EventActionService::ServiceType, EventActionService::MessageType::EnableEventAction, Message::TC, 0);
+		enableDefinition.appendUint8(1);
+		enableDefinition.appendEnum16(0);
+		enableDefinition.appendEnum16(10);
+		MessageParser::execute(enableDefinition);
+
+		eventActionService.executeAction(10);
+
+		Message report = ServiceTests::get(0);
+		CHECK(report.serviceType == ParameterService::ServiceType);
+		CHECK(report.messageType == ParameterService::MessageType::ParameterValuesReport);
+		CHECK(report.readUint16() == 3);
+		CHECK(report.readUint16() == 0);
+		CHECK(report.readUint8() == 3);
+		CHECK(report.readUint16() == 1);
+		CHECK(report.readUint16() == 7);
+		CHECK(report.readUint16() == 2);
+		CHECK(report.readUint32() == 10);
+	}
+}
\ No newline at end of file
diff --git a/test/Services/EventReportService.cpp b/test/Services/EventReportServiceTests.cpp
similarity index 99%
rename from test/Services/EventReportService.cpp
rename to test/Services/EventReportServiceTests.cpp
index 25a6b54f8a28f689ffb40198fb7ae9c86e1fed58..47f9bfaed247ab89cd56b0cd69a39f58fe0548c9 100644
--- a/test/Services/EventReportService.cpp
+++ b/test/Services/EventReportServiceTests.cpp
@@ -1,8 +1,8 @@
-#include <catch2/catch.hpp>
-#include <Services/EventReportService.hpp>
 #include <Message.hpp>
-#include "ServiceTests.hpp"
+#include <Services/EventReportService.hpp>
+#include <catch2/catch_all.hpp>
 #include <cstring>
+#include "ServiceTests.hpp"
 
 EventReportService& eventReportService = Services.eventReport;
 
diff --git a/test/Services/FunctionManagementService.cpp b/test/Services/FunctionManagementServiceTests.cpp
similarity index 94%
rename from test/Services/FunctionManagementService.cpp
rename to test/Services/FunctionManagementServiceTests.cpp
index b6548d79b46bbcb482431b602130084874cd10b7..cf9f7a95db13cb5ebc5295c49cabcea0c78d7006 100644
--- a/test/Services/FunctionManagementService.cpp
+++ b/test/Services/FunctionManagementServiceTests.cpp
@@ -1,9 +1,9 @@
-#include "catch2/catch.hpp"
 #include "Services/FunctionManagementService.hpp"
-#include "Services/RequestVerificationService.hpp"
+#include <iostream>
 #include "ServicePool.hpp"
 #include "ServiceTests.hpp"
-#include <iostream>
+#include "Services/RequestVerificationService.hpp"
+#include "catch2/catch_all.hpp"
 
 FunctionManagementService& fms = Services.functionManagement;
 
@@ -20,7 +20,7 @@ TEST_CASE("ST[08] - Call Tests") {
 
 		fms.include(String<ECSSFunctionNameLength>("test"), &test);
 		Message msg(FunctionManagementService::ServiceType, FunctionManagementService::MessageType::PerformFunction,
-			Message::TC, 1);
+		            Message::TC, 1);
 
 		msg.appendFixedString(String<ECSSFunctionNameLength>("test"));
 		msg.appendByte(199);
@@ -52,8 +52,7 @@ TEST_CASE("ST[08] - Call Tests") {
 		fms.include(String<ECSSFunctionNameLength>("test"), &test);
 		Message msg(FunctionManagementService::ServiceType, FunctionManagementService::MessageType::PerformFunction, Message::TC, 1);
 		msg.appendFixedString(String<ECSSFunctionNameLength>("test"));
-		msg.appendString(String<65>
-		    ("eqrhjweghjhwqgthjkrghthjkdsfhgsdfhjsdjsfdhgkjdfsghfjdgkdfsgdfgsgd"));
+		msg.appendString(String<65>("eqrhjweghjhwqgthjkrghthjkdsfhgsdfhjsdjsfdhgkjdfsghfjdgkdfsgdfgsgd"));
 		MessageParser::execute(msg);
 
 		CHECK(ServiceTests::get(0).messageType == RequestVerificationService::MessageType::FailedStartOfExecution);
diff --git a/test/Services/HousekeepingService.cpp b/test/Services/HousekeepingServiceTests.cpp
similarity index 57%
rename from test/Services/HousekeepingService.cpp
rename to test/Services/HousekeepingServiceTests.cpp
index 1aec796a3d4f5aaf3a1dc706e7e6adbf1f7fd64c..b1787fa73c14aa08fdb916d8ac528a0c50722806 100644
--- a/test/Services/HousekeepingService.cpp
+++ b/test/Services/HousekeepingServiceTests.cpp
@@ -1,8 +1,8 @@
-#include "Services/HousekeepingService.hpp"
 #include <iostream>
 #include "Message.hpp"
 #include "ServiceTests.hpp"
-#include "catch2/catch.hpp"
+#include "Services/HousekeepingService.hpp"
+#include "catch2/catch_all.hpp"
 #include "etl/algorithm.h"
 
 HousekeepingService& housekeepingService = Services.housekeeping;
@@ -252,8 +252,7 @@ TEST_CASE("Delete housekeeping structure") {
 TEST_CASE("Enable the periodic generation of housekeeping structures") {
 	SECTION("Both valid and invalid structure IDs in same request") {
 		initializeHousekeepingStructures();
-		Message request2(HousekeepingService::ServiceType,
-		                 HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1);
+		Message request2(HousekeepingService::ServiceType, HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1);
 		uint8_t numOfStructs = 5;
 		uint8_t idsToEnable[5] = {1, 3, 4, 6, 7};
 		request2.appendUint8(numOfStructs);
@@ -532,8 +531,12 @@ TEST_CASE("Append parameters in housekeeping report structure") {
 		Message request(HousekeepingService::ServiceType,
 		                HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1);
 
-		uint16_t numOfSimplyCommutatedParams = 13;
-		etl::vector<uint16_t, 13> simplyCommutatedIds = {0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 16};
+		uint16_t numOfSimplyCommutatedParams = 34;
+
+		etl::vector<uint16_t, 34> simplyCommutatedIds;
+		for (uint16_t i = 0; i < 34; i++) {
+			simplyCommutatedIds.push_back(i);
+		}
 
 		request.appendUint8(structId);
 		request.appendUint16(numOfSimplyCommutatedParams);
@@ -546,11 +549,11 @@ TEST_CASE("Append parameters in housekeeping report structure") {
 
 		MessageParser::execute(request);
 
-		REQUIRE(housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() == 10);
-		CHECK(ServiceTests::count() == 2);
+		REQUIRE(housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() == 30);
+		CHECK(ServiceTests::count() == 4);
 		CHECK(ServiceTests::countThrownErrors(
 		          ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters) == 1);
-		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter) == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter) == 3);
 
 		ServiceTests::reset();
 		Services.reset();
@@ -623,65 +626,470 @@ TEST_CASE("Reporting of housekeeping structure periodic properties") {
 }
 
 TEST_CASE("Periodically reporting Housekeeping Structures") {
-    uint32_t nextCollection = 0;
+	uint32_t nextCollection = 0;
 	uint32_t currentTime = 0;
 	uint32_t previousTime = 0;
-    SECTION("Non existent structures") {
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
-        CHECK(ServiceTests::count() == 0);
-        CHECK(nextCollection == std::numeric_limits<uint32_t>::max());
-    }
-    SECTION("Collection Intervals set to max") {
-        initializeHousekeepingStructures();
-        for (auto &housekeepingStructure: housekeepingService.housekeepingStructures) {
-            housekeepingStructure.second.collectionInterval = std::numeric_limits<uint32_t>::max();
-        }
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
-        CHECK(ServiceTests::count() == 0);
-        CHECK(nextCollection == std::numeric_limits<uint32_t>::max());
-    }
-    SECTION("Calculating properly defined collection intervals") {
-        housekeepingService.housekeepingStructures.at(0).collectionInterval = 900;
-        housekeepingService.housekeepingStructures.at(4).collectionInterval = 1000;
-        housekeepingService.housekeepingStructures.at(6).collectionInterval = 2700;
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+	SECTION("Non existent structures") {
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		CHECK(ServiceTests::count() == 0);
+		CHECK(nextCollection == std::numeric_limits<uint32_t>::max());
+	}
+	SECTION("Collection Intervals set to max") {
+		initializeHousekeepingStructures();
+		for (auto& housekeepingStructure: housekeepingService.housekeepingStructures) {
+			housekeepingStructure.second.collectionInterval = std::numeric_limits<uint32_t>::max();
+		}
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		CHECK(ServiceTests::count() == 0);
+		CHECK(nextCollection == std::numeric_limits<uint32_t>::max());
+	}
+	SECTION("Calculating properly defined collection intervals") {
+		housekeepingService.housekeepingStructures.at(0).collectionInterval = 900;
+		housekeepingService.housekeepingStructures.at(4).collectionInterval = 1000;
+		housekeepingService.housekeepingStructures.at(6).collectionInterval = 2700;
+		housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus = true;
+		housekeepingService.housekeepingStructures.at(4).periodicGenerationActionStatus = true;
+		housekeepingService.housekeepingStructures.at(6).periodicGenerationActionStatus = true;
+
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
 		previousTime = currentTime;
 		currentTime += nextCollection;
-        CHECK(currentTime == 900);
-        CHECK(ServiceTests::count() == 0);
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		CHECK(currentTime == 900);
+		CHECK(ServiceTests::count() == 0);
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
 		previousTime = currentTime;
 		currentTime += nextCollection;
-        CHECK(currentTime == 1000);
-        CHECK(ServiceTests::count() == 1);
+		CHECK(currentTime == 1000);
+		CHECK(ServiceTests::count() == 1);
 		currentTime += 6;
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
 		previousTime = currentTime;
 		currentTime += nextCollection;
-        CHECK(currentTime == 1800);
-        CHECK(ServiceTests::count() == 2);
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		CHECK(currentTime == 1800);
+		CHECK(ServiceTests::count() == 2);
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
 		previousTime = currentTime;
 		currentTime += nextCollection;
-        CHECK(ServiceTests::count() == 3);
-        CHECK(currentTime == 2000);
+		CHECK(ServiceTests::count() == 3);
+		CHECK(currentTime == 2000);
 		currentTime += 15;
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
 		previousTime = currentTime;
 		currentTime += nextCollection;
-        CHECK(ServiceTests::count() == 4);
-        CHECK(currentTime == 2700);
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		CHECK(ServiceTests::count() == 4);
+		CHECK(currentTime == 2700);
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
 		previousTime = currentTime;
 		currentTime += nextCollection;
-        CHECK(ServiceTests::count() == 6);
-        CHECK(currentTime == 3000);
-    }
-    SECTION("Collection Intervals set to 0") {
-        for (auto &housekeepingStructure: housekeepingService.housekeepingStructures) {
-            housekeepingStructure.second.collectionInterval = 0;
-        }
-        nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
-        CHECK(nextCollection == 0);
-    }
-}
\ No newline at end of file
+		CHECK(ServiceTests::count() == 6);
+		CHECK(currentTime == 3000);
+	}
+	SECTION("Collection Intervals set to 0") {
+		for (auto& housekeepingStructure: housekeepingService.housekeepingStructures) {
+			housekeepingStructure.second.periodicGenerationActionStatus = true;
+			housekeepingStructure.second.collectionInterval = 0;
+		}
+		nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection);
+		CHECK(nextCollection == 0);
+	}
+}
+
+TEST_CASE("Check getPeriodicGenerationActionStatus function") {
+	SECTION("Returns periodic generation status") {
+		initializeHousekeepingStructures();
+		housekeepingService.housekeepingStructures.at(4).periodicGenerationActionStatus = true;
+
+		CHECK(housekeepingService.getPeriodicGenerationActionStatus(0) == false);
+		CHECK(housekeepingService.getPeriodicGenerationActionStatus(4) == true);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Invalid structure ID in request") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.getPeriodicGenerationActionStatus(1);
+
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check getStruct function") {
+	SECTION("Returns periodic generation status") {
+		Message request(HousekeepingService::ServiceType,
+		                HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1);
+		uint8_t idToCreate = 2;
+		uint32_t interval = 7;
+		uint16_t numOfSimplyCommutatedParams = 3;
+		etl::array<uint16_t, 3> simplyCommutatedIds = {4, 5, 8};
+
+		request.appendUint8(idToCreate);
+		request.appendUint32(interval);
+		request.appendUint16(numOfSimplyCommutatedParams);
+		for (auto& id: simplyCommutatedIds) {
+			request.appendUint16(id);
+		}
+
+		MessageParser::execute(request);
+		HousekeepingStructure newStruct = housekeepingService.housekeepingStructures[idToCreate];
+
+		CHECK(std::addressof(housekeepingService.housekeepingStructures.at(2)) == std::addressof(housekeepingService.getStruct(2)->get()));
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Invalid structure ID in request") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.getStruct(1);
+
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check getCollectionInterval function") {
+	SECTION("Returns Collection Interval") {
+		initializeHousekeepingStructures();
+
+		CHECK(housekeepingService.getCollectionInterval(0) == 7);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Invalid structure ID in request") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.getCollectionInterval(1);
+
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check setPeriodicGenerationActionStatus function") {
+	SECTION("Set Periodic Generation Action Status") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.setPeriodicGenerationActionStatus(0, true);
+
+		CHECK(housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus == true);
+		CHECK(housekeepingService.housekeepingStructures.at(4).periodicGenerationActionStatus == false);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Invalid structure ID in request") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.setPeriodicGenerationActionStatus(1, true);
+
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check setCollectionInterval function") {
+	SECTION("Sets Collection Interval") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.setCollectionInterval(0, 8);
+
+		CHECK(housekeepingService.housekeepingStructures.at(0).collectionInterval == 8);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Invalid structure ID in request") {
+		initializeHousekeepingStructures();
+
+		housekeepingService.setCollectionInterval(1, 8);
+
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check structExists function") {
+	SECTION("Check if it returns correct boolean") {
+		initializeHousekeepingStructures();
+
+		CHECK(housekeepingService.structExists(0) == true);
+		CHECK(housekeepingService.structExists(1) == false);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasNonExistingStructExecutionError function") {
+	SECTION("Check if it returns correct boolean") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1);
+		initializeHousekeepingStructures();
+
+		CHECK(housekeepingService.hasNonExistingStructExecutionError(0, request) == false);
+		CHECK(housekeepingService.hasNonExistingStructExecutionError(1, request) == true);
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasNonExistingStructError function") {
+	SECTION("Check if it returns correct boolean") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1);
+		initializeHousekeepingStructures();
+
+		CHECK(housekeepingService.hasNonExistingStructError(0, request) == false);
+		CHECK(housekeepingService.hasNonExistingStructError(1, request) == true);
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::RequestedNonExistingStructure) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasNonExistingStructInternalError function") {
+	SECTION("Check if it returns correct boolean") {
+		initializeHousekeepingStructures();
+
+		CHECK(housekeepingService.hasNonExistingStructInternalError(0) == false);
+		CHECK(housekeepingService.hasNonExistingStructInternalError(1) == true);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasAlreadyExistingParameterError function") {
+	SECTION("Check if it returns correct boolean") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1);
+		uint8_t idToCreate = 2;
+		uint32_t interval = 7;
+		uint16_t numOfSimplyCommutatedParams = 3;
+		etl::array<uint16_t, 3> simplyCommutatedIds = {4, 5, 8};
+
+		request.appendUint8(idToCreate);
+		request.appendUint32(interval);
+		request.appendUint16(numOfSimplyCommutatedParams);
+		for (auto& id: simplyCommutatedIds) {
+			request.appendUint16(id);
+		}
+
+		MessageParser::execute(request);
+		HousekeepingStructure newStruct = housekeepingService.housekeepingStructures[idToCreate];
+
+		auto& housekeepingStructure = housekeepingService.getStruct(idToCreate)->get();
+
+		CHECK(housekeepingService.hasAlreadyExistingParameterError(housekeepingStructure, 6, request) == false);
+		CHECK(housekeepingService.hasAlreadyExistingParameterError(housekeepingStructure, 5, request) == true);
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasAlreadyExistingStructError function") {
+	SECTION("Check if it returns correct boolean") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1);
+		initializeHousekeepingStructures();
+
+		CHECK(housekeepingService.hasAlreadyExistingStructError(1, request) == false);
+		CHECK(housekeepingService.hasAlreadyExistingStructError(0, request) == true);
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedAlreadyExistingStructure) == 1);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasExceededMaxNumOfHousekeepingStructsError function") {
+	SECTION("Check if it returns correct boolean") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1);
+		uint8_t idsToCreate[11] = {1, 3, 5, 7, 8, 9, 10, 11, 12, 13, 14};
+		uint16_t numOfSimplyCommutatedParams = 3;
+		etl::vector<uint16_t, 3> simplyCommutatedIds = {8, 4, 5};
+		uint32_t interval = 12;
+
+		REQUIRE(housekeepingService.housekeepingStructures.size() == 0);
+
+		for (auto& structId: idsToCreate) {
+			request.appendUint8(structId);
+			request.appendUint32(interval);
+			request.appendUint16(numOfSimplyCommutatedParams);
+			for (auto& parameterId: simplyCommutatedIds) {
+				request.appendUint16(parameterId);
+			}
+			MessageParser::execute(request);
+
+			if (housekeepingService.housekeepingStructures.size() < 9) {
+				CHECK(housekeepingService.hasExceededMaxNumOfHousekeepingStructsError(request) == false);
+			}
+		}
+
+		REQUIRE(housekeepingService.housekeepingStructures.size() == 10);
+
+		CHECK(housekeepingService.hasExceededMaxNumOfHousekeepingStructsError(request) == true);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfHousekeepingStructures) == 2);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasRequestedAppendToEnabledHousekeepingError function") {
+	SECTION("Error exists") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1);
+		// Enable 1 periodic struct with id=0
+		HousekeepingStructure newStruct;
+		newStruct.structureId = 0;
+		newStruct.periodicGenerationActionStatus = true;
+		housekeepingService.housekeepingStructures.insert({0, newStruct});
+
+		request.appendUint8(1);
+		request.appendUint8(0);
+		MessageParser::execute(request);
+
+		REQUIRE(housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus);
+		Message request2(HousekeepingService::ServiceType, HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1);
+		uint8_t structId = 0;
+		request2.appendUint8(structId);
+		MessageParser::execute(request2);
+
+		CHECK(housekeepingService.hasRequestedAppendToEnabledHousekeepingError(newStruct, request) == true);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedAppendToEnabledHousekeeping) == 2);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Error doesn't exist") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1);
+		// Enable 1 periodic struct with id=0
+		HousekeepingStructure newStruct;
+		newStruct.structureId = 0;
+		newStruct.periodicGenerationActionStatus = false;
+		housekeepingService.housekeepingStructures.insert({0, newStruct});
+
+		request.appendUint8(1);
+		request.appendUint8(0);
+		MessageParser::execute(request);
+
+		REQUIRE(housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus);
+		Message request2(HousekeepingService::ServiceType, HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1);
+		uint8_t structId = 0;
+		request2.appendUint8(structId);
+		MessageParser::execute(request2);
+
+
+		CHECK(housekeepingService.hasRequestedAppendToEnabledHousekeepingError(newStruct, request) == false);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasRequestedDeletionOfEnabledHousekeepingError function") {
+	SECTION("Error exists") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::DeleteHousekeepingReportStructure, Message::TC, 1);
+		HousekeepingStructure periodicStruct;
+		periodicStruct.structureId = 4;
+		periodicStruct.periodicGenerationActionStatus = true;
+		housekeepingService.housekeepingStructures.insert({4, periodicStruct});
+
+		uint8_t numOfStructs = 1;
+		uint8_t structureId = 4;
+		request.appendUint8(numOfStructs);
+		request.appendUint8(structureId);
+
+		MessageParser::execute(request);
+
+
+		CHECK(housekeepingService.hasRequestedDeletionOfEnabledHousekeepingError(4, request) == true);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedDeletionOfEnabledHousekeeping) == 2);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+	SECTION("Error doesn't exists") {
+		Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::DeleteHousekeepingReportStructure, Message::TC, 1);
+		HousekeepingStructure periodicStruct;
+		periodicStruct.structureId = 4;
+		periodicStruct.periodicGenerationActionStatus = false;
+		housekeepingService.housekeepingStructures.insert({4, periodicStruct});
+
+		uint8_t numOfStructs = 1;
+		uint8_t structureId = 4;
+		request.appendUint8(numOfStructs);
+		request.appendUint8(structureId);
+
+		MessageParser::execute(request);
+
+
+		CHECK(housekeepingService.hasRequestedDeletionOfEnabledHousekeepingError(4, request) == false);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
+
+TEST_CASE("Check hasExceededMaxNumOfSimplyCommutatedParamsError function") {
+	SECTION("Check if it returns correct boolean") {
+		initializeHousekeepingStructures();
+		uint8_t structId = 6;
+		Message request(HousekeepingService::ServiceType,
+		                HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1);
+
+		uint16_t numOfSimplyCommutatedParams = 34;
+
+		etl::vector<uint16_t, 34> simplyCommutatedIds;
+		for (uint16_t i = 0; i < 34; i++) {
+			simplyCommutatedIds.push_back(i);
+		}
+
+		request.appendUint8(structId);
+		request.appendUint16(numOfSimplyCommutatedParams);
+		for (auto& id: simplyCommutatedIds) {
+			request.appendUint16(id);
+
+			if (housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() < 30) {
+				CHECK(housekeepingService.hasExceededMaxNumOfSimplyCommutatedParamsError(housekeepingService.housekeepingStructures[structId], request) == false);
+			}
+		}
+		REQUIRE(housekeepingService.housekeepingStructures.find(structId) != housekeepingService.housekeepingStructures.end());
+		REQUIRE(housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() == 3);
+
+		MessageParser::execute(request);
+
+		REQUIRE(housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() == 30);
+
+		CHECK(housekeepingService.hasExceededMaxNumOfSimplyCommutatedParamsError(housekeepingService.housekeepingStructures[structId], request) == true);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters) == 2);
+
+		ServiceTests::reset();
+		Services.reset();
+	}
+}
diff --git a/test/Services/LargePacketTransferService.cpp b/test/Services/LargePacketTransferServiceTests.cpp
similarity index 96%
rename from test/Services/LargePacketTransferService.cpp
rename to test/Services/LargePacketTransferServiceTests.cpp
index 100e7be06eefab28b11f39c6aa1dac58066f72eb..3cdb99433cb6420435bf3e2eb769dafdb6fa7418 100644
--- a/test/Services/LargePacketTransferService.cpp
+++ b/test/Services/LargePacketTransferServiceTests.cpp
@@ -1,10 +1,10 @@
-#include <catch2/catch.hpp>
-#include <Services/LargePacketTransferService.hpp>
 #include <Message.hpp>
-#include "ServiceTests.hpp"
+#include <Services/LargePacketTransferService.hpp>
+#include <catch2/catch_all.hpp>
 #include <cstring>
 #include <etl/String.hpp>
 #include "ECSS_Definitions.hpp"
+#include "ServiceTests.hpp"
 
 LargePacketTransferService& lPT = Services.largePacketTransferService;
 
@@ -70,19 +70,19 @@ TEST_CASE("Last Uplink Part TC[13,11]", "[service][st13]") {
 
 TEST_CASE("Split function", "[no][service]") {
 	Message message(13, 0, Message::TC, 0);
-	for (uint16_t i = 0; i < 800; i++){
+	for (uint16_t i = 0; i < 800; i++) {
 		message.appendUint8(UINT8_MAX);
 	}
 	uint16_t largeMessageTransactionIdentifier = 1;
 	lPT.split(message, largeMessageTransactionIdentifier);
 	Message message5(13, 0, Message::TC, 0);
 
-	for (int i = 0; i < 4; i++){
+	for (int i = 0; i < 4; i++) {
 		uint16_t partSequenceNumber = i;
 		CHECK(largeMessageTransactionIdentifier == ServiceTests::get(i).readUint16());
 		CHECK(partSequenceNumber == ServiceTests::get(i).readUint16());
 		CHECK(ECSSMaxFixedOctetStringSize == ServiceTests::get(i).readUint16());
-		for (int j = 0; j < 256; j++){
+		for (int j = 0; j < 256; j++) {
 			message5.appendUint8(ServiceTests::get(i).readUint8());
 		}
 	}
diff --git a/test/Services/MemoryManagementService.cpp b/test/Services/MemoryManagementServiceTests.cpp
similarity index 90%
rename from test/Services/MemoryManagementService.cpp
rename to test/Services/MemoryManagementServiceTests.cpp
index 5e99f191027fae3b4d2ed6c9f9608b8a14a3aa74..2ad8097ee385bcc0a64ae88ad54da3ad60993571 100644
--- a/test/Services/MemoryManagementService.cpp
+++ b/test/Services/MemoryManagementServiceTests.cpp
@@ -1,8 +1,8 @@
-#include <catch2/catch.hpp>
-#include <Services/MemoryManagementService.hpp>
 #include <Message.hpp>
-#include "ServiceTests.hpp"
+#include <Services/MemoryManagementService.hpp>
+#include <catch2/catch_all.hpp>
 #include "Helpers/CRCHelper.hpp"
+#include "ServiceTests.hpp"
 
 MemoryManagementService& memMangService = Services.memoryManagement;
 
@@ -16,18 +16,20 @@ TEST_CASE("TC[6,2]", "[service][st06]") {
 
 	Message receivedPacket = Message(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::LoadRawMemoryDataAreas, Message::TC, 1);
 	receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID
-	receivedPacket.appendUint16(2); // Iteration count
-	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(pStr)); // Start address
+	receivedPacket.appendUint16(2);                                          // Iteration count
+	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(pStr));           // Start address
 	receivedPacket.appendOctetString(String<2>(data));
-	receivedPacket.appendBits(16, CRCHelper::calculateCRC(data, 2)); // Append CRC
+	receivedPacket.appendBits(16, CRCHelper::calculateCRC(data, 2));   // Append CRC
 	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(pStr + 2)); // Start address
-	receivedPacket.appendOctetString(String<1>(data)); // Append CRC
+	receivedPacket.appendOctetString(String<1>(data));                 // Append CRC
 	receivedPacket.appendBits(16, CRCHelper::calculateCRC(data, 1));
 	MessageParser::execute(receivedPacket);
 
 	CHECK(pStr[0] == 'h');
 	CHECK(pStr[1] == 'R');
 	CHECK(pStr[2] == 'h');
+
+	free(pStr);
 }
 
 TEST_CASE("TC[6,5]", "[service][st06]") {
@@ -39,9 +41,9 @@ TEST_CASE("TC[6,5]", "[service][st06]") {
 	uint16_t readSize = 0, checksum = 0;
 
 	Message receivedPacket = Message(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::DumpRawMemoryData, Message::TC, 1);
-	receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID
-	receivedPacket.appendUint16(3); // Iteration count (Equal to 3 test strings)
-	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(testString_1)); // Start address
+	receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL);     // Memory ID
+	receivedPacket.appendUint16(3);                                              // Iteration count (Equal to 3 test strings)
+	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(testString_1));       // Start address
 	receivedPacket.appendUint16(sizeof(testString_1) / sizeof(testString_1[0])); // Data read length
 
 	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(testString_2));
@@ -100,9 +102,9 @@ TEST_CASE("TC[6,9]", "[service][st06]") {
 	uint16_t readSize = 0, checksum = 0;
 
 	Message receivedPacket = Message(MemoryManagementService::ServiceType, MemoryManagementService::MessageType::CheckRawMemoryData, Message::TC, 1);
-	receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID
-	receivedPacket.appendUint16(2); // Iteration count
-	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(testString_1)); // Start address
+	receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL);     // Memory ID
+	receivedPacket.appendUint16(2);                                              // Iteration count
+	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(testString_1));       // Start address
 	receivedPacket.appendUint16(sizeof(testString_1) / sizeof(testString_1[0])); // Data read length
 
 	receivedPacket.appendUint64(reinterpret_cast<uint64_t>(testString_2));
diff --git a/test/Services/OnBoardMonitoringService.cpp b/test/Services/OnBoardMonitoringServiceTests.cpp
similarity index 99%
rename from test/Services/OnBoardMonitoringService.cpp
rename to test/Services/OnBoardMonitoringServiceTests.cpp
index 548cf83969d2fe97e21987e877dc6b147e7b3147..6e9074823189f79d775de4565c1b2509aa62aa7e 100644
--- a/test/Services/OnBoardMonitoringService.cpp
+++ b/test/Services/OnBoardMonitoringServiceTests.cpp
@@ -1,10 +1,10 @@
-#include <catch2/catch.hpp>
-#include <Services/OnBoardMonitoringService.hpp>
 #include <Message.hpp>
-#include "ServiceTests.hpp"
-#include <etl/array.h>
-#include <etl/String.hpp>
 #include <ServicePool.hpp>
+#include <Services/OnBoardMonitoringService.hpp>
+#include <catch2/catch_all.hpp>
+#include <etl/String.hpp>
+#include <etl/array.h>
+#include "ServiceTests.hpp"
 
 OnBoardMonitoringService& onBoardMonitoringService = Services.onBoardMonitoringService;
 
diff --git a/test/Services/ParameterService.cpp b/test/Services/ParameterServiceTests.cpp
similarity index 98%
rename from test/Services/ParameterService.cpp
rename to test/Services/ParameterServiceTests.cpp
index 018bc9af98dabca06187836692cdf81695b5741c..fc80719b56751228fb6bfdf20658fbdf8ca1ff95 100644
--- a/test/Services/ParameterService.cpp
+++ b/test/Services/ParameterServiceTests.cpp
@@ -1,8 +1,8 @@
-#include "catch2/catch.hpp"
-#include "Message.hpp"
-#include "ServiceTests.hpp"
 #include "Services/ParameterService.hpp"
+#include "Message.hpp"
 #include "Parameters/PlatformParameters.hpp"
+#include "ServiceTests.hpp"
+#include "catch2/catch_all.hpp"
 
 static void resetParameterValues() {
 	PlatformParameters::parameter1.setValue(3);
@@ -13,7 +13,7 @@ static void resetParameterValues() {
 TEST_CASE("Parameter Report Subservice") {
 	SECTION("All requested parameters invalid") {
 		Message request = Message(ParameterService::ServiceType, ParameterService::MessageType::ReportParameterValues,
-		                          Message::TC, 1);
+		                          Message::TC, ApplicationId);
 		request.appendUint16(3);
 		request.appendUint16(54432);
 		request.appendUint16(60000);
diff --git a/test/Services/ParameterStatisticsService.cpp b/test/Services/ParameterStatisticsServiceTests.cpp
similarity index 66%
rename from test/Services/ParameterStatisticsService.cpp
rename to test/Services/ParameterStatisticsServiceTests.cpp
index fbc1c361efd386cfd25a92d5a53c048d0212280c..25ae3c908379fff554f93e189be57bc00f29bfa7 100644
--- a/test/Services/ParameterStatisticsService.cpp
+++ b/test/Services/ParameterStatisticsServiceTests.cpp
@@ -1,8 +1,8 @@
 #include <iostream>
-#include "catch2/catch.hpp"
+#include "ECSS_Definitions.hpp"
 #include "Message.hpp"
 #include "ServiceTests.hpp"
-#include "ECSS_Definitions.hpp"
+#include "catch2/catch_all.hpp"
 
 /**
  * System-statistics initialization, so there are actual statistics in the map to work with.
@@ -27,12 +27,8 @@ void initializeStatistics(uint16_t interval1, uint16_t interval2) {
 	Services.parameterStatistics.statisticsMap.insert({id2, stat2});
 }
 
-void resetSystem() {
-	Services.parameterStatistics.statisticsMap.clear();
-}
-
 TEST_CASE("Reporting of statistics") {
-	SECTION("Report statistics, with auto statistic reset disabled") {
+	SECTION("Report statistics, with auto statistic reset disabled with TC") {
 		initializeStatistics(6, 7);
 		Message request = Message(ParameterStatisticsService::ServiceType,
 		                          ParameterStatisticsService::MessageType::ReportParameterStatistics, Message::TC, 1);
@@ -44,33 +40,33 @@ TEST_CASE("Reporting of statistics") {
 		Message report = ServiceTests::get(0);
 		CHECK(report.serviceType == ParameterStatisticsService::ServiceType);
 		CHECK(report.messageType == ParameterStatisticsService::MessageType::ParameterStatisticsReport);
-		CHECK(report.readUint16() == 1); // start time
-		CHECK(report.readUint16() == 1); // end time
-		CHECK(report.readUint16() == 2); // number of parameters reported
+		CHECK(report.readUint32() == 86769000); // start time
+		CHECK(report.readUint32() == 86769000); // end time
+		CHECK(report.readUint16() == 2);        // number of parameters reported
 		// Parameter B
-		CHECK(report.readUint16() == 5); // ID-2
-		CHECK(report.readUint16() == 6); // number of samples
-		CHECK(report.readFloat() == 13); // max value
-		CHECK(report.readUint32() == 0); // max time
-		CHECK(report.readFloat() == 3); // min value
-		CHECK(report.readUint32() == 0); // min time
-		CHECK(report.readFloat() == 8); // mean
-		CHECK(report.readFloat() == Approx(3.41565).epsilon(0.01));
+		CHECK(report.readUint16() == 5);        // ID-2
+		CHECK(report.readUint16() == 6);        // number of samples
+		CHECK(report.readFloat() == 13);        // max value
+		CHECK(report.readUint32() == 86769000); // max time
+		CHECK(report.readFloat() == 3);         // min value
+		CHECK(report.readUint32() == 86769000); // min time
+		CHECK(report.readFloat() == 8);         // mean
+		CHECK(report.readFloat() == Catch::Approx(3.41565).epsilon(0.01));
 		// Parameter A
-		CHECK(report.readUint16() == 7); // ID-1
-		CHECK(report.readUint16() == 3); // number of samples
-		CHECK(report.readFloat() == 5); // max value
-		CHECK(report.readUint32() == 0); // max time
-		CHECK(report.readFloat() == 1); // min value
-		CHECK(report.readUint32() == 0); // min time
-		CHECK(report.readFloat() == 3); // mean
+		CHECK(report.readUint16() == 7);                  // ID-1
+		CHECK(report.readUint16() == 3);                  // number of samples
+		CHECK(report.readFloat() == 5);                   // max value
+		CHECK(report.readUint32() == 86769000);           // max time
+		CHECK(report.readFloat() == 1);                   // min value
+		CHECK(report.readUint32() == 86769000);           // min time
+		CHECK(report.readFloat() == 3);                   // mean
 		CHECK(static_cast<int>(report.readFloat()) == 1); // stddev
 
 		CHECK(not Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
 		CHECK(not Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
 	}
 
-	SECTION("Report statistics, with auto statistics reset enabled") {
+	SECTION("Report statistics, with auto statistics reset enabled with TC") {
 		Message request = Message(ParameterStatisticsService::ServiceType,
 		                          ParameterStatisticsService::MessageType::ReportParameterStatistics, Message::TC, 1);
 		Services.parameterStatistics.hasAutomaticStatisticsReset = true;
@@ -95,10 +91,66 @@ TEST_CASE("Reporting of statistics") {
 
 		CHECK(Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
 		CHECK(Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
+	}
 
-		resetSystem();
-		ServiceTests::reset();
-		Services.reset();
+	ServiceTests::reset();
+
+	SECTION("Report statistics, with auto statistic reset disabled without TC") {
+		initializeStatistics(6, 7);
+		Services.parameterStatistics.reportParameterStatistics(false);
+		Services.parameterStatistics.hasAutomaticStatisticsReset = false;
+
+		CHECK(ServiceTests::count() == 1);
+
+		Message report = ServiceTests::get(0);
+		CHECK(report.serviceType == ParameterStatisticsService::ServiceType);
+		CHECK(report.messageType == ParameterStatisticsService::MessageType::ParameterStatisticsReport);
+		CHECK(report.readUint32() == 86769000); // start time
+		CHECK(report.readUint32() == 86769000); // end time
+		CHECK(report.readUint16() == 2);        // number of parameters reported
+		// Parameter B
+		CHECK(report.readUint16() == 5);        // ID-2
+		CHECK(report.readUint16() == 6);        // number of samples
+		CHECK(report.readFloat() == 13);        // max value
+		CHECK(report.readUint32() == 86769000); // max time
+		CHECK(report.readFloat() == 3);         // min value
+		CHECK(report.readUint32() == 86769000); // min time
+		CHECK(report.readFloat() == 8);         // mean
+		CHECK(report.readFloat() == Catch::Approx(3.41565).epsilon(0.01));
+		// Parameter A
+		CHECK(report.readUint16() == 7);                  // ID-1
+		CHECK(report.readUint16() == 3);                  // number of samples
+		CHECK(report.readFloat() == 5);                   // max value
+		CHECK(report.readUint32() == 86769000);           // max time
+		CHECK(report.readFloat() == 1);                   // min value
+		CHECK(report.readUint32() == 86769000);           // min time
+		CHECK(report.readFloat() == 3);                   // mean
+		CHECK(static_cast<int>(report.readFloat()) == 1); // stddev
+
+		CHECK(not Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
+		CHECK(not Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
+	}
+
+	SECTION("Report statistics, with auto statistics reset enabled without TC") {
+		Services.parameterStatistics.hasAutomaticStatisticsReset = true;
+		Services.parameterStatistics.reportParameterStatistics(false);
+
+		CHECK(Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
+		CHECK(Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
+	}
+
+	SECTION("Report statistics, with auto statistics reset disabled, but reset is given with args, without TC") {
+		Services.parameterStatistics.statisticsMap[5].mean = 5;
+		Services.parameterStatistics.statisticsMap[7].mean = 3;
+		Services.parameterStatistics.hasAutomaticStatisticsReset = false;
+
+		CHECK(not Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
+		CHECK(not Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
+
+		Services.parameterStatistics.reportParameterStatistics(true);
+
+		CHECK(Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
+		CHECK(Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
 	}
 }
 
@@ -116,9 +168,7 @@ TEST_CASE("Resetting the parameter statistics") {
 		CHECK(Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
 		CHECK(Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 
 	SECTION("Reset without TC") {
@@ -132,9 +182,7 @@ TEST_CASE("Resetting the parameter statistics") {
 		CHECK(Services.parameterStatistics.statisticsMap[5].statisticsAreInitialized());
 		CHECK(Services.parameterStatistics.statisticsMap[7].statisticsAreInitialized());
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 }
 
@@ -145,14 +193,14 @@ TEST_CASE("Enable the periodic reporting of statistics") {
 		    Message(ParameterStatisticsService::ServiceType,
 		            ParameterStatisticsService::MessageType::EnablePeriodicParameterReporting, Message::TC, 1);
 		request.appendUint16(6);
-		Services.parameterStatistics.periodicStatisticsReportingStatus = false;
-		CHECK(Services.parameterStatistics.reportingInterval == 5);
+		Services.parameterStatistics.setPeriodicReportingStatus(false);
+		CHECK(Services.parameterStatistics.getReportingIntervalMs() == 700);
 
 		MessageParser::execute(request);
 		CHECK(ServiceTests::count() == 0);
 
-		CHECK(Services.parameterStatistics.periodicStatisticsReportingStatus == true);
-		CHECK(Services.parameterStatistics.reportingInterval == 6);
+		CHECK(Services.parameterStatistics.getPeriodicReportingStatus() == true);
+		CHECK(Services.parameterStatistics.getReportingIntervalMs() == 6);
 	}
 
 	SECTION("Invalid reporting interval requested") {
@@ -160,18 +208,16 @@ TEST_CASE("Enable the periodic reporting of statistics") {
 		    Message(ParameterStatisticsService::ServiceType,
 		            ParameterStatisticsService::MessageType::EnablePeriodicParameterReporting, Message::TC, 1);
 		request2.appendUint16(3);
-		Services.parameterStatistics.periodicStatisticsReportingStatus = false;
-		CHECK(Services.parameterStatistics.reportingInterval == 6);
+		Services.parameterStatistics.setPeriodicReportingStatus(false);
+		CHECK(Services.parameterStatistics.getReportingIntervalMs() == 6);
 
 		MessageParser::execute(request2);
 		CHECK(ServiceTests::count() == 1);
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InvalidSamplingRateError) == 1);
-		CHECK(Services.parameterStatistics.periodicStatisticsReportingStatus == false);
-		CHECK(Services.parameterStatistics.reportingInterval == 6);
+		CHECK(Services.parameterStatistics.getPeriodicReportingStatus() == false);
+		CHECK(Services.parameterStatistics.getReportingIntervalMs() == 6);
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 }
 
@@ -181,20 +227,18 @@ TEST_CASE("Disabling the periodic reporting of statistics") {
 		Message request =
 		    Message(ParameterStatisticsService::ServiceType,
 		            ParameterStatisticsService::MessageType::DisablePeriodicParameterReporting, Message::TC, 1);
-		Services.parameterStatistics.periodicStatisticsReportingStatus = true;
+		Services.parameterStatistics.setPeriodicReportingStatus(true);
 
 		MessageParser::execute(request);
-		REQUIRE(Services.parameterStatistics.periodicStatisticsReportingStatus == false);
+		REQUIRE(Services.parameterStatistics.getPeriodicReportingStatus() == false);
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 }
 
 TEST_CASE("Add/Update statistics definitions") {
 	SECTION("Update existing parameter statistic definition") {
-		initializeStatistics(7, 6);
+		initializeStatistics(750, 2400);
 		Statistic newStatistic;
 		newStatistic.setSelfSamplingInterval(0);
 		Services.parameterStatistics.statisticsMap.insert({0, newStatistic});
@@ -206,7 +250,7 @@ TEST_CASE("Add/Update statistics definitions") {
 		request.appendUint16(numOfIds);
 
 		uint16_t paramId1 = 0;
-		uint16_t interval1 = 14;
+		uint16_t interval1 = 1400;
 		request.appendUint16(paramId1);
 		request.appendUint16(interval1);
 
@@ -216,11 +260,9 @@ TEST_CASE("Add/Update statistics definitions") {
 
 		REQUIRE(ServiceTests::count() == 0);
 		CHECK(Services.parameterStatistics.statisticsMap.size() == 3);
-		CHECK(Services.parameterStatistics.statisticsMap[0].selfSamplingInterval == 14);
+		CHECK(Services.parameterStatistics.statisticsMap[0].selfSamplingInterval == 1400);
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 
 	SECTION("Add new statistic definition") {
@@ -232,7 +274,7 @@ TEST_CASE("Add/Update statistics definitions") {
 		request.appendUint16(numOfIds);
 
 		uint16_t paramId1 = 1;
-		uint16_t interval1 = 32;
+		uint16_t interval1 = 3200;
 		request.appendUint16(paramId1);
 		request.appendUint16(interval1);
 
@@ -242,15 +284,13 @@ TEST_CASE("Add/Update statistics definitions") {
 
 		REQUIRE(ServiceTests::count() == 0);
 		CHECK(Services.parameterStatistics.statisticsMap.size() == 3);
-		CHECK(Services.parameterStatistics.statisticsMap[1].selfSamplingInterval == 32);
+		CHECK(Services.parameterStatistics.statisticsMap[1].selfSamplingInterval == 3200);
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 
 	SECTION("All possible invalid requests combined with add/update") {
-		initializeStatistics(7, 6);
+		initializeStatistics(7000, 6000);
 		Statistic newStatistic;
 		newStatistic.setSelfSamplingInterval(0);
 		Services.parameterStatistics.statisticsMap.insert({0, newStatistic});
@@ -268,12 +308,12 @@ TEST_CASE("Add/Update statistics definitions") {
 		uint16_t paramId5 = ECSSParameterCount + 1;
 		uint16_t paramId6 = 3;
 
-		uint16_t interval1 = 14;
-		uint16_t interval2 = 32;
-		uint16_t interval3 = 2;
-		uint16_t interval4 = 7;
-		uint16_t interval5 = 8;
-		uint16_t interval6 = 9;
+		uint16_t interval1 = 14000;
+		uint16_t interval2 = 32000;
+		uint16_t interval3 = 20;
+		uint16_t interval4 = 7000;
+		uint16_t interval5 = 8000;
+		uint16_t interval6 = 9000;
 
 		request.appendUint16(paramId1);
 		request.appendUint16(interval1);
@@ -297,12 +337,10 @@ TEST_CASE("Add/Update statistics definitions") {
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::InvalidSamplingRateError) == 1);
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::SetNonExistingParameter) == 2);
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::MaxStatisticDefinitionsReached) == 1);
-		CHECK(Services.parameterStatistics.statisticsMap[0].selfSamplingInterval == 14);
-		CHECK(Services.parameterStatistics.statisticsMap[1].selfSamplingInterval == 32);
+		CHECK(Services.parameterStatistics.statisticsMap[0].selfSamplingInterval == 14000);
+		CHECK(Services.parameterStatistics.statisticsMap[1].selfSamplingInterval == 32000);
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 }
 
@@ -330,10 +368,10 @@ TEST_CASE("Delete statistics definitions") {
 		request.appendUint16(id1);
 		request.appendUint16(id2);
 
-		Services.parameterStatistics.periodicStatisticsReportingStatus = true;
+		Services.parameterStatistics.setPeriodicReportingStatus(true);
 		MessageParser::execute(request);
 
-		CHECK(Services.parameterStatistics.periodicStatisticsReportingStatus == true);
+		CHECK(Services.parameterStatistics.getPeriodicReportingStatus() == true);
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::GetNonExistingParameter) == 1);
 		CHECK(Services.parameterStatistics.statisticsMap.size() == 2);
 	}
@@ -347,13 +385,10 @@ TEST_CASE("Delete statistics definitions") {
 
 		MessageParser::execute(request);
 
-		CHECK(Services.parameterStatistics.periodicStatisticsReportingStatus == false);
-		CHECK(ServiceTests::countThrownErrors(ErrorHandler::GetNonExistingParameter) == 1);
+		CHECK(Services.parameterStatistics.getPeriodicReportingStatus() == false);
 		CHECK(Services.parameterStatistics.statisticsMap.empty());
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 }
 
@@ -372,15 +407,13 @@ TEST_CASE("Parameter statistics definition report") {
 
 		CHECK(ServiceTests::count() == 1);
 		Message report = ServiceTests::get(0);
-		CHECK(report.readUint16() == 0); // Reporting interval
-		CHECK(report.readUint16() == 2); // Num of valid Ids
-		CHECK(report.readUint16() == 5); // Valid parameter ID
-		CHECK(report.readUint16() == 12); // Sampling interval
+		CHECK(report.readUint16() == 700); // Reporting interval
+		CHECK(report.readUint16() == 2);   // Num of valid Ids
+		CHECK(report.readUint16() == 5);   // Valid parameter ID
+		CHECK(report.readUint16() == 12);  // Sampling interval
 		CHECK(report.readUint16() == 7);
 		CHECK(report.readUint16() == 0);
 
-		resetSystem();
 		ServiceTests::reset();
-		Services.reset();
 	}
 }
diff --git a/test/Services/RealTimeForwardingControl.cpp b/test/Services/RealTimeForwardingControl.cpp
index dd1a3351766df0e610fb046a60d9eded54635edc..f648802ce5bac4983428b13198c55dc02f0a8570 100644
--- a/test/Services/RealTimeForwardingControl.cpp
+++ b/test/Services/RealTimeForwardingControl.cpp
@@ -3,9 +3,9 @@
 #include "Message.hpp"
 #include "ServiceTests.hpp"
 #include "Services/RealTimeForwardingControlService.hpp"
-#include "catch2/catch.hpp"
+#include "catch2/catch_all.hpp"
 
-RealTimeForwardingControlService& realTimeForwarding = Services.realTimeForwarding;
+static RealTimeForwardingControlService& realTimeForwarding = Services.realTimeForwarding;
 
 uint8_t applications[] = {1};
 uint8_t services[] = {3, 5};
@@ -307,7 +307,7 @@ TEST_CASE("Add report types to the Application Process Configuration") {
 		realTimeForwarding.controlledApplications.push_back(applicationID);
 		validReportTypes(request);
 
-		for (auto message: AllMessageTypes::messagesOfService[serviceType]) {
+		for (auto& message: AllMessageTypes::MessagesOfService.at(serviceType)) {
 			realTimeForwarding.applicationProcessConfiguration.definitions[std::make_pair(applicationID, serviceType)]
 			    .push_back(message);
 		}
@@ -319,7 +319,7 @@ TEST_CASE("Add report types to the Application Process Configuration") {
 		      2);
 		REQUIRE(
 		    realTimeForwarding.applicationProcessConfiguration.definitions[std::make_pair(applicationID, serviceType)]
-		        .size() == AllMessageTypes::messagesOfService[serviceType].size());
+		        .size() == AllMessageTypes::MessagesOfService.at(serviceType).size());
 
 		resetAppProcessConfiguration();
 		ServiceTests::reset();
@@ -345,8 +345,8 @@ TEST_CASE("Add report types to the Application Process Configuration") {
 		REQUIRE(applicationProcessConfig.definitions[appServicePair1].empty());
 		REQUIRE(applicationProcessConfig.definitions[appServicePair2].empty());
 
-		auto numOfMessages1 = AllMessageTypes::messagesOfService[serviceType1].size();
-		auto numOfMessages2 = AllMessageTypes::messagesOfService[serviceType2].size();
+		auto numOfMessages1 = AllMessageTypes::MessagesOfService.at(serviceType1).size();
+		auto numOfMessages2 = AllMessageTypes::MessagesOfService.at(serviceType2).size();
 
 		for (uint8_t i = 0; i < numOfMessages1 - 1; i++) {
 			applicationProcessConfig.definitions[appServicePair1].push_back(i);
@@ -450,7 +450,7 @@ TEST_CASE("Add report types to the Application Process Configuration") {
 		auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions;
 		for (auto serviceType: services) {
 			REQUIRE(applicationProcesses[std::make_pair(applicationID1, serviceType)].size() ==
-			        AllMessageTypes::messagesOfService[serviceType].size());
+			        AllMessageTypes::MessagesOfService.at(serviceType).size());
 		}
 
 		resetAppProcessConfiguration();
@@ -491,11 +491,11 @@ TEST_CASE("Add report types to the Application Process Configuration") {
 
 		for (auto& serviceType: allServices) {
 			REQUIRE(definitions[std::make_pair(applicationID1, serviceType)].size() ==
-			        AllMessageTypes::messagesOfService[serviceType].size());
+			        AllMessageTypes::MessagesOfService.at(serviceType).size());
 		}
 		for (auto& serviceType: services) {
 			REQUIRE(definitions[std::make_pair(applicationID2, serviceType)].size() ==
-			        AllMessageTypes::messagesOfService[serviceType].size());
+			        AllMessageTypes::MessagesOfService.at(serviceType).size());
 		}
 
 		resetAppProcessConfiguration();
@@ -520,7 +520,7 @@ TEST_CASE("Add report types to the Application Process Configuration") {
 		for (auto serviceType: allServices) {
 			REQUIRE(std::equal(definitions[std::make_pair(applicationID1, serviceType)].begin(),
 			                   definitions[std::make_pair(applicationID1, serviceType)].end(),
-			                   AllMessageTypes::messagesOfService[serviceType].begin()));
+			                   AllMessageTypes::MessagesOfService.at(serviceType).begin()));
 		}
 
 		resetAppProcessConfiguration();
diff --git a/test/Services/RequestVerificationService.cpp b/test/Services/RequestVerificationServiceTests.cpp
similarity index 56%
rename from test/Services/RequestVerificationService.cpp
rename to test/Services/RequestVerificationServiceTests.cpp
index 223cd1169c9d2688083d4b2dd7090a1e6d5b8254..99e11ed9530281f06092805bb605575432c8ea9f 100644
--- a/test/Services/RequestVerificationService.cpp
+++ b/test/Services/RequestVerificationServiceTests.cpp
@@ -1,6 +1,6 @@
-#include <catch2/catch.hpp>
-#include <Services/RequestVerificationService.hpp>
 #include <Message.hpp>
+#include <Services/RequestVerificationService.hpp>
+#include <catch2/catch_all.hpp>
 #include "ServiceTests.hpp"
 
 RequestVerificationService& reqVerifService = Services.requestVerification;
@@ -13,17 +13,17 @@ TEST_CASE("TM[1,1]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::SuccessfulAcceptanceReport);
+	CHECK(response.messageType == RequestVerificationService::MessageType::SuccessfulAcceptanceReport);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
 	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(1) == Message::TC);        // packet type
+	CHECK(response.readBits(1) == 1);                        // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                 // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);  // sequence flags
+	CHECK(response.readBits(14) == 0);                       // packet sequence count
 }
 
 TEST_CASE("TM[1,2]", "[service][st01]") {
@@ -34,17 +34,17 @@ TEST_CASE("TM[1,2]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::FailedAcceptanceReport);
+	CHECK(response.messageType == RequestVerificationService::MessageType::FailedAcceptanceReport);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
-	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(3) == CCSDSPacketVersion);              // packet version number
+	CHECK(response.readEnumerated(1) == Message::TC);                     // packet type
+	CHECK(response.readBits(1) == 1);                                     // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                              // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);               // sequence flags
+	CHECK(response.readBits(14) == 0);                                    // packet sequence count
 	CHECK(response.readEnum16() == ErrorHandler::UnknownAcceptanceError); // error code
 }
 
@@ -56,17 +56,17 @@ TEST_CASE("TM[1,3]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::SuccessfulStartOfExecution);
+	CHECK(response.messageType == RequestVerificationService::MessageType::SuccessfulStartOfExecution);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
 	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(1) == Message::TC);        // packet type
+	CHECK(response.readBits(1) == 1);                        // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                 // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);  // sequence flags
+	CHECK(response.readBits(14) == 0);                       // packet sequence count
 }
 
 TEST_CASE("TM[1,4]", "[service][st01]") {
@@ -77,17 +77,17 @@ TEST_CASE("TM[1,4]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::FailedStartOfExecution);
+	CHECK(response.messageType == RequestVerificationService::MessageType::FailedStartOfExecution);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
-	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(3) == CCSDSPacketVersion);                  // packet version number
+	CHECK(response.readEnumerated(1) == Message::TC);                         // packet type
+	CHECK(response.readBits(1) == 1);                                         // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                                  // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);                   // sequence flags
+	CHECK(response.readBits(14) == 0);                                        // packet sequence count
 	CHECK(response.readEnum16() == ErrorHandler::UnknownExecutionStartError); // error code
 }
 
@@ -99,18 +99,18 @@ TEST_CASE("TM[1,5]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::SuccessfulProgressOfExecution);
+	CHECK(response.messageType == RequestVerificationService::MessageType::SuccessfulProgressOfExecution);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 5); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
 	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
-	CHECK(response.readByte() == 0); // step ID
+	CHECK(response.readEnumerated(1) == Message::TC);        // packet type
+	CHECK(response.readBits(1) == 1);                        // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                 // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);  // sequence flags
+	CHECK(response.readBits(14) == 0);                       // packet sequence count
+	CHECK(response.readByte() == 0);                         // step ID
 }
 
 TEST_CASE("TM[1,6]", "[service][st01]") {
@@ -121,18 +121,18 @@ TEST_CASE("TM[1,6]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::FailedProgressOfExecution);
+	CHECK(response.messageType == RequestVerificationService::MessageType::FailedProgressOfExecution);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 7); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
 	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
-	CHECK(response.readByte() == 0); // step ID
+	CHECK(response.readEnumerated(1) == Message::TC);        // packet type
+	CHECK(response.readBits(1) == 1);                        // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                 // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);  // sequence flags
+	CHECK(response.readBits(14) == 0);                       // packet sequence count
+	CHECK(response.readByte() == 0);                         // step ID
 	CHECK(response.readEnum16() == ErrorHandler::UnknownExecutionProgressError);
 }
 
@@ -144,17 +144,17 @@ TEST_CASE("TM[1,7]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::SuccessfulCompletionOfExecution);
+	CHECK(response.messageType == RequestVerificationService::MessageType::SuccessfulCompletionOfExecution);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
 	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(1) == Message::TC);        // packet type
+	CHECK(response.readBits(1) == 1);                        // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                 // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);  // sequence flags
+	CHECK(response.readBits(14) == 0);                       // packet sequence count
 }
 
 TEST_CASE("TM[1,8]", "[service][st01]") {
@@ -164,17 +164,17 @@ TEST_CASE("TM[1,8]", "[service][st01]") {
 
 	Message response = ServiceTests::get(0);
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::FailedCompletionOfExecution);
+	CHECK(response.messageType == RequestVerificationService::MessageType::FailedCompletionOfExecution);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
-	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(3) == CCSDSPacketVersion);                       // packet version number
+	CHECK(response.readEnumerated(1) == Message::TC);                              // packet type
+	CHECK(response.readBits(1) == 1);                                              // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                                       // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);                        // sequence flags
+	CHECK(response.readBits(14) == 0);                                             // packet sequence count
 	CHECK(response.readEnum16() == ErrorHandler::UnknownExecutionCompletionError); // error code
 }
 
@@ -186,16 +186,16 @@ TEST_CASE("TM[1,10]", "[service][st01]") {
 	Message response = ServiceTests::get(0);
 	// Checks for the data-members of the object response
 	CHECK(response.serviceType == RequestVerificationService::ServiceType);
-	CHECK(response.messageType ==  RequestVerificationService::MessageType::FailedRoutingReport);
+	CHECK(response.messageType == RequestVerificationService::MessageType::FailedRoutingReport);
 	CHECK(response.packetType == Message::TM); // packet type
-	CHECK(response.applicationId == 0);
+	CHECK(response.applicationId == ApplicationId);
 	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
 	// Check for the value that is stored in <<data>> array(data-member of object response)
-	CHECK(response.readEnumerated(3) == CCSDSPacketVersion); // packet version number
-	CHECK(response.readEnumerated(1) == Message::TC); // packet type
-	CHECK(response.readBits(1) == 1); // secondary header flag
-	CHECK(response.readEnumerated(11) == 3); // application process ID
-	CHECK(response.readEnumerated(2) == ECSSSequenceFlags); // sequence flags
-	CHECK(response.readBits(14) == 0); // packet sequence count
+	CHECK(response.readEnumerated(3) == CCSDSPacketVersion);           // packet version number
+	CHECK(response.readEnumerated(1) == Message::TC);                  // packet type
+	CHECK(response.readBits(1) == 1);                                  // secondary header flag
+	CHECK(response.readEnumerated(11) == 3);                           // application process ID
+	CHECK(response.readEnumerated(2) == ECSSSequenceFlags);            // sequence flags
+	CHECK(response.readBits(14) == 0);                                 // packet sequence count
 	CHECK(response.readEnum16() == ErrorHandler::UnknownRoutingError); // error code
 }
diff --git a/test/Services/ServiceTests.hpp b/test/Services/ServiceTests.hpp
index d5b76b882b1f788b7da4267f5ab4d3f4841f5168..f45726d85f89bf15afa216d3fdadd684dec47239 100644
--- a/test/Services/ServiceTests.hpp
+++ b/test/Services/ServiceTests.hpp
@@ -84,13 +84,17 @@ public:
 		return count() == 1;
 	}
 
+	static void resetErrors() {
+		queuedMessages.clear();
+		thrownErrors.clear();
+		expectingErrors = false;
+	}
+
 	/**
 	 * Reset the testing environment, starting from zero for all parameters
 	 */
 	static void reset() {
-		queuedMessages.clear();
-		thrownErrors.clear();
-		expectingErrors = false;
+		resetErrors();
 
 		Services.reset();
 	}
@@ -150,6 +154,19 @@ public:
 
 		return thrownErrors.count(std::make_pair(errorSource, errorType));
 	}
+
+	/**
+	 * Get the list of all thrown errors
+	 */
+	static std::vector<std::pair<ErrorHandler::ErrorSource, uint16_t>> getThrownErrors() {
+		std::vector<std::pair<ErrorHandler::ErrorSource, uint16_t>> errors;
+
+		for (auto error : thrownErrors) {
+			errors.push_back(error.first);
+		}
+
+		return errors;
+	}
 };
 
 #endif // ECSS_SERVICES_TESTS_SERVICES_SERVICETESTS_HPP
diff --git a/test/Services/StorageAndRetrievalService.cpp b/test/Services/StorageAndRetrievalServiceTests.cpp
similarity index 96%
rename from test/Services/StorageAndRetrievalService.cpp
rename to test/Services/StorageAndRetrievalServiceTests.cpp
index fd7020db5c5f9deb294b670be75474fd0a45099b..55b2193be7bd0bbcbb9d0f94b658e0ce9c97d8c3 100644
--- a/test/Services/StorageAndRetrievalService.cpp
+++ b/test/Services/StorageAndRetrievalServiceTests.cpp
@@ -1,8 +1,8 @@
 #include <iostream>
-#include "catch2/catch.hpp"
 #include "Message.hpp"
 #include "ServiceTests.hpp"
 #include "Services/StorageAndRetrievalService.hpp"
+#include "catch2/catch_all.hpp"
 
 StorageAndRetrievalService& storageAndRetrieval = Services.storageAndRetrieval;
 
@@ -123,7 +123,7 @@ void padWithZeros(etl::array<String<ECSSPacketStoreIdSize>, 4>& packetStoreIds)
 	uint8_t offsets[] = {3, 4, 5, 6};
 	int index = 0;
 	// Padding every empty position with zeros, to avoid memory garbage collection, which leads to a faulty result.
-	for (auto& packetStoreId : packetStoreIds) {
+	for (auto& packetStoreId: packetStoreIds) {
 		uint8_t startingPosition = offsets[index++];
 		for (uint8_t i = startingPosition; i < ECSSPacketStoreIdSize; i++) {
 			packetStoreId[i] = 0;
@@ -134,16 +134,16 @@ void padWithZeros(etl::array<String<ECSSPacketStoreIdSize>, 4>& packetStoreIds)
 void addTelemetryPacketsInPacketStores() {
 	auto packetStoreIds = validPacketStoreIds();
 
-	for (auto& timestamp : timestamps1) {
+	for (auto& timestamp: timestamps1) {
 		storageAndRetrieval.addTelemetryToPacketStore(packetStoreIds[0], timestamp);
 	}
-	for (auto& timestamp : timestamps2) {
+	for (auto& timestamp: timestamps2) {
 		storageAndRetrieval.addTelemetryToPacketStore(packetStoreIds[1], timestamp);
 	}
-	for (auto& timestamp : timestamps3) {
+	for (auto& timestamp: timestamps3) {
 		storageAndRetrieval.addTelemetryToPacketStore(packetStoreIds[2], timestamp);
 	}
-	for (auto& timestamp : timestamps4) {
+	for (auto& timestamp: timestamps4) {
 		storageAndRetrieval.addTelemetryToPacketStore(packetStoreIds[3], timestamp);
 	}
 }
@@ -242,7 +242,7 @@ TEST_CASE("Deleting packet stores") {
 		uint16_t numOfPacketStores = 4;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.byTimeRangeRetrievalStatus = false;
@@ -270,7 +270,7 @@ TEST_CASE("Deleting packet stores") {
 		uint16_t numOfPacketStores = 0;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.byTimeRangeRetrievalStatus = false;
@@ -297,7 +297,7 @@ TEST_CASE("Deleting packet stores") {
 		uint16_t numOfPacketStores = 4;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.byTimeRangeRetrievalStatus = false;
@@ -332,7 +332,7 @@ TEST_CASE("Deleting packet stores") {
 		uint16_t numOfPacketStores = 4;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(not storageAndRetrieval.packetStoreExists(packetStoreId));
 			request.appendString(packetStoreId);
 		}
@@ -358,7 +358,7 @@ TEST_CASE("Deleting packet stores") {
 		uint16_t numOfPacketStores = 0;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.byTimeRangeRetrievalStatus = false;
@@ -394,7 +394,7 @@ TEST_CASE("Deleting packet stores") {
 		uint16_t numOfPacketStores = 8;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.byTimeRangeRetrievalStatus = false;
@@ -402,7 +402,7 @@ TEST_CASE("Deleting packet stores") {
 			request.appendString(packetStoreId);
 		}
 
-		for (auto& packetStoreId : wrongPacketStoreIds) {
+		for (auto& packetStoreId: wrongPacketStoreIds) {
 			REQUIRE(not storageAndRetrieval.packetStoreExists(packetStoreId));
 			request.appendString(packetStoreId);
 		}
@@ -498,7 +498,7 @@ TEST_CASE("Enabling the storage of packet stores") {
 		MessageParser::execute(request);
 
 		CHECK(ServiceTests::count() == 0);
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).storageStatus == true);
 		}
 
@@ -578,7 +578,7 @@ TEST_CASE("Disabling the storage of packet stores") {
 		MessageParser::execute(request);
 
 		CHECK(ServiceTests::count() == 0);
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).storageStatus == false);
 		}
 
@@ -602,7 +602,7 @@ TEST_CASE("Changing the open retrieval start-time-tag") {
 		request.appendUint32(startTimeTag);
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStartTimeTag == 0);
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 			request.appendString(packetStoreId);
@@ -677,7 +677,7 @@ TEST_CASE("Changing the open retrieval start-time-tag") {
 		request.appendUint32(startTimeTag);
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStartTimeTag == 0);
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 		}
@@ -711,7 +711,7 @@ TEST_CASE("Resuming the open retrieval process") {
 
 		uint16_t numOfPacketStores = 3;
 		request.appendUint16(numOfPacketStores);
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = false;
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 			request.appendString(packetStoreId);
@@ -787,7 +787,7 @@ TEST_CASE("Resuming the open retrieval process") {
 		uint16_t numOfPacketStores = 0;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = false;
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 		}
@@ -821,7 +821,7 @@ TEST_CASE("Suspending the open retrieval process") {
 
 		uint16_t numOfPacketStores = 3;
 		request.appendUint16(numOfPacketStores);
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::InProgress;
 			request.appendString(packetStoreId);
 		}
@@ -894,7 +894,7 @@ TEST_CASE("Suspending the open retrieval process") {
 		uint16_t numOfPacketStores = 0;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.packetStoreExists(packetStoreId));
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::InProgress;
 		}
@@ -930,7 +930,7 @@ TEST_CASE("Starting the by-time-range retrieval of packet stores") {
 		uint32_t timeTags2[4] = {60, 70, 80, 90};
 
 		int index = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = false;
 			request.appendString(packetStoreId);
@@ -1027,7 +1027,7 @@ TEST_CASE("Starting the by-time-range retrieval of packet stores") {
 		uint16_t numOfPacketStores = 3;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = false;
 			request.appendString(packetStoreId);
@@ -1047,7 +1047,7 @@ TEST_CASE("Starting the by-time-range retrieval of packet stores") {
 		REQUIRE(storageAndRetrieval.getPacketStore(packetStoreIds[2]).byTimeRangeRetrievalStatus == false);
 		REQUIRE(storageAndRetrieval.getPacketStore(packetStoreIds[3]).byTimeRangeRetrievalStatus == false);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).retrievalStartTime == 0);
 		}
 
@@ -1069,7 +1069,7 @@ TEST_CASE("Aborting the by-time-range retrieval of packet stores") {
 		uint16_t numOfPacketStores = 3;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = true;
 			request.appendString(packetStoreId);
@@ -1100,7 +1100,7 @@ TEST_CASE("Aborting the by-time-range retrieval of packet stores") {
 		uint16_t numOfPacketStores = 3;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = true;
 		}
 
@@ -1114,7 +1114,7 @@ TEST_CASE("Aborting the by-time-range retrieval of packet stores") {
 
 		CHECK(ServiceTests::count() == 3);
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::NonExistingPacketStore) == 3);
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = true;
 		}
 
@@ -1134,7 +1134,7 @@ TEST_CASE("Aborting the by-time-range retrieval of packet stores") {
 		uint16_t numOfPacketStores = 0;
 		request.appendUint16(numOfPacketStores);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = true;
 		}
 
@@ -1165,7 +1165,7 @@ TEST_CASE("Reporting the status of packet stores") {
 		uint8_t packetStoreData4[ECSSPacketStoreIdSize] = "ps5555";
 
 		int count = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = (count % 2 == 0);
 			packetStore.byTimeRangeRetrievalStatus = (count % 2 != 0);
@@ -1228,7 +1228,7 @@ TEST_CASE("Reporting the configuration of packet stores") {
 		uint8_t packetStoreData4[ECSSPacketStoreIdSize] = "ps5555";
 
 		int count = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).packetStoreType =
 			    (count % 2 == 0) ? PacketStore::Circular : PacketStore::Bounded;
 			count++;
@@ -1291,7 +1291,7 @@ TEST_CASE("Resizing the packet stores") {
 		uint16_t numOfPacketStores = 3;
 		request.appendUint16(numOfPacketStores);
 		int index = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.openRetrievalStatus = PacketStore::Suspended;
@@ -1328,7 +1328,7 @@ TEST_CASE("Resizing the packet stores") {
 		uint16_t numOfPacketStores = 4;
 		request.appendUint16(numOfPacketStores);
 		int index = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = (index % 2 == 0);
 			packetStore.byTimeRangeRetrievalStatus = (index == 1);
@@ -1347,7 +1347,7 @@ TEST_CASE("Resizing the packet stores") {
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::GetPacketStoreWithByTimeRangeRetrieval) == 1);
 		int i = 0;
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).sizeInBytes == oldSizes[i++]);
 		}
 
@@ -1369,7 +1369,7 @@ TEST_CASE("Resizing the packet stores") {
 		uint16_t numOfPacketStores = 4;
 		request.appendUint16(numOfPacketStores);
 		int index = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.storageStatus = false;
 			packetStore.byTimeRangeRetrievalStatus = false;
@@ -1402,7 +1402,7 @@ TEST_CASE("Resizing the packet stores") {
 
 		uint16_t numOfPacketStores = 4;
 		request.appendUint16(numOfPacketStores);
-		for (auto& packetStoreId : wrongPacketStoreIds) {
+		for (auto& packetStoreId: wrongPacketStoreIds) {
 			request.appendString(packetStoreId);
 			request.appendUint16(35);
 		}
@@ -1412,7 +1412,7 @@ TEST_CASE("Resizing the packet stores") {
 		CHECK(ServiceTests::count() == 4);
 		CHECK(ServiceTests::countThrownErrors(ErrorHandler::NonExistingPacketStore) == 4);
 		int i = 0;
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).sizeInBytes == oldSizes[i++]);
 		}
 
@@ -1428,7 +1428,7 @@ TEST_CASE("Changing the packet store type to circular") {
 		auto packetStoreIds = validPacketStoreIds();
 		padWithZeros(packetStoreIds);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.packetStoreType = PacketStore::Bounded;
 			packetStore.storageStatus = false;
@@ -1472,7 +1472,7 @@ TEST_CASE("Changing the packet store type to circular") {
 		padWithZeros(correctPacketStoreIds);
 
 		int count = 0;
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			auto& packetStore = storageAndRetrieval.getPacketStore(packetStoreId);
 			packetStore.packetStoreType = PacketStore::Bounded;
 			packetStore.storageStatus = (count == 0);
@@ -1482,7 +1482,7 @@ TEST_CASE("Changing the packet store type to circular") {
 		}
 
 		String<ECSSPacketStoreIdSize> finalIds[4] = {wrongPacketStoreIds[0], correctPacketStoreIds[0],
-		                                                correctPacketStoreIds[1], correctPacketStoreIds[2]};
+		                                             correctPacketStoreIds[1], correctPacketStoreIds[2]};
 
 		ErrorHandler::ExecutionStartErrorType expectedErrors[4] = {
 		    ErrorHandler::ExecutionStartErrorType::NonExistingPacketStore,
@@ -1517,7 +1517,7 @@ TEST_CASE("Changing the packet store type to bounded") {
 		auto packetStoreIds = validPacketStoreIds();
 		padWithZeros(packetStoreIds);
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).packetStoreType = PacketStore::Circular;
 			storageAndRetrieval.getPacketStore(packetStoreId).storageStatus = false;
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = false;
@@ -1560,7 +1560,7 @@ TEST_CASE("Changing the packet store type to bounded") {
 		padWithZeros(correctPacketStoreIds);
 
 		int count = 0;
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).packetStoreType = PacketStore::Circular;
 			storageAndRetrieval.getPacketStore(packetStoreId).storageStatus = (count == 0);
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = (count == 1);
@@ -1570,7 +1570,7 @@ TEST_CASE("Changing the packet store type to bounded") {
 		}
 
 		String<ECSSPacketStoreIdSize> finalIds[4] = {wrongPacketStoreIds[0], correctPacketStoreIds[0],
-		                                                correctPacketStoreIds[1], correctPacketStoreIds[2]};
+		                                             correctPacketStoreIds[1], correctPacketStoreIds[2]};
 
 		ErrorHandler::ExecutionStartErrorType expectedErrors[4] = {
 		    ErrorHandler::ExecutionStartErrorType::NonExistingPacketStore,
@@ -1607,7 +1607,7 @@ TEST_CASE("Changing the virtual channel of packet stores") {
 
 		uint8_t virtualChannels[2] = {1, 5};
 
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = false;
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus = PacketStore::Suspended;
 		}
@@ -1654,7 +1654,7 @@ TEST_CASE("Changing the virtual channel of packet stores") {
 		uint8_t oldVirtualChannels[4] = {4, 6, 1, 2};
 
 		int count = 0;
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = (count == 0);
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus =
 			    (count == 1) ? PacketStore::InProgress : PacketStore::Suspended;
@@ -1662,7 +1662,7 @@ TEST_CASE("Changing the virtual channel of packet stores") {
 		}
 
 		String<ECSSPacketStoreIdSize> finalIds[4] = {wrongPacketStoreIds[0], correctPacketStoreIds[0],
-		                                                correctPacketStoreIds[1], correctPacketStoreIds[2]};
+		                                             correctPacketStoreIds[1], correctPacketStoreIds[2]};
 
 		ErrorHandler::ExecutionStartErrorType expectedErrors[4] = {
 		    ErrorHandler::ExecutionStartErrorType::NonExistingPacketStore,
@@ -1682,7 +1682,7 @@ TEST_CASE("Changing the virtual channel of packet stores") {
 		}
 
 		int index = 0;
-		for (auto& packetStoreId : correctPacketStoreIds) {
+		for (auto& packetStoreId: correctPacketStoreIds) {
 			REQUIRE(storageAndRetrieval.getPacketStore(packetStoreId).virtualChannel == oldVirtualChannels[index]);
 			index++;
 		}
@@ -1728,16 +1728,16 @@ TEST_CASE("Reporting the content summary of packet stores") {
 		CHECK(report.readUint32() == timestamps1[0]);
 		CHECK(report.readUint32() == timestamps1[5]);
 		CHECK(report.readUint32() == 5);
-		CHECK(report.readUint16() == 30);
-		CHECK(report.readUint16() == 20);
+		CHECK(report.readUint16() == 60);
+		CHECK(report.readUint16() == 40);
 		// Packet store 2
 		report.readString(data, ECSSPacketStoreIdSize);
 		CHECK(std::equal(std::begin(packetStoreData2), std::end(packetStoreData2), std::begin(data)));
 		CHECK(report.readUint32() == timestamps2[0]);
 		CHECK(report.readUint32() == timestamps2[4]);
 		CHECK(report.readUint32() == 5);
-		CHECK(report.readUint16() == 25);
-		CHECK(report.readUint16() == 10);
+		CHECK(report.readUint16() == 50);
+		CHECK(report.readUint16() == 20);
 
 		ServiceTests::reset();
 		Services.reset();
@@ -1752,7 +1752,7 @@ TEST_CASE("Reporting the content summary of packet stores") {
 		padWithZeros(packetStoreIds);
 
 		int count = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStartTimeTag = (count == 3) ? 20 : 15;
 			count++;
 		}
@@ -1782,7 +1782,7 @@ TEST_CASE("Reporting the content summary of packet stores") {
 		CHECK(report.readUint32() == timestamps1[0]);
 		CHECK(report.readUint32() == timestamps1[5]);
 		CHECK(report.readUint32() == 15);
-		CHECK(report.readUint16() == 30);
+		CHECK(report.readUint16() == 60);
 		CHECK(report.readUint16() == 0);
 		// Packet store 2
 		report.readString(data, ECSSPacketStoreIdSize);
@@ -1790,23 +1790,23 @@ TEST_CASE("Reporting the content summary of packet stores") {
 		CHECK(report.readUint32() == timestamps2[0]);
 		CHECK(report.readUint32() == timestamps2[4]);
 		CHECK(report.readUint32() == 15);
-		CHECK(report.readUint16() == 25);
-		CHECK(report.readUint16() == 10);
+		CHECK(report.readUint16() == 50);
+		CHECK(report.readUint16() == 20);
 		// Packet store 3
 		report.readString(data, ECSSPacketStoreIdSize);
 		CHECK(std::equal(std::begin(packetStoreData3), std::end(packetStoreData3), std::begin(data)));
 		CHECK(report.readUint32() == timestamps4[0]);
 		CHECK(report.readUint32() == timestamps4[7]);
 		CHECK(report.readUint32() == 20);
-		CHECK(report.readUint16() == 40);
-		CHECK(report.readUint16() == 30);
+		CHECK(report.readUint16() == 80);
+		CHECK(report.readUint16() == 60);
 		// Packet store 4
 		report.readString(data, ECSSPacketStoreIdSize);
 		CHECK(std::equal(std::begin(packetStoreData4), std::end(packetStoreData4), std::begin(data)));
 		CHECK(report.readUint32() == timestamps3[0]);
 		CHECK(report.readUint32() == timestamps3[3]);
 		CHECK(report.readUint32() == 15);
-		CHECK(report.readUint16() == 20);
+		CHECK(report.readUint16() == 40);
 		CHECK(report.readUint16() == 0);
 
 		ServiceTests::reset();
@@ -1823,7 +1823,7 @@ TEST_CASE("Reporting the content summary of packet stores") {
 		padWithZeros(correctPacketStoreIds);
 
 		String<ECSSPacketStoreIdSize> finalIds[3] = {wrongPacketStoreIds[0], wrongPacketStoreIds[1],
-		                                                correctPacketStoreIds[0]};
+		                                             correctPacketStoreIds[0]};
 
 		storageAndRetrieval.getPacketStore(correctPacketStoreIds[0]).openRetrievalStartTimeTag = 5;
 
@@ -1854,8 +1854,8 @@ TEST_CASE("Reporting the content summary of packet stores") {
 		CHECK(report.readUint32() == timestamps1[0]);
 		CHECK(report.readUint32() == timestamps1[5]);
 		CHECK(report.readUint32() == 5);
-		CHECK(report.readUint16() == 30);
-		CHECK(report.readUint16() == 20);
+		CHECK(report.readUint16() == 60);
+		CHECK(report.readUint16() == 40);
 
 		ServiceTests::reset();
 		Services.reset();
@@ -1897,11 +1897,11 @@ TEST_CASE("Deleting packet store content") {
 		uint32_t leftTimeStamps2[2];
 
 		int count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[0]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[0]).storedTelemetryPackets) {
 			leftTimeStamps1[count++] = tmPacket.first;
 		}
 		count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[1]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[1]).storedTelemetryPackets) {
 			leftTimeStamps2[count++] = tmPacket.first;
 		}
 		REQUIRE(storageAndRetrieval.getPacketStore(packetStoreIds[0]).storedTelemetryPackets.size() == 3);
@@ -1949,11 +1949,11 @@ TEST_CASE("Deleting packet store content") {
 		uint32_t leftTimeStamps2[8];
 
 		int count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[2]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[2]).storedTelemetryPackets) {
 			leftTimeStamps1[count++] = tmPacket.first;
 		}
 		count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[3]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[3]).storedTelemetryPackets) {
 			leftTimeStamps2[count++] = tmPacket.first;
 		}
 		REQUIRE(storageAndRetrieval.getPacketStore(packetStoreIds[2]).storedTelemetryPackets.size() == 4);
@@ -2019,7 +2019,7 @@ TEST_CASE("Deleting packet store content") {
 		request.appendUint16(numOfPacketStores);
 
 		int count = 0;
-		for (auto& packetStoreId : packetStoreIds) {
+		for (auto& packetStoreId: packetStoreIds) {
 			storageAndRetrieval.getPacketStore(packetStoreId).byTimeRangeRetrievalStatus = (count == 0);
 			storageAndRetrieval.getPacketStore(packetStoreId).openRetrievalStatus =
 			    (count == 1) ? PacketStore::InProgress : PacketStore::Suspended;
@@ -2050,15 +2050,15 @@ TEST_CASE("Deleting packet store content") {
 		uint32_t leftTimeStamps4[6];
 
 		count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[0]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[0]).storedTelemetryPackets) {
 			leftTimeStamps1[count++] = tmPacket.first;
 		}
 		count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[1]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[1]).storedTelemetryPackets) {
 			leftTimeStamps2[count++] = tmPacket.first;
 		}
 		count = 0;
-		for (auto& tmPacket : storageAndRetrieval.getPacketStore(packetStoreIds[3]).storedTelemetryPackets) {
+		for (auto& tmPacket: storageAndRetrieval.getPacketStore(packetStoreIds[3]).storedTelemetryPackets) {
 			leftTimeStamps4[count++] = tmPacket.first;
 		}
 
@@ -2083,7 +2083,7 @@ TEST_CASE("Deleting packet store content") {
 		padWithZeros(correctPacketStoreIds);
 
 		String<ECSSPacketStoreIdSize> finalIds[7] = {
-		    wrongPacketStoreIds[0],   wrongPacketStoreIds[1],   wrongPacketStoreIds[2],  correctPacketStoreIds[0],
+		    wrongPacketStoreIds[0], wrongPacketStoreIds[1], wrongPacketStoreIds[2], correctPacketStoreIds[0],
 		    correctPacketStoreIds[1], correctPacketStoreIds[2], correctPacketStoreIds[3]};
 
 		Message request(StorageAndRetrievalService::ServiceType,
@@ -2213,7 +2213,7 @@ TEST_CASE("Copying packets in time window, from tag to tag") {
 		auto& targetPacketStore = storageAndRetrieval.getPacketStore(toPacketStoreId);
 		REQUIRE(targetPacketStore.storedTelemetryPackets.size() == 2);
 		int index = 0;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			REQUIRE(tmPacket.first == timestamps1[index++]);
 		}
 
@@ -2260,7 +2260,7 @@ TEST_CASE("Copying packets in time window, from tag to tag") {
 		auto& targetPacketStore = storageAndRetrieval.getPacketStore(toPacketStoreId);
 		REQUIRE(targetPacketStore.storedTelemetryPackets.size() == 4);
 		int index = 3;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			REQUIRE(tmPacket.first == timestamps4[index++]);
 		}
 
@@ -2307,7 +2307,7 @@ TEST_CASE("Copying packets in time window, from tag to tag") {
 		auto& targetPacketStore = storageAndRetrieval.getPacketStore(toPacketStoreId);
 		REQUIRE(targetPacketStore.storedTelemetryPackets.size() == 3);
 		int index = 2;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			REQUIRE(tmPacket.first == timestamps2[index++]);
 		}
 
@@ -2541,7 +2541,7 @@ TEST_CASE("Copying packets in time window, after time-tag") {
 		uint32_t existingTimestamps[3];
 
 		int index = 0;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			existingTimestamps[index++] = tmPacket.first;
 		}
 		REQUIRE(
@@ -2584,7 +2584,7 @@ TEST_CASE("Copying packets in time window, after time-tag") {
 		uint32_t existingTimestamps[6];
 
 		int index = 0;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			existingTimestamps[index++] = tmPacket.first;
 		}
 		REQUIRE(std::equal(std::begin(timestamps1), std::end(timestamps1), std::begin(existingTimestamps)));
@@ -2665,7 +2665,7 @@ TEST_CASE("Copying packets in time window, before time-tag") {
 		uint32_t existingTimestamps[3];
 
 		int index = 0;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			existingTimestamps[index++] = tmPacket.first;
 		}
 		REQUIRE(
@@ -2708,7 +2708,7 @@ TEST_CASE("Copying packets in time window, before time-tag") {
 		uint32_t existingTimestamps[6];
 
 		int index = 0;
-		for (auto& tmPacket : targetPacketStore.storedTelemetryPackets) {
+		for (auto& tmPacket: targetPacketStore.storedTelemetryPackets) {
 			existingTimestamps[index++] = tmPacket.first;
 		}
 		REQUIRE(std::equal(std::begin(timestamps1), std::end(timestamps1), std::begin(existingTimestamps)));
diff --git a/test/Services/TestService.cpp b/test/Services/TestServiceTests.cpp
similarity index 55%
rename from test/Services/TestService.cpp
rename to test/Services/TestServiceTests.cpp
index 7fb18f85a7c52fad0349ce9fbde5011736b13d7e..caee8703e9874cfc4b6dafa4007ab5f4c325c9a3 100644
--- a/test/Services/TestService.cpp
+++ b/test/Services/TestServiceTests.cpp
@@ -1,11 +1,11 @@
-#include <catch2/catch.hpp>
-#include <Services/TestService.hpp>
 #include <Message.hpp>
+#include <Services/TestService.hpp>
+#include <catch2/catch_all.hpp>
 #include "ServiceTests.hpp"
 
 TestService& testService = Services.testService;
 
-TEST_CASE("TM[17,1]", "[service][st17]") {
+TEST_CASE("TC[17,1]", "[service][st17]") {
 	Message receivedPacket = Message(TestService::ServiceType, TestService::MessageType::AreYouAliveTest, Message::TC, 1);
 	MessageParser::execute(receivedPacket);
 	REQUIRE(ServiceTests::hasOneMessage());
@@ -16,12 +16,31 @@ TEST_CASE("TM[17,1]", "[service][st17]") {
 	REQUIRE(response.dataSize == 0);
 }
 
-TEST_CASE("TM[17,3]", "[service][st17]") {
+TEST_CASE("TM[17,2]", "[service][st17]") {
+	testService.areYouAliveReport();
+
+	Message response = ServiceTests::get(0);
+	CHECK(response.serviceType == TestService::ServiceType);
+	CHECK(response.messageType == TestService::MessageType::AreYouAliveTestReport);
+	REQUIRE(response.dataSize == 0);
+}
+
+TEST_CASE("TC[17,3]", "[service][st17]") {
 	Message receivedPacket = Message(TestService::ServiceType, TestService::MessageType::OnBoardConnectionTest, Message::TC, 1);
-	receivedPacket.appendEnum16(40);
+	receivedPacket.appendEnum16(ApplicationId);
 	MessageParser::execute(receivedPacket);
 	REQUIRE(ServiceTests::hasOneMessage());
 
+	Message response = ServiceTests::get(0);
+	CHECK(response.serviceType == TestService::ServiceType);
+	CHECK(response.messageType == TestService::MessageType::OnBoardConnectionTestReport);
+	REQUIRE(response.dataSize == 2);
+	CHECK(response.readEnum16() == ApplicationId);
+}
+
+TEST_CASE("TM[17,4]", "[service][st17]") {
+	testService.onBoardConnectionReport(40);
+
 	Message response = ServiceTests::get(0);
 	CHECK(response.serviceType == TestService::ServiceType);
 	CHECK(response.messageType == TestService::MessageType::OnBoardConnectionTestReport);
diff --git a/test/Services/TimeBasedSchedulingService.cpp b/test/Services/TimeBasedSchedulingServiceTests.cpp
similarity index 52%
rename from test/Services/TimeBasedSchedulingService.cpp
rename to test/Services/TimeBasedSchedulingServiceTests.cpp
index c1f601b671e184b1d7db352b5f8f1487c0e9a7f3..a48361e9112b716f75851498424cb075c007410c 100644
--- a/test/Services/TimeBasedSchedulingService.cpp
+++ b/test/Services/TimeBasedSchedulingServiceTests.cpp
@@ -1,17 +1,18 @@
-#include <catch2/catch.hpp>
-#include "ServiceTests.hpp"
 #include <Services/TimeBasedSchedulingService.hpp>
+#include <catch2/catch_all.hpp>
+#include "ServiceTests.hpp"
 
 #include <ctime>
 #include <vector>
 
+using namespace std::chrono_literals;
+
 /*
  * A namespace defined explicitly for the purposes of testing. This namespace contains a
  * structure, which has been declared as a friend in the TimeBasedSchedulingService class, so
  * that it can access the private members required for testing validation.
  */
-namespace unit_test
-{
+namespace unit_test {
 	struct Tester {
 		static bool executionFunctionStatus(TimeBasedSchedulingService& tmService) {
 			return tmService.executionFunctionStatus;
@@ -24,8 +25,9 @@ namespace unit_test
 		static auto scheduledActivities(TimeBasedSchedulingService& tmService) {
 			std::vector<TimeBasedSchedulingService::ScheduledActivity*> listElements;
 
-			std::transform(tmService.scheduledActivities.begin(), tmService.scheduledActivities.end(),
-				std::back_inserter(listElements), [](auto& activity) -> auto { return &activity; });
+			std::transform(
+			    tmService.scheduledActivities.begin(), tmService.scheduledActivities.end(),
+			    std::back_inserter(listElements), [](auto& activity) -> auto{ return &activity; });
 
 			return listElements; // Return the list elements
 		}
@@ -33,8 +35,8 @@ namespace unit_test
 } // namespace unit_test
 
 Message testMessage1, testMessage2, testMessage3, testMessage4;
-auto currentTime = static_cast<uint32_t>(time(nullptr)); // Get the current system time
-bool messagesPopulated = false; // Indicate whether the test messages are initialized
+Time::DefaultCUC currentTime = TimeGetter::getCurrentTimeDefaultCUC(); // Get the current system time
+bool messagesPopulated = false;                                        // Indicate whether the test messages are initialized
 
 // Run this function to set the service up before moving on with further testing
 auto activityInsertion(TimeBasedSchedulingService& timeService) {
@@ -43,13 +45,13 @@ auto activityInsertion(TimeBasedSchedulingService& timeService) {
 		testMessage1.serviceType = 6;
 		testMessage1.messageType = 5;
 		testMessage1.packetType = Message::TC;
-		testMessage1.applicationId = 8; // todo: Remove the dummy application ID
+		testMessage1.applicationId = 8;  // todo: Remove the dummy application ID
 		testMessage1.appendUint16(4253); // Append dummy data
 
 		testMessage2.serviceType = 4;
 		testMessage2.messageType = 5;
 		testMessage2.packetType = Message::TC;
-		testMessage2.applicationId = 4; // todo: Remove the dummy application ID
+		testMessage2.applicationId = 4;   // todo: Remove the dummy application ID
 		testMessage2.appendUint16(45667); // Append dummy data
 
 		testMessage3.serviceType = 3;
@@ -58,7 +60,7 @@ auto activityInsertion(TimeBasedSchedulingService& timeService) {
 		testMessage3.appendUint16(456); // Append dummy data
 
 		testMessage4.serviceType = 12;
-		testMessage4.messageType = 23;
+		testMessage4.messageType = 3;
 		testMessage4.packetType = Message::TC;
 		testMessage4.appendUint16(934); // Append dummy data
 
@@ -69,19 +71,19 @@ auto activityInsertion(TimeBasedSchedulingService& timeService) {
 	receivedMessage.appendUint16(4); // Total number of requests
 
 	// Test activity 1
-	receivedMessage.appendUint32(currentTime + 1556435);
+	receivedMessage.appendDefaultCUCTimeStamp(currentTime + 155643s);
 	receivedMessage.appendMessage(testMessage1, ECSSTCRequestStringSize);
 
 	// Test activity 2
-	receivedMessage.appendUint32(currentTime + 1957232);
+	receivedMessage.appendDefaultCUCTimeStamp(currentTime + 195723s);
 	receivedMessage.appendMessage(testMessage2, ECSSTCRequestStringSize);
 
 	// Test activity 3
-	receivedMessage.appendUint32(currentTime + 1726435);
+	receivedMessage.appendDefaultCUCTimeStamp(currentTime + 172643s);
 	receivedMessage.appendMessage(testMessage3, ECSSTCRequestStringSize);
 
 	// Test activity 4
-	receivedMessage.appendUint32(currentTime + 17248435);
+	receivedMessage.appendDefaultCUCTimeStamp(currentTime + 1724843s);
 	receivedMessage.appendMessage(testMessage4, ECSSTCRequestStringSize);
 
 	// Insert activities in the schedule. They have to be inserted sorted
@@ -91,13 +93,54 @@ auto activityInsertion(TimeBasedSchedulingService& timeService) {
 }
 
 
-TimeBasedSchedulingService & timeBasedService = Services.timeBasedScheduling;
+TimeBasedSchedulingService& timeBasedService = Services.timeBasedScheduling;
+
+TEST_CASE("Execute the first activity, removes it from the list and return the release time of next activity to be executed") {
+	Services.reset();
+	auto scheduledActivities = activityInsertion(timeBasedService);
+
+	auto nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 155643s);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 172643s);
+
+	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DetailReportAllScheduledActivities, Message::TC, 1);
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	Message response = ServiceTests::get(0);
+	uint16_t iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 3);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 10s);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 172643s);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 172643s);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 195723s);
+
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	response = ServiceTests::get(1);
+	iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 2);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 195723s);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 1724843s);
+
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	response = ServiceTests::get(2);
+	iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 1);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 1724843s);
+	REQUIRE(nextActivityExecutionCUCTime == Time::DefaultCUC::max());
+
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	response = ServiceTests::get(3);
+	iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 0);
+}
 
 TEST_CASE("TC[11,1] Enable Schedule Execution", "[service][st11]") {
 	Services.reset();
 	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::EnableTimeBasedScheduleExecutionFunction, Message::TC, 1);
 
-	MessageParser::execute(receivedMessage);//timeService.enableScheduleExecution(receivedMessage);
+	MessageParser::execute(receivedMessage); //timeService.enableScheduleExecution(receivedMessage);
 	CHECK(unit_test::Tester::executionFunctionStatus(timeBasedService));
 }
 
@@ -105,7 +148,7 @@ TEST_CASE("TC[11,2] Disable Schedule Execution", "[service][st11]") {
 	Services.reset();
 	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DisableTimeBasedScheduleExecutionFunction, Message::TC, 1);
 
-	MessageParser::execute(receivedMessage);//timeService.disableScheduleExecution(receivedMessage);
+	MessageParser::execute(receivedMessage); //timeService.disableScheduleExecution(receivedMessage);
 	CHECK(not unit_test::Tester::executionFunctionStatus(timeBasedService));
 }
 
@@ -115,10 +158,11 @@ TEST_CASE("TC[11,4] Activity Insertion", "[service][st11]") {
 
 	REQUIRE(scheduledActivities.size() == 4);
 
-	REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 1556435);
-	REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1726435);
-	REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 1957232);
-	REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 17248435);
+	REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 155643s);
+	REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 172643s);
+	REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 195723s);
+	REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 1724843s);
+
 	REQUIRE(testMessage1.bytesEqualWith(scheduledActivities.at(0)->request));
 	REQUIRE(testMessage3.bytesEqualWith(scheduledActivities.at(1)->request));
 	REQUIRE(testMessage2.bytesEqualWith(scheduledActivities.at(2)->request));
@@ -128,8 +172,8 @@ TEST_CASE("TC[11,4] Activity Insertion", "[service][st11]") {
 		Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::InsertActivities, Message::TC, 1);
 		receivedMessage.appendUint16(1); // Total number of requests
 
-		receivedMessage.appendUint32(currentTime - 15564350);
-		MessageParser::execute(receivedMessage);//timeService.insertActivities(receivedMessage);
+		receivedMessage.appendDefaultCUCTimeStamp(currentTime - 155643s);
+		MessageParser::execute(receivedMessage); //timeService.insertActivities(receivedMessage);
 
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
 	}
@@ -140,37 +184,36 @@ TEST_CASE("TC[11,15] Time shift all scheduled activities", "[service][st11]") {
 	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::TimeShiftALlScheduledActivities, Message::TC, 1);
 
 	auto scheduledActivities = activityInsertion(timeBasedService);
-	const int32_t timeShift = 6789;
+	const Time::RelativeTime timeShift = 6789;
 
 	SECTION("Positive Shift") {
-		receivedMessage.appendSint32(-timeShift);
+		receivedMessage.appendRelativeTime(-timeShift);
 
 		CHECK(scheduledActivities.size() == 4);
-		MessageParser::execute(receivedMessage);//timeService.timeShiftAllActivities(receivedMessage);
+		MessageParser::execute(receivedMessage); //timeService.timeShiftAllActivities(receivedMessage);
 
-		REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 1556435 - timeShift);
-		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1726435 - timeShift);
-		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 1957232 - timeShift);
-		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 17248435 - timeShift);
+		REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 155643s - std::chrono::seconds(timeShift));
+		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 172643s - std::chrono::seconds(timeShift));
+		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 195723s - std::chrono::seconds(timeShift));
+		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 1724843s - std::chrono::seconds(timeShift));
 	}
 
 	SECTION("Negative Shift") {
-		receivedMessage.appendSint32(timeShift);
+		receivedMessage.appendRelativeTime(timeShift);
 
 		CHECK(scheduledActivities.size() == 4);
-		MessageParser::execute(receivedMessage);//timeService.timeShiftAllActivities(receivedMessage);
-
-		REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 1556435 + timeShift);
-		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1726435 + timeShift);
-		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 1957232 + timeShift);
-		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 17248435 + timeShift);
+		MessageParser::execute(receivedMessage); //timeService.timeShiftAllActivities(receivedMessage);
+		REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 155643s + std::chrono::seconds(timeShift));
+		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 172643s + std::chrono::seconds(timeShift));
+		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 195723s + std::chrono::seconds(timeShift));
+		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 1724843s + std::chrono::seconds(timeShift));
 	}
 
 	SECTION("Error throwing") {
-		receivedMessage.appendSint32(-6789000); // Provide a huge time shift to cause an error
+		receivedMessage.appendRelativeTime(-6789000); // Provide a huge time shift to cause an error
 
 		CHECK(scheduledActivities.size() == 4);
-		MessageParser::execute(receivedMessage);//timeService.timeShiftAllActivities(receivedMessage);
+		MessageParser::execute(receivedMessage); //timeService.timeShiftAllActivities(receivedMessage);
 
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::SubServiceExecutionStartError));
 	}
@@ -184,55 +227,55 @@ TEST_CASE("TC[11,7] Time shift activities by ID", "[service][st11]") {
 	scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
 	CHECK(scheduledActivities.size() == 4);
 
-	const int32_t timeShift = 67890000; // Relative time-shift value
+	const Time::RelativeTime timeShift = 67890000; // Relative time-shift value
 
 	SECTION("Positive Shift") {
-		receivedMessage.appendSint32(timeShift); // Time-shift value
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendRelativeTime(timeShift);            // Time-shift value
+		receivedMessage.appendUint16(1);                          // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
 		timeBasedService.timeShiftActivitiesByID(receivedMessage);
 		scheduledActivities = unit_test::Tester::scheduledActivities(timeBasedService);
 
 		// Make sure the new value is inserted sorted
-		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 1957232 + timeShift);
+		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 195723s + std::chrono::seconds(timeShift));
 		REQUIRE(testMessage2.bytesEqualWith(scheduledActivities.at(3)->request));
 	}
 
 	SECTION("Negative Shift") {
-		receivedMessage.appendSint32(-250000); // Time-shift value
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendRelativeTime(-25000);              // Time-shift value
+		receivedMessage.appendUint16(1);                          // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
 		timeBasedService.timeShiftActivitiesByID(receivedMessage);
 		scheduledActivities = unit_test::Tester::scheduledActivities(timeBasedService);
 
 		// Output should be sorted
-		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1957232 - 250000);
+		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 195723s - 25000s);
 		REQUIRE(testMessage2.bytesEqualWith(scheduledActivities.at(1)->request));
 	}
 
 	SECTION("Error throw on wrong request ID") {
-		receivedMessage.appendSint32(-250000); // Time-shift value
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Dummy source ID
-		receivedMessage.appendUint16(80); // Dummy application ID to throw an error
-		receivedMessage.appendUint16(0); // Dummy sequence count
+		receivedMessage.appendRelativeTime(-250000); // Time-shift value
+		receivedMessage.appendUint16(1);             // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);              // Dummy source ID
+		receivedMessage.appendUint16(80);            // Dummy application ID to throw an error
+		receivedMessage.appendUint16(0);             // Dummy sequence count
 
 		timeBasedService.timeShiftActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
 	}
 
 	SECTION("Error throw on wrong time offset") {
-		receivedMessage.appendSint32(-6789000); // Time-shift value
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendRelativeTime(-6789000);             // Time-shift value
+		receivedMessage.appendUint16(1);                          // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
 		timeBasedService.timeShiftActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
@@ -251,14 +294,14 @@ TEST_CASE("TC[11,9] Detail report scheduled activities by ID", "[service][st11]"
 		scheduledActivities.at(0)->requestID.applicationID = 8; // Append a dummy application ID
 		scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
 
-		receivedMessage.appendUint16(2); // Two instructions in the request
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendUint16(2);                          // Two instructions in the request
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage1.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
 		timeBasedService.detailReportActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::hasOneMessage());
@@ -270,13 +313,12 @@ TEST_CASE("TC[11,9] Detail report scheduled activities by ID", "[service][st11]"
 		uint16_t iterationCount = response.readUint16();
 		CHECK(iterationCount == 2);
 		for (uint16_t i = 0; i < iterationCount; i++) {
-			uint32_t receivedReleaseTime = response.readUint32();
+			Time::DefaultCUC receivedReleaseTime = response.readDefaultCUCTimeStamp();
 
 			Message receivedTCPacket;
 			uint8_t receivedDataStr[ECSSTCRequestStringSize];
 			response.readString(receivedDataStr, ECSSTCRequestStringSize);
 			receivedTCPacket = MessageParser::parseECSSTC(receivedDataStr);
-
 			if (i == 0) {
 				REQUIRE(receivedReleaseTime == scheduledActivities.at(0)->requestReleaseTime);
 				REQUIRE(receivedTCPacket == scheduledActivities.at(0)->request);
@@ -288,16 +330,64 @@ TEST_CASE("TC[11,9] Detail report scheduled activities by ID", "[service][st11]"
 	}
 
 	SECTION("Error throw on wrong request ID") {
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Dummy source ID
+		receivedMessage.appendUint16(1);  // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);   // Dummy source ID
 		receivedMessage.appendUint16(80); // Dummy application ID to throw an error
-		receivedMessage.appendUint16(0); // Dummy sequence count
+		receivedMessage.appendUint16(0);  // Dummy sequence count
 
 		timeBasedService.detailReportActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
 	}
 }
 
+TEST_CASE("TM[11,10] time-based schedule detail report", "[service][st11]") {
+	Services.reset();
+	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DetailReportActivitiesById, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeBasedService);
+
+	SECTION("Detailed activity report") {
+		// Verify that everything is in place
+		CHECK(scheduledActivities.size() == 4);
+		scheduledActivities.at(0)->requestID.applicationID = 8; // Append a dummy application ID
+		scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
+
+		receivedMessage.appendUint16(2);                          // Two instructions in the request
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
+		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
+
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
+		receivedMessage.appendUint16(testMessage1.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
+
+		timeBasedService.detailReportActivitiesByID(receivedMessage);
+		REQUIRE(ServiceTests::hasOneMessage());
+
+		Message response = ServiceTests::get(0);
+		CHECK(response.serviceType == 11);
+		CHECK(response.messageType == 10);
+
+		uint16_t iterationCount = response.readUint16();
+		CHECK(iterationCount == 2);
+		for (uint16_t i = 0; i < iterationCount; i++) {
+			Time::DefaultCUC receivedReleaseTime = response.readDefaultCUCTimeStamp();
+
+			Message receivedTCPacket;
+			uint8_t receivedDataStr[ECSSTCRequestStringSize];
+			response.readString(receivedDataStr, ECSSTCRequestStringSize);
+			receivedTCPacket = MessageParser::parseECSSTC(receivedDataStr);
+			if (i == 0) {
+				REQUIRE(receivedReleaseTime == scheduledActivities.at(0)->requestReleaseTime);
+				REQUIRE(receivedTCPacket == scheduledActivities.at(0)->request);
+			} else {
+				REQUIRE(receivedReleaseTime == scheduledActivities.at(2)->requestReleaseTime);
+				REQUIRE(receivedTCPacket == scheduledActivities.at(2)->request);
+			}
+		}
+	}
+}
+
 TEST_CASE("TC[11,12] Summary report scheduled activities by ID", "[service][st11]") {
 	Services.reset();
 	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::ActivitiesSummaryReportById, Message::TC, 1);
@@ -310,14 +400,14 @@ TEST_CASE("TC[11,12] Summary report scheduled activities by ID", "[service][st11
 		scheduledActivities.at(0)->requestID.applicationID = 8; // Append a dummy application ID
 		scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
 
-		receivedMessage.appendUint16(2); // Two instructions in the request
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendUint16(2);                          // Two instructions in the request
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage1.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
 		timeBasedService.summaryReportActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::hasOneMessage());
@@ -328,7 +418,7 @@ TEST_CASE("TC[11,12] Summary report scheduled activities by ID", "[service][st11
 
 		uint16_t iterationCount = response.readUint16();
 		for (uint16_t i = 0; i < iterationCount; i++) {
-			uint32_t receivedReleaseTime = response.readUint32();
+			Time::DefaultCUC receivedReleaseTime = response.readDefaultCUCTimeStamp();
 			uint8_t receivedSourceID = response.readUint8();
 			uint16_t receivedApplicationID = response.readUint16();
 			uint16_t receivedSequenceCount = response.readUint16();
@@ -348,16 +438,66 @@ TEST_CASE("TC[11,12] Summary report scheduled activities by ID", "[service][st11
 	}
 
 	SECTION("Error throw on wrong request ID") {
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Dummy source ID
+		receivedMessage.appendUint16(1);  // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);   // Dummy source ID
 		receivedMessage.appendUint16(80); // Dummy application ID to throw an error
-		receivedMessage.appendUint16(0); // Dummy sequence count
+		receivedMessage.appendUint16(0);  // Dummy sequence count
 
 		timeBasedService.summaryReportActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
 	}
 }
 
+TEST_CASE("TM[11,13] time-based schedule summary report", "[service][st11]") {
+	Services.reset();
+	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::ActivitiesSummaryReportById, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeBasedService);
+
+	SECTION("Summary report") {
+		// Verify that everything is in place
+		CHECK(scheduledActivities.size() == 4);
+		scheduledActivities.at(0)->requestID.applicationID = 8; // Append a dummy application ID
+		scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
+
+		receivedMessage.appendUint16(2);                          // Two instructions in the request
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
+		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
+
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
+		receivedMessage.appendUint16(testMessage1.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
+
+		timeBasedService.summaryReportActivitiesByID(receivedMessage);
+		REQUIRE(ServiceTests::hasOneMessage());
+
+		Message response = ServiceTests::get(0);
+		CHECK(response.serviceType == 11);
+		CHECK(response.messageType == 13);
+
+		uint16_t iterationCount = response.readUint16();
+		for (uint16_t i = 0; i < iterationCount; i++) {
+			Time::DefaultCUC receivedReleaseTime = response.readDefaultCUCTimeStamp();
+			uint8_t receivedSourceID = response.readUint8();
+			uint16_t receivedApplicationID = response.readUint16();
+			uint16_t receivedSequenceCount = response.readUint16();
+
+			if (i == 0) {
+				REQUIRE(receivedReleaseTime == scheduledActivities.at(0)->requestReleaseTime);
+				REQUIRE(receivedSourceID == scheduledActivities.at(0)->requestID.sourceID);
+				REQUIRE(receivedApplicationID == scheduledActivities.at(0)->requestID.applicationID);
+				REQUIRE(receivedSequenceCount == scheduledActivities.at(0)->requestID.sequenceCount);
+			} else {
+				REQUIRE(receivedReleaseTime == scheduledActivities.at(2)->requestReleaseTime);
+				REQUIRE(receivedSourceID == scheduledActivities.at(2)->requestID.sourceID);
+				REQUIRE(receivedApplicationID == scheduledActivities.at(2)->requestID.applicationID);
+				REQUIRE(receivedSequenceCount == scheduledActivities.at(2)->requestID.sequenceCount);
+			}
+		}
+	}
+}
+
 TEST_CASE("TC[11,16] Detail report all scheduled activities", "[service][st11]") {
 	Services.reset();
 	auto scheduledActivities = activityInsertion(timeBasedService);
@@ -374,13 +514,12 @@ TEST_CASE("TC[11,16] Detail report all scheduled activities", "[service][st11]")
 	REQUIRE(iterationCount == scheduledActivities.size());
 
 	for (uint16_t i = 0; i < iterationCount; i++) {
-		uint32_t receivedReleaseTime = response.readUint32();
+		Time::DefaultCUC receivedReleaseTime = response.readDefaultCUCTimeStamp();
 
 		Message receivedTCPacket;
 		uint8_t receivedDataStr[ECSSTCRequestStringSize];
 		response.readString(receivedDataStr, ECSSTCRequestStringSize);
 		receivedTCPacket = MessageParser::parseECSSTC(receivedDataStr);
-
 		REQUIRE(receivedReleaseTime == scheduledActivities.at(i)->requestReleaseTime);
 		REQUIRE(receivedTCPacket.bytesEqualWith(scheduledActivities.at(i)->request));
 	}
@@ -397,25 +536,25 @@ TEST_CASE("TC[11,5] Activity deletion by ID", "[service][st11]") {
 		CHECK(scheduledActivities.size() == 4);
 		scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
 
-		receivedMessage.appendUint16(1); // Just one instruction to delete an activity
-		receivedMessage.appendUint8(0); // Source ID is not implemented
+		receivedMessage.appendUint16(1);                          // Just one instruction to delete an activity
+		receivedMessage.appendUint8(0);                           // Source ID is not implemented
 		receivedMessage.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
-		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+		receivedMessage.appendUint16(0);                          // todo: Remove the dummy sequence count
 
 		CHECK(scheduledActivities.size() == 4);
 		timeBasedService.deleteActivitiesByID(receivedMessage);
 		scheduledActivities = unit_test::Tester::scheduledActivities(timeBasedService);
 
 		REQUIRE(scheduledActivities.size() == 3);
-		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 17248435);
+		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 1724843s);
 		REQUIRE(testMessage4.bytesEqualWith(scheduledActivities.at(2)->request));
 	}
 
 	SECTION("Error throw on wrong request ID") {
-		receivedMessage.appendUint16(1); // Just one instruction to time-shift an activity
-		receivedMessage.appendUint8(0); // Dummy source ID
+		receivedMessage.appendUint16(1);  // Just one instruction to time-shift an activity
+		receivedMessage.appendUint8(0);   // Dummy source ID
 		receivedMessage.appendUint16(80); // Dummy application ID to throw an error
-		receivedMessage.appendUint16(0); // Dummy sequence count
+		receivedMessage.appendUint16(0);  // Dummy sequence count
 
 		timeBasedService.deleteActivitiesByID(receivedMessage);
 		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
diff --git a/test/TestPlatform.cpp b/test/TestPlatform.cpp
index d5df134fce675f822a5fa7a5ea2f8e41e3bb23b4..d0f491f171f4230313d67611ea24b07bdec2f425 100644
--- a/test/TestPlatform.cpp
+++ b/test/TestPlatform.cpp
@@ -1,13 +1,28 @@
 #define CATCH_CONFIG_EXTERNAL_INTERFACES
 
-#include <catch2/catch.hpp>
+
+#include <Logger.hpp>
 #include <Message.hpp>
 #include <Service.hpp>
-#include <Logger.hpp>
-#include "Services/ServiceTests.hpp"
+#include <catch2/catch_all.hpp>
+#include <cxxabi.h>
 #include "Helpers/Parameter.hpp"
-#include "Services/ParameterService.hpp"
+#include "Helpers/TimeGetter.hpp"
 #include "Parameters/PlatformParameters.hpp"
+#include "Services/ParameterService.hpp"
+#include "Services/ParameterStatisticsService.hpp"
+#include "Services/ServiceTests.hpp"
+
+UTCTimestamp TimeGetter::getCurrentTimeUTC() {
+	UTCTimestamp currentTime(2020, 4, 10, 10, 15, 0);
+	return currentTime;
+}
+
+Time::DefaultCUC TimeGetter::getCurrentTimeDefaultCUC() {
+	UTCTimestamp timeUTC = getCurrentTimeUTC();
+	Time::DefaultCUC timeCUC(timeUTC);
+	return timeCUC;
+}
 
 // Explicit template specializations for the logError() function
 template void ErrorHandler::logError(const Message&, ErrorHandler::AcceptanceErrorType);
@@ -36,23 +51,36 @@ void ErrorHandler::logError(const Message& message, ErrorType errorType) {
 template <typename ErrorType>
 void ErrorHandler::logError(ErrorType errorType) {
 	ServiceTests::addError(ErrorHandler::findErrorSource(errorType), errorType);
+
+	auto errorCategory = abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr);
+	auto errorNumber = std::underlying_type_t<ErrorType>(errorType);
+
+	LOG_ERROR << "Error " << errorCategory << " with number " << errorNumber;
 }
 
 void Logger::log(Logger::LogLevel level, etl::istring& message) {
-	// Logs while testing are completely ignored
+	// Logs while testing are passed on to Catch2, if they are important enough
+	if (level >= Logger::warning) {
+		UNSCOPED_INFO(message.c_str());
+	}
 }
 
-struct ServiceTestsListener : Catch::TestEventListenerBase {
-	using TestEventListenerBase::TestEventListenerBase; // inherit constructor
+struct ServiceTestsListener : Catch::EventListenerBase {
+	using EventListenerBase::EventListenerBase; // inherit constructor
 
 	void sectionEnded(Catch::SectionStats const& sectionStats) override {
 		// Make sure we don't have any errors
 		if (not ServiceTests::isExpectingErrors()) {
 			// An Error was thrown with this Message. If you expected this to happen, please call a
 			// corresponding assertion function from ServiceTests to silence this message.
-
+			UNSCOPED_INFO("Found " << ServiceTests::countErrors() << " errors at end of section: ");
+			for (auto error: ServiceTests::getThrownErrors()) {
+				UNSCOPED_INFO("  Error " << error.second << " (type " << error.first << ")");
+			}
 			CHECK(ServiceTests::hasNoErrors());
 		}
+
+		ServiceTests::resetErrors();
 	}
 
 	void testCaseEnded(Catch::TestCaseStats const& testCaseStats) override {
@@ -75,23 +103,76 @@ namespace PlatformParameters {
 	inline Parameter<uint32_t> parameter10(43);
 	inline Parameter<uint32_t> parameter11(91);
 	inline Parameter<uint8_t> parameter12(1);
-}
+	inline Parameter<uint8_t> parameter13(1);
+	inline Parameter<uint8_t> parameter14(1);
+	inline Parameter<uint8_t> parameter15(1);
+	inline Parameter<uint8_t> parameter16(1);
+	inline Parameter<uint8_t> parameter17(1);
+	inline Parameter<uint8_t> parameter18(1);
+	inline Parameter<uint8_t> parameter19(1);
+	inline Parameter<uint8_t> parameter20(1);
+	inline Parameter<uint8_t> parameter21(1);
+	inline Parameter<uint8_t> parameter22(1);
+	inline Parameter<uint8_t> parameter23(1);
+	inline Parameter<uint8_t> parameter24(1);
+	inline Parameter<uint8_t> parameter25(1);
+	inline Parameter<uint8_t> parameter26(1);
+	inline Parameter<uint8_t> parameter27(1);
+	inline Parameter<uint8_t> parameter28(1);
+	inline Parameter<uint8_t> parameter29(1);
+	inline Parameter<uint8_t> parameter30(1);
+	inline Parameter<uint8_t> parameter31(1);
+	inline Parameter<uint8_t> parameter32(1);
+	inline Parameter<uint8_t> parameter33(1);
+	inline Parameter<uint8_t> parameter34(1);
+
+} // namespace PlatformParameters
 
 /**
  * Specific definition for \ref ParameterService's initialize function, for testing purposes.
  */
 void ParameterService::initializeParameterMap() {
-	parameters = {{static_cast<uint16_t>(0), PlatformParameters::parameter1},
-	              {static_cast<uint16_t>(1), PlatformParameters::parameter2},
-	              {static_cast<uint16_t>(2), PlatformParameters::parameter3},
-	              {static_cast<uint16_t>(3), PlatformParameters::parameter4},
-	              {static_cast<uint16_t>(4), PlatformParameters::parameter5},
-	              {static_cast<uint16_t>(5), PlatformParameters::parameter6},
-	              {static_cast<uint16_t>(6), PlatformParameters::parameter7},
-	              {static_cast<uint16_t>(7), PlatformParameters::parameter8},
-	              {static_cast<uint16_t>(8), PlatformParameters::parameter9},
-	              {static_cast<uint16_t>(9), PlatformParameters::parameter10},
-	              {static_cast<uint16_t>(10), PlatformParameters::parameter11},
-	              {static_cast<uint16_t>(11), PlatformParameters::parameter12}};
+	parameters = {
+	    {uint16_t{0}, PlatformParameters::parameter1},
+	    {uint16_t{1}, PlatformParameters::parameter2},
+	    {uint16_t{2}, PlatformParameters::parameter3},
+	    {uint16_t{3}, PlatformParameters::parameter4},
+	    {uint16_t{4}, PlatformParameters::parameter5},
+	    {uint16_t{5}, PlatformParameters::parameter6},
+	    {uint16_t{6}, PlatformParameters::parameter7},
+	    {uint16_t{7}, PlatformParameters::parameter8},
+	    {uint16_t{8}, PlatformParameters::parameter9},
+	    {uint16_t{9}, PlatformParameters::parameter10},
+	    {uint16_t{10}, PlatformParameters::parameter11},
+	    {uint16_t{11}, PlatformParameters::parameter12},
+	    {uint16_t{12}, PlatformParameters::parameter13},
+	    {uint16_t{13}, PlatformParameters::parameter14},
+	    {uint16_t{14}, PlatformParameters::parameter15},
+	    {uint16_t{15}, PlatformParameters::parameter16},
+	    {uint16_t{16}, PlatformParameters::parameter17},
+	    {uint16_t{17}, PlatformParameters::parameter18},
+	    {uint16_t{18}, PlatformParameters::parameter19},
+	    {uint16_t{19}, PlatformParameters::parameter20},
+	    {uint16_t{20}, PlatformParameters::parameter21},
+	    {uint16_t{21}, PlatformParameters::parameter22},
+	    {uint16_t{22}, PlatformParameters::parameter23},
+	    {uint16_t{23}, PlatformParameters::parameter24},
+	    {uint16_t{24}, PlatformParameters::parameter25},
+	    {uint16_t{25}, PlatformParameters::parameter26},
+	    {uint16_t{26}, PlatformParameters::parameter27},
+	    {uint16_t{27}, PlatformParameters::parameter28},
+	    {uint16_t{28}, PlatformParameters::parameter29},
+	    {uint16_t{29}, PlatformParameters::parameter30},
+	    {uint16_t{30}, PlatformParameters::parameter31},
+	    {uint16_t{31}, PlatformParameters::parameter32},
+	    {uint16_t{32}, PlatformParameters::parameter33},
+	    {uint16_t{33}, PlatformParameters::parameter34}};
 }
+
+void TimeBasedSchedulingService::notifyNewActivityAddition() {}
+
+void ParameterStatisticsService::initializeStatisticsMap() {
+	statisticsMap = {};
+}
+
 CATCH_REGISTER_LISTENER(ServiceTestsListener)
diff --git a/test/Time/TimeFormats.cpp b/test/Time/TimeFormats.cpp
deleted file mode 100644
index 883af362b940848bb07bfe4cae5a117fb5178098..0000000000000000000000000000000000000000
--- a/test/Time/TimeFormats.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "catch2/catch.hpp"
-#include "Time/Time.hpp"
-#include "Time/UTCTimestamp.hpp"
-#include "../Services/ServiceTests.hpp"
-
-TEST_CASE("UTC timestamps") {
-	// invalid year
-	UTCTimestamp Timestamp0{1950, 4, 10, 10, 15, 0};
-
-	// invalid month
-	UTCTimestamp Timestamp1{2020, 60, 10, 10, 15, 0};
-
-	// invalid day
-	UTCTimestamp Timestamp2{2020, 4, 35, 10, 15, 0};
-
-	// invalid hour
-	UTCTimestamp Timestamp3{2020, 4, 10, 100, 15, 0};
-
-	// invalid minute
-	UTCTimestamp Timestamp4{2020, 4, 10, 10, 200, 0};
-
-	// invalid second
-	UTCTimestamp Timestamp5{2020, 4, 10, 10, 15, 100};
-
-	CHECK(ServiceTests::countErrors() == 6);
-	CHECK(ServiceTests::thrownError(ErrorHandler::InvalidDate));
-}
diff --git a/test/Time/TimeFormatsTests.cpp b/test/Time/TimeFormatsTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c7c0720930c619335c5fff1c7d323d032a38e525
--- /dev/null
+++ b/test/Time/TimeFormatsTests.cpp
@@ -0,0 +1,79 @@
+#include "../Services/ServiceTests.hpp"
+#include "Time/Time.hpp"
+#include "Time/UTCTimestamp.hpp"
+#include "Message.hpp"
+#include "catch2/catch_all.hpp"
+
+TEST_CASE("UTC timestamps") {
+	// invalid year
+	UTCTimestamp Timestamp0{1950, 4, 10, 10, 15, 0};
+
+	// invalid month
+	UTCTimestamp Timestamp1{2020, 60, 10, 10, 15, 0};
+
+	// invalid day
+	UTCTimestamp Timestamp2{2020, 4, 35, 10, 15, 0};
+
+	// invalid hour
+	UTCTimestamp Timestamp3{2020, 4, 10, 100, 15, 0};
+
+	// invalid minute
+	UTCTimestamp Timestamp4{2020, 4, 10, 10, 200, 0};
+
+	// invalid second
+	UTCTimestamp Timestamp5{2020, 4, 10, 10, 15, 100};
+
+	CHECK(ServiceTests::countErrors() == 6);
+	CHECK(ServiceTests::thrownError(ErrorHandler::InvalidDate));
+}
+
+TEST_CASE("UTC timestamp addition") {
+	using namespace std::chrono_literals;
+
+	UTCTimestamp time1 = UTCTimestamp{2020, 1, 1, 0, 0, 0};
+	UTCTimestamp time2 = UTCTimestamp{2035, 11, 19, 23, 57, 24};
+
+	SECTION("Valid ranges") {
+		auto time = time1;
+		time += -1s;
+		CHECK(ServiceTests::thrownError(ErrorHandler::InvalidTimeStampInput));
+	}
+
+	SECTION("Simple addition") {
+		auto time = time1;
+		time += 10s;
+		CHECK(time == UTCTimestamp{2020, 1, 1, 0, 0, 10});
+
+		time += 25h;
+		CHECK(time == UTCTimestamp{2020, 1, 2, 1, 0, 10});
+	}
+
+	SECTION("Overflow within range") {
+		auto time = time2;
+		time += 1209780s;
+		CHECK(time == UTCTimestamp{2035, 12, 4, 0, 0, 24});
+
+		time += 60 * 24h;
+		CHECK(time == UTCTimestamp{2036, 2, 2, 0, 0, 24});
+	}
+
+	SECTION("Future dates") {
+		auto time = time2;
+		time += 999999h;
+		CHECK(time == UTCTimestamp{2149, 12, 18, 14, 57, 24});
+	}
+}
+
+TEST_CASE("CUC Custom Timestamp as Parameter") {
+	using namespace Time;
+	DefaultCUC time(999_t);
+
+	auto parameter = Parameter<DefaultCUC>(time);
+
+	auto message = Message(0, 0, Message::TC);
+	parameter.appendValueToMessage(message);
+	CHECK(message.dataSize == 4);
+
+	parameter.setValueFromMessage(message);
+	CHECK(time == parameter.getValue());
+}
diff --git a/test/Time/TimeStamp.cpp b/test/Time/TimeStamp.cpp
deleted file mode 100644
index ac99522ba966f817f7a048a615ab4782975007bd..0000000000000000000000000000000000000000
--- a/test/Time/TimeStamp.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-#include "catch2/catch.hpp"
-#include "Time/TimeStamp.hpp"
-
-using namespace Time;
-
-TEST_CASE("TimeStamp class construction") {
-	// SECTION("Initialize with excessive precision, breaks at compile time"){
-	//   TimeStamp<5, 10> Epoch3;
-	//   TimeStamp<4, 4> Epoch4;
-	// }
-}
-
-TEST_CASE("CUC headers generation") {
-	auto cuc_header1 = buildCUCHeader<uint8_t, 2, 2>();
-	CHECK(cuc_header1 == 0b00100110);
-
-	auto cuc_header2 = buildCUCHeader<uint8_t, 4, 1>();
-	CHECK(cuc_header2 == 0b00101101);
-
-	auto cuc_header3 = buildCUCHeader<uint8_t, 1, 1>();
-	CHECK(cuc_header3 == 0b00100001);
-
-	auto cuc_header4 = buildCUCHeader<uint16_t, 5, 1>();
-	CHECK(cuc_header4 == 0b1010110110100000);
-
-	auto cuc_header5 = buildCUCHeader<uint16_t, 1, 6>();
-	CHECK(cuc_header5 == 0b1010001110001100);
-
-	auto cuc_header6 = buildCUCHeader<uint16_t, 7, 1>();
-	CHECK(cuc_header6 == 0b1010110111100000);
-}
-
-TEST_CASE("TAI idempotence") {
-	int input_time = 1000;
-	TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(input_time);
-
-	REQUIRE(time.asTAIseconds() == input_time);
-}
-
-TEST_CASE("CUC idempotence") {
-	etl::array<uint8_t, 9> input1 = {0b00101010, 0, 1, 1, 3, 0, 0, 0, 0};
-	TimeStamp<3, 2> time1(input1);
-	etl::array<uint8_t, 9> cuc1 = time1.toCUCtimestamp();
-
-	for (uint8_t i = 0; i < 9; i++) {
-		CHECK(input1[i] == cuc1[i]);
-	}
-
-	etl::array<uint8_t, 9> input2 = {0b10101101, 0b10100000, 218, 103, 11, 0, 3, 23, 0};
-	TimeStamp<5, 1> time2(input2);
-	etl::array<uint8_t, 9> cuc2 = time2.toCUCtimestamp();
-
-	for (auto i = 0; i < 9; i++) {
-		CHECK(input2[i] == cuc2[i]);
-	}
-
-	etl::array<uint8_t, 9> input3 = {0b10100011, 0b10001100, 218, 103, 11, 0, 3, 23, 2};
-	TimeStamp<1, 6> time3(input3);
-	etl::array<uint8_t, 9> cuc3 = time3.toCUCtimestamp();
-
-	for (auto i = 0; i < 9; i++) {
-		CHECK(input3[i] == cuc3[i]);
-	}
-}
-
-TEST_CASE("Conversion between CUC formats") {
-	SECTION("Base unit conversion") {
-		TimeStamp<2, 2> time1(20123);
-		TimeStamp<5, 2> time2(time1.toCUCtimestamp());
-		CHECK(time1.asTAIseconds() == time2.asTAIseconds());
-	}
-
-	SECTION("Floating unit conversion") {
-		etl::array<uint8_t, 9> timeInput = {0b00101010, 0, 1, 1, 3, 0, 0, 0, 0};
-		TimeStamp<3, 2> time1(timeInput);
-
-		TimeStamp<3, 5> time2(time1.toCUCtimestamp());
-		CHECK(time1.asTAIseconds() == time2.asTAIseconds());
-	}
-
-	SECTION("All units conversion") {
-		etl::array<uint8_t, 9> timeInput = {0b00101010, 0, 1, 1, 3, 0, 0, 0, 0};
-		TimeStamp<3, 2> time1(timeInput);
-
-		TimeStamp<4, 4> time2(time1.toCUCtimestamp());
-		CHECK(time1.asTAIseconds() == time2.asTAIseconds());
-	}
-}
-
-TEST_CASE("Use of custom Acubesat CUC format") {
-	SECTION("Check forward conversion") {
-		Time::CustomCUC_t customCUC1 = {1001};
-		TimeStamp<3, 0> time1(customCUC1);
-		CHECK(time1.asTAIseconds() == 100);
-		CHECK(time1.asCustomCUCTimestamp().elapsed100msTicks == 1000);
-		TimeStamp<3, 2> time2(customCUC1);
-		CHECK(time2.asTAIseconds() == 100);
-		CHECK(time2.asCustomCUCTimestamp().elapsed100msTicks == 1000);
-
-		// check rounding errors
-		Time::CustomCUC_t customCUC2 = {1004};
-		TimeStamp<3, 0> time3(customCUC2);
-		CHECK(time3.asTAIseconds() == 100);
-		CHECK(time3.asCustomCUCTimestamp().elapsed100msTicks == 1000);
-		TimeStamp<3, 2> time4(customCUC2);
-		CHECK(time4.asTAIseconds() == 100);
-		CHECK(time4.asCustomCUCTimestamp().elapsed100msTicks == 1003);
-
-		// check rounding errors
-		Time::CustomCUC_t customCUC3 = {1005};
-		TimeStamp<3, 0> time5(customCUC3);
-		CHECK(time5.asTAIseconds() == 100);
-		CHECK(time5.asCustomCUCTimestamp().elapsed100msTicks == 1000);
-		TimeStamp<3, 2> time6(customCUC3);
-		CHECK(time6.asTAIseconds() == 100);
-		CHECK(time6.asCustomCUCTimestamp().elapsed100msTicks == 1005);
-	}
-
-	SECTION("Check idempotence") {
-		Time::CustomCUC_t customCUC1 = {1000};
-		TimeStamp<3, 3> time1(customCUC1);
-		Time::CustomCUC_t customCUC2 = time1.asCustomCUCTimestamp();
-		CHECK(customCUC1.elapsed100msTicks == customCUC2.elapsed100msTicks);
-	}
-}
-
-TEST_CASE("UTC idempotence") {
-	{
-		UTCTimestamp timestamp1(2020, 4, 10, 10, 15, 0); // 10 Apr 2020, 10:15:00;
-		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
-		UTCTimestamp timestamp2 = time.toUTCtimestamp();
-		bool cond = (timestamp2 == timestamp1);
-		REQUIRE(cond);
-	}
-	{
-		UTCTimestamp timestamp1(2035, 1, 1, 0, 0, 1); // 1 Jan 2035 midnight passed;
-		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
-		UTCTimestamp timestamp2 = time.toUTCtimestamp();
-		bool cond = (timestamp2 == timestamp1);
-		REQUIRE(cond);
-	}
-}
-
-TEST_CASE("UTC conversion to and from seconds timestamps") {
-	{
-		UTCTimestamp timestamp1(2020, 12, 5, 0, 0, 0);
-		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
-		REQUIRE(time.asTAIseconds() == 29289600);
-	}
-	{
-		UTCTimestamp timestamp1(2020, 2, 29, 0, 0, 0);
-		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
-		REQUIRE(time.asTAIseconds() == 5097600);
-	}
-	{
-		UTCTimestamp timestamp1(2025, 3, 10, 0, 0, 0);
-		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
-		REQUIRE(time.asTAIseconds() == 163728000);
-	}
-}
-
-// SECTION("Check different templates, should break at compile"){
-//   TimeStamp<1, 2> time1;
-//   TimeStamp<4, 4> time2;
-//   REQUIRE(time1==time2);
-// }
-
-TEST_CASE("Time operators") {
-	TimeStamp<1, 2> time1;
-	TimeStamp<1, 2> time2;
-	TimeStamp<1, 2> time3(10);
-	TimeStamp<1, 2> time4(12);
-	TimeStamp<1, 2> time5(10);
-	TimeStamp<2, 2> time6;
-	REQUIRE(time1 == time2);
-	REQUIRE(time2 == time1);
-	REQUIRE(time3 == time5);
-	REQUIRE(time1 != time3);
-	REQUIRE(time3 != time4);
-	REQUIRE(time3 <= time4);
-	REQUIRE(time3 < time4);
-
-	// REQUIRE(time1 == time6); //should fail at compile, different templates
-}
-
-TEST_CASE("Time runtime class size") {
-	int input_time = 1000;
-	TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(input_time);
-	REQUIRE(sizeof(time) < 32);
-}
diff --git a/test/Time/TimeStampTests.cpp b/test/Time/TimeStampTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5338de0d5cc600cb0bfcd0967229aeac60658b0
--- /dev/null
+++ b/test/Time/TimeStampTests.cpp
@@ -0,0 +1,353 @@
+#include "../Services/ServiceTests.hpp"
+#include "Time/TimeStamp.hpp"
+#include "catch2/catch_all.hpp"
+
+using namespace Time;
+using Catch::Approx;
+
+TEST_CASE("TimeStamp class construction") {
+	// SECTION("Initialize with excessive precision, breaks at compile time"){
+	//   TimeStamp<5, 10> Epoch3;
+	//   TimeStamp<4, 4> Epoch4;
+	// }
+}
+
+TEST_CASE("CUC headers generation") {
+	auto cuc_header1 = buildCUCHeader<uint8_t, 2, 2>();
+	CHECK(cuc_header1 == 0b00100110);
+
+	auto cuc_header2 = buildCUCHeader<uint8_t, 4, 1>();
+	CHECK(cuc_header2 == 0b00101101);
+
+	auto cuc_header3 = buildCUCHeader<uint8_t, 1, 1>();
+	CHECK(cuc_header3 == 0b00100001);
+
+	auto cuc_header4 = buildCUCHeader<uint16_t, 5, 1>();
+	CHECK(cuc_header4 == 0b1010110110100000);
+
+	auto cuc_header5 = buildCUCHeader<uint16_t, 1, 6>();
+	CHECK(cuc_header5 == 0b1010001110001100);
+
+	auto cuc_header6 = buildCUCHeader<uint16_t, 7, 1>();
+	CHECK(cuc_header6 == 0b1010110111100000);
+}
+
+TEST_CASE("TAI idempotence") {
+	int input_time = 1000;
+	TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(input_time);
+
+	REQUIRE(time.asTAIseconds() == input_time);
+}
+
+TEST_CASE("CUC idempotence") {
+	etl::array<uint8_t, 9> input1 = {0b00101010, 0, 1, 1, 3, 0, 0, 0, 0};
+	TimeStamp<3, 2> time1(input1);
+	etl::array<uint8_t, 9> cuc1 = time1.formatAsCUC();
+
+	for (uint8_t i = 0; i < 9; i++) {
+		CHECK(input1[i] == cuc1[i]);
+	}
+
+	etl::array<uint8_t, 9> input2 = {0b10101101, 0b10100000, 218, 103, 11, 0, 3, 23, 0};
+	TimeStamp<5, 1> time2(input2);
+	etl::array<uint8_t, 9> cuc2 = time2.formatAsCUC();
+
+	for (auto i = 0; i < 9; i++) {
+		CHECK(input2[i] == cuc2[i]);
+	}
+
+	etl::array<uint8_t, 9> input3 = {0b10100011, 0b10001100, 218, 103, 11, 0, 3, 23, 2};
+	TimeStamp<1, 6> time3(input3);
+	etl::array<uint8_t, 9> cuc3 = time3.formatAsCUC();
+
+	for (auto i = 0; i < 9; i++) {
+		CHECK(input3[i] == cuc3[i]);
+	}
+}
+
+TEST_CASE("Conversion between CUC formats") {
+	SECTION("Base unit conversion") {
+		TimeStamp<2, 2> time1(20123);
+		TimeStamp<5, 2> time2(time1.formatAsCUC());
+		CHECK(time1.asTAIseconds() == time2.asTAIseconds());
+	}
+
+	SECTION("Floating unit conversion") {
+		etl::array<uint8_t, 9> timeInput = {0b00101010, 0, 1, 1, 3, 0, 0, 0, 0};
+		TimeStamp<3, 2> time1(timeInput);
+
+		TimeStamp<3, 5> time2(time1.formatAsCUC());
+		CHECK(time1.asTAIseconds() == time2.asTAIseconds());
+	}
+
+	SECTION("All units conversion") {
+		etl::array<uint8_t, 9> timeInput = {0b00101010, 0, 1, 1, 3, 0, 0, 0, 0};
+		TimeStamp<3, 2> time1(timeInput);
+
+		TimeStamp<4, 4> time2(time1.formatAsCUC());
+		CHECK(time1.asTAIseconds() == time2.asTAIseconds());
+	}
+}
+
+TEST_CASE("Use of custom Acubesat CUC format") {
+	SECTION("Check forward conversion") {
+		using namespace Time;
+		DefaultCUC defaultCUC1(1001_t);
+		TimeStamp<3, 0> time1(defaultCUC1);
+		CHECK(time1.asTAIseconds() == 100);
+		CHECK(DefaultCUC(time1).formatAsBytes() == 1000);
+		TimeStamp<3, 2> time2(defaultCUC1);
+		CHECK(time2.asTAIseconds() == 100);
+		CHECK(DefaultCUC(time2).formatAsBytes() == 1001);
+
+		// check rounding errors
+		Time::DefaultCUC defaultCUC2(1004_t);
+		TimeStamp<3, 0> time3(defaultCUC2);
+		CHECK(time3.asTAIseconds() == 100);
+		CHECK(DefaultCUC(time3).formatAsBytes() == 1000);
+		TimeStamp<3, 2> time4(defaultCUC2);
+		CHECK(time4.asTAIseconds() == 100);
+		CHECK(DefaultCUC(time4).formatAsBytes() == 1004);
+
+		// check rounding errors
+		Time::DefaultCUC defaultCUC3(1005_t);
+		TimeStamp<3, 0> time5(defaultCUC3);
+		CHECK(time5.asTAIseconds() == 101);
+		CHECK(DefaultCUC(time5).formatAsBytes() == 1010);
+		TimeStamp<3, 2> time6(defaultCUC3);
+		CHECK(time6.asTAIseconds() == 100);
+		CHECK(DefaultCUC(time6).formatAsBytes() == 1005);
+	}
+
+	SECTION("Check idempotence") {
+		Time::DefaultCUC defaultCUC1(1000_t);
+		TimeStamp<3, 3> time1(defaultCUC1);
+		Time::DefaultCUC defaultCUC2(time1);
+		CHECK(defaultCUC1 == defaultCUC2);
+	}
+}
+
+TEST_CASE("UTC idempotence") {
+	{
+		UTCTimestamp timestamp1(2020, 4, 10, 10, 15, 0); // 10 Apr 2020, 10:15:00;
+		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
+		UTCTimestamp timestamp2 = time.toUTCtimestamp();
+		bool cond = (timestamp2 == timestamp1);
+		CHECK(cond);
+	}
+	{
+		UTCTimestamp timestamp1(2035, 1, 1, 0, 0, 1); // 1 Jan 2035 midnight passed;
+		TimeStamp<CUCSecondsBytes, CUCFractionalBytes> time(timestamp1);
+		UTCTimestamp timestamp2 = time.toUTCtimestamp();
+		bool cond = (timestamp2 == timestamp1);
+		CHECK(cond);
+	}
+}
+
+TEST_CASE("UTC conversion to and from seconds timestamps") {
+	{
+		UTCTimestamp utc(2020, 12, 5, 0, 0, 0);
+		TimeStamp<4, 1> time(utc);
+		CHECK(time.asTAIseconds() == 29289600);
+	}
+	{
+		UTCTimestamp utc(2020, 2, 29, 0, 0, 0);
+		TimeStamp<4, 1> time(utc);
+		CHECK(time.asTAIseconds() == 5097600);
+	}
+	{
+		UTCTimestamp utc(2025, 3, 10, 0, 0, 0);
+		TimeStamp<4, 1> time(utc);
+		CHECK(time.asTAIseconds() == 163728000);
+	}
+	{
+		UTCTimestamp utc(2025, 3, 10, 0, 0, 0);
+		TimeStamp<4, 1, 2, 3> time(utc);
+		CHECK(time.asTAIseconds() == 163728000);
+	}
+}
+
+TEST_CASE("UTC overflow tests") {
+	SECTION("Year too high") {
+		UTCTimestamp utc(2999, 3, 11, 0, 0, 0);
+		TimeStamp<2, 1> time(utc);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::TimeStampOutOfBounds));
+	}
+	SECTION("Seconds too high, small variable") {
+		UTCTimestamp utc(Epoch.year, Epoch.month, Epoch.day, 0, 7, 0);
+		TimeStamp<1, 1> time(utc);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::TimeStampOutOfBounds));
+	}
+	SECTION("Seconds too high, wide variable") {
+		UTCTimestamp utc(Epoch.year, Epoch.month, Epoch.day, 0, 7, 0);
+		TimeStamp<1, 4> time(utc);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::TimeStampOutOfBounds));
+	}
+}
+
+TEST_CASE("Time comparison operators") {
+	SECTION("Same type") {
+		TimeStamp<1, 2> time1;
+		TimeStamp<1, 2> time2;
+		TimeStamp<1, 2> time3(10);
+		TimeStamp<1, 2> time4(12);
+		TimeStamp<1, 2> time5(10);
+		CHECK(time1 == time2);
+		CHECK(time2 == time1);
+		CHECK(time3 == time5);
+		CHECK(time1 != time3);
+		CHECK(time3 != time4);
+		CHECK(time3 <= time4);
+		CHECK(time3 < time4);
+	}
+
+	SECTION("Different size") {
+		TimeStamp<1, 2> time1(10);
+		TimeStamp<2, 1> time2(10);
+		TimeStamp<3, 2> time3(15);
+		TimeStamp<2, 2> time4(5);
+		CHECK(time1 == time2);
+		CHECK(time3 != time2);
+		CHECK(time4 < time2);
+		CHECK(time3 > time4);
+		CHECK(time2 >= time1);
+		CHECK(time1 <= time3);
+	}
+
+	SECTION("Different units") {
+		TimeStamp<1, 2, 10> time1(10);
+		TimeStamp<1, 2, 1, 10> time2(10);
+		TimeStamp<3, 2, 3, 2> time3(15);
+		TimeStamp<2, 2, 57, 89> time4(5);
+		CHECK(time1 == time2);
+		CHECK(time3 != time2);
+		CHECK(time4 < time2);
+		CHECK(time3 > time4);
+		CHECK(time2 >= time1);
+		CHECK(time1 <= time3);
+	}
+
+	SECTION("Overflow") {
+		TimeStamp<1, 0> time1(1);
+		TimeStamp<4, 4> time2(std::numeric_limits<uint32_t>::max());
+
+		CHECK(time1 != time2);
+		CHECK_FALSE(time1 == time2);
+		CHECK(time1 < time2);
+		CHECK(time1 <= time2);
+		CHECK(time2 > time1);
+		CHECK(time2 >= time1);
+	}
+}
+
+TEST_CASE("Finding distance between times") {
+	using namespace std::literals;
+
+	SECTION("Same type") {
+		TimeStamp<1, 2> time1(15);
+		TimeStamp<1, 2> time2(30);
+
+		CHECK(time2 - time1 == 15s);
+		CHECK(time1 - time2 == -15s);
+	}
+
+	SECTION("Different type") {
+		TimeStamp<1, 2> time1(15);
+		TimeStamp<2, 1> time2(30);
+		TimeStamp<1, 0, 1, 1000> time3(300ms);
+		TimeStamp<1, 2> time4(300ms);
+		TimeStamp<1, 3> time5(300ms);
+
+		CHECK(time2 - time1 == 15s);
+		CHECK(time1 - time2 == -15s);
+		CHECK(time3 - time1 == -14700ms);
+		CHECK(time1 - time4 == time1 - time5);
+	}
+}
+
+TEST_CASE("Time runtime class size") {
+	REQUIRE(sizeof(TimeStamp<CUCSecondsBytes, CUCFractionalBytes>) <= 8);
+}
+
+TEST_CASE("CUC conversions") {
+	SECTION("Base unit, without fractions") {
+		TimeStamp<2, 0, 10, 1> time1(100);
+		CHECK(time1.asTAIseconds() == 100);
+
+		TimeStamp<2, 0, 1, 10> time2(time1);
+		CHECK(time2.asTAIseconds() == 100);
+	}
+
+	SECTION("Base unit, with fractions") {
+		TimeStamp<2, 2, 10, 1> time1(100);
+		CHECK(time1.asTAIseconds() == 100);
+
+		TimeStamp<2, 2, 1, 10> time2(time1);
+		CHECK(time2.asTAIseconds() == 100);
+	}
+
+	SECTION("Addition of fraction") {
+		TimeStamp<2, 0, 1, 1> time1(100);
+		CHECK(time1.asTAIseconds() == 100);
+
+		TimeStamp<2, 2, 1, 1> time2(time1);
+		CHECK(time2.asTAIseconds() == 100);
+	}
+
+	SECTION("Removal of fraction") {
+		TimeStamp<2, 2, 1, 1> time1(100);
+		CHECK(time1.asTAIseconds() == 100);
+
+		TimeStamp<2, 0, 1, 1> time2(time1);
+		CHECK(time2.asTAIseconds() == 100);
+	}
+
+	SECTION("Many changes") {
+		TimeStamp<2, 2, 3, 2> time1(1000);
+		CHECK(time1.asTAIseconds() == Approx(1000).epsilon(1));
+
+		TimeStamp<3, 4, 100, 29> time2(time1);
+		CHECK(time2.asTAIseconds() == Approx(1000).epsilon(1));
+
+		TimeStamp<2, 1, 1, 1> time3(time1);
+		CHECK(time3.asTAIseconds() == Approx(1000).epsilon(1));
+	}
+
+	SECTION("Large numbers") {
+		TimeStamp<4, 0, 1, 1> time1(10000);
+		CHECK(time1.asTAIseconds() == 10000);
+
+		TimeStamp<2, 1, 7907, 7559> time2(time1);
+		CHECK(time2.asTAIseconds() == 9999);
+	}
+}
+
+TEST_CASE("Duration conversions") {
+	using namespace std::chrono_literals;
+
+	SECTION("Conversion to duration") {
+		TimeStamp<2, 2, 1, 1> time(3600);
+		auto duration = time.asDuration<std::chrono::hours>();
+		CHECK(duration == 1h);
+	}
+
+	SECTION("Conversion from duration") {
+		auto duration = 90min;
+		TimeStamp<2, 2, 1, 1> time(duration);
+		CHECK(time.asTAIseconds() == 5400);
+	}
+
+	SECTION("Duration idempotence") {
+		auto duration = 13532s;
+		TimeStamp<2, 2, 1, 1> time(duration);
+
+		CHECK(time.asDuration() == duration);
+	}
+
+	SECTION("Overflow") {
+		auto duration = 24h;
+		TimeStamp<2, 2, 1, 1> time(duration);
+
+		CHECK(time.asTAIseconds() == 20864);
+	}
+}
diff --git a/test/tests.cpp b/test/tests.cpp
index f481b16fe25e9b620f1dcf078a53f4f357d466c5..13928b9a80b6b91a1f06b6c17727c32de4098f69 100644
--- a/test/tests.cpp
+++ b/test/tests.cpp
@@ -1,3 +1,3 @@
 #define CATCH_CONFIG_MAIN
 
-#include <catch2/catch.hpp>
+#include <catch2/catch_all.hpp>