deleted the scheduing files for now, will be added after tests
This commit is contained in:
parent
36616bfbbe
commit
95fdbbee78
@ -1,221 +0,0 @@
|
||||
#include "ScheduleTable.h"
|
||||
|
||||
|
||||
/*ctor
|
||||
* max_Commands: maximum number of commands in schedule
|
||||
* max_Subschedules: maximum number of subschedules
|
||||
*/
|
||||
|
||||
|
||||
ScheduleTable::ScheduleTable(object_id_t objectid, uint8_t max_Commands, uint8_t max_Subschedules):SystemObject(objectid)
|
||||
,schedule(max_Commands)/*TBD*/,statusMap(max_Subschedules){
|
||||
|
||||
}
|
||||
|
||||
ScheduleTable::~ScheduleTable(){
|
||||
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t ScheduleTable::setStatus(bool state){
|
||||
|
||||
for (statusIterator=statusMap.begin();statusIterator!=statusMap.end(); statusIterator++){
|
||||
|
||||
statusIterator->second.status=State;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t ScheduleTable::setStatusInMap(bool state,subscheduleId_t subscheduleId){
|
||||
|
||||
ReturnValue_t result = statusMap.exists(subscheduleId);
|
||||
|
||||
if (result!= HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
|
||||
statusIterator = statusMap.find(subschduleId);
|
||||
statusIterator->second.status=state;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t ScheduleTable::addCommandEntry(timeval TcTime,store_address_t TcAddress,subscheduleId_t SubscheduleId){
|
||||
|
||||
commandInfo newCommandInfo = {TcAddress, SubscheduleId};
|
||||
result = schedule.insert(TcTime,newCommandInfo);
|
||||
if (result != HasRetrnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
statusIterator = statusMap.find(subscheduleId);
|
||||
//would above return null?
|
||||
statusIterator->second.tcCount ++;
|
||||
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t ScheduleTable:: addSubschedule(subscheduleId_t subscheduleId){
|
||||
// default status is false
|
||||
return statusMap.insert(subscheduleId,{false,0});
|
||||
}
|
||||
|
||||
ReturnValue_t ScheduleTable:: shiftMap(timeval timeOffset){
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
schedule.clear();
|
||||
scheduleIterator = schedule.begin();
|
||||
for (scheduleIterator=schedule.begin();scheduleIterator!=schedule.end(); scheduleIterator++){
|
||||
result = shiftCommand(scheduleIterator, timeOffset);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t ScheduleTable::shiftInMap(timeval timeOffset, subscheduleId_t subscheduleId){
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
scheduleIterator = schedule.begin();
|
||||
for (scheduleIterator=schedule.begin();scheduleIterator!=schedule.end(); schdeuleIterator++){
|
||||
|
||||
if ((scheduleIterator->second.subschedule)==subscheduleId){
|
||||
result = shiftCommand(scheduleIterator, timeOffset);
|
||||
if (result !=HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t ScheduleTable::shiftCommand(OnboardSchedule_map::iterator it, timeval time_delta){
|
||||
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
timeval tctime;
|
||||
//TODO check syntax
|
||||
timeradd(it.first, &time_delta , &tctime);
|
||||
commandInfo copyCommand= it->second;
|
||||
result = schedule.erase(it);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
// expect no errors, as we already used the iterator
|
||||
result =schedule.insert(tctime, copyCommand);
|
||||
//should not happen really.
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
timeval ScheduleTable::findStart(subscheduleId_t subscheduleId){
|
||||
|
||||
scheduleIterator = schedule.begin();
|
||||
timeval startTime= (*scheduleIterator).first;
|
||||
if (subscheduleId == 0){
|
||||
return startTime;
|
||||
}
|
||||
|
||||
timeval checkTime;
|
||||
for (scheduleIterator = schedule.begin(); scheduleIterator!=schedule.end();scheduleIterator++){
|
||||
if ((scheduleIterator->second.subschedule)==subscheduleId){
|
||||
checkTime= scheduleIterator->first;
|
||||
if (checkTime < startTime){
|
||||
startTime=checkTime;
|
||||
}
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
return startTime;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScheduleTable::isNew(subscheduleId_t subscheduleId){
|
||||
bool newId = true;
|
||||
ReturnValue_t result = statusMap.exists(SubscheduleId);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
NewId= true;
|
||||
}
|
||||
else {
|
||||
NewId= false;
|
||||
}
|
||||
|
||||
return NewId;
|
||||
}
|
||||
|
||||
void scheduleTable::goToStart(){
|
||||
scheduleIterator = schedule.begin();
|
||||
}
|
||||
|
||||
void scheduleTable::getNextTc(timeval OnboardTime, stor_address_t *address){
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
commandReached = false;
|
||||
timeval time;
|
||||
while ( !commandReached){
|
||||
|
||||
subscheduleId_t subscheduleId = scheduleIterator->second.subschedule;
|
||||
statusItertaor = statusMap.find (subscheduleId);
|
||||
if (statusIterator-> second.status != true){
|
||||
schdeuleIterator++;
|
||||
continue;
|
||||
}
|
||||
|
||||
time = scheduleIterator.first;
|
||||
if (OnboardTime > time){
|
||||
address = scheduleIterator-> second.commandAddress;
|
||||
commandReached = true;
|
||||
//do sth with result??
|
||||
result = schedule.erase(&scheduleIterator);
|
||||
scheduleIterator++;
|
||||
statusIterator->second.tccount --;
|
||||
if (statusIterator-> second.tccount ==0){
|
||||
result = status.erase(&statusIterator);
|
||||
//for now I do nothing with the fail here
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scheduleTable::clearScheduleMap(){
|
||||
schedule.clear();
|
||||
statusMap.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
void scheduleTable::printAll(uint8_t* pointer, uint32_t maxSize) {
|
||||
|
||||
uint32_t size = 0;
|
||||
uint16_t count = scheduleMap.scheduleSize();//should iterate and add all subschedule sizes
|
||||
ReturnValue_t result = SerializeAdapter<uint16_t>::serialize(&count,
|
||||
&pointer, &size, maxSize, true);
|
||||
|
||||
for (scheduleIterator = schedule.begin(), scheduleIterator != schedule.end() && result == HasReturnvaluesIF::RETURN_OK;
|
||||
++iter) {
|
||||
for (subscheduleIterator = (scheduleIterator->second).begin();
|
||||
subscheduleIterator != (scheduleIterator->second).end()&& result == HasReturnvaluesIF::RETURN_OK;
|
||||
subscheduleIterator++ ){
|
||||
result = SerializeAdapter<subscheduleId_t>::serialize(&scheduleIterator->first,
|
||||
&pointer, &size, maxSize, true);
|
||||
uint8_t health = iter->second;
|
||||
result = SerializeAdapter<uint8_t>::serialize(&, &pointer, &size,
|
||||
maxSize, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scheduleSize()
|
||||
|
||||
//how much the size should be?
|
||||
uint16_t count = 0;
|
||||
*/
|
||||
*/
|
@ -1,58 +0,0 @@
|
||||
|
||||
#ifndef SCHEDULETABLE_H_
|
||||
#define SCHEDULETABLE_H_
|
||||
|
||||
#include "ScheduleTableIF.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../container/FixedOrderedMultiMap.h"
|
||||
//include time
|
||||
|
||||
|
||||
typedef struct {
|
||||
Store_address_t commandAddress;
|
||||
subscheduleId_t subschedule;
|
||||
} commandInfo;
|
||||
|
||||
typedef struct {
|
||||
bool status;
|
||||
uint8_t tcCount;
|
||||
} subscheduleInfo;
|
||||
typedef FixedOrderedMultimap<timeval, commandInfo, CCSDSTime::TimevalLess> Schedule_Map;
|
||||
|
||||
typedef FixedOrderedMultimap<SubscheduleId_t,subscheduleInfo> Subschedule_Status;
|
||||
|
||||
class ScheduleTable: public ScheduleTableIF ,
|
||||
public SystemObject {
|
||||
|
||||
public:
|
||||
|
||||
ScheduleTable(object_id_t objectid, uint8_t max_Commands, uint8_t max_Subschedules);
|
||||
virtual ~ScheduleTable();
|
||||
|
||||
ReturnValue_t setStatus(bool state)override;
|
||||
ReturnValue_t setStatusInMap(bool state,subscheduleId_t subscheduleId)override;
|
||||
|
||||
ReturnValue_t addCommandEntry(timeval TcTime,store_address_t TcAddress,subscheduleId_t subscheduleId) override;
|
||||
ReturnValue_t addSubschedule(subscheduleId_t subscheduleId)override;
|
||||
|
||||
ReturnValue_t shiftinMap(timeval timeOffset, subscheduleId_t subscheduleId)override;
|
||||
ReturnValue_t shiftMap(timeval timeOffset)override;
|
||||
ReturnValue_t shiftOneSubschedule(Schedule_map::iterator it, timeval time_delta)override;
|
||||
void getNextTc(timeval OnboardTime,store_address_t *address)override;
|
||||
timeval findStart(subscheduleId_t subscheduleId = 0)override;
|
||||
bool isNew(subscheduleId_t subscheduleId)override;
|
||||
void goToStart()override;
|
||||
void clearScheduleMap()override;
|
||||
//add Interface Id
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SCHEDULE_TABLE;
|
||||
|
||||
protected:
|
||||
|
||||
OnboardSchedule_Map schedule;
|
||||
Subschedule_Status statusMap;
|
||||
|
||||
Schedule_Map::iterator scheduleIterator;
|
||||
Subschedule_Status::iterator statusIterator;
|
||||
|
||||
private:
|
||||
ReturnValue_t shiftCommand(OnboardSchedule_Map::iterator it, timeval time_delta);
|
@ -1,35 +0,0 @@
|
||||
#ifndef SCHEDULETABLEIF_H_
|
||||
#define SCHEDULETANLEIF_H_
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
|
||||
class ScheduleTableIF : public HasReturnvaluesIF {
|
||||
|
||||
//any inheritance???
|
||||
//any friend class? I don't see any now, as there is only the scheduling service accessing this table.
|
||||
|
||||
public:
|
||||
|
||||
virtual ~ScheduleTableIF();
|
||||
|
||||
virtual ReturnValue_t addCommandEntry(timeval TcTime, store_address_t TcAddress,subscheduleId_t subSchedule= 0)= 0;
|
||||
virtual ReturnValue_t getNextTC(timeval OnboardTime,timeval* time,store_address_t* address) = 0;
|
||||
virtual timeval findStart(subscheduleId_t subscheduleId) = 0;
|
||||
virtual void goToStart()=0;
|
||||
virtual bool isNew(subscheduleId_t subscheduleId) = 0;
|
||||
virtual ReturnValue_t addSubschedule(subscheduleId)= 0;
|
||||
virtual ReturnValue_t shiftMap(timeval timeOffset) = 0;
|
||||
virtual ReturnValue_t shiftInMap(timeval timeOffset,subscheduleId_t subscheduleId)= 0;
|
||||
virtual void clearScheduleMap()= 0;
|
||||
virtual ReturnValue_t setStatus(bool state) = 0;
|
||||
virtual ReturnValue_t setStatusInMap(bool state, subscheduleId_t subScheduleId) = 0;
|
||||
|
||||
|
||||
//TODO print entries
|
||||
//TODO delete an entry
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,504 +0,0 @@
|
||||
/*
|
||||
* Scheduling.cpp
|
||||
*
|
||||
* Created on: Dec 4, 2019
|
||||
* Author: mala
|
||||
*/
|
||||
#include "Scheduling.h"
|
||||
|
||||
#include <framework/tmtcservices/TmTcMessage.h>
|
||||
#include "../events/EventManagerIF.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
|
||||
//#include <mission/controllers/time/TimeManager.h>//not yet implemented, but necessary?
|
||||
|
||||
/*figure out if we would like to act on any events,
|
||||
*also the sizes of queue and pool and schedule and subschedule.
|
||||
*also maybe a default true for subscheduling enabled?
|
||||
*/
|
||||
//the size of TC pool for ESBO? TODO
|
||||
//Maybe given that we move it to framework, it should be set from user config? TODO
|
||||
|
||||
|
||||
const uint16_t OPS_Scheduling::POOL_SIZES [N_POOLS] = {32,64,128,256};
|
||||
const uint16_t OPS_Scheduling::N_ELEMENTS[N_POOLS]= {900,40,30,30};
|
||||
|
||||
|
||||
//TODO TC_QUEUE construction, helper construction
|
||||
OPS_Scheduling::OPS_Scheduling(uint16_t apid, bool HasInitialSchedule, bool HasSubschedules):
|
||||
PusServiceBase(object::PUS_Scheduler, apid,SERVICE::Onboard_Scheduling),SchedulingEnabled(true),NoTimeError(false)
|
||||
,CommandStorage(objects::PUS_SCHEDULING_STORAGE, POOL_SIZES,N_ELEMENTS,false,true), loadingIsComplete(false),
|
||||
supportSubschedule (HasSubschedules),loadIninitialSchedule(HasInitialSchedule)
|
||||
{
|
||||
eventQueue = QueueFactory::instance()->createMessageQueue();
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||
|
||||
}
|
||||
|
||||
OPS_Scheduling::~OPS_Scheduling();
|
||||
|
||||
ReturnValue_t OPS_Scheduling::handleRequest(uint8_t subservice){
|
||||
switch (subservice){
|
||||
case subServices::ENABLE_RELEASE_OF_TC:
|
||||
return enableScheduling();
|
||||
case subServices::DISABLE_RELEASE_OF_TC:
|
||||
return disableScheduling();
|
||||
case subServices::ENABLE_SUBSCHEDULE:
|
||||
return enable_Subschedule(currentPacket.getApplicationData());
|
||||
case subServices::DISABLE_SUBSCHEDULE:
|
||||
return disable_Subschedule(currentPacket.getApplicationData());
|
||||
case subServices::RESET_SCHEDULE:
|
||||
return resetSchedule();
|
||||
case subServices::TIMESHIFT_SCHEDULE:
|
||||
return shift_Schedule(currentPacket.getApplicationData(), currentPacket.getApplicationDataSize());
|
||||
case subServices::TIMESHIFT_SUBSCHEDULE:
|
||||
return shift_SubSchedule(currentPacket.getApplicationData(), currentPacket.getApplicationDataSize());
|
||||
case subServices::INSERT_TC_SCHEDULE:
|
||||
//With Ramses, we only have fixed length packet sizes, so we need to only put one command in one packet.
|
||||
return insertCommandinSchedule(currentPacket.getApplicationData(), currentPacket.getApplicationDataSize());
|
||||
//TODO report schedule
|
||||
//case REPORT_SCHEDULE:
|
||||
//return Create_Schedule_Report();
|
||||
|
||||
//delete TC, we should discuss if based on what criteria we delete it
|
||||
//case DELETE_TC
|
||||
//return Delete_Command(currentPacket.getApplicationData());
|
||||
default:
|
||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
Returnvalue_t OPS_Scheduling::initialize()
|
||||
{
|
||||
//base class init
|
||||
Returnvalue_t result= PusServiceBase::initialize();
|
||||
if (result!= RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
//storage init
|
||||
result= commandStorage.initialize();
|
||||
if (result!=RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
//helper init
|
||||
/*result = scheduleHelper.initialize();
|
||||
if (result !=HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}*/
|
||||
scheduleMap = objectManager->get<ScheduleTableIF>(objects::SCHEDULE_TABLE);
|
||||
if (scheduleTable == NULL){
|
||||
return HasReturnValuesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
|
||||
//queue initialization
|
||||
|
||||
AcceptsTelecommandsIF* distributor = objectManager->get<
|
||||
AcceptsTelecommandsIF>(objects::CCSDS_PACKET_DISTRIBUTOR);
|
||||
if (distributor == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
commandQueue.setDefaultDestination(distributor->getRequestQueue());
|
||||
|
||||
//event manager initialization
|
||||
|
||||
EventManagerIF* eventManager = objectManager->get<EventManagerIF>(
|
||||
objects::EVENT_MANAGER);
|
||||
if (eventManager == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
//listening to what??
|
||||
result = eventManager->registerListener(eventQueue->getId(), true);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
//this list to be edited, after we have the time manager and know what events we declare
|
||||
//result = eventManager->subscribeToEventRange(eventReceptionQueue.getId(),
|
||||
//EVENT::getEventId(TimeManager::TIME_WAS_SET),
|
||||
//EVENT::getEventId(TimeManager::TIME_JUMP_DETECTED), false);
|
||||
//if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
//return result;
|
||||
//}
|
||||
result = eventManager->subscribeToAllEventsFrom(eventReceptionQueue.getId(),
|
||||
objects::SYSTEM);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//we should check time error before loading, required by insertTc
|
||||
//TODO checkEvents first to get timeset
|
||||
|
||||
//load schedule: initialization does not fail fully if loading fails
|
||||
|
||||
if (loadInitialSchedule){
|
||||
|
||||
scheduleLoader = objectManager->get<scheduleLoaderIF>(
|
||||
objects::SCHEDULE_LOADER);
|
||||
if (scheduleLoader != NULL){
|
||||
result = scheduleLoader->initializeLoader();
|
||||
if (result!=RETURN_OK){
|
||||
triggerEvent (SCHEDULE_LOAD_FAILED);
|
||||
}else{
|
||||
result = loadSchedule();
|
||||
}
|
||||
|
||||
} else if (scheduleLoader == NULL) {
|
||||
triggerEvent (SCHEDULE_LOAD_FAILED);
|
||||
}else {
|
||||
//nothing
|
||||
}
|
||||
}
|
||||
return HasreturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t OPS_Scheduling::loadSchedule(){
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
uint8_t *data;
|
||||
size_t size;
|
||||
while (!loadingIsComplete){
|
||||
|
||||
result = scheduleLoader->getCommandPacket(**data, &size);
|
||||
if (result!= HasReturnvaluesIF::RETURN_OK){
|
||||
loadingIsComplete= true;
|
||||
break;
|
||||
}
|
||||
//needs set system time!
|
||||
result = insertCommandinSchedule(data, size);
|
||||
tcCounter++;
|
||||
if (result!= HasReturnvaluesIF:: RETURN_OK){ //only when map is full, normally should not reach here
|
||||
// we can report how many commands are transferred
|
||||
triggerEvent(SCHEDULE_LOADED_INCOMPLETE,tcCounter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//complete
|
||||
ReturnValue_t OPS_Scheduling::enableScheduling()
|
||||
{
|
||||
if (NoTimeError){
|
||||
SchedulingEnabled = true;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return TIME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPS_Scheduling::disableScheduling()
|
||||
{
|
||||
if (SchedulingEnabled){
|
||||
triggerEvent(OPS_SCHEDULE_DISABLED);
|
||||
SchedulingEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
//default subscheduleId is zero, which translates to enable/disable all subschedules
|
||||
//set status is only a subschedule/group-specific feature.
|
||||
|
||||
ReturnValue_t OPS_Scheduling::enable_Subschedule(SubscheduleId_t subScheduleId)
|
||||
{
|
||||
/*bool state = STATE_ENABLED;
|
||||
return scheduleHelper.setScheduleStatus(state, subScheduleId);
|
||||
*/
|
||||
ReturnValue_t result;
|
||||
if (subScheduleId == 0){
|
||||
result = scheduleMap->setStatus(true);
|
||||
}else{
|
||||
result = scheduleMap->setStatusInMap(true, subScheduleId);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//complete
|
||||
ReturnValue_t OPS_Scheduling::disable_Subschedule (SubscheduleId_t subScheduleId)
|
||||
{
|
||||
/* bool state = STATE_DISABLED;
|
||||
return scheduleHelper.setScheduleStatus(state , subScheduleId);*/
|
||||
ReturnValue_t result;
|
||||
if (subScheduleId == 0){
|
||||
result = scheduleMap->setStatus(false);
|
||||
}else{
|
||||
result = scheduleMap->setStatusInMap(false, subScheduleId);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//complete
|
||||
ReturnValue_t OPS_Scheduling::performService()
|
||||
{
|
||||
|
||||
Do_Schedule();
|
||||
Check_Events();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//complete
|
||||
ReturnValue_t OPS_Scheduling::insertCommandinSchedule(const uint8_t* data, uint16_t size)
|
||||
{
|
||||
|
||||
uint32_t dataLength = 0;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
//get subschedule from packet 1st byte
|
||||
if (supportSubschedule){
|
||||
SubscheduleId_t subscheduleId = 0;
|
||||
getSubschedule(&subscheduleId,data);
|
||||
data++;
|
||||
size --;
|
||||
}
|
||||
timeval TcTime;
|
||||
timeval OnboardTime;
|
||||
//TODO, SSC time format is different
|
||||
CCSDSTime::convertFromCUC(&TcTime, CCSDSTime::P_FIELD_CUC_6B_CCSDS, data, &dataLength, size)
|
||||
data += dataLength;
|
||||
size-= dataLength;
|
||||
|
||||
if (NoTimeError){
|
||||
OSAL::getClock_timeval(&OnboardTime);
|
||||
if (TcTime < OnboardTime){
|
||||
return COMMAND_EXPIRED;
|
||||
}
|
||||
}else{
|
||||
//does nothing and continue
|
||||
}
|
||||
|
||||
TcPacketBase NewCommand(data);
|
||||
if (NewCommand.getFullSize()!=size){
|
||||
return ILLEGAL_APPLICATION_DATA;
|
||||
}
|
||||
store_address_t TcAddress;
|
||||
result = CommandStorage.addData(&TcAddress, NewCommand.getWholeData(),NewCommand.getFullSize());
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
//Helper should have both options
|
||||
if (supportSubschedule){
|
||||
//result = scheduleHelper.addCommandtoSchedule(TcTime,TcAddress, subscheduleId);
|
||||
bool newSubSchedule = scheduleMap->isNew(subSchedule);
|
||||
if (newSubschedule){
|
||||
result = scheduleMap->addsubSchedule();
|
||||
if (result !=HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return scheduleMap->addCommandEntry(TcTime, TcAddress,subSchedule);
|
||||
|
||||
}else{
|
||||
//result = scheduleHelper.addCommandtoSchedule(TcTime,TcAddress);
|
||||
return scheduleMap->addCommandEntry(TcTime, TcAddress);
|
||||
}
|
||||
//TODO check if it works with RETURN_OK, result is passed from Map
|
||||
/* if (result!= HasReturnvaluesIF::RETURN_OK){
|
||||
return SCHEDULE_MAP_FULL;
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
//only if subschedule supported
|
||||
void OPS_Scheduling::get_Subschedule( SubscheduleId_t* subscheduleId,const uint8_t* data)
|
||||
{
|
||||
|
||||
*subschdeuleId = *data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//done
|
||||
ReturnValue_t OPS_Scheduling::resetSchedule()
|
||||
{
|
||||
//scheduleHelper.clearSchedule();
|
||||
scheduleMap->clearScheduleMap();
|
||||
CommandStorage.clearStore();
|
||||
SchedulingEnabled= false;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Returnvalue_t OPS_Scheduling::shift_Schedule (const uint8_t* data, uint16_t size){
|
||||
|
||||
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
timeval time_offset;
|
||||
uint32_t time_length;
|
||||
//here the pfield is changed for the epoch not to be CCSDS, the time field is 6 bytes as usual
|
||||
|
||||
CCSDSTime::convertFromCUC(&time_offset, CCSDSTime::P_FIELD_CUC_6B_Agency, data, size, &time_length);
|
||||
|
||||
result = shiftIsValid(time_offset);
|
||||
if (result !=HasReturnvaluesIF::RETURN_OK){
|
||||
return INVALID_SHIFT;
|
||||
}
|
||||
//TODO shift returns replies from map, check if it works
|
||||
//result = scheduleHelper.shiftSchedule(time_offset)
|
||||
|
||||
result = scheduleMap->shiftMap(timeOffset)
|
||||
if (result == HasReturnvaluesIF::RETURN_OK){
|
||||
return SCHEDULE_SCHIFTED;
|
||||
}else{
|
||||
return SCHEDULE_SHIFT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
//it is only for subschedule support case
|
||||
Returnvalue_t OPS_Scheduling::shift_SubSchedule (const uint8_t* data, uint16_t size){
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
timeval timeOffset;
|
||||
SubschedulId_t subScheduleId = 0;
|
||||
uint32_t dataLength = 0;
|
||||
|
||||
get_Subschedule(&subScheduleId, data);
|
||||
data ++;
|
||||
size --;
|
||||
CCSDSTime::convertFromCUC(&time_offset, CCSDSTime::P_FIELD_CUC_6B_Agency, data, size, &dataLength);
|
||||
|
||||
//result = scheduleHelper.shiftIsValid(timeOffset, subSchedule);
|
||||
result = shiftIsValid(time_offset);
|
||||
if (result !=HasReturnvaluesIF::RETURN_OK){
|
||||
return INVALID_SHIFT;
|
||||
}
|
||||
//TODO shift returns replies from map, check if it works
|
||||
//result = scheduleHelper.shiftSchedule(timeOffset, subScheduleId);
|
||||
bool newSubschedule = scheduleMap->isNew(subscheduleId);
|
||||
if (newSubschedule){
|
||||
return SCHEDULE_SHIFT_FAILED;
|
||||
}
|
||||
result= scheduleMap->shiftInMap(timeOffset,subscheduleId);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK){
|
||||
return SCHEDULE_SCHIFTED;
|
||||
}else{
|
||||
return SCHEDULE_SHIFT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t OPS_Scheduling::shiftIsValid(timeval timeOffset, SubscheduleId_t subscheduleId){
|
||||
//can be improved, putting it zero is not the best option
|
||||
//maybe overloading
|
||||
timeval scheduleStart = ScheduleMap->FindStart(subscheduleId)
|
||||
|
||||
timeval checkTime;//clean this up
|
||||
timeradd(&scheduleStart, &timeOffset ,&checkTime);
|
||||
timeval OnboardTime;
|
||||
OSAL::getClock_timeval(&OnboardTime);
|
||||
if (checkTime<OnboardTime){
|
||||
return HasReturnValuesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnValuesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
void OPS_Scheduling::do_Schedule()
|
||||
{
|
||||
if (schedulingEnabled){
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
store_address_t TcAddress;
|
||||
timeval OnboardTime;
|
||||
scheduleMap->goToStart();
|
||||
//scheduleHelper.startScheduleIteration();
|
||||
//Clock::getClock_timeval(&OnboardTime)
|
||||
//what is the precison? would this work for schedule??
|
||||
OSAL::getClock_timeval(&OnboardTime);
|
||||
|
||||
while (!reachedEnd()){
|
||||
//scheduleHelper.getNextValidCommand(OnboardTime, &TcAddress);
|
||||
scheduleMap->getNextTc(OnboardTime, address);
|
||||
releaseCommand(TcAddress);
|
||||
commandStorage.deleteData(TcAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool OPS_Scheduling::reachedEnd(){
|
||||
//check syntax TODO
|
||||
if(scheduleMap->scheduleIterator == scheduleMap->schedule.end()){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void releaseCommand(store_address_t address){
|
||||
const uint8_t* pakcet;
|
||||
uint32_t size;
|
||||
ReturnValue_t result = commandStorage.getData(TcAddress, &packet, &size);
|
||||
TcPacketStored Telecommand(packet,size);
|
||||
if(Telecommand.getWholeData()==NULL){
|
||||
triggerEvent(COMMAND_LOST);
|
||||
} else {
|
||||
message.setStorageId(Telecommand.getStoreAddress());
|
||||
result=commandQueue.sendToDefault(&message);
|
||||
if (result!=HasReturnvaluesIF::RETURN_OK){
|
||||
triggerEvent(COMMAND_LOST,result);
|
||||
}
|
||||
}
|
||||
Telecommand.deletePacket();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//still not working TODO
|
||||
/*ReturnValue_t OPS_Scheduling::Create_Schedule_Report(){
|
||||
|
||||
//How big the packet can be??
|
||||
//what happens if it is bigger than the maximum size?
|
||||
|
||||
ScheduleReportTmpacket schedulePacket;
|
||||
|
||||
OnboardSchedule_map::iterator it = Schedule.begin();
|
||||
Subschedule_map::iterator sub_it = NULL;
|
||||
const uint8_t* tcPacket;
|
||||
uint32_t size;
|
||||
timeval tctime;
|
||||
SubscheduleId_t subscheduleId;
|
||||
for (it = Schedule.begin();it!=Schedule.end();it++){
|
||||
subscheduleId = *it.first;
|
||||
sub_it = ((*it).second).begin();
|
||||
while (sub_it!=((*it).second).end()){
|
||||
tcime = *sub_it.first;
|
||||
result = commandStorage->getData(*sub_it.second, &tcPacket, &tcLen);
|
||||
schedulePacket.appendCommand(subscheduleId,tctime,tcPacket,tcLen);
|
||||
this->tcCounter++;
|
||||
}
|
||||
}
|
||||
schedulePacket.setCount(tcCounter);
|
||||
TmPacketStored tmPacketStored(this->apid, this->serviceId,
|
||||
subService, this->packetCounter, &schedukeReportPacket);
|
||||
ReturnValue_t result = tmPacketStored.sendPacket(requestQueue.getDefaultDestination(), requestQueue.getId());
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
this->packetCounter++;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/*void OPS_Scheduling::Check_Events() {
|
||||
EventMessage message;
|
||||
for (ReturnValue_t result = eventQueue.receiveMessage(&message);
|
||||
result == HasReturnvaluesIF::RETURN_OK;
|
||||
result = eventQueue.receiveMessage(&message)) {
|
||||
//based on time manager events, react
|
||||
if (message.getEvent() == TimeManager::TIME_JUMP_DETECTED) {
|
||||
DisableScheduling();
|
||||
}
|
||||
if (message.getEvent() == TimeManager::TIME_WAS_SET) {
|
||||
NoTimeError = true;
|
||||
}
|
||||
//Disable schedule in case a high severity event (soft reboot, safe mode, ..) comes from SYSTEM.
|
||||
if (message.getReporter() == objects::SYSTEM
|
||||
&& message.getSeverity() == SEVERITY::HIGH) {
|
||||
|
||||
DisableScheduling();
|
||||
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Scheduling.h
|
||||
*
|
||||
* Created on: Nov 5, 2019
|
||||
* Author: mala
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef STUDIO_TMTCSERVICES_SCHEDULING_H_
|
||||
#define STUDIO_TMTCSERVICES_SCHEDULING_H_
|
||||
|
||||
|
||||
#include <framework/container/FixedOrderedMultimap.h>
|
||||
#include <framework/storagemanager/LocalPool.h>
|
||||
#include <framework/timemanager/CCSDSTime.h>
|
||||
#include <framework/tmtcservices/PusServiceBase.h>
|
||||
#include "ScheduleTableIF.h"
|
||||
|
||||
//make sure this alias works in global scope
|
||||
|
||||
typedef uint8_t SubscheduleId_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief manages onboard time-based schedule, PUS service 11
|
||||
* @details
|
||||
*
|
||||
* This service is responsible in managing an onboard time-based schedule of telecommands.
|
||||
* The schedule can be through this service enabled, disabled, and time-shifted
|
||||
* It can support subschedules. subschedules can be created,enabled and disabled, and time-shifted
|
||||
*
|
||||
* The service stores the schedule in the ScheduleMap, which has a ScheduleMapIF.
|
||||
* Current Map includes subschedules, but it can be replaced by implementing the interface
|
||||
* The service also can pre-load commands through scheduleLoaderIF.
|
||||
* scheduleLoader and scheduleTable should be instantiated in factory
|
||||
*
|
||||
* right now we do not have control over one single command,in terms of
|
||||
* shift/disable/delete. it might be required in future though,
|
||||
|
||||
*The following constants are in standards but not implemented in this version
|
||||
*Time margin declared static const Time_Based_Schedule_Margin
|
||||
*Time between specified release time and actual release time , maximum, declared
|
||||
*
|
||||
* @author M.Taheran
|
||||
*
|
||||
*/
|
||||
|
||||
class OPS_Scheduling: public PusServiceBase {
|
||||
|
||||
|
||||
public:
|
||||
|
||||
OPS_Scheduling(uint16_t apid,bool HasInitialSchedule, bool HasSubschedules);
|
||||
virtual ~OPS_Scheduling();
|
||||
ReturnValue_t handleRequest(uint8_t subservice) override;
|
||||
ReturnValue_t performService() override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
ScheduleTableIF* scheduleMap = nullptr;
|
||||
ScheduleLoaderIF * scheduleLoader = nullptr;
|
||||
bool loadInitialSchedule;
|
||||
bool supportSubschedules;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
enum class subServices {
|
||||
|
||||
|
||||
static const uint8_t ENABLE_RELEASE_OF_TC = 1,
|
||||
static const uint8_t DISABLE_RELEASE_OF_TC =2,
|
||||
static const uint8_t ENABLE_SUBSCHEDULE = 20,
|
||||
static const uint8_t DISABLE_SUBSCHEDULE = 21,
|
||||
|
||||
//static const uint8_t DELETE_TC = 5;//not implemented
|
||||
static const uint8_t RESET_SCHEDULE = 3,
|
||||
static const uint8_t TIMESHIFT_SCHEDULE = 15,
|
||||
static const uint8_t TIMESHIFT_SUBSCHEDULE = 8,
|
||||
static const uint8_t INSERT_TC_SCHEDULE = 4,
|
||||
//TODO
|
||||
//static const uint8_t REPORT_SCHEDULE = 16;//TM is type 10
|
||||
};
|
||||
//Interface and subsystem ID to be included in mission config
|
||||
|
||||
static const unit8_t INTERFACE_ID = CLASS_ID::OPS_SCHEDULING_SERVICE;
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OPS_SCHEDULER;
|
||||
|
||||
//list of return codes, tbc
|
||||
static const ReturnValue_t TIME_ERROR = MAKE_RETURN_CODE (1);
|
||||
static const ReturnValue_t COMMAND_EXPIRED = MAKE_RETURN_CODE (2);
|
||||
static const ReturnValue_t ILLEGAL_APPLICATION_DATA= MAKE_RETURN_CODE (3);
|
||||
//static const ReturnValue_t SCHEDULE_MAP_FULL= MAKE_RETURN_CODE (4);
|
||||
static const ReturnValue_t INVALID_SHIFT= MAKE_RETURN_CODE (4);
|
||||
static const ReturnValue_t SCHEDULE_SHIFTED= MAKE_RETURN_CODE (5);
|
||||
static const ReturnValue_t SCHEDULE_SHIFT_FAILED= MAKE_RETURN_CODE (6);
|
||||
|
||||
//list of events,tbc
|
||||
|
||||
static const Event = OPS_SCHEDULE_DISABLED = MAKE_EVENT(1, SEVERITY::MEDIUM);
|
||||
static const Event = COMMAND_LOST = MAKE_EVENT (2, SEVERITY::LOW);
|
||||
static const Event = SCHEDULE_LOAD_FAILED = MAKE_EVENT (3, SEVERITY::MEDIUM);
|
||||
static const Event = SCHEDULE_LOADED_INCOMPLETE = MAKE_EVENT (4, SEVERITY::LOW);
|
||||
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
MessageQueueIF* eventQueue = nullptr;
|
||||
|
||||
|
||||
static const uint8_t N_POOLS = 4;
|
||||
static const uint16_t POOL_SIZES[N_POOLS];
|
||||
static const uint16_t N_ELEMENTS[N_POOLS];
|
||||
LocalPool<N_POOLS> commandStorage;
|
||||
|
||||
//only used for reporting on incomplete loading
|
||||
|
||||
uint8_t tcCounter = 0;
|
||||
bool SchedulingEnabled;
|
||||
bool NoTimeError;
|
||||
|
||||
|
||||
Returnvalue_t enableScheduling();
|
||||
void disableScheduling();
|
||||
ReturnValue_t enable_Subschedule (SubscheduleId_t SubScheduleID=0);
|
||||
ReturnValue_t disable_Subschedule(SubscheduleId_t SubScheduleID=0);
|
||||
Returnvalue_t resetSchedule();
|
||||
Returnvalue_t insertCommandinSchedule(const uint8_t* data, uint16_t size);
|
||||
void do_Schedule();
|
||||
void check_Events();
|
||||
|
||||
Returnvalue_t shift_Schedule (const uint8_t* data, uint16_t size);
|
||||
Returnvalue_t shift_SubSchedule (const uint8_t* data, uint16_t size);
|
||||
void shift_Subschedule_Map(OnboardSchedule_map::iterator it, timeval time_delta);
|
||||
void get_Subschedule(SubscheduleId_t* SubscheduleId,const uint8_t* data, uint32_t maxlength, uint32_t* foundlength, bool* NewId = false);
|
||||
|
||||
ReturnValue_t loadSchedule();
|
||||
void releaseCommand(store_address_t address);
|
||||
|
||||
//TODO
|
||||
//ReturnValue_t Create_Schedule_Report();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* STUDIO_TMTCSERVICES_SCHEDULING_H_ */
|
@ -1,29 +0,0 @@
|
||||
#ifndef SCHEDULELOADERIF_H_
|
||||
#define SCHEDULELOADERIF_H_
|
||||
|
||||
#include<>
|
||||
|
||||
//either has returnvalues or include HasReturnValueIF.h
|
||||
class ScheduleLoaderIF: public HasReturnValuesIF {
|
||||
|
||||
public:
|
||||
|
||||
/*this interface is used to get commands from another object
|
||||
* and pass to scheduling to load at first. commands are get one by one
|
||||
* in an application data packet.
|
||||
haven't used it for anything else yet. changes come after
|
||||
we implement the JSON system
|
||||
*/
|
||||
//ctor specific to implementation
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SCHEDULE_LOADER_IF;
|
||||
//add ReturnValues
|
||||
//TBD
|
||||
|
||||
virtual ~ScheduleLoaderIF();
|
||||
//not sure if needed, might be.
|
||||
virtual ReturnValue_t initializeLoader() = 0;
|
||||
virtual ReturnValue_t getCommandPacket(uint8_t **data, uint32_t *size)= 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user