WIP: develop_update #706

Draft
muellerr wants to merge 710 commits from eive/fsfw:develop_update into development
187 changed files with 3304 additions and 1475 deletions

8
.idea/cmake.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Test" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host" />
</configurations>
</component>
</project>

View File

@ -10,8 +10,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
data with a size limited only by the size of `size_t`.
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
number fields stored the actual length of the field instead of the length minus 1 like specified
in the CFDP standard.
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
@ -22,8 +27,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field.
## Changed
- HK generation is now countdown based.
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
@ -32,6 +40,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
- Health functions are virtual now.
# [v6.0.0] 2023-02-10
@ -107,6 +116,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.

View File

@ -51,7 +51,10 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
html_theme = "alabaster"
html_theme_options = {
"extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
"extra_nav_links": {
"Impressum": "https://www.uni-stuttgart.de/impressum",
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
}
}

View File

@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
bool hasAdditionalData = false;
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
ReturnValue_t result;
if (dataAddress != store_address_t::invalid()) {
hasAdditionalData = true;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
}
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
if (hasAdditionalData) {
ipcStore->deleteData(dataAddress);
}
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, true, result);

View File

@ -16,8 +16,8 @@ class CommandActionHelper {
public:
explicit CommandActionHelper(CommandsActionsIF* owner);
virtual ~CommandActionHelper();
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
uint32_t size);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
const uint8_t* data = nullptr, uint32_t size = 0);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
ReturnValue_t initialize();
ReturnValue_t handleReply(CommandMessage* reply);

View File

@ -2,7 +2,9 @@
#define FSFW_CFDP_H
#include "cfdp/definitions.h"
#include "cfdp/handler/DestHandler.h"
#include "cfdp/handler/FaultHandlerBase.h"
#include "cfdp/helpers.h"
#include "cfdp/tlv/Lv.h"
#include "cfdp/tlv/StringLv.h"
#include "cfdp/tlv/Tlv.h"

View File

@ -1 +1,2 @@
target_sources(${LIB_FSFW_NAME} PRIVATE FaultHandlerBase.cpp UserBase.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp)

View File

@ -0,0 +1,546 @@
#include "DestHandler.h"
#include <etl/crc32.h>
#include <utility>
#include "fsfw/FSFW.h"
#include "fsfw/cfdp/pdu/EofPduReader.h"
#include "fsfw/cfdp/pdu/FileDataReader.h"
#include "fsfw/cfdp/pdu/FinishedPduCreator.h"
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
#include "fsfw/objectmanager.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwParams fsfwParams)
: tlvVec(params.maxTlvsInOnePdu),
userTlvVec(params.maxTlvsInOnePdu),
dp(std::move(params)),
fp(fsfwParams),
tp(params.maxFilenameLen) {
tp.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
}
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
ReturnValue_t result;
uint8_t errorIdx = 0;
fsmRes.resetOfIteration();
if (fsmRes.step == TransactionStep::IDLE) {
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
if (infoIter->pduType == PduType::FILE_DIRECTIVE and
infoIter->directiveType == FileDirective::METADATA) {
result = handleMetadataPdu(*infoIter);
checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used
dp.packetListRef.erase(infoIter++);
} else {
infoIter++;
}
}
if (fsmRes.step == TransactionStep::IDLE) {
// To decrease the already high complexity of the software, all packets arriving before
// a metadata PDU are deleted.
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
fp.tcStore->deleteData(infoIter->storeId);
infoIter++;
}
dp.packetListRef.clear();
}
if (fsmRes.step != TransactionStep::IDLE) {
fsmRes.callStatus = CallStatus::CALL_AGAIN;
}
return updateFsmRes(errorIdx);
}
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
if (infoIter->pduType == PduType::FILE_DATA) {
result = handleFileDataPdu(*infoIter);
checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used
dp.packetListRef.erase(infoIter++);
} else if (infoIter->pduType == PduType::FILE_DIRECTIVE and
infoIter->directiveType == FileDirective::EOF_DIRECTIVE) {
// TODO: Support for check timer missing
result = handleEofPdu(*infoIter);
checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used
dp.packetListRef.erase(infoIter++);
} else {
infoIter++;
}
}
}
if (fsmRes.step == TransactionStep::TRANSFER_COMPLETION) {
result = handleTransferCompletion();
checkAndHandleError(result, errorIdx);
}
if (fsmRes.step == TransactionStep::SENDING_FINISHED_PDU) {
result = sendFinishedPdu();
checkAndHandleError(result, errorIdx);
finish();
}
return updateFsmRes(errorIdx);
}
if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
// TODO: Will be implemented at a later stage
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CFDP state machine for acknowledged mode not implemented yet" << std::endl;
#endif
}
return updateFsmRes(errorIdx);
}
ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) {
if (dp.packetListRef.full()) {
return FAILED;
}
dp.packetListRef.push_back(packet);
return OK;
}
ReturnValue_t cfdp::DestHandler::initialize() {
if (fp.tmStore == nullptr) {
fp.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (fp.tmStore == nullptr) {
return FAILED;
}
}
if (fp.tcStore == nullptr) {
fp.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (fp.tcStore == nullptr) {
return FAILED;
}
}
if (fp.msgQueue == nullptr) {
return FAILED;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
// Process metadata PDU
auto constAccessorPair = fp.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
cfdp::StringLv sourceFileName;
cfdp::StringLv destFileName;
MetadataInfo metadataInfo(tp.fileSize, sourceFileName, destFileName);
cfdp::Tlv* tlvArrayAsPtr = tlvVec.data();
metadataInfo.setOptionsArray(&tlvArrayAsPtr, std::nullopt, tlvVec.size());
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
metadataInfo);
ReturnValue_t result = reader.parseData();
// TODO: The standard does not really specify what happens if this kind of error happens
// I think it might be a good idea to cache some sort of error code, which
// is translated into a warning and/or event by an upper layer
if (result != OK) {
return handleMetadataParseError(result, constAccessorPair.second.data(),
constAccessorPair.second.size());
}
return startTransaction(reader, metadataInfo);
}
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
// Process file data PDU
auto constAccessorPair = fp.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
cfdp::FileSize offset;
FileDataInfo fdInfo(offset);
FileDataReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), fdInfo);
ReturnValue_t result = reader.parseData();
if (result != OK) {
return result;
}
size_t fileSegmentLen = 0;
const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen);
FileOpParams fileOpParams(tp.destName.data(), fileSegmentLen);
fileOpParams.offset = offset.value();
if (dp.cfg.indicCfg.fileSegmentRecvIndicRequired) {
FileSegmentRecvdParams segParams;
segParams.offset = offset.value();
segParams.id = tp.transactionId;
segParams.length = fileSegmentLen;
segParams.recContState = fdInfo.getRecordContinuationState();
size_t segmentMetadatLen = 0;
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
segParams.segmentMetadata = {segMetadata, segmentMetadatLen};
dp.user.fileSegmentRecvdIndication(segParams);
}
result = dp.user.vfs.writeToFile(fileOpParams, fileData);
if (result != returnvalue::OK) {
// TODO: Proper Error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
<< result << std::endl;
#endif
tp.vfsErrorCount++;
if (tp.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step),
result);
}
return result;
} else {
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
tp.vfsErrorCount = 0;
}
if (offset.value() + fileSegmentLen > tp.progress) {
tp.progress = offset.value() + fileSegmentLen;
}
return result;
}
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
// Process EOF PDU
auto constAccessorPair = fp.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
EofInfo eofInfo(nullptr);
EofPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), eofInfo);
ReturnValue_t result = reader.parseData();
if (result != OK) {
return result;
}
// TODO: Error handling
if (eofInfo.getConditionCode() == ConditionCode::NO_ERROR) {
tp.crc = eofInfo.getChecksum();
uint64_t fileSizeFromEof = eofInfo.getFileSize().value();
// CFDP 4.6.1.2.9: Declare file size error if progress exceeds file size
if (fileSizeFromEof > tp.progress) {
// TODO: File size error
}
tp.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
}
if (dp.cfg.indicCfg.eofRecvIndicRequired) {
dp.user.eofRecvIndication(getTransactionId());
}
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
} else if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
fsmRes.step = TransactionStep::SENDING_ACK_PDU;
}
}
return returnvalue::OK;
}
ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
const uint8_t* rawData, size_t maxSize) {
// TODO: try to extract destination ID for error
// TODO: Invalid metadata PDU.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Parsing Metadata PDU failed with code " << result << std::endl;
#else
#endif
PduHeaderReader headerReader(rawData, maxSize);
result = headerReader.parseData();
if (result != OK) {
// TODO: Now this really should not happen. Warning or error,
// yield or cache appropriate returnvalue
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Parsing Header failed" << std::endl;
#else
#endif
// TODO: Trigger appropriate event
return result;
}
cfdp::EntityId destId;
headerReader.getDestId(destId);
RemoteEntityCfg* remoteCfg;
if (not dp.remoteCfgTable.getRemoteCfg(destId, &remoteCfg)) {
// TODO: No remote config for dest ID. I consider this a configuration error, which is not
// covered by the standard.
// Warning or error, yield or cache appropriate returnvalue
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "No remote config exists for destination ID" << std::endl;
#else
#endif
// TODO: Trigger appropriate event
}
// TODO: Appropriate returnvalue?
return returnvalue::FAILED;
}
ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, MetadataInfo& info) {
if (fsmRes.state != CfdpStates::IDLE) {
// According to standard, discard metadata PDU if we are busy
return OK;
}
ReturnValue_t result = OK;
size_t sourceNameSize = 0;
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize + 1 > tp.sourceName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
return FAILED;
}
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
tp.sourceName[sourceNameSize] = '\0';
size_t destNameSize = 0;
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
if (destNameSize + 1 > tp.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
return FAILED;
}
std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
tp.destName[destNameSize] = '\0';
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
// so there is no need to create a file or truncate an existing file
if (destNameSize > 0 and sourceNameSize > 0) {
FilesystemParams fparams(tp.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
if (dp.user.vfs.isDirectory(tp.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
if (dp.user.vfs.fileExists(fparams)) {
result = dp.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
} else {
result = dp.user.vfs.createFile(fparams);
if (result != OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
}
}
EntityId sourceId;
reader.getSourceId(sourceId);
if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) {
// TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__
<< ": No remote configuration found for destination ID "
<< tp.pduConf.sourceId.getValue() << std::endl;
#endif
return FAILED;
}
fsmRes.step = TransactionStep::TRANSACTION_START;
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
}
tp.checksumType = info.getChecksumType();
tp.closureRequested = info.isClosureRequested();
reader.fillConfig(tp.pduConf);
tp.pduConf.direction = Direction::TOWARDS_SENDER;
tp.transactionId.entityId = tp.pduConf.sourceId;
tp.transactionId.seqNum = tp.pduConf.seqNum;
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
params.fileSize = tp.fileSize.getSize();
params.destFileName = tp.destName.data();
params.sourceFileName = tp.sourceName.data();
params.msgsToUserArray = dynamic_cast<MessageToUserTlv*>(userTlvVec.data());
params.msgsToUserLen = info.getOptionsLen();
dp.user.metadataRecvdIndication(params);
return result;
}
cfdp::CfdpStates cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
ReturnValue_t result;
if (tp.checksumType != ChecksumType::NULL_CHECKSUM) {
result = checksumVerification();
if (result != OK) {
// TODO: Warning / error handling?
}
} else {
tp.conditionCode = ConditionCode::NO_ERROR;
}
result = noticeOfCompletion();
if (result != OK) {
}
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
if (tp.closureRequested) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
} else {
finish();
}
} else if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
char baseNameBuf[tp.destName.size()]{};
FilesystemParams fparamsSrc(tp.sourceName.data());
size_t baseNameLen = 0;
ReturnValue_t result =
dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED;
}
// Destination name + slash + base name + null termination
if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
tp.destName[destNameSize++] = '/';
std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
tp.destName[destNameSize++] = '\0';
return OK;
}
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
static_cast<uint8_t>(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif
}
void cfdp::DestHandler::finish() {
tp.reset();
dp.packetListRef.clear();
fsmRes.state = CfdpStates::IDLE;
fsmRes.step = TransactionStep::IDLE;
}
ReturnValue_t cfdp::DestHandler::checksumVerification() {
std::array<uint8_t, 1024> buf{};
// TODO: Checksum verification and notice of completion
etl::crc32 crcCalc;
uint64_t currentOffset = 0;
FileOpParams params(tp.destName.data(), tp.fileSize.value());
while (currentOffset < tp.fileSize.value()) {
uint64_t readLen;
if (currentOffset + buf.size() > tp.fileSize.value()) {
readLen = tp.fileSize.value() - currentOffset;
} else {
readLen = buf.size();
}
if (readLen > 0) {
params.offset = currentOffset;
params.size = readLen;
auto result = dp.user.vfs.readFromFile(params, buf.data(), buf.size());
if (result != OK) {
// TODO: I think this is a case for a filestore rejection, but it might sense to print
// a warning or trigger an event because this should generally not happen
return FAILED;
}
crcCalc.add(buf.begin(), buf.begin() + readLen);
}
currentOffset += readLen;
}
uint32_t value = crcCalc.value();
if (value == tp.crc) {
tp.conditionCode = ConditionCode::NO_ERROR;
tp.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
} else {
// TODO: Proper error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CRC check for file " << tp.destName.data() << " failed" << std::endl;
#endif
tp.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::noticeOfCompletion() {
if (dp.cfg.indicCfg.transactionFinishedIndicRequired) {
TransactionFinishedParams params(tp.transactionId, tp.conditionCode, tp.deliveryCode,
tp.deliveryStatus);
dp.user.transactionFinishedIndication(params);
}
return OK;
}
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
FinishedInfo info(tp.conditionCode, tp.deliveryCode, tp.deliveryStatus);
FinishPduCreator finishedPdu(tp.pduConf, info);
store_address_t storeId;
uint8_t* dataPtr = nullptr;
ReturnValue_t result =
fp.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler:sendFinishedPdu: Getting store slot failed" << std::endl;
#endif
fp.eventReporter->forwardEvent(events::STORE_ERROR, result, 0);
return result;
}
size_t serLen = 0;
result = finishedPdu.serialize(dataPtr, serLen, finishedPdu.getSerializedSize());
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Serializing Finished PDU failed"
<< std::endl;
#endif
fp.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
return result;
}
TmTcMessage msg(storeId);
result = fp.msgQueue->sendMessage(fp.packetDest.getReportReceptionQueue(), &msg);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
#endif
fp.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0);
return result;
}
fsmRes.packetsSent++;
return OK;
}
cfdp::DestHandler::TransactionStep cfdp::DestHandler::getTransactionStep() const {
return fsmRes.step;
}
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::updateFsmRes(uint8_t errors) {
fsmRes.errors = errors;
fsmRes.result = OK;
if (fsmRes.errors > 0) {
fsmRes.result = FAILED;
}
return fsmRes;
}
const cfdp::TransactionId& cfdp::DestHandler::getTransactionId() const { return tp.transactionId; }
void cfdp::DestHandler::checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx) {
if (result != OK and errorIdx < 3) {
fsmRes.errorCodes[errorIdx] = result;
errorIdx++;
}
}
void cfdp::DestHandler::setMsgQueue(MessageQueueIF& queue) { fp.msgQueue = &queue; }
void cfdp::DestHandler::setEventReporter(EventReportingProxyIF& reporter) {
fp.eventReporter = &reporter;
}
const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const { return dp; }
StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fp.tmStore; }
StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fp.tcStore; }

View File

@ -0,0 +1,206 @@
#ifndef FSFW_CFDP_CFDPDESTHANDLER_H
#define FSFW_CFDP_CFDPDESTHANDLER_H
#include <etl/list.h>
#include <etl/set.h>
#include <optional>
#include <utility>
#include "RemoteConfigTableIF.h"
#include "UserBase.h"
#include "defs.h"
#include "fsfw/cfdp/handler/mib.h"
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
#include "fsfw/cfdp/pdu/PduConfig.h"
#include "fsfw/container/DynamicFIFO.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
namespace cfdp {
struct PacketInfo {
PacketInfo(PduType type, store_address_t storeId,
std::optional<FileDirective> directive = std::nullopt)
: pduType(type), directiveType(directive), storeId(storeId) {}
PduType pduType = PduType::FILE_DATA;
std::optional<FileDirective> directiveType = FileDirective::INVALID_DIRECTIVE;
store_address_t storeId = store_address_t::invalid();
PacketInfo() = default;
};
template <size_t SIZE>
using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>;
template <size_t SIZE>
using PacketInfoList = etl::list<PacketInfo, SIZE>;
using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>;
using PacketInfoListBase = etl::ilist<PacketInfo>;
struct DestHandlerParams {
DestHandlerParams(LocalEntityCfg cfg, UserBase& user, RemoteConfigTableIF& remoteCfgTable,
PacketInfoListBase& packetList,
// TODO: This container can potentially take tons of space. For a better
// memory efficient implementation, an additional abstraction could be
// be used so users can use uint32_t as the pair type
LostSegmentsListBase& lostSegmentsContainer)
: cfg(std::move(cfg)),
user(user),
remoteCfgTable(remoteCfgTable),
packetListRef(packetList),
lostSegmentsContainer(lostSegmentsContainer) {}
LocalEntityCfg cfg;
UserBase& user;
RemoteConfigTableIF& remoteCfgTable;
PacketInfoListBase& packetListRef;
LostSegmentsListBase& lostSegmentsContainer;
uint8_t maxTlvsInOnePdu = 10;
size_t maxFilenameLen = 255;
};
struct FsfwParams {
FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore,
StorageManagerIF& tmStore)
: FsfwParams(packetDest, msgQueue, eventReporter) {
this->tcStore = &tcStore;
this->tmStore = &tmStore;
}
FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
EventReportingProxyIF* eventReporter)
: packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {}
AcceptsTelemetryIF& packetDest;
MessageQueueIF* msgQueue;
EventReportingProxyIF* eventReporter = nullptr;
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
};
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
class DestHandler {
public:
enum class TransactionStep : uint8_t {
IDLE = 0,
TRANSACTION_START = 1,
RECEIVING_FILE_DATA_PDUS = 2,
SENDING_ACK_PDU = 3,
TRANSFER_COMPLETION = 4,
SENDING_FINISHED_PDU = 5
};
struct FsmResult {
public:
ReturnValue_t result = returnvalue::OK;
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
TransactionStep step = TransactionStep::IDLE;
CfdpStates state = CfdpStates::IDLE;
uint32_t packetsSent = 0;
uint8_t errors = 0;
std::array<ReturnValue_t, 3> errorCodes = {};
void resetOfIteration() {
result = returnvalue::OK;
callStatus = CallStatus::CALL_AFTER_DELAY;
packetsSent = 0;
errors = 0;
errorCodes.fill(returnvalue::OK);
}
};
/**
* Will be returned if it is advisable to call the state machine operation call again
*/
ReturnValue_t PARTIAL_SUCCESS = returnvalue::makeCode(0, 2);
ReturnValue_t FAILURE = returnvalue::makeCode(0, 3);
explicit DestHandler(DestHandlerParams handlerParams, FsfwParams fsfwParams);
/**
*
* @return
* - @c returnvalue::OK State machine OK for this execution cycle
* - @c CALL_FSM_AGAIN State machine should be called again.
*/
const FsmResult& performStateMachine();
void setMsgQueue(MessageQueueIF& queue);
void setEventReporter(EventReportingProxyIF& reporter);
ReturnValue_t passPacket(PacketInfo packet);
ReturnValue_t initialize();
[[nodiscard]] CfdpStates getCfdpState() const;
[[nodiscard]] TransactionStep getTransactionStep() const;
[[nodiscard]] const TransactionId& getTransactionId() const;
[[nodiscard]] const DestHandlerParams& getDestHandlerParams() const;
[[nodiscard]] StorageManagerIF* getTcStore() const;
[[nodiscard]] StorageManagerIF* getTmStore() const;
private:
struct TransactionParams {
// Initialize char vectors with length + 1 for 0 termination
explicit TransactionParams(size_t maxFileNameLen)
: sourceName(maxFileNameLen + 1), destName(maxFileNameLen + 1) {}
void reset() {
pduConf = PduConfig();
transactionId = TransactionId();
std::fill(sourceName.begin(), sourceName.end(), '\0');
std::fill(destName.begin(), destName.end(), '\0');
fileSize.setFileSize(0, false);
conditionCode = ConditionCode::NO_ERROR;
deliveryCode = FileDeliveryCode::DATA_INCOMPLETE;
deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY;
crc = 0;
progress = 0;
remoteCfg = nullptr;
closureRequested = false;
vfsErrorCount = 0;
checksumType = ChecksumType::NULL_CHECKSUM;
}
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
bool closureRequested = false;
uint16_t vfsErrorCount = 0;
std::vector<char> sourceName;
std::vector<char> destName;
cfdp::FileSize fileSize;
TransactionId transactionId;
PduConfig pduConf;
ConditionCode conditionCode = ConditionCode::NO_ERROR;
FileDeliveryCode deliveryCode = FileDeliveryCode::DATA_INCOMPLETE;
FileDeliveryStatus deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY;
uint32_t crc = 0;
uint64_t progress = 0;
RemoteEntityCfg* remoteCfg = nullptr;
};
std::vector<cfdp::Tlv> tlvVec;
std::vector<cfdp::Tlv> userTlvVec;
DestHandlerParams dp;
FsfwParams fp;
TransactionParams tp;
FsmResult fsmRes;
ReturnValue_t startTransaction(MetadataPduReader& reader, MetadataInfo& info);
ReturnValue_t handleMetadataPdu(const PacketInfo& info);
ReturnValue_t handleFileDataPdu(const PacketInfo& info);
ReturnValue_t handleEofPdu(const PacketInfo& info);
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
size_t maxSize);
ReturnValue_t handleTransferCompletion();
ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize);
ReturnValue_t sendFinishedPdu();
ReturnValue_t noticeOfCompletion();
ReturnValue_t checksumVerification();
void fileErrorHandler(Event event, ReturnValue_t result, const char* info);
const FsmResult& updateFsmRes(uint8_t errors);
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
void finish();
};
} // namespace cfdp
#endif // FSFW_CFDP_CFDPDESTHANDLER_H

View File

@ -0,0 +1 @@
#include "SourceHandler.h"

View File

@ -0,0 +1,6 @@
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
class SourceHandler {};
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H

View File

@ -5,5 +5,18 @@ namespace cfdp {
enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
}
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP;
namespace events {
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
} // namespace events
} // namespace cfdp
#endif // FSFW_CFDP_HANDLER_DEFS_H

View File

@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
*buffer += 1;
**buffer = pduDataFieldLen & 0x00ff;
*buffer += 1;
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
pduConf.seqNum.getWidth();
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
*buffer += 1;
*size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);

View File

@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
}
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
}
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
}
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {

View File

@ -4,48 +4,31 @@
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth)
ControllerBase::ControllerBase(object_id_t setObjectId, size_t commandQueueDepth)
: SystemObject(setObjectId),
parentId(parentId),
mode(MODE_OFF),
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
ReturnValue_t result = modeHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == nullptr) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
result = healthHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
return SystemObject::initialize();
}
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
@ -75,7 +58,7 @@ void ControllerBase::handleQueue() {
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode);
triggerEvent(CHANGING_MODE, mode_, submode_);
mode = mode_;
submode = submode_;
modeHelper.modeChanged(mode, submode);
@ -118,3 +101,13 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
const HasHealthIF* ControllerBase::getOptHealthIF() const { return this; }
const HasModesIF& ControllerBase::getModeIF() const { return *this; }
ModeTreeChildIF& ControllerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t ControllerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}

View File

@ -6,6 +6,9 @@
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeHelper.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
#include "fsfw/subsystem/ModeTreeChildIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
@ -18,13 +21,18 @@
class ControllerBase : public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public SystemObject {
public:
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
ControllerBase(object_id_t setObjectId, size_t commandQueueDepth = 3);
~ControllerBase() override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/** SystemObject override */
ReturnValue_t initialize() override;
@ -38,6 +46,8 @@ class ControllerBase : public HasModesIF,
ReturnValue_t performOperation(uint8_t opCode) override;
void setTaskIF(PeriodicTaskIF *task) override;
ReturnValue_t initializeAfterTaskCreation() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
protected:
/**
@ -56,8 +66,6 @@ class ControllerBase : public HasModesIF,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override = 0;
const object_id_t parentId;
Mode_t mode;
Submode_t submode;

View File

@ -1,8 +1,7 @@
#include "fsfw/controller/ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth)
: ControllerBase(objectId, parentId, commandQueueDepth),
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
: ControllerBase(objectId, commandQueueDepth),
poolManager(this, commandQueue),
actionHelper(this, commandQueue) {}

View File

@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
public HasActionsIF,
public HasLocalDataPoolIF {
public:
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
~ExtendedControllerBase() override;
/* SystemObjectIF overrides */

View File

@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
timeval timeSinceEpoch = time - epoch;
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
double monthsSinceEpoch = minutesSinceEpoch / 60 / 24 / 30;
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
if ((monthsSinceEpoch > 1) || (monthsSinceEpoch < -1)) {
return TLE_TOO_OLD;
}

View File

@ -70,8 +70,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() {
return initializeHousekeepingPoolEntriesOnce();
}
@ -506,9 +505,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
result = changeCollectionInterval(sid, newCollIntvl, true);
result = changeCollectionInterval(sid, newCollIntvl);
} else {
result = changeCollectionInterval(sid, newCollIntvl, false);
result = changeCollectionInterval(sid, newCollIntvl);
}
break;
}
@ -570,6 +569,10 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
CommandMessage reply;
if (result != returnvalue::OK) {
if (result == WRONG_HK_PACKET_TYPE) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
WRONG_HK_PACKET_TYPE);
}
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
} else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
@ -657,10 +660,6 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
}
void LocalDataPoolManager::setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor) {
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
}
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
@ -714,15 +713,15 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
return REPORTING_STATUS_UNCHANGED;
return returnvalue::OK;
}
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics) {
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
@ -730,11 +729,6 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne
return DATASET_NOT_FOUND;
}
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
@ -825,6 +819,8 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
errorPrint = "Dataset not found";
} else if (error == POOLOBJECT_NOT_FOUND) {
errorPrint = "Pool Object not found";
} else if (error == WRONG_HK_PACKET_TYPE) {
errorPrint = "Wrong Packet Type";
} else if (error == returnvalue::FAILED) {
if (outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";

View File

@ -102,7 +102,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* @param nonDiagInvlFactor
* @return
*/
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
ReturnValue_t initializeAfterTaskCreation();
/**
* @brief This should be called in the periodic handler of the owner.
@ -152,17 +152,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
/**
* Non-Diagnostics packets usually have a lower minimum sampling frequency
* than diagnostic packets.
* A factor can be specified to determine the minimum sampling frequency
* for non-diagnostic packets. The minimum sampling frequency of the
* diagnostics packets,which is usually jusst the period of the
* performOperation calls, is multiplied with that factor.
* @param factor
*/
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
/**
* @brief The manager is also able to handle housekeeping messages.
* @details
@ -185,6 +174,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
HasLocalDataPoolIF* getOwner();
@ -348,8 +338,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);

View File

@ -250,9 +250,8 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
dur_millis_t minimumPeriodicInterval) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval);
}
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }

View File

@ -162,6 +162,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
object_id_t getCreatorObjectId();
bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/**
* Returns the current periodic HK generation interval this set
@ -189,10 +190,8 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* Used for periodic generation.
*/