Merge branch 'dev-7.5.0' into higher-acs-modes-only-str
All checks were successful
EIVE/eive-obsw/pipeline/pr-dev-7.5.0 This commit looks good
All checks were successful
EIVE/eive-obsw/pipeline/pr-dev-7.5.0 This commit looks good
This commit is contained in:
@ -87,6 +87,8 @@ static constexpr Event PTG_CTRL_NO_ATTITUDE_INFORMATION = MAKE_EVENT(6, severity
|
||||
static constexpr Event SAFE_MODE_CONTROLLER_FAILURE = MAKE_EVENT(7, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] The TLE for the SGP4 Propagator has become too old.
|
||||
static constexpr Event TLE_TOO_OLD = MAKE_EVENT(8, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] The TLE could not be read from the filesystem.
|
||||
static constexpr Event TLE_FILE_READ_FAILED = MAKE_EVENT(9, severity::LOW);
|
||||
|
||||
extern const char* getModeStr(AcsMode mode);
|
||||
|
||||
|
@ -65,7 +65,7 @@ void ArcsecJsonParamBase::addSetParamHeader(uint8_t* buffer, uint8_t setId) {
|
||||
*(buffer + 1) = setId;
|
||||
}
|
||||
|
||||
ReturnValue_t ArcsecJsonParamBase::init(const std::string filename) {
|
||||
ReturnValue_t ArcsecJsonParamBase::init(const std::string& filename) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (not std::filesystem::exists(filename)) {
|
||||
sif::warning << "ArcsecJsonParamBase::init: JSON file " << filename << " does not exist"
|
||||
|
@ -46,7 +46,7 @@ class ArcsecJsonParamBase {
|
||||
* @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise
|
||||
* returnvalue::OK
|
||||
*/
|
||||
ReturnValue_t init(const std::string filename);
|
||||
ReturnValue_t init(const std::string& filename);
|
||||
|
||||
/**
|
||||
* @brief Fills a buffer with a parameter set
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
#include <mission/acs/str/strJsonCommands.h>
|
||||
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
|
||||
extern "C" {
|
||||
#include <sagitta/client/actionreq.h>
|
||||
#include <sagitta/client/client_tm_structs.h>
|
||||
@ -24,8 +26,8 @@ extern "C" {
|
||||
std::atomic_bool JCFG_DONE(false);
|
||||
|
||||
StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
const char* jsonFileStr, StrComHandler* strHelper,
|
||||
power::Switch_t powerSwitch)
|
||||
StrComHandler* strHelper, power::Switch_t powerSwitch,
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter)
|
||||
: DeviceHandlerBase(objectId, comIF, comCookie),
|
||||
temperatureSet(this),
|
||||
versionSet(this),
|
||||
@ -57,8 +59,8 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
|
||||
centroidsSet(this),
|
||||
contrastSet(this),
|
||||
strHelper(strHelper),
|
||||
paramJsonFile(jsonFileStr),
|
||||
powerSwitch(powerSwitch) {
|
||||
powerSwitch(powerSwitch),
|
||||
cfgPathGetter(cfgPathGetter) {
|
||||
if (comCookie == nullptr) {
|
||||
sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl;
|
||||
}
|
||||
@ -82,17 +84,12 @@ void StarTrackerHandler::doStartUp() {
|
||||
// the device handler's submode to the star tracker's mode
|
||||
return;
|
||||
case StartupState::DONE:
|
||||
if (jcfgCountdown.isBusy()) {
|
||||
if (!JCFG_DONE) {
|
||||
startupState = StartupState::WAIT_JCFG;
|
||||
return;
|
||||
}
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
case StartupState::WAIT_JCFG: {
|
||||
if (jcfgCountdown.hasTimedOut()) {
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@ -139,8 +136,7 @@ ReturnValue_t StarTrackerHandler::initialize() {
|
||||
|
||||
// Spin up a thread to do the JSON initialization, takes 200-250 ms which would
|
||||
// delay whole satellite boot process.
|
||||
jcfgCountdown.resetTimer();
|
||||
jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), paramJsonFile.c_str()};
|
||||
reloadJsonCfgFile();
|
||||
|
||||
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (manager == nullptr) {
|
||||
@ -169,6 +165,20 @@ ReturnValue_t StarTrackerHandler::initialize() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
bool StarTrackerHandler::reloadJsonCfgFile() {
|
||||
jcfgCountdown.resetTimer();
|
||||
auto strCfgPath = cfgPathGetter.getCfgPath();
|
||||
if (strCfgPath.has_value()) {
|
||||
jcfgPending = true;
|
||||
JCFG_DONE = false;
|
||||
jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()};
|
||||
return true;
|
||||
}
|
||||
// Simplified FDIR: Just continue as usual..
|
||||
JCFG_DONE = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
@ -335,6 +345,24 @@ void StarTrackerHandler::performOperationHook() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jcfgPending) {
|
||||
if (JCFG_DONE) {
|
||||
if (startupState == StartupState::WAIT_JCFG) {
|
||||
startupState = StartupState::DONE;
|
||||
}
|
||||
jsonCfgTask.join();
|
||||
jcfgPending = false;
|
||||
auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE);
|
||||
if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) {
|
||||
actionHelper.finish(true, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE);
|
||||
}
|
||||
} else if (jcfgCountdown.hasTimedOut()) {
|
||||
auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE);
|
||||
if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) {
|
||||
actionHelper.finish(false, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submode_t StarTrackerHandler::getInitialSubmode() { return startracker::SUBMODE_BOOTLOADER; }
|
||||
@ -499,6 +527,16 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
preparePingRequest();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::RELOAD_JSON_CFG_FILE): {
|
||||
if (jcfgPending) {
|
||||
return HasActionsIF::IS_BUSY;
|
||||
}
|
||||
// It should be noted that this just reloads the JSON config structure in memory from the
|
||||
// JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve
|
||||
// this is to simply reboot the device after a reload.
|
||||
reloadJsonCfgFile();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::SET_TIME_FROM_SYS_TIME): {
|
||||
SetTimeActionRequest setTimeRequest{};
|
||||
timeval tv;
|
||||
@ -513,6 +551,7 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
rawPacket = commandBuffer;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
case (startracker::REQ_TIME): {
|
||||
prepareTimeRequest();
|
||||
return returnvalue::OK;
|
||||
@ -726,6 +765,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandMap(startracker::UPLOAD_IMAGE);
|
||||
this->insertInCommandMap(startracker::DOWNLOAD_IMAGE);
|
||||
this->insertInCommandMap(startracker::RELOAD_JSON_CFG_FILE);
|
||||
this->insertInCommandAndReplyMap(startracker::REQ_POWER, 3, &powerSet,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::REQ_INTERFACE, 3, &interfaceSet,
|
||||
@ -928,7 +968,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
|
||||
}
|
||||
}
|
||||
|
||||
void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile) {
|
||||
void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile) {
|
||||
cfgs.tracking.init(paramJsonFile);
|
||||
cfgs.logLevel.init(paramJsonFile);
|
||||
cfgs.logSubscription.init(paramJsonFile);
|
||||
@ -2811,3 +2851,5 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) {
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::acceptExternalDeviceCommands() { return returnvalue::OK; }
|
||||
|
@ -27,7 +27,9 @@ extern "C" {
|
||||
* @details Datasheet: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/
|
||||
* Arbeitsdaten/08_Used%20Components/ArcSec_KULeuven_Startracker/
|
||||
* Sagitta%201.0%20Datapack&fileid=659181
|
||||
* @author J. Meier
|
||||
* @note The STR code is a chaotic inconsistent mess and should be re-written with a simpler base
|
||||
* class. DO NOT USE THIS AS REFERENCE. Stay away from it.
|
||||
* @author J. Meier, R. Mueller
|
||||
*/
|
||||
class StarTrackerHandler : public DeviceHandlerBase {
|
||||
public:
|
||||
@ -42,8 +44,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* to high to enable the device.
|
||||
*/
|
||||
StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
const char* jsonFileStr, StrComHandler* strHelper,
|
||||
power::Switch_t powerSwitch);
|
||||
StrComHandler* strHelper, power::Switch_t powerSwitch,
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter);
|
||||
virtual ~StarTrackerHandler();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
@ -240,11 +242,12 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
Subscription subscription;
|
||||
AutoThreshold autoThreshold;
|
||||
};
|
||||
bool jcfgPending = false;
|
||||
JsonConfigs jcfgs;
|
||||
Countdown jcfgCountdown = Countdown(250);
|
||||
Countdown jcfgCountdown = Countdown(1000);
|
||||
bool commandExecuted = false;
|
||||
std::thread jsonCfgTask;
|
||||
static void setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile);
|
||||
static void setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile);
|
||||
|
||||
std::string paramJsonFile;
|
||||
|
||||
@ -311,6 +314,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
std::set<DeviceCommandId_t> additionalRequestedTm{};
|
||||
std::set<DeviceCommandId_t>::iterator currentSecondaryTmIter;
|
||||
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter;
|
||||
|
||||
/**
|
||||
* @brief Handles internal state
|
||||
*/
|
||||
@ -542,6 +547,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
void doNormalTransition(Mode_t modeFrom, Submode_t subModeFrom);
|
||||
void bootFirmware(Mode_t toMode);
|
||||
void bootBootloader();
|
||||
bool reloadJsonCfgFile();
|
||||
ReturnValue_t acceptExternalDeviceCommands() override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */
|
||||
|
@ -14,6 +14,12 @@ namespace startracker {
|
||||
static const Submode_t SUBMODE_BOOTLOADER = 1;
|
||||
static const Submode_t SUBMODE_FIRMWARE = 2;
|
||||
|
||||
class SdCardConfigPathGetter {
|
||||
public:
|
||||
virtual ~SdCardConfigPathGetter() = default;
|
||||
virtual std::optional<std::string> getCfgPath() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns the frame type field of a decoded frame.
|
||||
*/
|
||||
@ -381,6 +387,7 @@ static constexpr DeviceCommandId_t REQ_CENTROIDS = 94;
|
||||
static constexpr DeviceCommandId_t ADD_SECONDARY_TM_TO_NORMAL_MODE = 95;
|
||||
static constexpr DeviceCommandId_t RESET_SECONDARY_TM_SET = 96;
|
||||
static constexpr DeviceCommandId_t READ_SECONDARY_TM_SET = 97;
|
||||
static constexpr DeviceCommandId_t RELOAD_JSON_CFG_FILE = 100;
|
||||
static const DeviceCommandId_t NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32_t VERSION_SET_ID = REQ_VERSION;
|
||||
|
@ -54,8 +54,13 @@ ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
|
||||
}
|
||||
}
|
||||
} else if (result != MessageQueueIF::EMPTY) {
|
||||
sif::warning << "LiveTmTask: TM queue failure, returncode 0x" << std::hex << std::setw(4)
|
||||
<< result << std::dec << std::endl;
|
||||
const char* contextStr = "Regular TM queue";
|
||||
if (isCfdp) {
|
||||
contextStr = "CFDP TM queue";
|
||||
}
|
||||
sif::warning << "LiveTmTask: " << contextStr << " handling failure, returncode 0x"
|
||||
<< std::setfill('0') << std::hex << std::setw(4) << result << std::dec
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,15 +178,16 @@ ReturnValue_t LiveTmTask::handleGenericTmQueue(MessageQueueIF& queue, bool isCfd
|
||||
size_t writtenSize = 0;
|
||||
result = channel.write(data, size, writtenSize);
|
||||
if (result == DirectTmSinkIF::PARTIALLY_WRITTEN) {
|
||||
result = channel.handleWriteCompletionSynchronously(writtenSize, 200);
|
||||
result = channel.handleWriteCompletionSynchronously(writtenSize, 400);
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: Event? Might lead to dangerous spam though..
|
||||
sif::warning << "LiveTmTask: Synchronous write of last segment failed with code 0x"
|
||||
<< std::setw(4) << std::hex << result << std::dec << std::endl;
|
||||
<< std::setfill('0') << std::setw(4) << std::hex << result << std::dec
|
||||
<< std::endl;
|
||||
}
|
||||
} else if (result != returnvalue::OK) {
|
||||
sif::error << "LiveTmTask: Channel write failed with code 0x" << std::hex << std::setw(4)
|
||||
<< result << std::dec << std::endl;
|
||||
sif::error << "LiveTmTask: Channel write failed with code 0x" << std::setfill('0') << std::hex
|
||||
<< std::setw(4) << result << std::dec << std::endl;
|
||||
}
|
||||
}
|
||||
// Try delete in any case, ignore failures (which should not happen), it is more important to
|
||||
|
@ -141,11 +141,12 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
|
||||
size_t writtenSize = 0;
|
||||
result = channel.write(tmReader.getFullData(), dumpedLen, writtenSize);
|
||||
if (result == VirtualChannelIF::PARTIALLY_WRITTEN) {
|
||||
result = channel.handleWriteCompletionSynchronously(writtenSize, 200);
|
||||
result = channel.handleWriteCompletionSynchronously(writtenSize, 400);
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: Event? Might lead to dangerous spam though..
|
||||
sif::warning << "PersistentTmStore: Synchronous write of last segment failed with code 0x"
|
||||
<< std::setw(4) << std::hex << result << std::dec << std::endl;
|
||||
sif::warning << "LiveTmTask: Synchronous write of last segment failed with code 0x"
|
||||
<< std::setfill('0') << std::setw(4) << std::hex << result << std::dec
|
||||
<< std::endl;
|
||||
}
|
||||
} else if (result == DirectTmSinkIF::IS_BUSY) {
|
||||
sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl;
|
||||
|
@ -74,5 +74,7 @@ ReturnValue_t VirtualChannel::handleWriteCompletionSynchronously(size_t& written
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
// Timeout. Cancel the transfer
|
||||
cancelTransfer();
|
||||
return TIMEOUT;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
|
||||
if (performWriteOp) {
|
||||
result = write(data, size, writtenSize);
|
||||
if (result == PARTIALLY_WRITTEN) {
|
||||
result = handleWriteCompletionSynchronously(writtenSize, 200);
|
||||
result = handleWriteCompletionSynchronously(writtenSize, 400);
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: Event? Might lead to dangerous spam though..
|
||||
sif::warning
|
||||
|
@ -1,12 +1,9 @@
|
||||
#include "AcsController.h"
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/config/torquer.h>
|
||||
|
||||
AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
||||
AcsController::AcsController(object_id_t objectId, bool enableHkSets, SdCardMountedIF &sdcMan)
|
||||
: ExtendedControllerBase(objectId),
|
||||
enableHkSets(enableHkSets),
|
||||
sdcMan(sdcMan),
|
||||
attitudeEstimation(&acsParameters),
|
||||
fusedRotationEstimation(&acsParameters),
|
||||
guidance(&acsParameters),
|
||||
@ -24,8 +21,7 @@ AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
||||
ctrlValData(this),
|
||||
actuatorCmdData(this),
|
||||
fusedRotRateData(this),
|
||||
fusedRotRateSourcesData(this),
|
||||
tleData(this) {}
|
||||
fusedRotRateSourcesData(this) {}
|
||||
|
||||
ReturnValue_t AcsController::initialize() {
|
||||
ReturnValue_t result = parameterHelper.initialize();
|
||||
@ -69,22 +65,27 @@ ReturnValue_t AcsController::executeAction(ActionId_t actionId, MessageQueueId_t
|
||||
if (size != 69 * 2) {
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
ReturnValue_t result = navigation.updateTle(data, data + 69);
|
||||
ReturnValue_t result = updateTle(data, data + 69, false);
|
||||
if (result != returnvalue::OK) {
|
||||
PoolReadGuard pg(&tleData);
|
||||
navigation.updateTle(tleData.line1.value, tleData.line2.value);
|
||||
return result;
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(&tleData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(tleData.line1.value, data, 69);
|
||||
std::memcpy(tleData.line2.value, data + 69, 69);
|
||||
tleData.setValidity(true, true);
|
||||
}
|
||||
result = writeTleToFs(data);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
case (READ_TLE): {
|
||||
uint8_t tle[69 * 2] = {};
|
||||
uint8_t line2[69] = {};
|
||||
ReturnValue_t result = readTleFromFs(tle, line2);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(tle + 69, line2, 69);
|
||||
actionHelper.reportData(commandedBy, actionId, tle, 69 * 2);
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
default: {
|
||||
return HasActionsIF::INVALID_ACTION_ID;
|
||||
}
|
||||
@ -132,6 +133,10 @@ void AcsController::performControlOperation() {
|
||||
}
|
||||
case InternalState::INITIAL_DELAY: {
|
||||
if (initialCountdown.hasTimedOut()) {
|
||||
uint8_t line1[69] = {};
|
||||
uint8_t line2[69] = {};
|
||||
readTleFromFs(line1, line2);
|
||||
updateTle(line1, line2, true);
|
||||
internalState = InternalState::READY;
|
||||
}
|
||||
return;
|
||||
@ -816,9 +821,6 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL_QUEST, &rotRateTotalQuest);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL_STR, &rotRateTotalStr);
|
||||
poolManager.subscribeForRegularPeriodicPacket({fusedRotRateSourcesData.getSid(), false, 10.0});
|
||||
// TLE Data
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TLE_LINE_1, &line1);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TLE_LINE_2, &line2);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -1046,6 +1048,67 @@ void AcsController::copySusData() {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::updateTle(const uint8_t *line1, const uint8_t *line2, bool fromFile) {
|
||||
ReturnValue_t result = navigation.updateTle(line1, line2);
|
||||
if (result != returnvalue::OK) {
|
||||
if (not fromFile) {
|
||||
uint8_t fileLine1[69] = {};
|
||||
uint8_t fileLine2[69] = {};
|
||||
readTleFromFs(fileLine1, fileLine2);
|
||||
navigation.updateTle(fileLine1, fileLine2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::writeTleToFs(const uint8_t *tle) {
|
||||
auto mntPrefix = sdcMan.getCurrentMountPrefix();
|
||||
if (mntPrefix == nullptr or !sdcMan.isSdCardUsable(std::nullopt)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
std::string path = mntPrefix + TLE_FILE;
|
||||
// Clear existing TLE from file
|
||||
std::ofstream tleFile(path.c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
if (tleFile.is_open()) {
|
||||
tleFile.write(reinterpret_cast<const char *>(tle), 69);
|
||||
tleFile << "\n";
|
||||
tleFile.write(reinterpret_cast<const char *>(tle + 69), 69);
|
||||
} else {
|
||||
return WRITE_FILE_FAILED;
|
||||
}
|
||||
tleFile.close();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::readTleFromFs(uint8_t *line1, uint8_t *line2) {
|
||||
auto mntPrefix = sdcMan.getCurrentMountPrefix();
|
||||
if (mntPrefix == nullptr or !sdcMan.isSdCardUsable(std::nullopt)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
std::string path = mntPrefix + TLE_FILE;
|
||||
std::error_code e;
|
||||
if (std::filesystem::exists(path, e)) {
|
||||
// Read existing TLE from file
|
||||
std::fstream tleFile = std::fstream(path.c_str(), std::fstream::in);
|
||||
if (tleFile.is_open()) {
|
||||
std::string tleLine1, tleLine2;
|
||||
getline(tleFile, tleLine1);
|
||||
std::memcpy(line1, tleLine1.c_str(), 69);
|
||||
getline(tleFile, tleLine2);
|
||||
std::memcpy(line2, tleLine2.c_str(), 69);
|
||||
} else {
|
||||
triggerEvent(acs::TLE_FILE_READ_FAILED);
|
||||
return READ_FILE_FAILED;
|
||||
}
|
||||
tleFile.close();
|
||||
} else {
|
||||
triggerEvent(acs::TLE_FILE_READ_FAILED);
|
||||
return READ_FILE_FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void AcsController::copyGyrData() {
|
||||
{
|
||||
PoolReadGuard pg(&sensorValues.gyr0AdisSet);
|
||||
|
@ -4,15 +4,18 @@
|
||||
#include <eive/objects.h>
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <fsfw/coordinates/Sgp4Propagator.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/health/HealthTable.h>
|
||||
#include <fsfw/parameters/ParameterHelper.h>
|
||||
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||
#include <fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h>
|
||||
#include <fsfw_hal/devicehandlers/MgmRM3100Handler.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/acs/imtqHelpers.h>
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
#include <mission/acs/susMax1227Helpers.h>
|
||||
#include <mission/config/torquer.h>
|
||||
#include <mission/controller/acs/ActuatorCmd.h>
|
||||
#include <mission/controller/acs/AttitudeEstimation.h>
|
||||
#include <mission/controller/acs/FusedRotationEstimation.h>
|
||||
@ -24,13 +27,18 @@
|
||||
#include <mission/controller/acs/control/PtgCtrl.h>
|
||||
#include <mission/controller/acs/control/SafeCtrl.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
#include <mission/memory/SdCardMountedIF.h>
|
||||
#include <mission/utility/trace.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
class AcsController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
||||
public:
|
||||
static constexpr dur_millis_t INIT_DELAY = 500;
|
||||
|
||||
AcsController(object_id_t objectId, bool enableHkSets);
|
||||
AcsController(object_id_t objectId, bool enableHkSets, SdCardMountedIF& sdcMan);
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
@ -51,6 +59,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
|
||||
bool enableHkSets = false;
|
||||
|
||||
SdCardMountedIF& sdcMan;
|
||||
|
||||
timeval timeAbsolute;
|
||||
timeval timeRelative;
|
||||
double timeDelta = 0.0;
|
||||
@ -95,10 +105,15 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
static const DeviceCommandId_t RESET_MEKF = 0x1;
|
||||
static const DeviceCommandId_t RESTORE_MEKF_NONFINITE_RECOVERY = 0x2;
|
||||
static const DeviceCommandId_t UPDATE_TLE = 0x3;
|
||||
static const DeviceCommandId_t READ_TLE = 0x4;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
|
||||
//! [EXPORT] : [COMMENT] File deletion failed and at least one file is still existent.
|
||||
static constexpr ReturnValue_t FILE_DELETION_FAILED = MAKE_RETURN_CODE(0);
|
||||
//! [EXPORT] : [COMMENT] Writing the TLE to the file has failed.
|
||||
static constexpr ReturnValue_t WRITE_FILE_FAILED = MAKE_RETURN_CODE(1);
|
||||
//! [EXPORT] : [COMMENT] Reading the TLE to the file has failed.
|
||||
static constexpr ReturnValue_t READ_FILE_FAILED = MAKE_RETURN_CODE(2);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
@ -133,6 +148,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
|
||||
const double* tgtRotRate);
|
||||
|
||||
ReturnValue_t updateTle(const uint8_t* line1, const uint8_t* line2, bool fromFile);
|
||||
ReturnValue_t writeTleToFs(const uint8_t* tle);
|
||||
ReturnValue_t readTleFromFs(uint8_t* line1, uint8_t* line2);
|
||||
|
||||
const std::string TLE_FILE = "/conf/tle.txt";
|
||||
|
||||
/* ACS Sensor Values */
|
||||
ACS::SensorValues sensorValues;
|
||||
|
||||
@ -256,11 +277,6 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
PoolEntry<double> rotRateTotalQuest = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotalStr = PoolEntry<double>(3);
|
||||
|
||||
// TLE Dataset
|
||||
acsctrl::TleData tleData;
|
||||
PoolEntry<uint8_t> line1 = PoolEntry<uint8_t>(69);
|
||||
PoolEntry<uint8_t> line2 = PoolEntry<uint8_t>(69);
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners
|
||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||
};
|
||||
|
@ -119,9 +119,6 @@ enum PoolIds : lp_id_t {
|
||||
ROT_RATE_TOTAL_SUSMGM,
|
||||
ROT_RATE_TOTAL_QUEST,
|
||||
ROT_RATE_TOTAL_STR,
|
||||
// TLE
|
||||
TLE_LINE_1,
|
||||
TLE_LINE_2,
|
||||
};
|
||||
|
||||
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
|
||||
@ -136,7 +133,6 @@ static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
||||
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 4;
|
||||
static constexpr uint8_t FUSED_ROT_RATE_SOURCES_SET_ENTRIES = 5;
|
||||
static constexpr uint8_t TLE_SET_ENTRIES = 2;
|
||||
|
||||
/**
|
||||
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
|
||||
@ -329,16 +325,6 @@ class FusedRotRateSourcesData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENT
|
||||
private:
|
||||
};
|
||||
|
||||
class TleData : public StaticLocalDataSet<TLE_SET_ENTRIES> {
|
||||
public:
|
||||
TleData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, TLE_SET) {}
|
||||
|
||||
lp_vec_t<uint8_t, 69> line1 = lp_vec_t<uint8_t, 69>(sid.objectId, TLE_LINE_1, this);
|
||||
lp_vec_t<uint8_t, 69> line2 = lp_vec_t<uint8_t, 69>(sid.objectId, TLE_LINE_1, this);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace acsctrl
|
||||
|
||||
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/thermal/tcsDefinitions.h"
|
||||
#include "mission/payload/payloadPcduDefinitions.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include <fsfw_hal/linux/UnixFileGuard.h>
|
||||
@ -428,20 +429,20 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
params.getValue(PARAM_KEY_MAP[NEG_V_UPPER_BOUND], upperBound);
|
||||
if (not checkVoltage(adcSet.processed[U_NEG_V_FB], lowerBound, upperBound,
|
||||
NEG_V_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "Negative voltage was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
params.getValue(PARAM_KEY_MAP[DRO_U_LOWER_BOUND], lowerBound);
|
||||
params.getValue(PARAM_KEY_MAP[DRO_U_UPPER_BOUND], upperBound);
|
||||
if (not checkVoltage(adcSet.processed[U_DRO_DIV_6], lowerBound, upperBound,
|
||||
U_DRO_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "DRO voltage was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
params.getValue(PARAM_KEY_MAP[DRO_I_UPPER_BOUND], upperBound);
|
||||
if (not checkCurrent(adcSet.processed[I_DRO], upperBound, I_DRO_OUT_OF_BOUNDS)) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
sif::warning << "Detected out of bounds current for DRO: " << adcSet.processed[I_DRO]
|
||||
<< ", Raw: " << adcSet.channels[I_DRO] << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -455,10 +456,12 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
params.getValue(PARAM_KEY_MAP[X8_U_UPPER_BOUND], upperBound);
|
||||
if (not checkVoltage(adcSet.processed[U_X8_DIV_6], lowerBound, upperBound,
|
||||
U_X8_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "X8 voltage was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
params.getValue(PARAM_KEY_MAP[X8_I_UPPER_BOUND], upperBound);
|
||||
if (not checkCurrent(adcSet.processed[I_X8], upperBound, I_X8_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "X8 current was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -472,10 +475,12 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
params.getValue(PARAM_KEY_MAP[TX_U_UPPER_BOUND], upperBound);
|
||||
if (not checkVoltage(adcSet.processed[U_TX_DIV_6], lowerBound, upperBound,
|
||||
U_TX_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "TX voltage was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
params.getValue(PARAM_KEY_MAP[TX_I_UPPER_BOUND], upperBound);
|
||||
if (not checkCurrent(adcSet.processed[I_TX], upperBound, I_TX_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "TX current was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -489,10 +494,12 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
params.getValue(PARAM_KEY_MAP[MPA_U_UPPER_BOUND], upperBound);
|
||||
if (not checkVoltage(adcSet.processed[U_MPA_DIV_6], lowerBound, upperBound,
|
||||
U_MPA_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "MPA voltage was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
params.getValue(PARAM_KEY_MAP[MPA_I_UPPER_BOUND], upperBound);
|
||||
if (not checkCurrent(adcSet.processed[I_MPA], upperBound, I_MPA_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "MPA current was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -506,6 +513,7 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
params.getValue(PARAM_KEY_MAP[HPA_U_UPPER_BOUND], upperBound);
|
||||
if (not checkVoltage(adcSet.processed[U_HPA_DIV_6], lowerBound, upperBound,
|
||||
U_HPA_OUT_OF_BOUNDS)) {
|
||||
sif::warning << "HPA voltage was out of bounds, went back to OFF" << std::endl;
|
||||
return;
|
||||
}
|
||||
params.getValue(PARAM_KEY_MAP[HPA_I_UPPER_BOUND], upperBound);
|
||||
@ -576,6 +584,7 @@ void PayloadPcduHandler::performOperationHook() { checkJsonFileInit(); }
|
||||
|
||||
ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode,
|
||||
uint32_t* msToReachTheMode) {
|
||||
using namespace plpcdu;
|
||||
if (commandedMode != MODE_OFF) {
|
||||
PoolReadGuard pg(&enablePl);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
@ -584,45 +593,59 @@ ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode
|
||||
}
|
||||
}
|
||||
}
|
||||
return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode);
|
||||
}
|
||||
|
||||
ReturnValue_t PayloadPcduHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||
using namespace plpcdu;
|
||||
if (mode == MODE_NORMAL) {
|
||||
if (commandedMode == MODE_NORMAL) {
|
||||
uint8_t dhbSubmode = getSubmode();
|
||||
diffMask = submode ^ dhbSubmode;
|
||||
// Also deals with the case where the mode is MODE_ON, submode should be 0 here
|
||||
if ((((submode >> SOLID_STATE_RELAYS_ADC_ON) & 0b1) == SOLID_STATE_RELAYS_ADC_ON) and
|
||||
(getMode() == MODE_NORMAL and dhbSubmode != ALL_OFF_SUBMODE)) {
|
||||
diffMask = commandedSubmode ^ dhbSubmode;
|
||||
// For all higher level modes, SSR needs to be on. This is to ensure we have valid ADC
|
||||
// measurements
|
||||
if ((droOnForSubmode(commandedSubmode) or x8OnForSubmode(commandedSubmode) or
|
||||
txOnForSubmode(commandedSubmode) or mpaOnForSubmode(commandedSubmode) or
|
||||
hpaOnForSubmode(commandedSubmode)) and
|
||||
not ssrOnForSubmode(dhbSubmode)) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
if (((((submode >> DRO_ON) & 1) == 1) and
|
||||
((dhbSubmode & 0b1) != (1 << SOLID_STATE_RELAYS_ADC_ON)))) {
|
||||
if (disableChannelOrderCheck) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (x8OnForSubmode(commandedSubmode) and not droOnForSubmode(dhbSubmode)) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
if ((((submode >> X8_ON) & 1) == 1) and
|
||||
((dhbSubmode & 0b11) != ((1 << SOLID_STATE_RELAYS_ADC_ON) | (1 << DRO_ON)))) {
|
||||
if (txOnForSubmode(commandedSubmode) and
|
||||
(not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode))) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
if (((((submode >> TX_ON) & 1) == 1) and
|
||||
((dhbSubmode & 0b111) !=
|
||||
((1 << X8_ON) | (1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) {
|
||||
if (mpaOnForSubmode(commandedSubmode) and
|
||||
(not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode) or
|
||||
not txOnForSubmode(dhbSubmode))) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
if ((((submode >> MPA_ON) & 1) == 1 and
|
||||
((dhbSubmode & 0b1111) !=
|
||||
((1 << TX_ON) | (1 << X8_ON) | (1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
if ((((submode >> HPA_ON) & 1) == 1 and
|
||||
((dhbSubmode & 0b11111) != ((1 << MPA_ON) | (1 << TX_ON) | (1 << X8_ON) | (1 << DRO_ON) |
|
||||
(1 << SOLID_STATE_RELAYS_ADC_ON))))) {
|
||||
if (hpaOnForSubmode(commandedSubmode) and
|
||||
(not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode) or
|
||||
not txOnForSubmode(dhbSubmode) or not mpaOnForSubmode(dhbSubmode))) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return DeviceHandlerBase::isModeCombinationValid(mode, submode);
|
||||
return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode);
|
||||
}
|
||||
|
||||
bool PayloadPcduHandler::ssrOnForSubmode(uint8_t submode) {
|
||||
return submode & (1 << plpcdu::SOLID_STATE_RELAYS_ADC_ON);
|
||||
}
|
||||
bool PayloadPcduHandler::droOnForSubmode(uint8_t submode) {
|
||||
return submode & (1 << plpcdu::DRO_ON);
|
||||
}
|
||||
|
||||
bool PayloadPcduHandler::x8OnForSubmode(uint8_t submode) { return submode & (1 << plpcdu::X8_ON); }
|
||||
|
||||
bool PayloadPcduHandler::txOnForSubmode(uint8_t submode) { return submode & (1 << plpcdu::TX_ON); }
|
||||
|
||||
bool PayloadPcduHandler::mpaOnForSubmode(uint8_t submode) {
|
||||
return submode & (1 << plpcdu::MPA_ON);
|
||||
}
|
||||
|
||||
bool PayloadPcduHandler::hpaOnForSubmode(uint8_t submode) {
|
||||
return submode & (1 << plpcdu::HPA_ON);
|
||||
}
|
||||
|
||||
ReturnValue_t PayloadPcduHandler::serializeFloat(uint32_t& param, float val) {
|
||||
@ -637,56 +660,68 @@ ReturnValue_t PayloadPcduHandler::getParameter(uint8_t domainId, uint8_t uniqueI
|
||||
uint16_t startAtIndex) {
|
||||
using namespace plpcdu;
|
||||
switch (uniqueId) {
|
||||
case (PlPcduParamIds::NEG_V_LOWER_BOUND):
|
||||
case (PlPcduParamIds::NEG_V_UPPER_BOUND):
|
||||
case (PlPcduParamIds::DRO_U_LOWER_BOUND):
|
||||
case (PlPcduParamIds::DRO_U_UPPER_BOUND):
|
||||
case (PlPcduParamIds::DRO_I_UPPER_BOUND):
|
||||
case (PlPcduParamIds::X8_U_LOWER_BOUND):
|
||||
case (PlPcduParamIds::X8_U_UPPER_BOUND):
|
||||
case (PlPcduParamIds::X8_I_UPPER_BOUND):
|
||||
case (PlPcduParamIds::TX_U_LOWER_BOUND):
|
||||
case (PlPcduParamIds::TX_U_UPPER_BOUND):
|
||||
case (PlPcduParamIds::TX_I_UPPER_BOUND):
|
||||
case (PlPcduParamIds::MPA_U_LOWER_BOUND):
|
||||
case (PlPcduParamIds::MPA_U_UPPER_BOUND):
|
||||
case (PlPcduParamIds::MPA_I_UPPER_BOUND):
|
||||
case (PlPcduParamIds::HPA_U_LOWER_BOUND):
|
||||
case (PlPcduParamIds::HPA_U_UPPER_BOUND):
|
||||
case (PlPcduParamIds::HPA_I_UPPER_BOUND):
|
||||
case (PlPcduParamIds::SSR_TO_DRO_WAIT_TIME):
|
||||
case (PlPcduParamIds::DRO_TO_X8_WAIT_TIME):
|
||||
case (PlPcduParamIds::X8_TO_TX_WAIT_TIME):
|
||||
case (PlPcduParamIds::TX_TO_MPA_WAIT_TIME):
|
||||
case (PlPcduParamIds::MPA_TO_HPA_WAIT_TIME): {
|
||||
handleDoubleParamUpdate(PARAM_KEY_MAP[static_cast<PlPcduParamIds>(uniqueId)],
|
||||
parameterWrapper, newValues);
|
||||
case (PlPcduParamId::NEG_V_LOWER_BOUND):
|
||||
case (PlPcduParamId::NEG_V_UPPER_BOUND):
|
||||
case (PlPcduParamId::DRO_U_LOWER_BOUND):
|
||||
case (PlPcduParamId::DRO_U_UPPER_BOUND):
|
||||
case (PlPcduParamId::DRO_I_UPPER_BOUND):
|
||||
case (PlPcduParamId::X8_U_LOWER_BOUND):
|
||||
case (PlPcduParamId::X8_U_UPPER_BOUND):
|
||||
case (PlPcduParamId::X8_I_UPPER_BOUND):
|
||||
case (PlPcduParamId::TX_U_LOWER_BOUND):
|
||||
case (PlPcduParamId::TX_U_UPPER_BOUND):
|
||||
case (PlPcduParamId::TX_I_UPPER_BOUND):
|
||||
case (PlPcduParamId::MPA_U_LOWER_BOUND):
|
||||
case (PlPcduParamId::MPA_U_UPPER_BOUND):
|
||||
case (PlPcduParamId::MPA_I_UPPER_BOUND):
|
||||
case (PlPcduParamId::HPA_U_LOWER_BOUND):
|
||||
case (PlPcduParamId::HPA_U_UPPER_BOUND):
|
||||
case (PlPcduParamId::HPA_I_UPPER_BOUND):
|
||||
case (PlPcduParamId::SSR_TO_DRO_WAIT_TIME):
|
||||
case (PlPcduParamId::DRO_TO_X8_WAIT_TIME):
|
||||
case (PlPcduParamId::X8_TO_TX_WAIT_TIME):
|
||||
case (PlPcduParamId::TX_TO_MPA_WAIT_TIME):
|
||||
case (PlPcduParamId::MPA_TO_HPA_WAIT_TIME): {
|
||||
handleDoubleParamUpdate(PARAM_KEY_MAP[static_cast<PlPcduParamId>(uniqueId)], parameterWrapper,
|
||||
newValues);
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamIds::INJECT_SSR_TO_DRO_FAILURE): {
|
||||
case (PlPcduParamId::INJECT_SSR_TO_DRO_FAILURE): {
|
||||
ssrToDroInjectionRequested = true;
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamIds::INJECT_DRO_TO_X8_FAILURE): {
|
||||
case (PlPcduParamId::INJECT_DRO_TO_X8_FAILURE): {
|
||||
droToX8InjectionRequested = true;
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamIds::INJECT_X8_TO_TX_FAILURE): {
|
||||
case (PlPcduParamId::INJECT_X8_TO_TX_FAILURE): {
|
||||
x8ToTxInjectionRequested = true;
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamIds::INJECT_TX_TO_MPA_FAILURE): {
|
||||
case (PlPcduParamId::INJECT_TX_TO_MPA_FAILURE): {
|
||||
txToMpaInjectionRequested = true;
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamIds::INJECT_MPA_TO_HPA_FAILURE): {
|
||||
case (PlPcduParamId::INJECT_MPA_TO_HPA_FAILURE): {
|
||||
mpaToHpaInjectionRequested = true;
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamIds::INJECT_ALL_ON_FAILURE): {
|
||||
case (PlPcduParamId::INJECT_ALL_ON_FAILURE): {
|
||||
allOnInjectRequested = true;
|
||||
break;
|
||||
}
|
||||
case (PlPcduParamId::DISABLE_ORDER_CHECK_CHANNELS): {
|
||||
uint8_t newValue = 0;
|
||||
ReturnValue_t result = newValues->getElement(&newValue);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (newValue > 1) {
|
||||
return HasParametersIF::INVALID_VALUE;
|
||||
}
|
||||
parameterWrapper->set(disableChannelOrderCheck);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return DeviceHandlerBase::getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
|
@ -137,6 +137,12 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
PoolEntry<float>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0});
|
||||
PoolEntry<float> tempC = PoolEntry<float>({0.0});
|
||||
|
||||
/**
|
||||
* This parameter disables all checks for the channels except the SSR on check. The SSR on check
|
||||
* is kept to ensure that there is a common start point where the ADC is enabled.
|
||||
*/
|
||||
uint8_t disableChannelOrderCheck = false;
|
||||
|
||||
void updateSwitchGpio(gpioId_t id, gpio::Levels level);
|
||||
|
||||
void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
|
||||
@ -155,7 +161,6 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
|
||||
|
||||
@ -177,6 +182,12 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER);
|
||||
ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode,
|
||||
uint32_t* msToReachTheMode) override;
|
||||
static bool ssrOnForSubmode(uint8_t submode);
|
||||
static bool droOnForSubmode(uint8_t submode);
|
||||
static bool x8OnForSubmode(uint8_t submode);
|
||||
static bool txOnForSubmode(uint8_t submode);
|
||||
static bool mpaOnForSubmode(uint8_t submode);
|
||||
static bool hpaOnForSubmode(uint8_t submode);
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_PLPCDUHANDLER_H_ */
|
||||
|
@ -35,7 +35,7 @@ enum PlPcduAdcChannels : uint8_t {
|
||||
NUM_CHANNELS = 12
|
||||
};
|
||||
|
||||
enum PlPcduParamIds : uint8_t {
|
||||
enum PlPcduParamId : uint8_t {
|
||||
NEG_V_LOWER_BOUND = 0,
|
||||
NEG_V_UPPER_BOUND = 1,
|
||||
DRO_U_LOWER_BOUND = 2,
|
||||
@ -65,10 +65,12 @@ enum PlPcduParamIds : uint8_t {
|
||||
INJECT_X8_TO_TX_FAILURE = 32,
|
||||
INJECT_TX_TO_MPA_FAILURE = 33,
|
||||
INJECT_MPA_TO_HPA_FAILURE = 34,
|
||||
INJECT_ALL_ON_FAILURE = 35
|
||||
INJECT_ALL_ON_FAILURE = 35,
|
||||
|
||||
DISABLE_ORDER_CHECK_CHANNELS = 40
|
||||
};
|
||||
|
||||
static std::map<PlPcduParamIds, std::string> PARAM_KEY_MAP = {
|
||||
static std::map<PlPcduParamId, std::string> PARAM_KEY_MAP = {
|
||||
{NEG_V_LOWER_BOUND, "negVoltLowerBound"}, {NEG_V_UPPER_BOUND, "negVoltUpperBound"},
|
||||
{DRO_U_LOWER_BOUND, "droVoltLowerBound"}, {DRO_U_UPPER_BOUND, "droVoltUpperBound"},
|
||||
{DRO_I_UPPER_BOUND, "droCurrUpperBound"}, {X8_U_LOWER_BOUND, "x8VoltLowerBound"},
|
||||
|
@ -104,10 +104,6 @@ class SpTmReader : public SpacePacketReader {
|
||||
*/
|
||||
SpTmReader(const uint8_t* buf, size_t maxSize) : SpacePacketReader(buf, maxSize) {}
|
||||
|
||||
ReturnValue_t setData(const uint8_t* buf, size_t maxSize) {
|
||||
return setReadOnlyData(buf, maxSize);
|
||||
}
|
||||
|
||||
ReturnValue_t checkCrc() const {
|
||||
if (CRC::crc16ccitt(getFullData(), getFullPacketLen()) != 0) {
|
||||
return returnvalue::FAILED;
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "eive/objects.h"
|
||||
#include "linux/payload/FreshSupvHandler.h"
|
||||
|
||||
#ifndef RPI_TEST_ADIS16507
|
||||
#define RPI_TEST_ADIS16507 0
|
||||
@ -608,3 +610,25 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg
|
||||
0);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
ReturnValue_t pst::pstPayload(FixedTimeslotTaskIF *thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
|
||||
thisSequence->addSlot(objects::CAM_SWITCHER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0,
|
||||
FreshSupvHandler::OpCode::DEFAULT_OPERATION);
|
||||
// Two COM TM steps, which might cover telemetry which takes a bit longer to be sent.
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.1,
|
||||
FreshSupvHandler::OpCode::PARSE_TM);
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2,
|
||||
FreshSupvHandler::OpCode::PARSE_TM);
|
||||
static_cast<void>(length);
|
||||
|
||||
return thisSequence->checkSequence();
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ ReturnValue_t pstTcsAndAcs(FixedTimeslotTaskIF* thisSequence, AcsPstCfg cfg);
|
||||
|
||||
ReturnValue_t pstI2c(TmpSchedConfig schedConf, FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
ReturnValue_t pstPayload(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
/**
|
||||
* Generic test PST
|
||||
* @param thisSequence
|
||||
|
@ -106,7 +106,7 @@ Subsystem& satsystem::acs::init() {
|
||||
// Build TARGET PT transition 0
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_PTG_TRANS_0.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_PTG_TRANS_0.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_PTG_TRANS_0.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_PTG_TRANS_0.second, true);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_PTG_TRANS_0.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_PTG_TRANS_0.second);
|
||||
check(ACS_SUBSYSTEM.addTable(
|
||||
@ -161,6 +161,7 @@ void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
iht(objects::IMTQ_ASSY, OFF, 0, ACS_TABLE_OFF_TRANS_1.second);
|
||||
iht(objects::STR_ASSY, OFF, 0, ACS_TABLE_OFF_TRANS_1.second);
|
||||
iht(objects::ACS_BOARD_ASS, OFF, 0, ACS_TABLE_OFF_TRANS_1.second);
|
||||
iht(objects::SUS_BOARD_ASS, OFF, 0, ACS_TABLE_OFF_TRANS_1.second);
|
||||
iht(objects::RW_ASSY, OFF, 0, ACS_TABLE_OFF_TRANS_1.second);
|
||||
check(ss.addTable(TableEntry(ACS_TABLE_OFF_TRANS_1.first, &ACS_TABLE_OFF_TRANS_1.second)), ctxc);
|
||||
|
||||
@ -199,13 +200,13 @@ void buildSafeSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
iht(objects::ACS_CONTROLLER, acs::AcsMode::SAFE, acs::SafeSubmode::DEFAULT,
|
||||
ACS_TABLE_SAFE_TGT.second, true);
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_SAFE_TGT.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_SAFE_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_SAFE_TGT.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_SAFE_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_SAFE_TGT.second, true);
|
||||
check(ss.addTable(&ACS_TABLE_SAFE_TGT.second, ACS_TABLE_SAFE_TGT.first, false, true), ctxc);
|
||||
|
||||
// Build SAFE transition 0
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_SAFE_TRANS_0.second);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_SAFE_TRANS_0.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_SAFE_TRANS_0.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_SAFE_TRANS_0.second, true);
|
||||
iht(objects::STR_ASSY, OFF, 0, ACS_TABLE_SAFE_TRANS_0.second);
|
||||
iht(objects::RW_ASSY, OFF, 0, ACS_TABLE_SAFE_TRANS_0.second);
|
||||
@ -256,13 +257,13 @@ void buildIdleSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_IDLE_TGT.second);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_IDLE_TGT.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_IDLE_TGT.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_IDLE_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_IDLE_TGT.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_IDLE_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_IDLE_TGT.second, true);
|
||||
ss.addTable(&ACS_TABLE_IDLE_TGT.second, ACS_TABLE_IDLE_TGT.first, false, true);
|
||||
|
||||
// Build IDLE transition 0
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_IDLE_TRANS_0.second);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_IDLE_TRANS_0.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_IDLE_TRANS_0.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_IDLE_TRANS_0.second, true);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_IDLE_TRANS_0.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_IDLE_TRANS_0.second);
|
||||
@ -306,8 +307,8 @@ void buildTargetPtSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
// Build TARGET PT table
|
||||
iht(objects::ACS_CONTROLLER, acs::AcsMode::PTG_TARGET, 0, ACS_TABLE_PTG_TARGET_TGT.second);
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_TGT.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_TGT.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_PTG_TARGET_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_PTG_TARGET_TGT.second, true);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_TGT.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_TGT.second);
|
||||
check(ss.addTable(&ACS_TABLE_PTG_TARGET_TGT.second, ACS_TABLE_PTG_TARGET_TGT.first, false, true),
|
||||
@ -355,8 +356,8 @@ void buildTargetPtNadirSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
// Build TARGET PT table
|
||||
iht(objects::ACS_CONTROLLER, acs::AcsMode::PTG_NADIR, 0, ACS_TABLE_PTG_TARGET_NADIR_TGT.second);
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_NADIR_TGT.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_NADIR_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_NADIR_TGT.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_PTG_TARGET_NADIR_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_PTG_TARGET_NADIR_TGT.second, true);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_NADIR_TGT.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_NADIR_TGT.second);
|
||||
check(ss.addTable(TableEntry(ACS_TABLE_PTG_TARGET_NADIR_TGT.first,
|
||||
@ -408,8 +409,8 @@ void buildTargetPtGsSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
// Build TARGET PT table
|
||||
iht(objects::ACS_CONTROLLER, acs::AcsMode::PTG_TARGET_GS, 0, ACS_TABLE_PTG_TARGET_GS_TGT.second);
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_GS_TGT.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_GS_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_GS_TGT.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_PTG_TARGET_GS_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_PTG_TARGET_GS_TGT.second, true);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_GS_TGT.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_GS_TGT.second);
|
||||
check(ss.addTable(
|
||||
@ -461,8 +462,10 @@ void buildTargetPtInertialSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
iht(objects::ACS_CONTROLLER, acs::AcsMode::PTG_INERTIAL, 0,
|
||||
ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second);
|
||||
iht(objects::IMTQ_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second);
|
||||
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second, true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second, true);
|
||||
iht(objects::SUS_BOARD_ASS, NML, duallane::A_SIDE, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second,
|
||||
true);
|
||||
iht(objects::ACS_BOARD_ASS, NML, duallane::B_SIDE, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second,
|
||||
true);
|
||||
iht(objects::RW_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second);
|
||||
iht(objects::STR_ASSY, NML, 0, ACS_TABLE_PTG_TARGET_INERTIAL_TGT.second);
|
||||
check(ss.addTable(TableEntry(ACS_TABLE_PTG_TARGET_INERTIAL_TGT.first,
|
||||
|
@ -15,6 +15,7 @@ class DirectTmSinkIF {
|
||||
static constexpr ReturnValue_t IS_BUSY = returnvalue::makeCode(CLASS_ID, 0);
|
||||
static constexpr ReturnValue_t PARTIALLY_WRITTEN = returnvalue::makeCode(CLASS_ID, 1);
|
||||
static constexpr ReturnValue_t NO_WRITE_ACTIVE = returnvalue::makeCode(CLASS_ID, 2);
|
||||
static constexpr ReturnValue_t TIMEOUT = returnvalue::makeCode(CLASS_ID, 3);
|
||||
|
||||
/**
|
||||
* @brief Implements the functionality to write to a TM sink directly.
|
||||
|
@ -137,40 +137,68 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
|
||||
if (cmdMessage.getMessageType() == messagetypes::TM_STORE) {
|
||||
Command_t cmd = cmdMessage.getCommand();
|
||||
if (cmd == TmStoreMessage::DELETE_STORE_CONTENT_TIME) {
|
||||
Clock::getClock_timeval(¤tTv);
|
||||
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||
auto accessor = ipcStore.getData(storeId);
|
||||
uint32_t deleteUpToUnixSeconds = 0;
|
||||
size_t size = accessor.second.size();
|
||||
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, accessor.second.data(), &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
result = handleDeletionCmd(ipcStore, cmdMessage);
|
||||
execCmd = cmd;
|
||||
deleteUpTo(deleteUpToUnixSeconds);
|
||||
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
|
||||
Clock::getClock_timeval(¤tTv);
|
||||
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||
auto accessor = ipcStore.getData(storeId);
|
||||
if (accessor.second.size() < 8) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint32_t dumpFromUnixSeconds = 0;
|
||||
uint32_t dumpUntilUnixSeconds = 0;
|
||||
size_t size = 8;
|
||||
SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
||||
if (result == BUSY_DUMPING) {
|
||||
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
|
||||
return result;
|
||||
}
|
||||
result = handleDumpCmd(ipcStore, cmdMessage);
|
||||
execCmd = cmd;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PersistentTmStore::handleDeletionCmd(StorageManagerIF& ipcStore,
|
||||
CommandMessage& cmdMessage) {
|
||||
Clock::getClock_timeval(¤tTv);
|
||||
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||
auto accessor = ipcStore.getData(storeId);
|
||||
size_t size = accessor.second.size();
|
||||
if (size < 4) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
const uint8_t* data = accessor.second.data();
|
||||
uint32_t deleteUpToUnixSeconds = 0;
|
||||
if (size == 4) {
|
||||
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
deleteUpTo(deleteUpToUnixSeconds);
|
||||
} else if (size == 8) {
|
||||
uint32_t deleteFromUnixSeconds = 0;
|
||||
SerializeAdapter::deSerialize(&deleteFromUnixSeconds, &data, &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
deleteFromUpTo(deleteFromUnixSeconds, deleteUpToUnixSeconds);
|
||||
} else {
|
||||
sif::warning << "PersistentTmStore: Unknown deletion time specification" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PersistentTmStore::handleDumpCmd(StorageManagerIF& ipcStore,
|
||||
CommandMessage& cmdMessage) {
|
||||
Clock::getClock_timeval(¤tTv);
|
||||
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||
auto accessor = ipcStore.getData(storeId);
|
||||
if (accessor.second.size() < 8) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint32_t dumpFromUnixSeconds = 0;
|
||||
uint32_t dumpUntilUnixSeconds = 0;
|
||||
size_t size = 8;
|
||||
SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
ReturnValue_t result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
||||
if (result == BUSY_DUMPING) {
|
||||
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PersistentTmStore::startDumpFrom(uint32_t fromUnixSeconds) {
|
||||
return startDumpFromUpTo(fromUnixSeconds, currentTv.tv_sec);
|
||||
}
|
||||
@ -257,7 +285,9 @@ bool PersistentTmStore::updateBaseDir() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) {
|
||||
void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) { deleteFromUpTo(0, unixSeconds); }
|
||||
|
||||
void PersistentTmStore::deleteFromUpTo(uint32_t startUnixTime, uint32_t endUnixTime) {
|
||||
using namespace std::filesystem;
|
||||
for (auto const& file : directory_iterator(basePath)) {
|
||||
if (file.is_directory() or (activeFile.has_value() and (activeFile.value() == file.path()))) {
|
||||
@ -270,7 +300,8 @@ void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) {
|
||||
continue;
|
||||
}
|
||||
time_t fileEpoch = timegm(&fileTime);
|
||||
if (fileEpoch + rolloverDiffSeconds < unixSeconds) {
|
||||
if (fileEpoch + rolloverDiffSeconds < endUnixTime and
|
||||
static_cast<uint32_t>(fileEpoch) >= startUnixTime) {
|
||||
std::error_code e;
|
||||
std::filesystem::remove(file.path(), e);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/ipc/CommandMessage.h"
|
||||
|
||||
enum class RolloverInterval { MINUTELY, HOURLY, DAILY };
|
||||
|
||||
@ -60,6 +61,7 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
||||
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, Command_t& execCmd);
|
||||
|
||||
void deleteUpTo(uint32_t unixSeconds);
|
||||
void deleteFromUpTo(uint32_t startUnixTime, uint32_t endUnixTime);
|
||||
ReturnValue_t startDumpFrom(uint32_t fromUnixSeconds);
|
||||
ReturnValue_t startDumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
|
||||
/**
|
||||
@ -145,6 +147,8 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
||||
std::optional<uint8_t> extractSuffix(const std::string& pathStr);
|
||||
bool updateBaseDir();
|
||||
ReturnValue_t assignAndOrCreateMostRecentFile();
|
||||
ReturnValue_t handleDeletionCmd(StorageManagerIF& ipcStore, CommandMessage& cmdMessage);
|
||||
ReturnValue_t handleDumpCmd(StorageManagerIF& ipcStore, CommandMessage& cmdMessage);
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */
|
||||
|
@ -16,8 +16,9 @@ Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid,
|
||||
|
||||
ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) {
|
||||
switch (subservice) {
|
||||
case (Subservices::DELETE_UP_TO):
|
||||
case (Subservices::START_BY_TIME_RANGE_RETRIEVAL): {
|
||||
case (Subservice::DELETE_UP_TO):
|
||||
case (Subservice::DELETE_BY_TIME_RANGE):
|
||||
case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): {
|
||||
return OK;
|
||||
}
|
||||
default: {
|
||||
@ -45,34 +46,55 @@ ReturnValue_t Service15TmStorage::getMessageQueueAndObject(uint8_t subservice,
|
||||
ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||
const uint8_t *tcData, size_t tcDataLen,
|
||||
uint32_t *state, object_id_t objectId) {
|
||||
if (subservice == Subservices::START_BY_TIME_RANGE_RETRIEVAL) {
|
||||
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||
// to time reading and reply handling
|
||||
if (tcDataLen != 12) {
|
||||
return INVALID_TC;
|
||||
switch (subservice) {
|
||||
case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): {
|
||||
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||
// to time reading and reply handling
|
||||
if (tcDataLen != 12) {
|
||||
return INVALID_TC;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
// Store timestamps
|
||||
TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
case (Subservice::DELETE_UP_TO): {
|
||||
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||
// to time reading and reply handling
|
||||
if (tcDataLen != 8) {
|
||||
return INVALID_TC;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
// Store timestamps
|
||||
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
// Store timestamps
|
||||
TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
} else if (subservice == Subservices::DELETE_UP_TO) {
|
||||
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||
// to time reading and reply handling
|
||||
if (tcDataLen != 8) {
|
||||
return INVALID_TC;
|
||||
case (Subservice::DELETE_BY_TIME_RANGE): {
|
||||
// TODO: Hardcoded two UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||
// to time reading and reply handling
|
||||
if (tcDataLen != 12) {
|
||||
return INVALID_TC;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
// Store timestamps
|
||||
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
default: {
|
||||
return CommandingServiceBase::INVALID_SUBSERVICE;
|
||||
}
|
||||
// Store timestamps
|
||||
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
@ -5,7 +5,11 @@
|
||||
|
||||
class Service15TmStorage : public CommandingServiceBase {
|
||||
public:
|
||||
enum Subservices : uint8_t { START_BY_TIME_RANGE_RETRIEVAL = 9, DELETE_UP_TO = 11 };
|
||||
enum Subservice : uint8_t {
|
||||
START_BY_TIME_RANGE_RETRIEVAL = 9,
|
||||
DELETE_UP_TO = 11,
|
||||
DELETE_BY_TIME_RANGE = 128
|
||||
};
|
||||
explicit Service15TmStorage(object_id_t objectId, uint16_t apid, uint8_t numParallelCommands,
|
||||
uint16_t commandTimeoutSecs = 60, size_t queueDepth = 10);
|
||||
|
||||
|
Reference in New Issue
Block a user