Skip to content
Snippets Groups Projects
TimeBasedSchedulingService.cpp 11.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "ECSS_Configuration.hpp"
    #ifdef SERVICE_TIMESCHEDULING
    
    
    #include "Services/TimeBasedSchedulingService.hpp"
    
    TimeBasedSchedulingService::TimeBasedSchedulingService() {
    
    	serviceType = TimeBasedSchedulingService::ServiceType;
    
    Xhulio Luli's avatar
    Xhulio Luli committed
    Time::CustomCUC_t TimeBasedSchedulingService::executeScheduledActivity(Time::CustomCUC_t currentTime) {
    	if (currentTime >= scheduledActivities.front().requestReleaseTime && !scheduledActivities.empty()) {
    
    athatheo's avatar
    athatheo committed
    		if (scheduledActivities.front().requestID.applicationID == ApplicationId) {
    			MessageParser::execute(scheduledActivities.front().request);
    		}
    
    Xhulio Luli's avatar
    Xhulio Luli committed
    		scheduledActivities.pop_front();
    	}
    
    	if (!scheduledActivities.empty()) {
    		return scheduledActivities.front().requestReleaseTime;
    	} else {
    		Time::CustomCUC_t infinity;
    		infinity.elapsed100msTicks = std::numeric_limits<decltype(infinity.elapsed100msTicks)>::max();
    		return infinity;
    	}
    }
    
    
    void TimeBasedSchedulingService::enableScheduleExecution(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::EnableTimeBasedScheduleExecutionFunction);
    	executionFunctionStatus = true;
    
    void TimeBasedSchedulingService::disableScheduleExecution(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DisableTimeBasedScheduleExecutionFunction);
    	executionFunctionStatus = false;
    
    void TimeBasedSchedulingService::resetSchedule(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::ResetTimeBasedSchedule);
    	executionFunctionStatus = false;
    	scheduledActivities.clear();
    
    	// todo: Add resetting for sub-schedules and groups, if defined
    }
    
    
    void TimeBasedSchedulingService::insertActivities(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::InsertActivities);
    
    	// todo: Get the sub-schedule ID if they are implemented
    
    	uint16_t iterationCount = request.readUint16();
    
    	while (iterationCount-- != 0) {
    
    		// todo: Get the group ID first, if groups are used
    
    		Time::CustomCUC_t currentTime = TimeGetter::getCurrentTimeCustomCUC();
    
    		Time::CustomCUC_t releaseTime = request.readCustomCUCTimeStamp();
    
    kchristin22's avatar
    kchristin22 committed
    		if ((scheduledActivities.available() == 0) || (releaseTime < (currentTime + ECSSTimeMarginForActivation))) {
    
    			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
    
    kchristin22's avatar
    kchristin22 committed
    			request.skipBytes(ECSSTCRequestStringSize);
    
    kchristin22's avatar
    kchristin22 committed
    			uint8_t requestData[ECSSTCRequestStringSize] = {0};
    			request.readString(requestData, ECSSTCRequestStringSize);
    
    			Message receivedTCPacket = MessageParser::parseECSSTC(requestData);
    
    			ScheduledActivity newActivity;
    
    			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);
    
    	sortActivitiesReleaseTime(scheduledActivities);
    
    Xhulio Luli's avatar
    Xhulio Luli committed
    	notifyNewActivityAddition();
    
    void TimeBasedSchedulingService::timeShiftAllActivities(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::TimeShiftALlScheduledActivities);
    
    	Time::CustomCUC_t current_time = TimeGetter::getCurrentTimeCustomCUC();
    
    	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
    
    	Time::RelativeTime relativeOffset = request.readRelativeTime();
    
    kchristin22's avatar
    kchristin22 committed
    	if ((releaseTimes.first->requestReleaseTime + relativeOffset) < (current_time + ECSSTimeMarginForActivation)) {
    
    		ErrorHandler::reportError(request, ErrorHandler::SubServiceExecutionStartError);
    
    		for (auto& activity: scheduledActivities) {
    			activity.requestReleaseTime += relativeOffset;
    
    void TimeBasedSchedulingService::timeShiftActivitiesByID(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::TimeShiftActivitiesById);
    
    	Time::CustomCUC_t current_time = TimeGetter::getCurrentTimeCustomCUC();
    
    	Time::RelativeTime relativeOffset = request.readRelativeTime();
    	uint16_t iterationCount = request.readUint16();
    
    	while (iterationCount-- != 0) {
    
    		RequestID receivedRequestID;
    		receivedRequestID.sourceID = request.readUint8();
    		receivedRequestID.applicationID = request.readUint16();
    		receivedRequestID.sequenceCount = request.readUint16();
    
    		auto requestIDMatch = etl::find_if_not(scheduledActivities.begin(), scheduledActivities.end(),
    		                                       [&receivedRequestID](ScheduledActivity const& currentElement) {
    			                                       return receivedRequestID != currentElement.requestID;
    
    
    		if (requestIDMatch != scheduledActivities.end()) {
    			if ((requestIDMatch->requestReleaseTime + relativeOffset) <
    
    kchristin22's avatar
    kchristin22 committed
    			    (current_time + ECSSTimeMarginForActivation)) {
    
    				ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
    
    Xhulio Luli's avatar
    Xhulio Luli committed
    				requestIDMatch->requestReleaseTime += relativeOffset;
    
    		} else {
    			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
    
    	sortActivitiesReleaseTime(scheduledActivities);
    
    void TimeBasedSchedulingService::deleteActivitiesByID(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DeleteActivitiesById);
    
    	uint16_t iterationCount = request.readUint16();
    
    	while (iterationCount-- != 0) {
    
    		RequestID receivedRequestID;
    		receivedRequestID.sourceID = request.readUint8();
    		receivedRequestID.applicationID = request.readUint16();
    		receivedRequestID.sequenceCount = request.readUint16();
    
    		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);
    
    			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
    
    void TimeBasedSchedulingService::detailReportAllActivities(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DetailReportAllScheduledActivities);
    
    	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduleReportById);
    
    	report.appendUint16(static_cast<uint16_t>(scheduledActivities.size()));
    
    	for (auto& activity: scheduledActivities) {
    
    		// todo: append sub-schedule and group ID if they are defined
    
    		report.appendCustomCUCTimeStamp(activity.requestReleaseTime);
    
    		report.appendString(MessageParser::composeECSS(activity.request));
    
    	storeMessage(report);
    
    void TimeBasedSchedulingService::detailReportActivitiesByID(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DetailReportActivitiesById);
    
    	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduleReportById);
    
    kchristin22's avatar
    kchristin22 committed
    	etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities> matchedActivities;
    
    	uint16_t iterationCount = request.readUint16();
    
    	while (iterationCount-- != 0) {
    
    		RequestID receivedRequestID;
    		receivedRequestID.sourceID = request.readUint8();
    		receivedRequestID.applicationID = request.readUint16();
    		receivedRequestID.sequenceCount = request.readUint16();
    
    		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);
    
    			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
    
    	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.appendCustomCUCTimeStamp(match.requestReleaseTime); // todo: Replace with the time parser
    
    		report.appendString(MessageParser::composeECSS(match.request));
    
    	storeMessage(report);
    
    void TimeBasedSchedulingService::summaryReportActivitiesByID(Message& request) {
    
    	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::ActivitiesSummaryReportById);
    
    	Message report = createTM(TimeBasedSchedulingService::MessageType::TimeBasedScheduledSummaryReport);
    
    kchristin22's avatar
    kchristin22 committed
    	etl::list<ScheduledActivity, ECSSMaxNumberOfTimeSchedActivities> matchedActivities;
    
    	uint16_t iterationCount = request.readUint16();
    
    	while (iterationCount-- != 0) {
    
    		RequestID receivedRequestID;
    		receivedRequestID.sourceID = request.readUint8();
    		receivedRequestID.applicationID = request.readUint16();
    		receivedRequestID.sequenceCount = request.readUint16();
    
    		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);
    
    			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
    
    	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) {
    
    		// todo: append sub-schedule and group ID if they are defined
    
    		report.appendCustomCUCTimeStamp(match.requestReleaseTime);
    
    		report.appendUint8(match.requestID.sourceID);
    		report.appendUint16(match.requestID.applicationID);
    		report.appendUint16(match.requestID.sequenceCount);
    
    	storeMessage(report);
    
    hiluluk's avatar
    hiluluk committed
    
    
    hiluluk's avatar
    hiluluk committed
    void TimeBasedSchedulingService::execute(Message& message) {
    
    hiluluk's avatar
    hiluluk committed
    	switch (message.messageType) {
    
    		case EnableTimeBasedScheduleExecutionFunction:
    			enableScheduleExecution(message);
    
    hiluluk's avatar
    hiluluk committed
    			break;
    
    		case DisableTimeBasedScheduleExecutionFunction:
    			disableScheduleExecution(message);
    
    hiluluk's avatar
    hiluluk committed
    			break;
    
    		case ResetTimeBasedSchedule:
    			resetSchedule(message);
    
    hiluluk's avatar
    hiluluk committed
    			break;
    
    		case InsertActivities:
    			insertActivities(message);
    
    hiluluk's avatar
    hiluluk committed
    			break;
    
    		case DeleteActivitiesById:
    			deleteActivitiesByID(message);
    
    		case TimeShiftActivitiesById:
    			timeShiftActivitiesByID(message);
    
    		case DetailReportActivitiesById:
    			detailReportActivitiesByID(message);
    
    		case ActivitiesSummaryReportById:
    			summaryReportActivitiesByID(message);
    
    		case TimeShiftALlScheduledActivities:
    			timeShiftAllActivities(message);
    
    hiluluk's avatar
    hiluluk committed
    			break;
    
    		case DetailReportAllScheduledActivities:
    			detailReportAllActivities(message);
    
    hiluluk's avatar
    hiluluk committed
    			break;
    		default:
    
    			ErrorHandler::reportInternalError(ErrorHandler::OtherMessageType);
    
    hiluluk's avatar
    hiluluk committed
    	}
    }