Newer
Older
#ifndef ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
#define ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
#include "Helpers/CRCHelper.hpp"
#include "MessageParser.hpp"
#include "Service.hpp"
#include "etl/list.h"
// Include platform specific files
#include "Helpers/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
*/
/**
* @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.
*
* @ingroup Services
class TimeBasedSchedulingService : public Service {
/**
* @brief Indicator of the schedule execution
* @details The schedule execution indicator will be updated by the process that is running
* the time scheduling service.
*/
/**
* @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.
*/
struct RequestID {
uint16_t applicationID = 0; ///< Application process ID
uint16_t sequenceCount = 0; ///< Packet sequence count
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.
*
* @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
struct ScheduledActivity {
Message request; ///< Hold the received command request
RequestID requestID; ///< Request ID, characteristic of the definition
Time::CustomCUC_t requestReleaseTime{0}; ///< Keep the command release time
/**
* @brief Hold the scheduled activities
*
* @details The scheduled activities in this list are ordered by their release time, as the
etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities> 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.
*/
sortActivitiesReleaseTime(etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities>& 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;
/**
* Notifies the timeBasedSchedulingTask after the insertion of activities to scheduleActivity list.
*/
void notifyNewActivityAddition();
inline static const uint8_t ServiceType = 11;
enum MessageType : uint8_t {
EnableTimeBasedScheduleExecutionFunction = 1,
DisableTimeBasedScheduleExecutionFunction = 2,
ResetTimeBasedSchedule = 3,
InsertActivities = 4,
DeleteActivitiesById = 5,
TimeShiftActivitiesById = 7,
DetailReportActivitiesById = 9,
TimeBasedScheduleReportById = 10,
ActivitiesSummaryReportById = 12,
TimeBasedScheduledSummaryReport = 13,
TimeShiftALlScheduledActivities = 15,
DetailReportAllScheduledActivities = 16,
};
/**
* @brief Class constructor
* @details Initializes the serviceType
*/
/**
* 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::CustomCUC_t executeScheduledActivity(Time::CustomCUC_t currentTime);
* @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);
* @brief 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.
/**
* It is responsible to call the suitable function that executes a telecommand packet. The source of that packet
* is the ground station.
*
* @note This function is called from the main execute() that is defined in the file MessageParser.hpp
* @param message Contains the necessary parameters to call the suitable subservice
*/
#endif // ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP