diff --git a/CMakeLists.txt b/CMakeLists.txt
index a60c3aa629404e5c408e4a097762ca078bea7e81..0b046fbdf84bdb2de8dcf8f30a35096a515b4f73 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,8 +28,9 @@ add_library(common OBJECT
         src/Services/RequestVerificationService.cpp
         src/Services/TestService.cpp
         src/Services/TimeManagementService.cpp
+        src/Services/TimeBasedSchedulingService.cpp
+    	src/Services/EventActionService.cpp
         src/Services/FunctionManagementService.cpp
-	src/Services/EventActionService.cpp
         )
 
 # Specify the .cpp files for the executables
diff --git a/inc/ECSS_Definitions.hpp b/inc/ECSS_Definitions.hpp
index 1f000979a32969565a7cdee0d7e91f63779da207..de8033326c5e80391f4729fd889124f331bcc919 100644
--- a/inc/ECSS_Definitions.hpp
+++ b/inc/ECSS_Definitions.hpp
@@ -9,9 +9,41 @@
 #define CCSDS_PACKET_VERSION 0
 
 // 7.4.4.1c
-#define ECSS_PUS_VERSION 2
+#define ECSS_PUS_VERSION 2U
 
 // 9.3.1a.1.e
 #define ECSS_SEQUENCE_FLAGS 0x3
 
+/**
+ * @brief Maximum number of TC requests that can be contained in a single message request
+ * @details This definition accounts for the maximum number of TC packet requests that can be
+ * contained in the message of a request. This was defined for the time based command scheduling
+ * service and specifically to address the needs of the sub-services containing a TC packet in
+ * their message request.
+ * @attention This definition is probably dependent on the ECSS_TC_REQUEST_STRING_SIZE
+ */
+#define ECSS_MAX_REQUEST_COUNT 20 // todo: Needs to be defined
+
+/**
+ * @brief Maximum length of a String converted TC packet message
+ * @details This definition refers to the maximum length that an embedded TC packet, meaning a TC
+ * packet contained in a message request as a part of the request.
+ */
+#define ECSS_TC_REQUEST_STRING_SIZE 64
+
+// todo: Define the maximum number of activities
+#define ECSS_MAX_NUMBER_OF_TIME_SCHED_ACTIVITIES    10
+
+/**
+ * @brief Time margin used in the time based command scheduling service ST[11]
+ * @details This defines the time margin in seconds, from the current rime, that an activity must
+ * have in order
+ * @todo Define the time margin for the command activation
+ */
+#define ECSS_TIME_MARGIN_FOR_ACTIVATION  60
+
+// todo: Define the maximum delta between the specified
+#define ECSS_MAX_DELTA_OF_RELEASE_TIME   60
+// release time and the actual release time
+
 #endif //ECSS_SERVICES_ECSS_DEFINITIONS_H
diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp
index 75b116b5bf3df82c51287de78441136fc2e453a2..4f50837588ce77417bc2818c2093b675a9bfd267 100644
--- a/inc/ErrorHandler.hpp
+++ b/inc/ErrorHandler.hpp
@@ -110,6 +110,8 @@ public:
 	 */
 	enum ExecutionStartErrorType {
 		UnknownExecutionStartError = 0,
+		SubServiceExecutionStartError = 1,
+		InstructionExecutionStartError = 2,
 	};
 
 	/**
diff --git a/inc/Message.hpp b/inc/Message.hpp
index 3240626189f8848a4147f9e97e9d46399dfaa5fe..ac1509f9ea39dc2c8d330e0ebd4bcc34978c382a 100644
--- a/inc/Message.hpp
+++ b/inc/Message.hpp
@@ -22,6 +22,41 @@ class Message {
 public:
 	Message() = default;
 
+	/**
+	 * @brief Compare two messages
+	 * @details Check whether two Message objects are of the same type
+	 * @param msg1 First message for comparison
+	 * @param msg2 Second message for comparison
+	 * @return A boolean value indicating whether the messages are of the same type
+	 */
+	static bool isSameType(const Message &msg1, const Message &msg2) {
+		return (msg1.packetType == msg2.packetType) &&
+		       (msg1.messageType == msg2.messageType) && (msg1.serviceType == msg2.serviceType);
+	}
+
+	/**
+	 * @brief Overload the equality operator to compare messages
+	 * @details Compare two @ref ::Message objects, based on their contents and type
+	 * @param The message content to compare against
+	 * @todo Activate the dataSize check when the Message object data field is defined with a
+	 * fixed size
+	 * @return The result of comparison
+	 */
+	bool operator==(const Message &msg) const {
+		// todo: Enable the following check when the message data field has a fixed size padded
+		//  with zeros. At the moment the data array is not padded with zeros to fulfil the
+		//  maximum set number of a TC request message.
+		//if (this->dataSize != msg.dataSize) return false;
+
+		for (uint16_t i = 0; i < ECSS_MAX_MESSAGE_SIZE; i++) {
+			if (this->data[i] != msg.data[i]) {
+				return false;
+			}
+		}
+		return (this->packetType == msg.packetType) &&
+		       (this->messageType == msg.messageType) && (this->serviceType == msg.serviceType);
+	}
+
 	enum PacketType {
 		TM = 0, // Telemetry
 		TC = 1 // Telecommand
@@ -438,6 +473,16 @@ public:
 		return size; // Return the string size
 	}
 
+	/**
+	 * @brief Skip read bytes in the read string
+	 * @details Skips the provided number of bytes, by incrementing the readPosition and this is
+	 * done to avoid accessing the `readPosition` variable directly
+	 * @param numberOfBytes The number of bytes to be skipped
+	 */
+	void skipBytes(uint16_t numberOfBytes) {
+		readPosition += numberOfBytes;
+	}
+
 	/**
 	 * Reset the message reading status, and start reading data from it again
 	 */
diff --git a/inc/MessageParser.hpp b/inc/MessageParser.hpp
index 4d1985b274f049dd325287de6e623b9a85b0ea4b..4b848bc75c08f443d8a1302d4c683baf2b4abc01 100644
--- a/inc/MessageParser.hpp
+++ b/inc/MessageParser.hpp
@@ -37,7 +37,24 @@ public:
 	 * this great analysis:
 	 * stackoverflow.com/questions/15078638/can-i-turn-unsigned-char-into-char-and-vice-versa
 	 */
-	Message parseRequestTC(String<ECSS_EVENT_SERVICE_STRING_SIZE> data);
+	Message parseRequestTC(String<ECSS_TC_REQUEST_STRING_SIZE> data);
+
+	/**
+	 * @brief Overloaded version
+	 * @param data A uint8_t array of the TC packet data
+	 * @return Parsed message
+	 */
+	Message parseRequestTC(uint8_t* data);
+
+	/**
+	 * @brief Converts a TC packet of type Message to a String
+	 * @details Convert a parsed TC message to a string in order to be used by the services
+	 * @param message The Message object to be parsed to a String
+	 * @return A String class containing the parsed TC request
+	 * @attention The returned String has a fixed size, therefore the message size is considered
+	 * fixed and equal to the ECSS_TC_REQUEST_STRING_SIZE definition.
+	 */
+	String<ECSS_TC_REQUEST_STRING_SIZE> convertTCToStr(Message& message);
 
 private:
 	/**
@@ -49,7 +66,7 @@ private:
 	 * @param length The size of the header
 	 * @param message The Message to modify based on the header
 	 */
-	void parseTC(uint8_t *data, uint16_t length, Message &message);
+	void parseTC(const uint8_t *data, uint16_t length, Message &message);
 
 	/**
 	 * Parse the ECSS Telemetry packet secondary header
@@ -60,7 +77,7 @@ private:
 	 * @param length The size of the header
 	 * @param message The Message to modify based on the header
 	 */
-	void parseTM(uint8_t *data, uint16_t length, Message &message);
+	void parseTM(const uint8_t *data, uint16_t length, Message &message);
 };
 
 
diff --git a/inc/Platform/x86/TimeGetter.hpp b/inc/Platform/x86/TimeGetter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dcf22ed020dd6163ef5c1adede6e1f3dbf26d22
--- /dev/null
+++ b/inc/Platform/x86/TimeGetter.hpp
@@ -0,0 +1,24 @@
+#ifndef ECSS_SERVICES_TIMEGETTER_HPP
+#define ECSS_SERVICES_TIMEGETTER_HPP
+
+#include <iostream>
+#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/Services/EventActionService.hpp b/inc/Services/EventActionService.hpp
index 338a67345c0163bb8df8708f784c0b7aae868edc..3b561617d2cbe76b4423b6bcc83035c3fc5af79e 100644
--- a/inc/Services/EventActionService.hpp
+++ b/inc/Services/EventActionService.hpp
@@ -1,7 +1,6 @@
 #ifndef ECSS_SERVICES_EVENTACTIONSERVICE_HPP
 #define ECSS_SERVICES_EVENTACTIONSERVICE_HPP
 
-#define ECSS_EVENT_SERVICE_STRING_SIZE 64
 
 #define ECSS_EVENT_ACTION_STRUCT_ARRAY_SIZE 256
 
diff --git a/inc/Services/EventReportService.hpp b/inc/Services/EventReportService.hpp
index 0ecaf179e3468712fe49984cc3287fc643e32ee9..fdb32c0c5b9ea143c031d1efeaad730f5cd8e822 100644
--- a/inc/Services/EventReportService.hpp
+++ b/inc/Services/EventReportService.hpp
@@ -2,7 +2,7 @@
 #define ECSS_SERVICES_EVENTREPORTSERVICE_HPP
 
 #include "Service.hpp"
-#include <bitset>
+#include <etl/bitset.h>
 /**
  * Implementation of ST[05] event reporting service
  *
@@ -17,7 +17,7 @@
 class EventReportService : public Service {
 private:
 	static const uint16_t numberOfEvents = 7;
-	std::bitset<numberOfEvents> stateOfEvents;
+	etl::bitset<numberOfEvents> stateOfEvents;
 public:
 	// Variables that count the event reports per severity level
 	uint16_t lowSeverityReportCount;
@@ -170,7 +170,7 @@ public:
 	 * Getter for stateOfEvents bitset
 	 * @return stateOfEvents, just in case the whole bitset is needed
 	 */
-	std::bitset<numberOfEvents> getStateOfEvents() {
+	etl::bitset<numberOfEvents> getStateOfEvents() {
 		return stateOfEvents;
 	}
 };
diff --git a/inc/Services/TimeBasedSchedulingService.hpp b/inc/Services/TimeBasedSchedulingService.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..76343b5d76fa5aac07e9a59f29899ec00769e4bd
--- /dev/null
+++ b/inc/Services/TimeBasedSchedulingService.hpp
@@ -0,0 +1,250 @@
+#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 "Helpers/TimeHelper.hpp"
+
+// Include platform specific files
+#include "Platform/x86/TimeGetter.hpp"
+
+/**
+ * @def SUB_SCHEDULES_ENABLED
+ * @brief Indicates whether sub-schedules are supported
+ *
+ * @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
+
+
+/**
+ * @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
+
+/**
+ * @brief An implementation of the ECSS standard ST[11] service
+ *
+ * @details This service is taking care of the timed release of a received TC packet from the
+ * ground.
+ * @todo Define whether the parsed absolute release time is saved in the scheduled activity as an
+ * uint32_t or in the time format specified by the time management service.
+ */
+class TimeBasedSchedulingService : public Service {
+private:
+	/**
+	 * @brief Indicator of the schedule execution
+	 *
+	 * @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
+
+	MessageParser msgParser; // Parse TC packets
+
+	/**
+	 * @brief Request identifier of the received packet
+	 *
+	 * @details The request identifier consists of the application process ID, the packet
+	 * sequence count and the source ID, all defined in the ECSS standard.
+	 * @var applicationID Application process ID
+	 * @var sequenceCount Packet sequence count
+	 * @var sourceID Packet source ID
+	 */
+	struct RequestID {
+		uint16_t applicationID = 0;
+		uint16_t sequenceCount = 0;
+		uint8_t sourceID = 0;
+
+		bool operator!=(const RequestID &rightSide) const {
+			return (sequenceCount != rightSide.sequenceCount) or
+			       (applicationID != rightSide.applicationID) or (sourceID != rightSide.sourceID);
+		}
+	};
+
+	/**
+	 * @brief Instances of activities to run in the schedule
+	 *
+	 * @details All scheduled activities must contain the request they exist for, their release
+	 * time and the corresponding request identifier.
+	 * @var request Contains the received TC request
+	 * @var requestID Contains the unique request identifier for that activity
+	 * @var requestReleaseTime The absolute time is seconds of the request release
+	 */
+	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
+		// todo: If we decide to use sub-schedules, the ID of that has to be defined
+		// todo: If groups are used, then the group ID has to be defined here
+	};
+
+	/**
+	 * @brief Hold the scheduled activities
+	 *
+	 * @details The scheduled activities in this list are ordered by their release time, as the
+	 * standard requests.
+	 */
+	etl::list<ScheduledActivity, ECSS_MAX_NUMBER_OF_TIME_SCHED_ACTIVITIES> scheduledActivities;
+
+
+	/**
+	 * @brief Sort the activities by their release time
+	 *
+	 * @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 sortActivitiesReleaseTime(etl::list<ScheduledActivity,
+		ECSS_MAX_NUMBER_OF_TIME_SCHED_ACTIVITIES> &schedActivities) {
+		schedActivities.sort([](ScheduledActivity const &leftSide, ScheduledActivity const
+		&rightSide) { return leftSide.requestReleaseTime < rightSide.requestReleaseTime; });
+	}
+
+	/**
+	 * @brief Define a friend in order to be able to access private members during testing
+	 *
+	 * @details The private members defined in this class, must not in any way be public to avoid
+	 * misuse. During testing, access to private members for verification is required, so an
+	 * access friend structure is defined here.
+	 */
+	friend struct ::unit_test::Tester;
+
+
+public:
+	/**
+	 * @brief Class constructor
+	 * @details Initializes the serviceType
+	 */
+	TimeBasedSchedulingService();
+
+	/**
+	 * @brief TC[11,1] enable the time-based schedule execution function
+	 *
+	 * @details Enables the time-based command execution scheduling
+	 * @param request Provide the received message as a parameter
+	 */
+	void enableScheduleExecution(Message &request);
+
+	/**
+	 * @breif TC[11,2] disable the time-based schedule execution function
+	 *
+	 * @details Disables the time-based command execution scheduling
+	 * @param request Provide the received message as a parameter
+	 */
+	void disableScheduleExecution(Message &request);
+
+	/**
+	 * @brief TC[11,3] reset the time-based schedule
+	 *
+	 * @details Resets the time-based command execution schedule, by clearing all scheduled
+	 * activities.
+	 * @param request Provide the received message as a parameter
+	 */
+	void resetSchedule(Message &request);
+
+	/**
+	 * @brief TC[11,4] insert activities into the time based schedule
+	 *
+	 * @details Add activities into the schedule for future execution. The activities are inserted
+	 * by ascending order of their release time. This done to avoid confusion during the
+	 * execution of the schedule and also to make things easier whenever a release time sorted
+	 * report is requested by he corresponding service.
+	 * @param request Provide the received message as a parameter
+	 * @todo Definition of the time format is required
+	 * @throws ExecutionStartError If there is request to be inserted and the maximum
+	 * number of activities in the current schedule has been reached, then an @ref
+	 * ErrorHandler::ExecutionStartErrorType is being issued.  Also if the release time of the
+	 * request is less than a set time margin, defined in @ref ECSS_TIME_MARGIN_FOR_ACTIVATION,
+	 * from the current time a @ref ErrorHandler::ExecutionStartErrorType is also issued.
+	 */
+	void insertActivities(Message &request);
+
+	/**
+	 * @brief TC[11,15] time-shift all scheduled activities
+	 *
+	 * @details All scheduled activities are shifted per user request. The relative time offset
+	 * received and tested against the current time.
+	 * @param request Provide the received message as a parameter
+	 * @todo Definition of the time format is required for the relative time format
+	 * @throws ExecutionStartError If the release time of the request is less than a
+	 * set time margin, defined in @ref ECSS_TIME_MARGIN_FOR_ACTIVATION, from the current time an
+	 * @ref ErrorHandler::ExecutionStartErrorType report is issued for that instruction.
+	 */
+	void timeShiftAllActivities(Message &request);
+
+	/**
+	 * @brief TC[11,16] detail-report all activities
+	 *
+	 * @details Send a detailed report about the status of all the activities
+	 * on the current schedule. Generates a TM[11,10] response.
+	 * @param request Provide the received message as a parameter
+	 * @todo Replace the time parsing with the time parser
+	 */
+	void detailReportAllActivities(Message &request);
+
+	/**
+	 * @brief TC[11,9] detail-report activities identified by request identifier
+	 *
+	 * @details Send a detailed report about the status of the requested activities, based on the
+	 * provided request identifier. Generates a TM[11,10] response. The matched activities are
+	 * contained in the report, in an ascending order based on their release time.
+	 * @param request Provide the received message as a parameter
+	 * @todo Replace time parsing with the time parser
+	 * @throws ExecutionStartError If a requested activity, identified by the provided
+	 * request identifier is not found in the schedule issue an @ref
+	 * ErrorHandler::ExecutionStartErrorType for that instruction.
+	 */
+	void detailReportActivitiesByID(Message &request);
+
+	/**
+	 * @brief TC[11,12] summary-report activities identified by request identifier
+	 *
+	 * @details Send a summary report about the status of the requested activities. Generates a
+	 * TM[11,13] response, with activities ordered in an ascending order, based on their release
+	 * time.
+	 * @param request Provide the received message as a parameter
+	 * @throws ExecutionStartError If a requested activity, identified by the provided
+	 * request identifier is not found in the schedule issue an @ref
+	 * ErrorHandler::ExecutionStartErrorType for that instruction.
+	 */
+	void summaryReportActivitiesByID(Message &request);
+
+	/**
+	 * @brief TC[11,5] delete time-based scheduled activities identified by a request identifier
+	 *
+	 * @details Delete certain activities by using the unique request identifier.
+	 * @param request Provide the received message as a parameter
+	 * @throws ExecutionStartError If a requested activity, identified by the provided
+	 * request identifier is not found in the schedule issue an @ref
+	 * ErrorHandler::ExecutionStartErrorType for that instruction.
+	 */
+	void deleteActivitiesByID(Message &request);
+
+	/**
+	 * @brief TC[11,7] time-shift scheduled activities identified by a request identifier
+	 *
+	 * @details Time-shift certain activities by using the unique request identifier
+	 * @param request Provide the received message as a parameter
+	 * @todo Definition of the time format is required
+	 * @throws ExecutionStartError If the requested time offset is less than the earliest
+	 * time from the currently scheduled activities plus the @ref ECSS_TIME_MARGIN_FOR_ACTIVATION,
+	 * then the request is rejected and an @ref ErrorHandler::ExecutionStartErrorType is issued.
+	 * 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);
+};
+
+#endif //ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
diff --git a/lib/Catch2 b/lib/Catch2
index d63307279412de3870cf97cc6802bae8ab36089e..62460fafe6b54c3173bc5cbc46d05a5f071017ff 160000
--- a/lib/Catch2
+++ b/lib/Catch2
@@ -1 +1 @@
-Subproject commit d63307279412de3870cf97cc6802bae8ab36089e
+Subproject commit 62460fafe6b54c3173bc5cbc46d05a5f071017ff
diff --git a/src/MessageParser.cpp b/src/MessageParser.cpp
index af4988a1a302b2da35eed9d2cbe45e6b1508b706..d382dd3432bc10b1dbe1b097db8afec2a56827ef 100644
--- a/src/MessageParser.cpp
+++ b/src/MessageParser.cpp
@@ -1,4 +1,3 @@
-#include <cstring>
 #include <Services/EventActionService.hpp>
 #include <ServicePool.hpp>
 #include "ErrorHandler.hpp"
@@ -53,7 +52,7 @@ Message MessageParser::parse(uint8_t *data, uint32_t length) {
 	return message;
 }
 
-void MessageParser::parseTC(uint8_t *data, uint16_t length, Message &message) {
+void MessageParser::parseTC(const uint8_t *data, uint16_t length, Message &message) {
 	ErrorHandler::assertRequest(length >= 5, message, ErrorHandler::UnacceptableMessage);
 
 	// Individual fields of the TC header
@@ -61,6 +60,8 @@ void MessageParser::parseTC(uint8_t *data, uint16_t length, Message &message) {
 	uint8_t serviceType = data[1];
 	uint8_t messageType = data[2];
 
+	// todo: Fix this parsing function, because it assumes PUS header in data, which is not true
+	//  with the current implementation
 	ErrorHandler::assertRequest(pusVersion == 2, message, ErrorHandler::UnacceptableMessage);
 
 	// Remove the length of the header
@@ -74,15 +75,34 @@ void MessageParser::parseTC(uint8_t *data, uint16_t length, Message &message) {
 	message.dataSize = length;
 }
 
-Message MessageParser::parseRequestTC(String<ECSS_EVENT_SERVICE_STRING_SIZE> data) {
+Message MessageParser::parseRequestTC(String<ECSS_TC_REQUEST_STRING_SIZE> data) {
 	Message message;
 	auto *dataInt = reinterpret_cast<uint8_t *>(data.data());
 	message.packetType = Message::TC;
-	parseTC(dataInt, ECSS_EVENT_SERVICE_STRING_SIZE, message);
+	parseTC(dataInt, ECSS_TC_REQUEST_STRING_SIZE, message);
 	return message;
 }
 
-void MessageParser::parseTM(uint8_t *data, uint16_t length, Message &message) {
+Message MessageParser::parseRequestTC(uint8_t* data) {
+	Message message;
+	message.packetType = Message::TC;
+	parseTC(data, ECSS_TC_REQUEST_STRING_SIZE, message);
+	return message;
+}
+
+String<ECSS_TC_REQUEST_STRING_SIZE> MessageParser::convertTCToStr(Message &message) {
+	uint8_t tempString[ECSS_TC_REQUEST_STRING_SIZE] = {0};
+
+	tempString[0] = ECSS_PUS_VERSION << 4; // Assign the pusVersion = 2
+	tempString[1] = message.serviceType;
+	tempString[2] = message.messageType;
+	memcpy(tempString + 5, message.data, ECSS_TC_REQUEST_STRING_SIZE - 5);
+	String<ECSS_TC_REQUEST_STRING_SIZE> dataString(tempString);
+
+	return dataString;
+}
+
+void MessageParser::parseTM(const uint8_t *data, uint16_t length, Message &message) {
 	ErrorHandler::assertRequest(length >= 5, message, ErrorHandler::UnacceptableMessage);
 
 	// Individual fields of the TM header
diff --git a/src/Services/EventActionService.cpp b/src/Services/EventActionService.cpp
index 2ace42dd9796cfff95120b189ed95e35e44c9722..6ac29c0531184da62bbd617f94189fb240995cf6 100644
--- a/src/Services/EventActionService.cpp
+++ b/src/Services/EventActionService.cpp
@@ -34,12 +34,12 @@ void EventActionService::addEventActionDefinitions(Message message) {
 			eventActionDefinitionArray[index].enabled = true;
 			eventActionDefinitionArray[index].applicationId = applicationID;
 			eventActionDefinitionArray[index].eventDefinitionID = eventDefinitionID;
-			if (message.dataSize - 4 > ECSS_EVENT_SERVICE_STRING_SIZE) {
+			if (message.dataSize - 4 > ECSS_TC_REQUEST_STRING_SIZE) {
 				ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::MessageTooLarge);
 			} else {
-				char data[ECSS_EVENT_SERVICE_STRING_SIZE];
+				char data[ECSS_TC_REQUEST_STRING_SIZE];
 				message.readString(data, message.dataSize - 4);
-				eventActionDefinitionArray[index].request = String<ECSS_EVENT_SERVICE_STRING_SIZE>(
+				eventActionDefinitionArray[index].request = String<ECSS_TC_REQUEST_STRING_SIZE>(
 					data);
 			}
 		}
@@ -150,11 +150,11 @@ void EventActionService::eventActionStatusReport() {
 		}
 	}
 	report.appendUint8(count);
-	for (uint16_t i = 0; i < ECSS_EVENT_ACTION_STRUCT_ARRAY_SIZE; i++) {
-		if (not eventActionDefinitionArray[i].empty) {
-			report.appendEnum16(eventActionDefinitionArray[i].applicationId);
-			report.appendEnum16(eventActionDefinitionArray[i].eventDefinitionID);
-			report.appendBoolean(eventActionDefinitionArray[i].enabled);
+	for (const auto &definition : eventActionDefinitionArray) {
+		if (not definition.empty) {
+			report.appendEnum16(definition.applicationId);
+			report.appendEnum16(definition.eventDefinitionID);
+			report.appendBoolean(definition.enabled);
 		}
 	}
 	storeMessage(report);
@@ -178,13 +178,13 @@ void EventActionService::disableEventActionFunction(Message message) {
 void EventActionService::executeAction(uint16_t eventID) {
 	// Custom function
 	if (eventActionFunctionStatus) {
-		for (uint16_t i = 0; i < ECSS_EVENT_ACTION_STRUCT_ARRAY_SIZE; i++) {
-			if (not eventActionDefinitionArray[i].empty &&
-			    eventActionDefinitionArray[i].enabled) {
-				if (eventActionDefinitionArray[i].eventDefinitionID == eventID) {
+		for (const auto &definition : eventActionDefinitionArray) {
+			if (not definition.empty &&
+			    definition.enabled) {
+				if (definition.eventDefinitionID == eventID) {
 					MessageParser messageParser;
 					Message message = messageParser.parseRequestTC(
-						eventActionDefinitionArray[i].request);
+						definition.request);
 					messageParser.execute(message);
 				}
 			}
diff --git a/src/Services/TimeBasedSchedulingService.cpp b/src/Services/TimeBasedSchedulingService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a4b74861f91167a5dbbcd942daa51405e66265d5
--- /dev/null
+++ b/src/Services/TimeBasedSchedulingService.cpp
@@ -0,0 +1,283 @@
+#include "Services/TimeBasedSchedulingService.hpp"
+
+
+TimeBasedSchedulingService::TimeBasedSchedulingService() {
+	serviceType = 11;
+}
+
+void TimeBasedSchedulingService::enableScheduleExecution(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 1);
+
+	executionFunctionStatus = true; // Enable the service
+}
+
+void TimeBasedSchedulingService::disableScheduleExecution(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 2);
+
+	executionFunctionStatus = false; // Disable the service
+}
+
+void TimeBasedSchedulingService::resetSchedule(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 3);
+
+	executionFunctionStatus = false; // Disable the service
+	scheduledActivities.clear(); // Delete all scheduled activities
+	// 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 == 11);
+	assert(request.messageType == 4);
+
+	// todo: Get the sub-schedule ID if they are implemented
+	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	while (iterationCount--) {
+		// todo: Get the group ID first, if groups are used
+		uint32_t currentTime = TimeGetter::getSeconds(); // Get the current system time
+
+		uint32_t releaseTime = request.readUint32(); // Get the specified release time
+		if ((not scheduledActivities.available()) ||
+		    (releaseTime < (currentTime + ECSS_TIME_MARGIN_FOR_ACTIVATION))) {
+			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
+			request.skipBytes(ECSS_TC_REQUEST_STRING_SIZE);
+		} else {
+			// Get the TC packet request
+			uint8_t requestData[ECSS_TC_REQUEST_STRING_SIZE] = {0};
+			request.readString(requestData, ECSS_TC_REQUEST_STRING_SIZE);
+			Message receivedTCPacket = msgParser.parseRequestTC(requestData);
+			ScheduledActivity newActivity; // Create the new activity
+
+			// Assign the attributes to the newly created activity
+			newActivity.request = receivedTCPacket;
+			newActivity.requestReleaseTime = releaseTime;
+
+			// todo: When implemented save the source ID
+			newActivity.requestID.applicationID = request.applicationId;
+			newActivity.requestID.sequenceCount = request.packetSequenceCount;
+
+			scheduledActivities.push_back(newActivity); // Insert the new activities
+		}
+	}
+	sortActivitiesReleaseTime(scheduledActivities); // Sort activities by their release time
+}
+
+void TimeBasedSchedulingService::timeShiftAllActivities(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 15);
+
+	uint32_t current_time = TimeGetter::getSeconds(); // Get the current system time
+
+	// 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 + ECSS_TIME_MARGIN_FOR_ACTIVATION)) {
+		// Report the error
+		ErrorHandler::reportError(request, ErrorHandler::SubServiceExecutionStartError);
+	} else {
+		for (auto &activity : scheduledActivities) {
+			activity.requestReleaseTime += relativeOffset; // Time shift each activity
+		}
+	}
+}
+
+void TimeBasedSchedulingService::timeShiftActivitiesByID(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 7);
+
+	uint32_t current_time = TimeGetter::getSeconds(); // Get the current system time
+
+	int32_t relativeOffset = request.readSint32(); // Get the offset first
+	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	while (iterationCount--) {
+		// 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
+
+		// 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 + ECSS_TIME_MARGIN_FOR_ACTIVATION)) {
+				ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
+			} else {
+				requestIDMatch->requestReleaseTime += relativeOffset; // Add the time offset
+			}
+		} else {
+			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
+		}
+	}
+	sortActivitiesReleaseTime(scheduledActivities); // Sort activities by their release time
+}
+
+void TimeBasedSchedulingService::deleteActivitiesByID(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 5);
+
+	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	while (iterationCount--) {
+		// 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
+
+		// 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
+		} else {
+			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
+		}
+	}
+}
+
+void TimeBasedSchedulingService::detailReportAllActivities(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 16);
+
+	// Create the report message object of telemetry message subtype 10 for each activity
+	Message report = createTM(10);
+	report.appendUint16(static_cast<uint16_t >(scheduledActivities.size()));
+
+	for (auto &activity : scheduledActivities) {
+		// todo: append sub-schedule and group ID if they are defined
+
+		report.appendUint32(activity.requestReleaseTime);
+		report.appendString(msgParser.convertTCToStr(activity.request));
+	}
+	storeMessage(report); // Save the report
+}
+
+void TimeBasedSchedulingService::detailReportActivitiesByID(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 9);
+
+	// Create the report message object of telemetry message subtype 10 for each activity
+	Message report = createTM(10);
+	etl::list<ScheduledActivity, ECSS_MAX_NUMBER_OF_TIME_SCHED_ACTIVITIES> matchedActivities;
+
+	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	while (iterationCount--) {
+		// 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
+
+		// 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
+		} else {
+			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
+		}
+	}
+
+    sortActivitiesReleaseTime(matchedActivities); // Sort activities by their release time
+
+	// 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(msgParser.convertTCToStr(match.request));
+	}
+	storeMessage(report); // Save the report
+}
+
+void TimeBasedSchedulingService::summaryReportActivitiesByID(Message &request) {
+
+	// Check if the correct packet is being processed
+	assert(request.serviceType == 11);
+	assert(request.messageType == 12);
+
+	// Create the report message object of telemetry message subtype 13 for each activity
+	Message report = createTM(13);
+	etl::list<ScheduledActivity, ECSS_MAX_NUMBER_OF_TIME_SCHED_ACTIVITIES> matchedActivities;
+
+	uint16_t iterationCount = request.readUint16(); // Get the iteration count, (N)
+	while (iterationCount--) {
+		// 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
+
+		// 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()) {
+			matchedActivities.push_back(*requestIDMatch);
+		} else {
+			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
+		}
+	}
+	sortActivitiesReleaseTime(matchedActivities); // Sort activities by their release time
+
+	// todo: append sub-schedule and group ID if they are defined
+	report.appendUint16(static_cast<uint16_t >(matchedActivities.size()));
+	for (auto &match : matchedActivities) {
+		// todo: append sub-schedule and group ID if they are defined
+		report.appendUint32(match.requestReleaseTime);
+		report.appendUint8(match.requestID.sourceID);
+		report.appendUint16(match.requestID.applicationID);
+		report.appendUint16(match.requestID.sequenceCount);
+	}
+	storeMessage(report); // Save the report
+}
diff --git a/src/main.cpp b/src/main.cpp
index 2fcf832da10d29251cc5365c865f8ef78a90ac9c..6067a82a5459d2c2137f0b8702484c7ece768791 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -10,9 +10,9 @@
 #include "Services/FunctionManagementService.hpp"
 #include "Services/TimeManagementService.hpp"
 #include "Services/EventActionService.hpp"
+#include "Services/TimeBasedSchedulingService.hpp"
 #include "Message.hpp"
 #include "MessageParser.hpp"
-#include "Services/MemoryManagementService.hpp"
 #include "Helpers/CRCHelper.hpp"
 #include "ErrorHandler.hpp"
 #include "etl/String.hpp"
@@ -291,5 +291,44 @@ int main() {
 		.eventActionDefinitionArray[0].empty);
 
 
+	// ST[11] test
+	TimeBasedSchedulingService timeBasedSchedulingService;
+	MessageParser msgParser;
+	auto currentTime = static_cast<uint32_t >(time(nullptr)); // Get the current system time
+	std::cout << "\n\nST[11] service is running";
+	std::cout << "\nCurrent time in seconds (UNIX epoch): " << currentTime << std::endl;
+
+	Message receivedMsg = Message(11, 1, Message::TC, 1);
+	Message testMessage1(6, 5, Message::TC, 1), testMessage2(4, 5, Message::TC, 1);
+	testMessage1.appendUint16(4253); // Append dummy data
+	testMessage2.appendUint16(45667); // Append dummy data
+
+	timeBasedSchedulingService.enableScheduleExecution(receivedMsg); // Enable the schedule
+
+	// Insert activities in the schedule
+	receivedMsg = Message(11, 4, Message::TC, 1);
+	receivedMsg.appendUint16(2); // Total number of requests
+
+	receivedMsg.appendUint32(currentTime + 1556435);
+	receivedMsg.appendString(msgParser.convertTCToStr(testMessage1));
+
+	receivedMsg.appendUint32(currentTime + 1957232);
+	receivedMsg.appendString(msgParser.convertTCToStr(testMessage2));
+	timeBasedSchedulingService.insertActivities(receivedMsg);
+
+	// Time shift activities
+	receivedMsg = Message(11, 15, Message::TC, 1);
+	receivedMsg.appendSint32(-6789);
+	timeBasedSchedulingService.timeShiftAllActivities(receivedMsg);
+	std::cout << "Activities should be time shifted by: " << -6789 << " seconds." << std::endl;
+
+	// Report the activities
+	receivedMsg = Message(11, 16, Message::TC, 1);
+	timeBasedSchedulingService.detailReportAllActivities(receivedMsg);
+
+	// Report the activities by ID
+	receivedMsg = Message(11, 12, Message::TC, 1);
+	timeBasedSchedulingService.summaryReportActivitiesByID(receivedMsg);
+
 	return 0;
 }
diff --git a/test/Services/TimeBasedSchedulingService.cpp b/test/Services/TimeBasedSchedulingService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bfa878325c513b2a28dd5f1c840cd5d414a7c7ba
--- /dev/null
+++ b/test/Services/TimeBasedSchedulingService.cpp
@@ -0,0 +1,439 @@
+#include <catch2/catch.hpp>
+#include "ServiceTests.hpp"
+#include <Services/TimeBasedSchedulingService.hpp>
+
+#include <ctime>
+#include <vector>
+
+/*
+ * 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 {
+	struct Tester {
+		static bool executionFunctionStatus(TimeBasedSchedulingService &tmService) {
+			return tmService.executionFunctionStatus;
+		}
+
+		/*
+		 * Read the private member scheduled activities and since it is a list and it can't be
+		 * accessed, get each element and save it to a vector.
+		 */
+		static auto scheduledActivities(TimeBasedSchedulingService &tmService) {
+			std::vector<TimeBasedSchedulingService::ScheduledActivity*>listElements;
+
+			for (auto &element : tmService.scheduledActivities) {
+				listElements.push_back(&element);
+			}
+			return listElements; // Return the list elements
+		}
+	};
+}
+
+Message testMessage1, testMessage2, testMessage3, testMessage4;
+MessageParser msgParser;
+auto currentTime = static_cast<uint32_t >(time(nullptr)); // 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) {
+	if (not messagesPopulated) {
+		// Initialize the test messages
+		testMessage1.serviceType = 6;
+		testMessage1.messageType = 5;
+		testMessage1.packetType = Message::TC;
+		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.appendUint16(45667); // Append dummy data
+
+		testMessage3.serviceType = 3;
+		testMessage3.messageType = 2;
+		testMessage3.packetType = Message::TC;
+		testMessage3.appendUint16(456); // Append dummy data
+
+		testMessage4.serviceType = 12;
+		testMessage4.messageType = 23;
+		testMessage4.packetType = Message::TC;
+		testMessage4.appendUint16(934); // Append dummy data
+
+		messagesPopulated = true; // Indicate initialized test messages
+	}
+
+	Message receivedMessage(11, 4, Message::TC, 1);
+	receivedMessage.appendUint16(4); // Total number of requests
+
+	// Test activity 1
+	receivedMessage.appendUint32(currentTime + 1556435);
+	receivedMessage.appendString(msgParser.convertTCToStr(testMessage1));
+
+	// Test activity 2
+	receivedMessage.appendUint32(currentTime + 1957232);
+	receivedMessage.appendString(msgParser.convertTCToStr(testMessage2));
+
+	// Test activity 3
+	receivedMessage.appendUint32(currentTime + 1726435);
+	receivedMessage.appendString(msgParser.convertTCToStr(testMessage3));
+
+	// Test activity 4
+	receivedMessage.appendUint32(currentTime + 17248435);
+	receivedMessage.appendString(msgParser.convertTCToStr(testMessage4));
+
+	// Insert activities in the schedule. They have to be inserted sorted
+	timeService.insertActivities(receivedMessage);
+
+	return unit_test::Tester::scheduledActivities(timeService); // Return the activities vector
+}
+
+
+TEST_CASE("TC[11,1] Enable Schedule Execution", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	Message receivedMessage(11, 1, Message::TC, 1);
+
+	timeService.enableScheduleExecution(receivedMessage);
+	CHECK(unit_test::Tester::executionFunctionStatus(timeService));
+}
+
+TEST_CASE("TC[11,2] Disable Schedule Execution", "[service][st11]") {
+	Message receivedMessage(11, 2, Message::TC, 1);
+	TimeBasedSchedulingService timeService;
+
+	timeService.disableScheduleExecution(receivedMessage);
+	CHECK(not unit_test::Tester::executionFunctionStatus(timeService));
+}
+
+TEST_CASE("TC[11,4] Activity Insertion", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	auto scheduledActivities = activityInsertion(timeService);
+
+	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)->request == testMessage1);
+	REQUIRE(scheduledActivities.at(1)->request == testMessage3);
+	REQUIRE(scheduledActivities.at(2)->request == testMessage2);
+	REQUIRE(scheduledActivities.at(3)->request == testMessage4);
+
+	SECTION("Error throw test") {
+		Message receivedMessage(11, 4, Message::TC, 1);
+		receivedMessage.appendUint16(1); // Total number of requests
+
+		receivedMessage.appendUint32(currentTime - 15564350);
+		timeService.insertActivities(receivedMessage);
+
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
+	}
+}
+
+TEST_CASE("TC[11,15] Time shift all scheduled activities", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	Message receivedMessage(11, 15, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeService);
+	const int32_t timeShift = 6789;
+
+	SECTION("Positive Shift") {
+		receivedMessage.appendSint32(-timeShift);
+
+		CHECK(scheduledActivities.size() == 4);
+		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);
+	}
+
+	SECTION("Negative Shift") {
+		receivedMessage.appendSint32(timeShift);
+
+		CHECK(scheduledActivities.size() == 4);
+		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);
+	}
+
+	SECTION("Error throwing") {
+		receivedMessage.appendSint32(-6789000); // Provide a huge time shift to cause an error
+
+		CHECK(scheduledActivities.size() == 4);
+		timeService.timeShiftAllActivities(receivedMessage);
+
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::SubServiceExecutionStartError));
+	}
+}
+
+TEST_CASE("TC[11,7] Time shift activities by ID", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	Message receivedMessage(11, 7, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeService);
+	scheduledActivities.at(2)->requestID.applicationID = 4; // Append a dummy application ID
+	CHECK(scheduledActivities.size() == 4);
+
+	const int32_t 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.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+
+		timeService.timeShiftActivitiesByID(receivedMessage);
+		scheduledActivities = unit_test::Tester::scheduledActivities(timeService);
+
+		// Make sure the new value is inserted sorted
+		REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 1957232 + timeShift);
+		REQUIRE(scheduledActivities.at(3)->request == testMessage2);
+	}
+
+	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.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+
+		timeService.timeShiftActivitiesByID(receivedMessage);
+		scheduledActivities = unit_test::Tester::scheduledActivities(timeService);
+
+		// Output should be sorted
+		REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1957232 - 250000);
+		REQUIRE(scheduledActivities.at(1)->request == testMessage2);
+	}
+
+	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
+
+		timeService.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.appendUint16(testMessage2.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+
+		timeService.timeShiftActivitiesByID(receivedMessage);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
+	}
+}
+
+TEST_CASE("TC[11,9] Detail report scheduled activities by ID", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	Message receivedMessage(11, 9, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeService);
+
+	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
+
+		timeService.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++) {
+			uint32_t receivedReleaseTime = response.readUint32();
+
+			Message receivedTCPacket;
+			uint8_t receivedDataStr[ECSS_TC_REQUEST_STRING_SIZE];
+			response.readString(receivedDataStr, ECSS_TC_REQUEST_STRING_SIZE);
+			receivedTCPacket = msgParser.parseRequestTC(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);
+			}
+		}
+	}
+
+	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(80); // Dummy application ID to throw an error
+		receivedMessage.appendUint16(0); // Dummy sequence count
+
+		timeService.detailReportActivitiesByID(receivedMessage);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
+	}
+}
+
+TEST_CASE("TC[11,12] Summary report scheduled activities by ID", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	Message receivedMessage(11, 12, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeService);
+
+	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
+
+		timeService.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++) {
+			uint32_t receivedReleaseTime = response.readUint32();
+			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);
+			}
+		}
+	}
+
+	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(80); // Dummy application ID to throw an error
+		receivedMessage.appendUint16(0); // Dummy sequence count
+
+		timeService.summaryReportActivitiesByID(receivedMessage);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
+	}
+}
+
+TEST_CASE("TC[11,16] Detail report all scheduled activities", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	auto scheduledActivities = activityInsertion(timeService);
+
+	Message receivedMessage(11, 16, Message::TC, 1);
+	timeService.detailReportAllActivities(receivedMessage);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	CHECK(response.serviceType == 11);
+	CHECK(response.messageType == 10);
+
+	uint16_t iterationCount = response.readUint16();
+	REQUIRE(iterationCount == scheduledActivities.size());
+
+	for (uint16_t i = 0; i < iterationCount; i++) {
+		uint32_t receivedReleaseTime = response.readUint32();
+
+		Message receivedTCPacket;
+		uint8_t receivedDataStr[ECSS_TC_REQUEST_STRING_SIZE];
+		response.readString(receivedDataStr, ECSS_TC_REQUEST_STRING_SIZE);
+		receivedTCPacket = msgParser.parseRequestTC(receivedDataStr);
+
+		REQUIRE(receivedReleaseTime == scheduledActivities.at(i)->requestReleaseTime);
+		REQUIRE(scheduledActivities.at(i)->request == receivedTCPacket);
+	}
+}
+
+TEST_CASE("TC[11,5] Activity deletion by ID", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	Message receivedMessage(11, 5, Message::TC, 1);
+
+	auto scheduledActivities = activityInsertion(timeService);
+
+	SECTION("Activity deletion") {
+		// Verify that everything is in place
+		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(testMessage2.applicationId); // todo: Remove the dummy app ID
+		receivedMessage.appendUint16(0); // todo: Remove the dummy sequence count
+
+		CHECK(scheduledActivities.size() == 4);
+		timeService.deleteActivitiesByID(receivedMessage);
+		scheduledActivities = unit_test::Tester::scheduledActivities(timeService);
+
+		REQUIRE(scheduledActivities.size() == 3);
+		REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 17248435);
+		REQUIRE(scheduledActivities.at(2)->request == testMessage4);
+	}
+
+	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(80); // Dummy application ID to throw an error
+		receivedMessage.appendUint16(0); // Dummy sequence count
+
+		timeService.deleteActivitiesByID(receivedMessage);
+		REQUIRE(ServiceTests::thrownError(ErrorHandler::InstructionExecutionStartError));
+	}
+}
+
+TEST_CASE("TC[11,3] Reset schedule", "[service][st11]") {
+	TimeBasedSchedulingService timeService;
+	auto scheduledActivities = activityInsertion(timeService);
+
+	Message receivedMessage(11, 3, Message::TC, 1);
+
+	timeService.resetSchedule(receivedMessage);
+	scheduledActivities = unit_test::Tester::scheduledActivities(timeService); // Get the new list
+
+	REQUIRE(scheduledActivities.empty());
+	REQUIRE(not unit_test::Tester::executionFunctionStatus(timeService));
+}