Compare commits

..

1 Commits

Author SHA1 Message Date
Ulrich Mohr e73b9ff72c Merge pull request 'v6.0.0' (#729) from development into master
fsfw/fsfw/pipeline/head There was a failure building this commit Details
Reviewed-on: fsfw/fsfw#729
2023-02-23 13:42:48 +01:00
285 changed files with 1992 additions and 6267 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
# PyCharm and CLion
.idea/*
/.idea/*
!/.idea/runConfigurations
!/.idea/cmake.xml
!/.idea/codeStyles

View File

@ -1,8 +0,0 @@
<?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_OSAL=host -DFSFW_BUILD_TESTS=ON" NO_GENERATOR="true" />
</configurations>
</component>
</project>

View File

@ -8,45 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
## 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.
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
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field.
- Relative timeshift in the PUS time service.
## Changed
- The PUS time service now dumps the time before setting a new time and after having set the
time.
- 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`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
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.
- PUS Service Base request queue depth and maximum number of handled packets per cycle is now
configurable.
# [v6.0.0] 2023-02-10
## Fixes
@ -121,8 +82,6 @@ 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

@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
20
CACHE STRING "ETL library major version requirement")
set(FSFW_ETL_LIB_VERSION
${FSFW_ETL_LIB_MAJOR_VERSION}.35.14
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
CACHE STRING "ETL library exact version requirement")
set(FSFW_ETL_LINK_TARGET etl::etl)

View File

@ -51,10 +51,7 @@ 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

@ -32,7 +32,6 @@ add_subdirectory(timemanager)
add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices)
add_subdirectory(filesystem)
add_subdirectory(util)
# Optional

View File

@ -59,24 +59,17 @@ 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;
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;
}
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);
if (hasAdditionalData) {
ipcStore->deleteData(dataAddress);
}
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 = nullptr, uint32_t size = 0);
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, SerializeIF* data);
ReturnValue_t initialize();
ReturnValue_t handleReply(CommandMessage* reply);

View File

@ -2,9 +2,7 @@
#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

@ -4,9 +4,8 @@ CfdpMessage::CfdpMessage() = default;
CfdpMessage::~CfdpMessage() = default;
void CfdpMessage::setPutRequest(CommandMessage *message, store_address_t putRequest) {
message->setCommand(PUT_REQUEST);
message->setParameter(putRequest.raw);
void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
message->setParameter(cfdpPacket.raw);
}
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {

View File

@ -11,11 +11,9 @@ class CfdpMessage {
public:
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
static const Command_t PUT_REQUEST = MAKE_COMMAND_ID(1);
static const Command_t CANCEL_REQUEST = MAKE_COMMAND_ID(1);
virtual ~CfdpMessage();
static void setPutRequest(CommandMessage* message, store_address_t putRequest);
static void setCommand(CommandMessage* message, store_address_t cfdpPacket);
static store_address_t getStoreId(const CommandMessage* message);

View File

@ -8,14 +8,11 @@
namespace cfdp {
/**
* Helper type for the CFDP File Size Sensitive (FSS) fields.
*/
struct Fss : public SerializeIF {
struct FileSize : public SerializeIF {
public:
Fss() = default;
FileSize() = default;
explicit Fss(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
[[nodiscard]] uint64_t value() const { return fileSize; }

View File

@ -3,8 +3,8 @@
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h"
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
ReturnValue_t result = this->setValueAndWidth(width, value);
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() {
ReturnValue_t result = this->setValue(width, value);
if (result != returnvalue::OK) {
#if FSFW_DISABLE_PRINTOUT == 0
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -20,8 +20,8 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) {
switch (width_) {
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) {
switch (widthInBytes) {
case (cfdp::WidthInBytes::ONE_BYTE): {
if (value_ > UINT8_MAX) {
return returnvalue::FAILED;
@ -43,18 +43,15 @@ ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uin
this->value.fourBytes = value_;
break;
}
case (cfdp::WidthInBytes::EIGHT_BYTES): {
this->value.eightBytes = value_;
}
default: {
break;
}
}
this->width = width_;
this->width = widthInBytes;
return returnvalue::OK;
}
uint64_t cfdp::VarLenField::getValue() const {
size_t cfdp::VarLenField::getValue() const {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
return value.oneByte;
@ -65,9 +62,6 @@ uint64_t cfdp::VarLenField::getValue() const {
case (cfdp::WidthInBytes::FOUR_BYTES): {
return value.fourBytes;
}
case (cfdp::WidthInBytes::EIGHT_BYTES): {
return value.eightBytes;
}
}
return 0;
}
@ -90,10 +84,6 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
case (cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
}
case (cfdp::WidthInBytes::EIGHT_BYTES): {
return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize,
streamEndianness);
}
default: {
return returnvalue::FAILED;
}
@ -108,16 +98,11 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui
return deSerialize(buffer, size, streamEndianness);
}
ReturnValue_t cfdp::VarLenField::setValue(uint64_t value_) {
return setValueAndWidth(getWidth(), value_);
}
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
value.oneByte = **buffer;
*buffer += 1;
*size += 1;
return returnvalue::OK;
}
@ -127,9 +112,6 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
case (cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
}
case (cfdp::WidthInBytes::EIGHT_BYTES): {
return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness);
}
default: {
return returnvalue::FAILED;
}
@ -153,5 +135,3 @@ bool cfdp::VarLenField::operator==(const cfdp::VarLenField &other) const {
bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const {
return not(*this == other);
}
void cfdp::VarLenField::setWidth(cfdp::WidthInBytes width_) { this->width = width_; }

View File

@ -25,15 +25,13 @@ class VarLenField : public SerializeIF {
template <typename T>
explicit VarLenField(UnsignedByteField<T> byteField);
VarLenField(cfdp::WidthInBytes width, uint64_t value);
VarLenField(cfdp::WidthInBytes width, size_t value);
bool operator==(const VarLenField &other) const;
bool operator!=(const VarLenField &other) const;
bool operator<(const VarLenField &other) const;
ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value);
void setWidth(cfdp::WidthInBytes width);
ReturnValue_t setValue(uint64_t value);
ReturnValue_t setValue(cfdp::WidthInBytes, size_t value);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
@ -44,7 +42,7 @@ class VarLenField : public SerializeIF {
Endianness streamEndianness);
[[nodiscard]] cfdp::WidthInBytes getWidth() const;
[[nodiscard]] uint64_t getValue() const;
[[nodiscard]] size_t getValue() const;
#if FSFW_CPP_OSTREAM_ENABLED == 1
friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) {
@ -66,7 +64,7 @@ template <typename T>
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
static_assert((sizeof(T) % 2) == 0);
setValueAndWidth(width, byteField.getValue());
setValue(width, byteField.getValue());
}
struct EntityId : public VarLenField {
@ -75,32 +73,6 @@ struct EntityId : public VarLenField {
template <typename T>
explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {}
ReturnValue_t serializeAsLv(uint8_t **buffer, size_t *size, size_t maxSize) const {
if (buffer == nullptr or size == nullptr) {
return returnvalue::FAILED;
}
if (*size + 1 + getWidth() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = getWidth();
*buffer += 1;
*size += 1;
return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK);
}
ReturnValue_t deSerializeFromLv(const uint8_t **buffer, size_t *deserLen) {
if (buffer == nullptr or deserLen == nullptr) {
return returnvalue::FAILED;
}
if (*deserLen < 2) {
return SerializeIF::STREAM_TOO_SHORT;
}
auto width = static_cast<WidthInBytes>(**buffer);
*buffer += 1;
*deserLen -= 1;
return VarLenField::deSerialize(width, buffer, deserLen, SerializeIF::Endianness::NETWORK);
}
};
struct TransactionSeqNum : public VarLenField {

View File

@ -17,7 +17,7 @@ static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
static constexpr uint8_t CFDP_VERSION_2 = 0b001;
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP_BASE;
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP;
static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1);
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
@ -68,7 +68,6 @@ enum WidthInBytes : uint8_t {
ONE_BYTE = 1,
TWO_BYTES = 2,
FOUR_BYTES = 4,
EIGHT_BYTES = 8
};
enum FileDirective : uint8_t {
@ -143,20 +142,6 @@ enum RecordContinuationState {
CONTAINS_START_AND_END = 0b11
};
enum class ProxyOpMessageType : uint8_t {
PUT_REQUEST = 0x00,
MSG_TO_USR = 0x01,
FS_REQUEST = 0x02,
FAULT_HANDLER_OVERRIDE = 0x03,
TRANSMISSION_MODE = 0x04,
FLOW_LABEL = 0x05,
SEG_CTRL = 0x06,
PUT_RESPONSE = 0x07,
FS_RESPONSE = 0x08,
PUT_CANCEL = 0x09,
CLOSURE = 0x0b
};
} // namespace cfdp
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */

View File

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

View File

@ -1,574 +0,0 @@
#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),
msgToUserVec(params.maxTlvsInOnePdu),
transactionParams(params.maxFilenameLen),
destParams(std::move(params)),
fsfwParams(fsfwParams) {
transactionParams.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
}
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::stateMachine() {
ReturnValue_t result;
uint8_t errorIdx = 0;
fsmRes.resetOfIteration();
if (fsmRes.step == TransactionStep::IDLE) {
for (auto infoIter = destParams.packetListRef.begin();
infoIter != destParams.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
destParams.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 = destParams.packetListRef.begin();
infoIter != destParams.packetListRef.end();) {
fsfwParams.tcStore->deleteData(infoIter->storeId);
infoIter++;
}
destParams.packetListRef.clear();
}
if (fsmRes.step != TransactionStep::IDLE) {
fsmRes.callStatus = CallStatus::CALL_AGAIN;
}
return updateFsmRes(errorIdx);
}
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
for (auto infoIter = destParams.packetListRef.begin();
infoIter != destParams.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
destParams.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
destParams.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 == CfdpState::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 (destParams.packetListRef.full()) {
return FAILED;
}
destParams.packetListRef.push_back(packet);
return OK;
}
ReturnValue_t cfdp::DestHandler::initialize() {
if (fsfwParams.tmStore == nullptr) {
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (fsfwParams.tmStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.tcStore == nullptr) {
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (fsfwParams.tcStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.msgQueue == nullptr) {
return FAILED;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
// Process metadata PDU
auto constAccessorPair = fsfwParams.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;
MetadataGenericInfo metadataInfo(transactionParams.fileSize);
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
metadataInfo, tlvVec.data(), tlvVec.size());
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);
}
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
// Process file data PDU
auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
FileDataInfo fdInfo;
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(transactionParams.destName.data(), fileSegmentLen);
fileOpParams.offset = fdInfo.getOffset().value();
if (destParams.cfg.indicCfg.fileSegmentRecvIndicRequired) {
FileSegmentRecvdParams segParams;
segParams.offset = fdInfo.getOffset().value();
segParams.id = transactionParams.transactionId;
segParams.length = fileSegmentLen;
segParams.recContState = fdInfo.getRecordContinuationState();
size_t segmentMetadatLen = 0;
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
segParams.segmentMetadata = {segMetadata, segmentMetadatLen};
destParams.user.fileSegmentRecvdIndication(segParams);
}
result = destParams.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
transactionParams.vfsErrorCount++;
if (transactionParams.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter
fsfwParams.eventReporter->forwardEvent(events::FILESTORE_ERROR,
static_cast<uint8_t>(fsmRes.step), result);
}
return result;
} else {
transactionParams.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
transactionParams.vfsErrorCount = 0;
}
if (fdInfo.getOffset().value() + fileSegmentLen > transactionParams.progress) {
transactionParams.progress = fdInfo.getOffset().value() + fileSegmentLen;
}
return result;
}
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
// Process EOF PDU
auto constAccessorPair = fsfwParams.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) {
transactionParams.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 > transactionParams.progress) {
// TODO: File size error
}
transactionParams.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
}
if (destParams.cfg.indicCfg.eofRecvIndicRequired) {
destParams.user.eofRecvIndication(getTransactionId());
}
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
} else if (fsmRes.state == CfdpState::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 destParams.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(const MetadataPduReader& reader) {
if (fsmRes.state != CfdpState::IDLE) {
// According to standard, discard metadata PDU if we are busy
return OK;
}
ReturnValue_t result = OK;
size_t sourceNameSize = 0;
if (not reader.getSourceFileName().isEmpty()) {
const uint8_t* sourceNamePtr = reader.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
return FAILED;
}
std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
transactionParams.sourceName[sourceNameSize] = '\0';
}
size_t destNameSize = 0;
if (not reader.getDestFileName().isEmpty()) {
const uint8_t* destNamePtr = reader.getDestFileName().getValue(&destNameSize);
if (destNameSize + 1 > transactionParams.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
return FAILED;
}
std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
transactionParams.destName[destNameSize] = '\0';
}
transactionParams.metadataOnly = true;
// 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) {
transactionParams.metadataOnly = false;
FilesystemParams fparams(transactionParams.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
if (destParams.user.vfs.isDirectory(transactionParams.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
if (destParams.user.vfs.fileExists(fparams)) {
result = destParams.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 = destParams.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 destParams.remoteCfgTable.getRemoteCfg(sourceId, &transactionParams.remoteCfg)) {
// TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__
<< ": No remote configuration found for destination ID "
<< transactionParams.pduConf.sourceId.getValue() << std::endl;
#endif
return FAILED;
}
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
fsmRes.state = CfdpState::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpState::BUSY_CLASS_2_ACKED;
}
if (transactionParams.metadataOnly) {
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
} else {
// Kind of ugly, make FSM working on packet per packet basis..
fsmRes.step = TransactionStep::TRANSACTION_START;
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
}
auto& info = reader.getGenericInfo();
transactionParams.checksumType = info.getChecksumType();
transactionParams.closureRequested = info.isClosureRequested();
reader.fillConfig(transactionParams.pduConf);
transactionParams.pduConf.direction = Direction::TOWARDS_SENDER;
transactionParams.transactionId.entityId = transactionParams.pduConf.sourceId;
transactionParams.transactionId.seqNum = transactionParams.pduConf.seqNum;
transactionParams.fileSize = info.getFileSize();
MetadataRecvdParams params(transactionParams.transactionId, transactionParams.pduConf.sourceId,
transactionParams.fileSize);
params.destFileName = transactionParams.destName.data();
params.sourceFileName = transactionParams.sourceName.data();
params.numberOfMsgsToUser = 0;
for (const auto& opt : tlvVec) {
if (opt.getType() == TlvType::MSG_TO_USER) {
msgToUserVec[params.numberOfMsgsToUser] =
MessageToUserTlv(opt.getValue(), opt.getLengthField());
params.numberOfMsgsToUser++;
}
}
params.msgsToUserArray = msgToUserVec.data();
destParams.user.metadataRecvdIndication(params);
return result;
}
cfdp::CfdpState cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
ReturnValue_t result;
if (transactionParams.checksumType != ChecksumType::NULL_CHECKSUM) {
result = checksumVerification();
if (result != OK) {
// TODO: Warning / error handling?
}
} else {
transactionParams.conditionCode = ConditionCode::NO_ERROR;
}
result = noticeOfCompletion();
if (result != OK) {
}
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
if (transactionParams.closureRequested) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
} else {
finish();
}
} else if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
// A path may only have a maximum of 256 characters in CFDP, so this buffer should be sufficient
// for all use-cases.
char baseNameBuf[512]{};
FilesystemParams fparamsSrc(transactionParams.sourceName.data());
size_t baseNameLen = 0;
ReturnValue_t result = destParams.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 > transactionParams.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
transactionParams.destName[destNameSize++] = '/';
std::memcpy(transactionParams.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
transactionParams.destName[destNameSize++] = '\0';
return OK;
}
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result,
const char* info) const {
fsfwParams.eventReporter->forwardEvent(event, 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() {
transactionParams.reset();
destParams.packetListRef.clear();
fsmRes.state = CfdpState::IDLE;
fsmRes.step = TransactionStep::IDLE;
}
ReturnValue_t cfdp::DestHandler::checksumVerification() {
std::array<uint8_t, 1024> buf{};
etl::crc32 crcCalc;
uint64_t currentOffset = 0;
FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
while (currentOffset < transactionParams.fileSize.value()) {
uint64_t readLen;
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
readLen = transactionParams.fileSize.value() - currentOffset;
} else {
readLen = buf.size();
}
if (readLen > 0) {
params.offset = currentOffset;
params.size = readLen;
auto result = destParams.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 == transactionParams.crc) {
transactionParams.conditionCode = ConditionCode::NO_ERROR;
transactionParams.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
} else {
// TODO: Proper error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CRC check for file " << transactionParams.destName.data() << " failed"
<< std::endl;
#endif
transactionParams.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::noticeOfCompletion() {
if (destParams.cfg.indicCfg.transactionFinishedIndicRequired) {
TransactionFinishedParams params(
transactionParams.transactionId, transactionParams.conditionCode,
transactionParams.deliveryCode, transactionParams.deliveryStatus);
destParams.user.transactionFinishedIndication(params);
}
return OK;
}
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
FinishedInfo info(transactionParams.conditionCode, transactionParams.deliveryCode,
transactionParams.deliveryStatus);
FinishPduCreator finishedPdu(transactionParams.pduConf, info);
store_address_t storeId;
uint8_t* dataPtr = nullptr;
ReturnValue_t result =
fsfwParams.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
fsfwParams.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
fsfwParams.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
return result;
}
TmTcMessage msg(storeId);
result = fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &msg);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
#endif
fsfwParams.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 transactionParams.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) { fsfwParams.msgQueue = &queue; }
void cfdp::DestHandler::setEventReporter(EventReportingProxyIF& reporter) {
fsfwParams.eventReporter = &reporter;
}
const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const {
return destParams;
}
StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fsfwParams.tmStore; }
StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fsfwParams.tcStore; }

View File

@ -1,177 +0,0 @@
#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/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/container/DynamicFIFO.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
namespace cfdp {
template <size_t SIZE>
using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>;
using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>;
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
// TODO: Actually, we can provide a better abstraction via interface, which
// allows using something like a bounded map. This simplifies
// the implementation significantly.
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 = 20;
size_t maxFilenameLen = 255;
};
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;
CfdpState state = CfdpState::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& stateMachine();
void setMsgQueue(MessageQueueIF& queue);
void setEventReporter(EventReportingProxyIF& reporter);
ReturnValue_t passPacket(PacketInfo packet);
ReturnValue_t initialize();
[[nodiscard]] CfdpState 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;
metadataOnly = false;
closureRequested = false;
vfsErrorCount = 0;
checksumType = ChecksumType::NULL_CHECKSUM;
}
bool metadataOnly = false;
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
bool closureRequested = false;
uint16_t vfsErrorCount = 0;
std::vector<char> sourceName;
std::vector<char> destName;
cfdp::Fss 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<MessageToUserTlv> msgToUserVec;
TransactionParams transactionParams;
DestHandlerParams destParams;
cfdp::FsfwParams fsfwParams;
FsmResult fsmRes;
ReturnValue_t startTransaction(const MetadataPduReader& reader);
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;
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

@ -1,201 +0,0 @@
#include "PutRequest.h"
using namespace returnvalue;
cfdp::PutRequest::PutRequest(cfdp::EntityId destId, const uint8_t *msgsToUser,
size_t msgsToUserTotalSize, const uint8_t *fsRequests,
size_t fsRequestsSize)
: destId(std::move(destId)),
metadataOnly(true),
msgsToUsersTotalSize(msgsToUserTotalSize),
msgsToUserStartPtr(msgsToUser),
fsRequestsTotalSize(fsRequestsSize),
fsRequestStartPtr(fsRequests) {}
cfdp::PutRequest::PutRequest(cfdp::EntityId destId, cfdp::StringLv &sourceName,
cfdp::StringLv &destName)
: destId(std::move(destId)), sourceName(std::move(sourceName)), destName(std::move(destName)) {}
[[nodiscard]] bool cfdp::PutRequest::isMetadataOnly() const { return metadataOnly; }
ReturnValue_t cfdp::PutRequest::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
if (buffer == nullptr or size == nullptr) {
return FAILED;
}
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
ReturnValue_t result = destId.serializeAsLv(buffer, size, maxSize);
if (result != OK) {
return result;
}
result = SerializeAdapter::serialize(&metadataOnly, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
if (!metadataOnly) {
result = sourceName.serialize(buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result = destName.serialize(buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&hasTransmissionMode, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&transmissionMode, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&hasClosureRequested, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&closureRequested, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
}
result =
SerializeAdapter::serialize(&msgsToUsersTotalSize, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
std::memcpy(*buffer, msgsToUserStartPtr, msgsToUsersTotalSize);
*buffer += msgsToUsersTotalSize;
*size += msgsToUsersTotalSize;
result =
SerializeAdapter::serialize(&fsRequestsTotalSize, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
std::memcpy(*buffer, fsRequestStartPtr, fsRequestsTotalSize);
*buffer += fsRequestsTotalSize;
*size += fsRequestsTotalSize;
return OK;
}
ReturnValue_t cfdp::PutRequest::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
if (buffer == nullptr or size == nullptr) {
return FAILED;
}
ReturnValue_t result = destId.deSerializeFromLv(buffer, size);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&metadataOnly, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
if (!metadataOnly) {
result = sourceName.deSerialize(buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = destName.deSerialize(buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&hasTransmissionMode, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&transmissionMode, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&hasClosureRequested, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&closureRequested, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
}
result = SerializeAdapter::deSerialize(&msgsToUsersTotalSize, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
msgsToUserStartPtr = *buffer;
*buffer += msgsToUsersTotalSize;
*size += msgsToUsersTotalSize;
result = SerializeAdapter::deSerialize(&fsRequestsTotalSize, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
fsRequestStartPtr = *buffer;
*buffer += fsRequestsTotalSize;
*size += fsRequestsTotalSize;
return OK;
}
size_t cfdp::PutRequest::getSerializedSize() const {
// Entity ID LV (1 leading size byte) and the metadata only flag.
size_t baseSize = 1 + destId.getSerializedSize() + 1;
if (!metadataOnly) {
baseSize += sourceName.getSerializedSize() + destName.getSerializedSize() + 4;
}
baseSize += sizeof(msgsToUsersTotalSize) + msgsToUsersTotalSize + sizeof(fsRequestsTotalSize) +
fsRequestsTotalSize;
return baseSize;
}
void cfdp::PutRequest::setSourceAndDestName(cfdp::StringLv &sourceName_,
cfdp::StringLv &destName_) {
metadataOnly = false;
this->sourceName = std::move(sourceName_);
this->destName = std::move(destName_);
}
const cfdp::StringLv &cfdp::PutRequest::getSourceName() const { return sourceName; }
const cfdp::StringLv &cfdp::PutRequest::getDestName() const { return destName; }
const cfdp::EntityId &cfdp::PutRequest::getDestId() const { return destId; }
void cfdp::PutRequest::setDestId(cfdp::EntityId id) { destId = std::move(id); }
void cfdp::PutRequest::setTransmissionMode(cfdp::TransmissionMode transmissionMode_) {
this->transmissionMode = transmissionMode_;
hasTransmissionMode = true;
}
void cfdp::PutRequest::clearTransmissionMode() { hasTransmissionMode = false; }
void cfdp::PutRequest::clearClosureRequest() { hasClosureRequested = false; }
void cfdp::PutRequest::setClosureRequest(bool closureRequested_) {
this->closureRequested = closureRequested_;
hasClosureRequested = true;
}
const uint8_t *cfdp::PutRequest::getMessagesToUser(size_t &totalSize) {
totalSize = this->msgsToUsersTotalSize;
return msgsToUserStartPtr;
}
bool cfdp::PutRequest::getClosureRequested(bool &closureRequested_) const {
if (hasClosureRequested) {
closureRequested_ = this->closureRequested;
}
return hasClosureRequested;
}
bool cfdp::PutRequest::getTransmissionMode(cfdp::TransmissionMode &mode) const {
if (hasTransmissionMode) {
mode = static_cast<cfdp::TransmissionMode>(this->transmissionMode);
}
return hasTransmissionMode;
}

View File

@ -1,82 +0,0 @@
#pragma once
#include <optional>
#include <vector>
#include "fsfw/cfdp/VarLenFields.h"
#include "fsfw/cfdp/tlv/FilestoreRequestTlv.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
namespace cfdp {
class PutRequest : public SerializeIF {
public:
/**
* Metadata only constructor.
* @param destId
* @param msgsToUser
* @param msgsToUserTotalSize
* @param fsRequests
* @param fsRequestsSize
*/
PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
const uint8_t* fsRequests, size_t fsRequestsSize);
/**
* Put request to initiate file transfers. By default, the transmission mode and closure requested
* parameter are not present, thereby being derived from the remote configuration for a
* particular destination ID.
* @param destId
* @param sourceName
* @param destName
*/
PutRequest(EntityId destId, cfdp::StringLv& sourceName, cfdp::StringLv& destName);
/**
* Default constructor for deserialization.
*/
PutRequest() = default;
[[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
[[nodiscard]] size_t getSerializedSize() const override;
void setSourceAndDestName(cfdp::StringLv& sourceName, cfdp::StringLv& destName);
[[nodiscard]] const cfdp::StringLv& getSourceName() const;
[[nodiscard]] const cfdp::StringLv& getDestName() const;
void setTransmissionMode(cfdp::TransmissionMode transmissionMode);
void clearTransmissionMode();
void setClosureRequest(bool closureRequested);
void clearClosureRequest();
const uint8_t* getMessagesToUser(size_t& msgSize);
[[nodiscard]] bool isMetadataOnly() const;
bool getTransmissionMode(TransmissionMode& mode) const;
bool getClosureRequested(bool& closureRequested) const;
[[nodiscard]] const EntityId& getDestId() const;
void setDestId(EntityId id);
private:
EntityId destId;
uint8_t metadataOnly = true;
// Transaction parameters. Omitted if the put request is metadata only.
cfdp::StringLv sourceName;
cfdp::StringLv destName;
bool hasTransmissionMode = false;
uint8_t transmissionMode = TransmissionMode::UNACKNOWLEDGED;
bool hasClosureRequested = false;
uint8_t closureRequested = false;
// Metadata
size_t msgsToUsersTotalSize = 0;
const uint8_t* msgsToUserStartPtr = nullptr;
size_t fsRequestsTotalSize = 0;
const uint8_t* fsRequestStartPtr = nullptr;
};
} // namespace cfdp

View File

@ -16,7 +16,7 @@ class RemoteConfigTableIF {
*/
class OneRemoteConfigProvider : public RemoteConfigTableIF {
public:
explicit OneRemoteConfigProvider(RemoteEntityCfg& cfg) : cfg(cfg) {}
explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
if (remoteId != cfg.remoteId) {
@ -27,7 +27,7 @@ class OneRemoteConfigProvider : public RemoteConfigTableIF {
}
private:
RemoteEntityCfg& cfg;
RemoteEntityCfg cfg;
};
} // namespace cfdp

View File

@ -1,74 +0,0 @@
#include "ReservedMessageParser.h"
#include "fsfw/cfdp/CfdpMessage.h"
#include "fsfw/cfdp/handler/PutRequest.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/QueueFactory.h"
using namespace returnvalue;
cfdp::ReservedMessageParser::ReservedMessageParser(StorageManagerIF& ipcStore,
MessageQueueIF& msgQueue,
MessageQueueId_t userDestination)
: msgQueue(msgQueue), ipcStore(ipcStore), userDestination(userDestination) {}
ReturnValue_t cfdp::ReservedMessageParser::parse(const MessageToUserTlv* msgsToUserArray,
size_t numMsgToUser) {
ReturnValue_t result = returnvalue::OK;
cfdp::StringLv sourceFileName;
cfdp::StringLv destFileName;
PutRequest putRequest;
const uint8_t* currentPtr = nullptr;
size_t deserSize = 0;
bool needToSendPutRequest = false;
for (size_t idx = 0; idx < numMsgToUser; idx++) {
if (&msgsToUserArray[idx] == nullptr) {
continue;
}
uint8_t messageType = 0;
if (msgsToUserArray[idx].isReservedCfdpMessage(messageType, &currentPtr, deserSize)) {
if (messageType == static_cast<uint8_t>(ProxyOpMessageType::PUT_REQUEST)) {
EntityId entityIdLv;
result = entityIdLv.deSerializeFromLv(&currentPtr, &deserSize);
if (result != returnvalue::OK) {
return result;
}
putRequest.setDestId(entityIdLv);
result =
sourceFileName.deSerialize(&currentPtr, &deserSize, SerializeIF::Endianness::NETWORK);
if (result != OK) {
return result;
}
result =
destFileName.deSerialize(&currentPtr, &deserSize, SerializeIF::Endianness::NETWORK);
if (result != OK) {
return result;
}
putRequest.setSourceAndDestName(sourceFileName, destFileName);
needToSendPutRequest = true;
}
}
}
if (needToSendPutRequest) {
store_address_t storeId;
uint8_t* dataPtr;
result = ipcStore.getFreeElement(&storeId, putRequest.getSerializedSize(), &dataPtr);
if (result != OK) {
return result;
}
size_t serLen = 0;
result = putRequest.serialize(&dataPtr, &serLen, putRequest.getSerializedSize(),
SerializeIF::Endianness::MACHINE);
if (result != OK) {
return result;
}
CommandMessage msg;
CfdpMessage::setPutRequest(&msg, storeId);
result = msgQueue.sendMessage(userDestination, &msg);
if (result != OK) {
return result;
}
}
return OK;
}

View File

@ -1,27 +0,0 @@
#pragma once
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
namespace cfdp {
/**
* This class parses messages to user for special CFDP messages and converts them to appropriate
* CFDP requests sent via the IPC store where applicable. It also provides an API to retrieve
* custom messages which are not special CFDP messages from a provided bytestream.
*/
class ReservedMessageParser {
public:
ReservedMessageParser(StorageManagerIF& ipcStore, MessageQueueIF& msgQueue,
MessageQueueId_t userDestination);
ReturnValue_t parse(const MessageToUserTlv* msgsToUserArray, size_t numMsgsToUser);
private:
MessageQueueIF& msgQueue;
StorageManagerIF& ipcStore;
MessageQueueId_t userDestination;
};
} // namespace cfdp

View File

@ -1,376 +0,0 @@
#include "SourceHandler.h"
#include <etl/crc32.h>
#include <array>
#include "fsfw/cfdp/pdu/EofPduCreator.h"
#include "fsfw/cfdp/pdu/FileDataCreator.h"
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
#include "fsfw/filesystem/HasFileSystemIF.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/objectmanager.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
: sourceParams(std::move(params)), fsfwParams(fsfwParams) {
// The entity ID portion of the transaction ID will always remain fixed.
transactionParams.id.entityId = sourceParams.cfg.localId;
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
if (sourceParams.seqCountProvider.bitWidth() == 8) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
} else if (sourceParams.seqCountProvider.bitWidth() == 16) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::TWO_BYTES);
} else if (sourceParams.seqCountProvider.bitWidth() == 32) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::FOUR_BYTES);
} else if (sourceParams.seqCountProvider.bitWidth() == 64) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::EIGHT_BYTES);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "cfdp::SourceHandler: Seq count provider bit width "
<< sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl;
#else
sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n",
sourceParams.seqCountProvider.bitWidth());
#endif
// Yeah, what am I supposed to do here? Can't throw an exception in the FSFW..
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
}
transactionParams.pduConf.seqNum.setValue(0);
}
cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
ReturnValue_t result;
if (step == TransactionStep::IDLE) {
step = TransactionStep::TRANSACTION_START;
}
if (step == TransactionStep::TRANSACTION_START) {
sourceParams.user.transactionIndication(transactionParams.id);
result = checksumGeneration();
if (result != OK) {
addError(result);
}
step = TransactionStep::SENDING_METADATA;
}
if (step == TransactionStep::SENDING_METADATA) {
result = prepareAndSendMetadataPdu();
if (result != OK) {
addError(result);
}
fsmResult.callStatus = CallStatus::CALL_AGAIN;
return fsmResult;
}
if (step == TransactionStep::SENDING_FILE_DATA) {
bool noFdPdu = false;
result = prepareAndSendNextFileDataPdu(noFdPdu);
if (result == OK and !noFdPdu) {
fsmResult.callStatus = CallStatus::CALL_AGAIN;
return fsmResult;
}
}
if (step == TransactionStep::SENDING_EOF) {
result = prepareAndSendEofPdu();
if (result != OK) {
addError(result);
}
if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
sourceParams.user.eofSentIndication(transactionParams.id);
}
if (transactionParams.closureRequested) {
step = TransactionStep::WAIT_FOR_FINISH;
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
} else {
step = TransactionStep::NOTICE_OF_COMPLETION;
fsmResult.callStatus = CallStatus::CALL_AGAIN;
}
return fsmResult;
}
if (step == TransactionStep::WAIT_FOR_FINISH) {
// TODO: In case this is a request with closure, wait for finish.
// Done, issue notice of completion
step = TransactionStep::NOTICE_OF_COMPLETION;
}
if (step == TransactionStep::NOTICE_OF_COMPLETION) {
noticeOfCompletion();
reset();
}
return fsmResult;
}
const cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() {
fsmResult.packetsSent = 0;
fsmResult.errors = 0;
fsmResult.callStatus = CallStatus::DONE;
if (state == cfdp::CfdpState::IDLE) {
return fsmResult;
}
if (state == cfdp::CfdpState::BUSY_CLASS_1_NACKED) {
return fsmNacked();
}
return fsmResult;
}
ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
if (transactionParams.fileSize.value() == 0) {
// NULL checksum for empty file.
transactionParams.crc = 0;
return OK;
}
std::array<uint8_t, 1024> buf{};
etl::crc32 crcCalc;
uint64_t currentOffset = 0;
FileOpParams params(transactionParams.sourceName.data(), transactionParams.fileSize.value());
while (currentOffset < transactionParams.fileSize.value()) {
uint64_t readLen;
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
readLen = transactionParams.fileSize.value() - currentOffset;
} else {
readLen = buf.size();
}
if (readLen > 0) {
params.offset = currentOffset;
params.size = readLen;
auto result = sourceParams.user.vfs.readFromFile(params, buf.data(), buf.size());
if (result != OK) {
addError(result);
return FAILED;
}
crcCalc.add(buf.begin(), buf.begin() + readLen);
}
currentOffset += readLen;
}
transactionParams.crc = crcCalc.value();
return OK;
}
ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
if (state != CfdpState::IDLE) {
return SOURCE_TRANSACTION_PENDING;
}
if (cfg.remoteId != putRequest.getDestId()) {
return WRONG_REMOTE_CFG_ENTITY_ID;
}
if (putRequest.getSourceName().getValueLen() == 0) {
return SOURCE_NAME_EMPTY;
}
if (putRequest.getDestName().getValueLen() == 0) {
return DEST_NAME_EMPTY;
}
const char* srcNamePtr = putRequest.getSourceName().getCString(transactionParams.sourceNameSize);
const char* destNamePtr = putRequest.getDestName().getCString(transactionParams.destNameSize);
std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
// Add 0 termination. The source and dest name size can not be larger than UINT8_MAX, so this
// operation is safe.
transactionParams.sourceName[transactionParams.sourceNameSize] = '\0';
transactionParams.destName[transactionParams.destNameSize] = '\0';
FilesystemParams params(transactionParams.sourceName.data());
if (!sourceParams.user.vfs.fileExists(params)) {
return FILE_DOES_NOT_EXIST;
}
if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
return FILE_SEGMENT_LEN_INVALID;
}
// If transmission mode is not set, use default transmission mode for the remote entity.
if (not putRequest.getTransmissionMode(transactionParams.pduConf.mode)) {
transactionParams.pduConf.mode = cfg.defaultTransmissionMode;
}
// If closure request field is not set, use default option for the remote entity.
if (not putRequest.getClosureRequested(transactionParams.closureRequested)) {
transactionParams.closureRequested = cfg.closureRequested;
}
const EntityId& destId = putRequest.getDestId();
// The width of the source and destination ID must be the same. Use the larger ID value to
// ensure the width is large enough for both IDs
if (destId.getWidth() > transactionParams.pduConf.sourceId.getWidth()) {
transactionParams.pduConf.destId = destId;
transactionParams.pduConf.sourceId.setWidth(destId.getWidth());
} else {
transactionParams.pduConf.destId.setValueAndWidth(transactionParams.pduConf.sourceId.getWidth(),
destId.getValue());
}
// Only used for PDU forwarding, file is sent to file receiver regularly here.
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
transactionParams.pduConf.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement());
transactionParams.id.seqNum = transactionParams.pduConf.seqNum;
if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) {
state = cfdp::CfdpState::BUSY_CLASS_2_ACKED;
} else if (transactionParams.pduConf.mode == TransmissionMode::UNACKNOWLEDGED) {
state = cfdp::CfdpState::BUSY_CLASS_1_NACKED;
}
step = TransactionStep::IDLE;
uint64_t fileSize = 0;
sourceParams.user.vfs.getFileSize(params, fileSize);
transactionParams.pduConf.largeFile = false;
if (fileSize > UINT32_MAX) {
transactionParams.pduConf.largeFile = true;
}
if (fileSize == 0) {
transactionParams.checksumType = ChecksumType::NULL_CHECKSUM;
} else {
transactionParams.checksumType = ChecksumType::CRC_32;
}
transactionParams.fileSize.setFileSize(fileSize, transactionParams.pduConf.largeFile);
transactionParams.progress = 0;
transactionParams.remoteCfg = cfg;
return OK;
}
ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() {
cfdp::StringLv sourceName(transactionParams.sourceName.data(), transactionParams.sourceNameSize);
cfdp::StringLv destName(transactionParams.destName.data(), transactionParams.destNameSize);
auto metadataInfo =
MetadataGenericInfo(transactionParams.closureRequested, transactionParams.checksumType,
transactionParams.fileSize);
auto metadataPdu =
MetadataPduCreator(transactionParams.pduConf, metadataInfo, sourceName, destName, nullptr, 0);
ReturnValue_t result = sendGenericPdu(metadataPdu);
if (result != OK) {
return result;
}
// Advance FSM if everything works
step = TransactionStep::SENDING_FILE_DATA;
return OK;
}
ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu(bool& noFileDataPdu) {
cfdp::Fss offset(transactionParams.progress);
uint64_t readLen;
uint64_t fileSize = transactionParams.fileSize.value();
noFileDataPdu = false;
if (fileSize == 0) {
// We are done, no need to send file data PDUs for an empty file.
step = TransactionStep::SENDING_EOF;
noFileDataPdu = true;
return OK;
}
if (fileSize < transactionParams.remoteCfg.maxFileSegmentLen) {
readLen = transactionParams.fileSize.value();
} else {
if (transactionParams.progress + transactionParams.remoteCfg.maxFileSegmentLen > fileSize) {
readLen = fileSize - transactionParams.progress;
} else {
readLen = transactionParams.remoteCfg.maxFileSegmentLen;
}
}
FileOpParams fileParams(transactionParams.sourceName.data(), readLen);
fileParams.offset = transactionParams.progress;
ReturnValue_t result =
sourceParams.user.vfs.readFromFile(fileParams, fileBuf.data(), fileBuf.size());
if (result != returnvalue::OK) {
addError(result);
return result;
}
auto fileDataInfo = FileDataInfo(offset, fileBuf.data(), readLen);
auto fileDataPdu = FileDataCreator(transactionParams.pduConf, fileDataInfo);
result = sendGenericPdu(fileDataPdu);
if (result != OK) {
return result;
}
transactionParams.progress += readLen;
if (transactionParams.progress >= fileSize) {
// Advance FSM after all file data PDUs were sent.
step = TransactionStep::SENDING_EOF;
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
auto eofInfo =
EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize);
auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
ReturnValue_t result = sendGenericPdu(eofPdu);
if (result != OK) {
return result;
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::initialize() {
if (fsfwParams.tmStore == nullptr) {
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (fsfwParams.tmStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.tcStore == nullptr) {
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (fsfwParams.tcStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.msgQueue == nullptr) {
return FAILED;
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
uint8_t* dataPtr;
store_address_t storeId;
ReturnValue_t result =
fsfwParams.tmStore->getFreeElement(&storeId, pdu.getSerializedSize(), &dataPtr);
if (result != OK) {
addError(result);
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
if (result == StorageManagerIF::DATA_STORAGE_FULL) {
return TM_STORE_FULL;
}
return result;
}
size_t serializedLen = 0;
result = pdu.serializeBe(dataPtr, serializedLen, pdu.getSerializedSize());
if (result != OK) {
addError(result);
return result;
}
TmTcMessage tmMsg(storeId);
result =
fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg);
if (result != OK) {
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
}
if (result == MessageQueueIF::FULL) {
return TARGET_MSG_QUEUE_FULL;
} else if (result == OK) {
fsmResult.packetsSent += 1;
}
return result;
}
ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() {
if (sourceParams.cfg.indicCfg.transactionFinishedIndicRequired) {
cfdp::TransactionFinishedParams params(transactionParams.id, ConditionCode::NO_ERROR,
FileDeliveryCode::DATA_COMPLETE,
FileDeliveryStatus::RETAINED_IN_FILESTORE);
sourceParams.user.transactionFinishedIndication(params);
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::reset() {
step = TransactionStep::IDLE;
state = cfdp::CfdpState::IDLE;
fsmResult.callStatus = CallStatus::DONE;
transactionParams.reset();
return OK;
}
cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }
void cfdp::SourceHandler::addError(ReturnValue_t error) {
if (fsmResult.errors < fsmResult.errorCodes.size()) {
fsmResult.errorCodes[fsmResult.errors] = error;
fsmResult.errors++;
fsmResult.result = error;
}
}

View File

@ -1,110 +0,0 @@
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
#include <cstdint>
#include <vector>
#include "UserBase.h"
#include "defs.h"
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/handler/PutRequest.h"
#include "fsfw/cfdp/handler/mib.h"
#include "fsfw/events/EventReportingProxyIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
#include "fsfw/util/ProvidesSeqCountIF.h"
namespace cfdp {
struct SourceHandlerParams {
SourceHandlerParams(LocalEntityCfg cfg, UserBase& user, ProvidesSeqCountIF& seqCountProvider)
: cfg(std::move(cfg)), user(user), seqCountProvider(seqCountProvider) {}
LocalEntityCfg cfg;
UserBase& user;
ProvidesSeqCountIF& seqCountProvider;
};
class SourceHandler {
public:
enum class TransactionStep : uint8_t {
IDLE = 0,
TRANSACTION_START = 1,
SENDING_METADATA = 3,
SENDING_FILE_DATA = 4,
SENDING_EOF = 5,
WAIT_FOR_ACK = 6,
WAIT_FOR_FINISH = 7,
NOTICE_OF_COMPLETION = 8
};
struct FsmResult {
public:
ReturnValue_t result = returnvalue::OK;
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
CfdpState state = CfdpState::IDLE;
uint32_t packetsSent = 0;
uint8_t errors = 0;
std::array<ReturnValue_t, 3> errorCodes = {};
};
SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams);
[[nodiscard]] CfdpState getState() const;
[[nodiscard]] TransactionStep getStep() const;
/**
* Pass a put request to the source handler, which might initiate a CFDP transaction and start
* the state machine
* @return
*/
ReturnValue_t transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg);
const FsmResult& stateMachine();
ReturnValue_t initialize();
private:
struct TransactionParams {
uint32_t crc{};
std::array<char, UINT8_MAX + 1> sourceName{};
size_t sourceNameSize = 0;
std::array<char, UINT8_MAX + 1> destName{};
size_t destNameSize = 0;
cfdp::Fss fileSize;
size_t progress = 0;
bool closureRequested = false;
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
RemoteEntityCfg remoteCfg;
PduConfig pduConf;
cfdp::TransactionId id{};
void reset() {
sourceNameSize = 0;
destNameSize = 0;
fileSize.setFileSize(0, false);
progress = 0;
closureRequested = false;
}
} transactionParams;
cfdp::CfdpState state = cfdp::CfdpState::IDLE;
TransactionStep step = TransactionStep::IDLE;
std::array<uint8_t, 4096> fileBuf{};
SourceHandlerParams sourceParams;
cfdp::FsfwParams fsfwParams;
FsmResult fsmResult;
FsmResult& fsmNacked();
ReturnValue_t checksumGeneration();
ReturnValue_t prepareAndSendMetadataPdu();
ReturnValue_t prepareAndSendNextFileDataPdu(bool& noFileDataPdu);
ReturnValue_t prepareAndSendEofPdu();
ReturnValue_t noticeOfCompletion();
ReturnValue_t reset();
[[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu);
void addError(ReturnValue_t error);
};
} // namespace cfdp
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H

View File

@ -6,7 +6,6 @@
#include <vector>
#include "StatusReportIF.h"
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/VarLenFields.h"
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
@ -28,14 +27,14 @@ struct TransactionFinishedParams {
};
struct MetadataRecvdParams {
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId, Fss fileSize)
: id(id), sourceId(sourceId), fileSize(std::move(fileSize)) {}
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId)
: id(id), sourceId(sourceId) {}
const TransactionId& id;
const EntityId& sourceId;
Fss fileSize{};
uint64_t fileSize = 0;
const char* sourceFileName = "";
const char* destFileName = "";
size_t numberOfMsgsToUser = 0;
size_t msgsToUserLen = 0;
const MessageToUserTlv* msgsToUserArray = nullptr;
};
@ -66,7 +65,6 @@ struct FileSegmentRecvdParams {
*/
class UserBase {
friend class DestHandler;
friend class SourceHandler;
public:
explicit UserBase(HasFileSystemIF& vfs);

View File

@ -1,76 +1,9 @@
#ifndef FSFW_CFDP_HANDLER_DEFS_H
#define FSFW_CFDP_HANDLER_DEFS_H
#include <etl/list.h>
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
namespace cfdp {
enum class CfdpState { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP;
static constexpr uint8_t CID = CLASS_ID::CFDP_HANDLER;
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;
};
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;
};
template <size_t SIZE>
using PacketInfoList = etl::list<PacketInfo, SIZE>;
using PacketInfoListBase = etl::ilist<PacketInfo>;
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
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);
//! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode.
static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent(SSID, 5, severity::LOW);
} // namespace events
static constexpr ReturnValue_t SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0);
static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = returnvalue::makeCode(CID, 1);
static constexpr ReturnValue_t FILE_SEGMENT_LEN_INVALID = returnvalue::makeCode(CID, 2);
static constexpr ReturnValue_t SOURCE_NAME_EMPTY = returnvalue::makeCode(CID, 3);
static constexpr ReturnValue_t DEST_NAME_EMPTY = returnvalue::makeCode(CID, 4);
static constexpr ReturnValue_t WRONG_REMOTE_CFG_ENTITY_ID = returnvalue::makeCode(CID, 5);
static constexpr ReturnValue_t TARGET_MSG_QUEUE_FULL = returnvalue::makeCode(CID, 6);
static constexpr ReturnValue_t TM_STORE_FULL = returnvalue::makeCode(CID, 7);
} // namespace cfdp
}
#endif // FSFW_CFDP_HANDLER_DEFS_H

View File

@ -27,15 +27,14 @@ struct LocalEntityCfg {
};
struct RemoteEntityCfg {
RemoteEntityCfg() = default;
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
EntityId remoteId;
size_t maxFileSegmentLen = 1024;
size_t maxFileSegmentLen = 2048;
bool closureRequested = false;
bool crcOnTransmission = false;
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
uint8_t version = CFDP_VERSION_2;
const uint8_t version = CFDP_VERSION_2;
};
} // namespace cfdp

View File

@ -17,7 +17,7 @@ target_sources(
FinishedInfo.cpp
FinishedPduCreator.cpp
FinishedPduReader.cpp
MetadataGenericInfo.cpp
MetadataInfo.cpp
MetadataPduCreator.cpp
MetadataPduReader.cpp
KeepAlivePduCreator.cpp

View File

@ -1,13 +1,8 @@
#include "EofInfo.h"
#include <utility>
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
EntityIdTlv* faultLoc)
: conditionCode(conditionCode),
checksum(checksum),
fileSize(std::move(fileSize)),
faultLoc(faultLoc) {}
: conditionCode(conditionCode), checksum(checksum), fileSize(fileSize), faultLoc(faultLoc) {}
EofInfo::EofInfo(EntityIdTlv* faultLoc)
: conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
@ -21,15 +16,15 @@ cfdp::ConditionCode EofInfo::getConditionCode() const { return conditionCode; }
EntityIdTlv* EofInfo::getFaultLoc() const { return faultLoc; }
cfdp::Fss& EofInfo::getFileSize() { return fileSize; }
cfdp::FileSize& EofInfo::getFileSize() { return fileSize; }
void EofInfo::setChecksum(uint32_t checksum_) { this->checksum = checksum_; }
void EofInfo::setChecksum(uint32_t checksum) { this->checksum = checksum; }
void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode_) {
this->conditionCode = conditionCode_;
void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
this->conditionCode = conditionCode;
}
void EofInfo::setFaultLoc(EntityIdTlv* faultLoc_) { this->faultLoc = faultLoc_; }
void EofInfo::setFaultLoc(EntityIdTlv* faultLoc) { this->faultLoc = faultLoc; }
size_t EofInfo::getSerializedSize(bool fssLarge) {
// Condition code + spare + 4 byte checksum
@ -47,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
return size;
}
ReturnValue_t EofInfo::setFileSize(size_t fileSize_, bool isLarge) {
return this->fileSize.setFileSize(fileSize_, isLarge);
ReturnValue_t EofInfo::setFileSize(size_t fileSize, bool isLarge) {
return this->fileSize.setFileSize(fileSize, isLarge);
}

View File

@ -1,14 +1,14 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#include "../Fss.h"
#include "../FileSize.h"
#include "../definitions.h"
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
struct EofInfo {
public:
explicit EofInfo(EntityIdTlv* faultLoc = nullptr);
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
EntityIdTlv* faultLoc = nullptr);
size_t getSerializedSize(bool fssLarge = false);
@ -17,7 +17,7 @@ struct EofInfo {
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
cfdp::Fss& getFileSize();
cfdp::FileSize& getFileSize();
void setChecksum(uint32_t checksum);
void setConditionCode(cfdp::ConditionCode conditionCode);
void setFaultLoc(EntityIdTlv* faultLoc);
@ -26,7 +26,7 @@ struct EofInfo {
private:
cfdp::ConditionCode conditionCode;
uint32_t checksum;
cfdp::Fss fileSize;
cfdp::FileSize fileSize;
EntityIdTlv* faultLoc = nullptr;
};

View File

@ -37,7 +37,7 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
*buffer += segmentMetadataLen;
*size += segmentMetadataLen;
}
cfdp::Fss& offset = info.getOffset();
cfdp::FileSize& offset = info.getOffset();
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;

View File

@ -1,9 +1,9 @@
#include "FileDataInfo.h"
#include <utility>
FileDataInfo::FileDataInfo(cfdp::FileSize &offset, const uint8_t *fileData, size_t fileSize)
: offset(offset), fileData(fileData), fileSize(fileSize) {}
FileDataInfo::FileDataInfo(cfdp::Fss offset, const uint8_t *fileData, size_t fileSize)
: offset(std::move(offset)), fileData(fileData), fileSize(fileSize) {}
FileDataInfo::FileDataInfo(cfdp::FileSize &offset) : offset(offset) {}
void FileDataInfo::setSegmentMetadataFlag(bool enable) {
if (enable) {
@ -71,7 +71,7 @@ const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
return segmentMetadata;
}
cfdp::Fss &FileDataInfo::getOffset() { return offset; }
cfdp::FileSize &FileDataInfo::getOffset() { return offset; }
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
this->recContState = recContState;

View File

@ -1,17 +1,17 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#include <fsfw/cfdp/Fss.h>
#include <fsfw/cfdp/FileSize.h>
#include <fsfw/cfdp/definitions.h>
class FileDataInfo {
public:
FileDataInfo() = default;
FileDataInfo(cfdp::Fss offset, const uint8_t* fileData, size_t fileSize);
explicit FileDataInfo(cfdp::FileSize& offset);
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
[[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
cfdp::Fss& getOffset();
cfdp::FileSize& getOffset();
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
void setFileData(const uint8_t* fileData, size_t fileSize);
@ -33,7 +33,7 @@ class FileDataInfo {
private:
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
cfdp::Fss offset;
cfdp::FileSize& offset;
const uint8_t* fileData = nullptr;
size_t fileSize = 0;
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;

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() - 1) << 4) |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
pduConf.seqNum.getWidth();
*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) & 0b111) + 1);
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
}
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
}
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
@ -103,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons
}
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
void *sourcePtr) {
void *sourcePtr) const {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
field->setValueAndWidth(width, *fieldTyped);
field->setValue(width, *fieldTyped);
break;
}
case (cfdp::WidthInBytes::TWO_BYTES): {
@ -115,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
field->setValueAndWidth(width, fieldTyped);
field->setValue(width, fieldTyped);
break;
}
case (cfdp::WidthInBytes::FOUR_BYTES): {
@ -123,15 +123,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
field->setValueAndWidth(width, fieldTyped);
break;
}
case (cfdp::WidthInBytes::EIGHT_BYTES): {
uint64_t fieldTyped = 0;
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
field->setValueAndWidth(width, fieldTyped);
field->setValue(width, fieldTyped);
break;
}
}

View File

@ -1,6 +1,6 @@
#include "KeepAlivePduCreator.h"
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::Fss &progress)
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress)
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
updateDirectiveFieldLen();
}

View File

@ -1,12 +1,12 @@
#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
class KeepAlivePduCreator : public FileDirectiveCreator {
public:
KeepAlivePduCreator(PduConfig& conf, cfdp::Fss& progress);
KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress);
void updateDirectiveFieldLen();
@ -16,7 +16,7 @@ class KeepAlivePduCreator : public FileDirectiveCreator {
Endianness streamEndianness) const override;
private:
cfdp::Fss& progress;
cfdp::FileSize& progress;
};
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */

View File

@ -1,6 +1,7 @@
#include "KeepAlivePduReader.h"
KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress)
KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize,
cfdp::FileSize& progress)
: FileDirectiveReader(pduBuf, maxSize), progress(progress) {}
ReturnValue_t KeepAlivePduReader::parseData() {
@ -14,4 +15,4 @@ ReturnValue_t KeepAlivePduReader::parseData() {
return progress.deSerialize(&buffer, &remLen, getEndianness());
}
cfdp::Fss& KeepAlivePduReader::getProgress() { return progress; }
cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; }

View File

@ -1,19 +1,19 @@
#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_
#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
class KeepAlivePduReader : public FileDirectiveReader {
public:
KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress);
KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress);
ReturnValue_t parseData() override;
cfdp::Fss& getProgress();
cfdp::FileSize& getProgress();
private:
cfdp::Fss& progress;
cfdp::FileSize& progress;
};
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */

View File

@ -1,35 +0,0 @@
#include "MetadataGenericInfo.h"
MetadataGenericInfo::MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType,
cfdp::Fss fileSize)
: MetadataGenericInfo(std::move(fileSize)) {
this->closureRequested = closureRequested;
this->checksumType = checksumType;
}
MetadataGenericInfo::MetadataGenericInfo(cfdp::Fss fileSize) : fileSize(std::move(fileSize)) {}
cfdp::ChecksumType MetadataGenericInfo::getChecksumType() const { return checksumType; }
void MetadataGenericInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
checksumType = checksumType_;
}
bool MetadataGenericInfo::isClosureRequested() const { return closureRequested; }
void MetadataGenericInfo::setClosureRequested(bool closureRequested_) {
closureRequested = closureRequested_;
}
const cfdp::Fss& MetadataGenericInfo::getFileSize() const { return fileSize; }
size_t MetadataGenericInfo::getSerializedSize(bool fssLarge) {
// 1 byte + minimal FSS 4 bytes
size_t size = 5;
if (fssLarge) {
size += 4;
}
return size;
}
cfdp::Fss& MetadataGenericInfo::getMutFileSize() { return fileSize; }

View File

@ -1,35 +0,0 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#include <optional>
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/tlv/Lv.h"
#include "fsfw/cfdp/tlv/StringLv.h"
#include "fsfw/cfdp/tlv/Tlv.h"
class MetadataGenericInfo {
public:
MetadataGenericInfo() = default;
explicit MetadataGenericInfo(cfdp::Fss fileSize);
MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::Fss fileSize);
static size_t getSerializedSize(bool fssLarge = false);
[[nodiscard]] cfdp::ChecksumType getChecksumType() const;
void setChecksumType(cfdp::ChecksumType checksumType);
[[nodiscard]] bool isClosureRequested() const;
void setClosureRequested(bool closureRequested = false);
[[nodiscard]] const cfdp::Fss& getFileSize() const;
cfdp::Fss& getMutFileSize();
private:
bool closureRequested = false;
cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
cfdp::Fss fileSize;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */

View File

@ -0,0 +1,103 @@
#include "MetadataInfo.h"
MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType,
cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
cfdp::StringLv& destFileName)
: MetadataInfo(fileSize, sourceFileName, destFileName) {
this->closureRequested = closureRequested;
this->checksumType = checksumType;
}
MetadataInfo::MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
cfdp::StringLv& destFileName)
: fileSize(fileSize), sourceFileName(sourceFileName), destFileName(destFileName) {}
void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray_, std::optional<size_t> optionsLen_,
std::optional<size_t> maxOptionsLen_) {
this->optionsArray = optionsArray_;
if (maxOptionsLen_) {
this->maxOptionsLen = maxOptionsLen_.value();
}
if (optionsLen_) {
this->optionsLen = optionsLen_.value();
}
}
cfdp::ChecksumType MetadataInfo::getChecksumType() const { return checksumType; }
void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
checksumType = checksumType_;
}
bool MetadataInfo::isClosureRequested() const { return closureRequested; }
void MetadataInfo::setClosureRequested(bool closureRequested_) {
closureRequested = closureRequested_;
}
cfdp::StringLv& MetadataInfo::getDestFileName() { return destFileName; }
cfdp::FileSize& MetadataInfo::getFileSize() { return fileSize; }
ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray_, size_t* optionsLen_,
size_t* maxOptsLen) {
if (optionsArray_ == nullptr or optionsArray == nullptr) {
return returnvalue::FAILED;
}
*optionsArray_ = optionsArray;
if (optionsLen_ != nullptr) {
*optionsLen_ = this->optionsLen;
}
if (maxOptsLen != nullptr) {
*maxOptsLen = this->maxOptionsLen;
}
return returnvalue::OK;
}
bool MetadataInfo::hasOptions() const {
if (optionsArray != nullptr and optionsLen > 0) {
return true;
}
return false;
}
bool MetadataInfo::canHoldOptions() const {
if (optionsArray != nullptr and maxOptionsLen > 0) {
return true;
}
return false;
}
size_t MetadataInfo::getSerializedSize(bool fssLarge) {
// 1 byte + minimal FSS 4 bytes
size_t size = 5;
if (fssLarge) {
size += 4;
}
size += sourceFileName.getSerializedSize();
size += destFileName.getSerializedSize();
if (hasOptions()) {
for (size_t idx = 0; idx < optionsLen; idx++) {
size += optionsArray[idx]->getSerializedSize();
}
}
return size;
}
void MetadataInfo::setDestFileName(cfdp::StringLv& destFileName_) {
this->destFileName = destFileName_;
}
void MetadataInfo::setSourceFileName(cfdp::StringLv& sourceFileName_) {
this->sourceFileName = sourceFileName_;
}
size_t MetadataInfo::getMaxOptionsLen() const { return maxOptionsLen; }
void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen_) { this->maxOptionsLen = maxOptionsLen_; }
size_t MetadataInfo::getOptionsLen() const { return optionsLen; }
void MetadataInfo::setOptionsLen(size_t optionsLen_) { this->optionsLen = optionsLen_; }
cfdp::StringLv& MetadataInfo::getSourceFileName() { return sourceFileName; }

View File

@ -0,0 +1,55 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#include <optional>
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/tlv/Lv.h"
#include "fsfw/cfdp/tlv/StringLv.h"
#include "fsfw/cfdp/tlv/Tlv.h"
class MetadataInfo {
public:
MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
cfdp::StringLv& destFileName);
MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::FileSize& fileSize,
cfdp::StringLv& sourceFileName, cfdp::StringLv& destFileName);
size_t getSerializedSize(bool fssLarge = false);
void setOptionsArray(cfdp::Tlv** optionsArray, std::optional<size_t> optionsLen,
std::optional<size_t> maxOptionsLen);
[[nodiscard]] cfdp::ChecksumType getChecksumType() const;
void setChecksumType(cfdp::ChecksumType checksumType);
[[nodiscard]] bool isClosureRequested() const;
void setClosureRequested(bool closureRequested = false);
void setDestFileName(cfdp::StringLv& destFileName);
void setSourceFileName(cfdp::StringLv& sourceFileName);
cfdp::StringLv& getDestFileName();
cfdp::StringLv& getSourceFileName();
cfdp::FileSize& getFileSize();
[[nodiscard]] bool hasOptions() const;
[[nodiscard]] bool canHoldOptions() const;
ReturnValue_t getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, size_t* maxOptsLen);
void setOptionsLen(size_t optionsLen);
[[nodiscard]] size_t getOptionsLen() const;
void setMaxOptionsLen(size_t maxOptionsLen);
[[nodiscard]] size_t getMaxOptionsLen() const;
private:
bool closureRequested = false;
cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
cfdp::FileSize& fileSize;
cfdp::StringLv& sourceFileName;
cfdp::StringLv& destFileName;
cfdp::Tlv** optionsArray = nullptr;
size_t optionsLen = 0;
size_t maxOptionsLen = 0;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */

View File

@ -1,26 +1,12 @@
#include "MetadataPduCreator.h"
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataGenericInfo &info,
cfdp::StringLv &srcFileName, cfdp::StringLv &destFileName,
cfdp::Tlv **optionsArray, size_t optionsLen)
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5),
info(info),
srcFileName(srcFileName),
destFileName(destFileName),
optionsArray(optionsArray),
optionsLen(optionsLen) {
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info)
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) {
updateDirectiveFieldLen();
}
void MetadataPduCreator::updateDirectiveFieldLen() {
size_t dirFieldLen = MetadataGenericInfo::getSerializedSize(HeaderCreator::getLargeFileFlag()) +
srcFileName.getSerializedSize() + destFileName.getSerializedSize();
if (optionsLen > 0 and optionsArray != nullptr) {
for (size_t idx = 0; idx < optionsLen; idx++) {
dirFieldLen += optionsArray[idx]->getSerializedSize();
}
}
setDirectiveDataFieldLen(dirFieldLen);
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
}
size_t MetadataPduCreator::getSerializedSize() const {
@ -43,18 +29,21 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
if (result != returnvalue::OK) {
return result;
}
result = srcFileName.serialize(buffer, size, maxSize, streamEndianness);
result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = destFileName.serialize(buffer, size, maxSize, streamEndianness);
result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
if (optionsLen > 0 and optionsArray != nullptr) {
for (size_t idx = 0; idx < optionsLen; idx++) {
result = optionsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
if (info.hasOptions()) {
cfdp::Tlv **optsArray = nullptr;
size_t optsLen = 0;
info.getOptions(&optsArray, &optsLen, nullptr);
for (size_t idx = 0; idx < optsLen; idx++) {
result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
@ -62,5 +51,3 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
}
return result;
}
const cfdp::StringLv &MetadataPduCreator::getSourceFileName() const { return srcFileName; }
const cfdp::StringLv &MetadataPduCreator::getDestFileName() const { return destFileName; }

View File

@ -2,30 +2,22 @@
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
#include "fsfw/cfdp/pdu/MetadataInfo.h"
class MetadataPduCreator : public FileDirectiveCreator {
public:
MetadataPduCreator(PduConfig& conf, MetadataGenericInfo& info, cfdp::StringLv& srcFileName,
cfdp::StringLv& destFileName, cfdp::Tlv** optionsArray, size_t optionsLen);
MetadataPduCreator(PduConfig& conf, MetadataInfo& info);
void updateDirectiveFieldLen();
[[nodiscard]] size_t getSerializedSize() const override;
const cfdp::StringLv& getSourceFileName() const;
const cfdp::StringLv& getDestFileName() const;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
using FileDirectiveCreator::serialize;
private:
MetadataGenericInfo& info;
cfdp::StringLv& srcFileName;
cfdp::StringLv& destFileName;
cfdp::Tlv** optionsArray;
size_t optionsLen;
MetadataInfo& info;
};
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */

View File

@ -1,15 +1,9 @@
#include "MetadataPduReader.h"
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize,
MetadataGenericInfo& info, cfdp::Tlv* optionsArray,
size_t optArrayMaxSize)
: FileDirectiveReader(pduBuf, maxSize),
info(info),
optionArray(optionsArray),
optionArrayMaxSize(optArrayMaxSize) {}
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info)
: FileDirectiveReader(pduBuf, maxSize), info(info) {}
ReturnValue_t MetadataPduReader::parseData() {
parsedOptions = 0;
ReturnValue_t result = FileDirectiveReader::parseData();
if (result != returnvalue::OK) {
return result;
@ -25,43 +19,39 @@ ReturnValue_t MetadataPduReader::parseData() {
remSize -= 1;
buf += 1;
auto endianness = getEndianness();
result = info.getMutFileSize().deSerialize(&buf, &remSize, endianness);
result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
result = srcFileName.deSerialize(&buf, &remSize, endianness);
result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
result = destFileName.deSerialize(&buf, &remSize, endianness);
result = info.getDestFileName().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
info.setOptionsLen(0);
if (remSize > 0) {
if (optionArrayMaxSize == 0 or optionArray == nullptr) {
if (not info.canHoldOptions()) {
return cfdp::METADATA_CANT_PARSE_OPTIONS;
}
cfdp::Tlv** optionsArray = nullptr;
size_t optsMaxLen = 0;
size_t optsIdx = 0;
info.getOptions(&optionsArray, nullptr, &optsMaxLen);
while (remSize > 0) {
if (optsIdx > optionArrayMaxSize) {
if (optsIdx > optsMaxLen) {
return cfdp::METADATA_CANT_PARSE_OPTIONS;
}
result = optionArray[optsIdx].deSerialize(&buf, &remSize, endianness);
result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
optsIdx++;
}
parsedOptions = optsIdx;
info.setOptionsLen(optsIdx);
}
return result;
}
size_t MetadataPduReader::getNumberOfParsedOptions() const { return parsedOptions; }
const cfdp::StringLv& MetadataPduReader::getSourceFileName() const { return srcFileName; }
const cfdp::StringLv& MetadataPduReader::getDestFileName() const { return destFileName; }
const MetadataGenericInfo& MetadataPduReader::getGenericInfo() const { return info; }

View File

@ -2,28 +2,16 @@
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
#include "fsfw/cfdp/pdu/MetadataInfo.h"
class MetadataPduReader : public FileDirectiveReader {
public:
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataGenericInfo& info,
cfdp::Tlv* optionsArray, size_t optArrayMaxSize);
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
ReturnValue_t parseData() override;
[[nodiscard]] const MetadataGenericInfo& getGenericInfo() const;
[[nodiscard]] const cfdp::StringLv& getSourceFileName() const;
[[nodiscard]] const cfdp::StringLv& getDestFileName() const;
[[nodiscard]] size_t getNumberOfParsedOptions() const;
private:
cfdp::StringLv srcFileName;
cfdp::StringLv destFileName;
MetadataGenericInfo& info;
cfdp::Tlv* optionArray;
size_t optionArrayMaxSize;
size_t parsedOptions = 0;
MetadataInfo& info;
};
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */

View File

@ -1,6 +1,6 @@
#include "NakInfo.h"
NakInfo::NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope)
NakInfo::NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope)
: startOfScope(startOfScope), endOfScope(endOfScope) {}
size_t NakInfo::getSerializedSize(bool fssLarge) {
@ -57,9 +57,9 @@ void NakInfo::setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmen
}
}
cfdp::Fss& NakInfo::getStartOfScope() { return startOfScope; }
cfdp::FileSize& NakInfo::getStartOfScope() { return startOfScope; }
cfdp::Fss& NakInfo::getEndOfScope() { return endOfScope; }
cfdp::FileSize& NakInfo::getEndOfScope() { return endOfScope; }
size_t NakInfo::getSegmentRequestsLen() const { return segmentRequestsLen; }

View File

@ -3,21 +3,21 @@
#include <utility>
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/FileSize.h"
class NakInfo {
public:
using SegmentRequest = std::pair<cfdp::Fss, cfdp::Fss>;
using SegmentRequest = std::pair<cfdp::FileSize, cfdp::FileSize>;
NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope);
NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope);
void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen,
size_t* maxSegmentRequestLen);
size_t getSerializedSize(bool fssLarge = false);
cfdp::Fss& getStartOfScope();
cfdp::Fss& getEndOfScope();
cfdp::FileSize& getStartOfScope();
cfdp::FileSize& getEndOfScope();
bool hasSegmentRequests() const;
bool canHoldSegmentRequests() const;
@ -31,8 +31,8 @@ class NakInfo {
void setSegmentRequestLen(size_t readLen);
private:
cfdp::Fss startOfScope;
cfdp::Fss endOfScope;
cfdp::FileSize startOfScope;
cfdp::FileSize endOfScope;
SegmentRequest* segmentRequests = nullptr;
size_t segmentRequestsLen = 0;
size_t maxSegmentRequestsLen = 0;

View File

@ -4,7 +4,7 @@
#include <vector>
#include "NakInfo.h"
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"

View File

@ -105,8 +105,7 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
* @return
*/
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
void* sourcePtr);
void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const;
void* sourceIdRaw = nullptr;
void* seqNumRaw = nullptr;
void* destIdRaw = nullptr;

View File

@ -8,5 +8,4 @@ target_sources(
StringLv.cpp
FlowLabelTlv.cpp
MessageToUserTlv.cpp
FaultHandlerOverrideTlv.cpp
ReservedMessageCreator.cpp)
FaultHandlerOverrideTlv.cpp)

View File

@ -14,6 +14,23 @@ cfdp::Lv::Lv(const std::vector<uint8_t>& data) : value(data.data(), data.size(),
cfdp::Lv::Lv() : value(static_cast<uint8_t*>(nullptr), 0, true) {}
cfdp::Lv::Lv(const Lv& other)
: value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
if (other.value.getSerializedSize() - 1 > 0) {
zeroLen = false;
}
}
cfdp::Lv& cfdp::Lv::operator=(const Lv& other) {
size_t otherSize = 0;
auto* otherVal = const_cast<uint8_t*>(other.getValue(&otherSize));
if (otherVal == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setConstBuffer(otherVal, otherSize);
return *this;
}
ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
if (maxSize < 1) {
@ -32,8 +49,10 @@ ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize
}
size_t cfdp::Lv::getSerializedSize() const {
if (zeroLen or value.getConstBuffer() == nullptr) {
if (zeroLen) {
return 1;
} else if (value.getConstBuffer() == nullptr) {
return 0;
}
return value.getSerializedSize();
}
@ -66,34 +85,7 @@ ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size,
const uint8_t* cfdp::Lv::getValue(size_t* size) const {
if (size != nullptr) {
// Length without length field
*size = getSerializedSize() - 1;
*size = value.getSerializedSize() - 1;
}
return value.getConstBuffer();
}
cfdp::Lv::Lv(cfdp::Lv&& other) noexcept
: value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
if (other.value.getSerializedSize() - 1 > 0) {
zeroLen = false;
}
// Leave other class in intact state.
other.zeroLen = false;
other.value = SerialBufferAdapter<uint8_t>();
}
cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
size_t otherSize = 0;
this->zeroLen = false;
auto* otherVal = const_cast<uint8_t*>(other.getValue(&otherSize));
if (otherVal == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setConstBuffer(otherVal, otherSize);
// Leave other class in intact state.
other.zeroLen = false;
other.value = SerialBufferAdapter<uint8_t>();
return *this;
}
size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }
bool cfdp::Lv::isEmpty() const { return zeroLen; }

View File

@ -18,12 +18,8 @@ class Lv : public SerializeIF {
Lv(const uint8_t* value, size_t size);
Lv();
// Semantically, this class is a zero-copy helper, so the copy ctor and copy assigment do not
// really make sense here.
Lv(const Lv&) = delete;
Lv& operator=(const Lv&) = delete;
Lv(Lv&&) noexcept;
Lv& operator=(Lv&&) noexcept;
Lv(const Lv&);
Lv& operator=(const Lv&);
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
@ -40,8 +36,6 @@ class Lv : public SerializeIF {
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
size_t getValueLen() const;
/**
* Get value field and its size.
* @param size Optionally retrieve size. Size will be the size of the actual value field
@ -50,8 +44,6 @@ class Lv : public SerializeIF {
*/
const uint8_t* getValue(size_t* size) const;
bool isEmpty() const;
private:
bool zeroLen = true;
SerialBufferAdapter<uint8_t> value;

View File

@ -7,22 +7,3 @@ MessageToUserTlv::MessageToUserTlv() : Tlv() {}
MessageToUserTlv::MessageToUserTlv(const std::vector<uint8_t>& data)
: Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {}
MessageToUserTlv::MessageToUserTlv(const uint8_t* value, size_t size)
: Tlv(cfdp::TlvType::MSG_TO_USER, value, size) {}
bool MessageToUserTlv::isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
size_t& msgLen) const {
if (cfdp::Tlv::getLengthField() < 5) {
return false;
}
if (std::strncmp(reinterpret_cast<const char*>(getValue()), "cfdp", 4) == 0) {
messageType = getValue()[4];
if (msgDataStart != nullptr) {
*msgDataStart = getValue() + 5;
}
msgLen = cfdp::Tlv::getSerializedSize() - 5;
return true;
}
return false;
}

View File

@ -9,12 +9,8 @@ class MessageToUserTlv : public cfdp::Tlv {
public:
MessageToUserTlv();
MessageToUserTlv(uint8_t* value, size_t size);
MessageToUserTlv(const uint8_t* value, size_t size);
explicit MessageToUserTlv(const std::vector<uint8_t>& data);
bool isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
size_t& msgLen) const;
private:
};

View File

@ -1,39 +0,0 @@
#include "ReservedMessageCreator.h"
cfdp::ReservedMessageCreator::ReservedMessageCreator(uint8_t messageType, uint8_t *msgData,
size_t msgLen)
: messageType(messageType), msgData(msgData), msgSize(msgLen) {}
ReturnValue_t cfdp::ReservedMessageCreator::serialize(
uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = TlvType::MSG_TO_USER;
*buffer += 1;
*size += 1;
**buffer = getSerializedSize() - 2;
*size += 1;
*buffer += 1;
std::memcpy(*buffer, MSG_HEADER, 4);
*buffer += 4;
*size += 4;
**buffer = messageType;
*buffer += 1;
*size += 1;
std::memcpy(*buffer, msgData, msgSize);
*buffer += msgSize;
*size += msgSize;
return returnvalue::OK;
}
size_t cfdp::ReservedMessageCreator::getSerializedSize() const {
// 2 bytes type and length, 4 bytes CFDP, 1 byte reserved message type, message data.
return 2 + 5 + msgSize;
}
ReturnValue_t cfdp::ReservedMessageCreator::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
return returnvalue::FAILED;
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "Tlv.h"
namespace cfdp {
class ReservedMessageCreator : public SerializeIF {
public:
static constexpr char MSG_HEADER[] = "cfdp";
ReservedMessageCreator(uint8_t messageType, uint8_t *msgData, size_t msgLen);
[[nodiscard]] ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
[[nodiscard]] size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
private:
uint8_t messageType;
uint8_t *msgData;
size_t msgSize;
};
} // namespace cfdp

View File

@ -7,12 +7,3 @@ cfdp::StringLv::StringLv(const char* filename, size_t len)
: Lv(reinterpret_cast<const uint8_t*>(filename), len) {}
cfdp::StringLv::StringLv() : Lv() {}
const char* cfdp::StringLv::getCString(size_t& fileSize) const {
return reinterpret_cast<const char*>(getValue(&fileSize));
}
std::string cfdp::StringLv::getString() const {
size_t fileSize;
return {getCString(fileSize), fileSize};
}

View File

@ -13,8 +13,6 @@ class StringLv : public Lv {
explicit StringLv(const std::string& fileName);
explicit StringLv(const char* filename, size_t len);
const char* getCString(size_t& fileSize) const;
std::string getString() const;
// Delete the move constructor to avoid passing in a temporary
StringLv(const std::string&&) = delete;
};

View File

@ -54,7 +54,6 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
return STREAM_TOO_SHORT;
}
rawData = *buffer;
uint8_t rawType = **buffer;
if (not checkType(rawType)) {
return INVALID_TLV_TYPE;
@ -103,5 +102,3 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }
void cfdp::Tlv::setType(TlvType type) { this->type = type; }
const uint8_t *cfdp::Tlv::getRawData() const { return rawData; }

View File

@ -47,7 +47,6 @@ class Tlv : public TlvIF {
void setValue(uint8_t *value, size_t len);
[[nodiscard]] const uint8_t *getValue() const;
[[nodiscard]] const uint8_t *getRawData() const;
void setType(TlvType type);
[[nodiscard]] TlvType getType() const override;
[[nodiscard]] uint8_t getLengthField() const override;
@ -56,7 +55,6 @@ class Tlv : public TlvIF {
bool checkType(uint8_t rawType);
bool zeroLen = true;
const uint8_t *rawData = nullptr;
TlvType type = TlvType::INVALID_TLV;
SerialBufferAdapter<uint8_t> value;
};

View File

@ -12,7 +12,6 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList : public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
"count_t is not large enough to hold MAX_SIZE");
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
private:
T data[MAX_SIZE];

View File

@ -4,31 +4,48 @@
#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, size_t commandQueueDepth)
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth)
: SystemObject(setObjectId),
parentId(parentId),
mode(MODE_OFF),
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
}
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = modeHelper.initialize();
ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) {
return result;
}
result = healthHelper.initialize();
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);
if (result != returnvalue::OK) {
return result;
}
return SystemObject::initialize();
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
@ -58,7 +75,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);
@ -72,17 +89,18 @@ void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
*submode_ = this->submode;
}
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue();
performControlOperation();
return returnvalue::OK;
}
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) {
case HEALTHY:
@ -100,13 +118,3 @@ 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,9 +6,6 @@
#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"
@ -21,18 +18,13 @@
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, size_t commandQueueDepth = 3);
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ControllerBase() override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/** SystemObject override */
ReturnValue_t initialize() override;
@ -46,8 +38,6 @@ 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:
/**
@ -66,6 +56,8 @@ 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,7 +1,8 @@
#include "fsfw/controller/ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
: ControllerBase(objectId, commandQueueDepth),
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth)
: ControllerBase(objectId, parentId, 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, size_t commandQueueDepth = 3);
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ExtendedControllerBase() override;
/* SystemObjectIF overrides */

View File

@ -6,8 +6,6 @@
#include "fsfw/globalfunctions/constants.h"
#include "fsfw/globalfunctions/math/MatrixOperations.h"
#include "fsfw/globalfunctions/math/VectorOperations.h"
#include "fsfw/globalfunctions/sign.h"
#include "fsfw/serviceinterface.h"
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition, double* eciPosition,
timeval* timeUTC) {
@ -99,14 +97,7 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates, double* e
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
timeval timeTT;
ReturnValue_t result = Clock::convertUTCToTT(timeUTC, &timeTT);
if (result != returnvalue::OK) {
// i think it is better to continue here than to abort
timeTT = timeUTC;
sif::error << "CoordinateTransformations::Conversion from UTC to TT failed. Continuing "
"calculations with UTC."
<< std::endl;
}
Clock::convertUTCToTT(timeUTC, &timeTT);
double jD2000TT;
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
@ -216,61 +207,3 @@ void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC, double T
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
};
void CoordinateTransformations::cartesianFromLatLongAlt(const double lat, const double longi,
const double alt, double* cartesianOutput) {
/* @brief: cartesianFromLatLongAlt() - calculates cartesian coordinates in ECEF from latitude,
* longitude and altitude
* @param: lat geodetic latitude [rad]
* longi longitude [rad]
* alt altitude [m]
* cartesianOutput Cartesian Coordinates in ECEF (3x1)
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.34ff
* Landis Markley and John L. Crassidis*/
double radiusPolar = 6356752.314;
double radiusEqua = 6378137;
double eccentricity = sqrt(1 - pow(radiusPolar, 2) / pow(radiusEqua, 2));
double auxRadius = radiusEqua / sqrt(1 - pow(eccentricity, 2) * pow(sin(lat), 2));
cartesianOutput[0] = (auxRadius + alt) * cos(lat) * cos(longi);
cartesianOutput[1] = (auxRadius + alt) * cos(lat) * sin(longi);
cartesianOutput[2] = ((1 - pow(eccentricity, 2)) * auxRadius + alt) * sin(lat);
};
void CoordinateTransformations::latLongAltFromCartesian(const double* vector, double& latitude,
double& longitude, double& altitude) {
/* @brief: latLongAltFromCartesian() - calculates latitude, longitude and altitude from
* cartesian coordinates in ECEF
* @param: x x-value of position vector [m]
* y y-value of position vector [m]
* z z-value of position vector [m]
* latitude geodetic latitude [rad]
* longitude longitude [rad]
* altitude altitude [m]
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.35 f
* Landis Markley and John L. Crassidis*/
// From World Geodetic System the Earth Radii
double a = 6378137.0; // semimajor axis [m]
double b = 6356752.3142; // semiminor axis [m]
// Calculation
double e2 = 1 - pow(b, 2) / pow(a, 2);
double epsilon2 = pow(a, 2) / pow(b, 2) - 1;
double rho = sqrt(pow(vector[0], 2) + pow(vector[1], 2));
double p = std::abs(vector[2]) / epsilon2;
double s = pow(rho, 2) / (e2 * epsilon2);
double q = pow(p, 2) - pow(b, 2) + s;
double u = p / sqrt(q);
double v = pow(b, 2) * pow(u, 2) / q;
double P = 27 * v * s / q;
double Q = pow(sqrt(P + 1) + sqrt(P), 2. / 3.);
double t = (1 + Q + 1 / Q) / 6;
double c = sqrt(pow(u, 2) - 1 + 2 * t);
double w = (c - u) / 2;
double d = sign(vector[2]) * sqrt(q) * (w + sqrt(sqrt(pow(t, 2) + v) - u * w - t / 2 - 1. / 4.));
double N = a * sqrt(1 + epsilon2 * pow(d, 2) / pow(b, 2));
latitude = asin((epsilon2 + 1) * d / N);
altitude = rho * cos(latitude) + vector[2] * sin(latitude) - pow(a, 2) / N;
longitude = atan2(vector[1], vector[0]);
}

View File

@ -23,12 +23,6 @@ class CoordinateTransformations {
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
static void cartesianFromLatLongAlt(const double lat, const double longi, const double alt,
double* cartesianOutput);
static void latLongAltFromCartesian(const double* vector, double& latitude, double& longitude,
double& altitude);
private:
CoordinateTransformations();
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,

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 daysSinceEpoch = minutesSinceEpoch / 60 / 24;
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
if ((daysSinceEpoch > 7) || (daysSinceEpoch < -7)) {
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
return TLE_TOO_OLD;
}

View File

@ -70,7 +70,8 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() {
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
return initializeHousekeepingPoolEntriesOnce();
}
@ -505,9 +506,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);
result = changeCollectionInterval(sid, newCollIntvl, true);
} else {
result = changeCollectionInterval(sid, newCollIntvl);
result = changeCollectionInterval(sid, newCollIntvl, false);
}
break;
}
@ -569,10 +570,6 @@ 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);
@ -660,6 +657,10 @@ 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);
@ -713,15 +714,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 returnvalue::OK;
return REPORTING_STATUS_UNCHANGED;
}
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval) {
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
@ -729,6 +730,11 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
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);
@ -819,8 +825,6 @@ 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();
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
/**
* @brief This should be called in the periodic handler of the owner.
@ -152,6 +152,17 @@ 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
@ -174,7 +185,6 @@ 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();
@ -338,6 +348,8 @@ 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,8 +250,9 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval);
dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
}
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }

View File

@ -162,7 +162,6 @@ 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
@ -190,8 +189,10 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* Used for periodic generation.
*/
bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);
/**
* If the valid state of a dataset is always relevant to the whole

View File

@ -12,8 +12,10 @@ class LocalPoolDataSetAttorney {
static bool isDiagnostics(LocalPoolDataSetBase& set) { return set.isDiagnostics(); }
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
uint32_t minimumPeriodicIntervalMs) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs);
uint32_t minimumPeriodicIntervalMs,
uint8_t nonDiagIntervalFactor = 5) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
nonDiagIntervalFactor);
}
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {

View File

@ -1,7 +1,7 @@
#include "fsfw/devicehandlers/AssemblyBase.h"
AssemblyBase::AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, MODE_OFF, commandQueueDepth),
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
internalState(STATE_NONE),
recoveryState(RECOVERY_IDLE),
recoveringDevice(childrenMap.end()),
@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode);
triggerModeHelperEvents(mode, submode);
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
}
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY, iter->first, 0);
triggerEvent(TRYING_RECOVERY);
recoveryState = RECOVERY_STARTED;
recoveringDevice = iter;
// The user needs to take care of commanding the children off in commandChildren
doStartTransition(targetMode, targetSubmode);
} else {
triggerEvent(CHILD_CHANGED_HEALTH);
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) {
case RECOVERY_STARTED:
// The recovery was already start in #handleChildrenChangedHealth and we just need
// to wait for an off time period.
// TODO: make time period configurable
recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer();
return true;
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
}
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}

View File

@ -12,8 +12,7 @@
* Documentation: Dissertation Baetz p.156, 157.
*
* This class reduces the complexity of controller components which would
* otherwise be needed for the handling of redundant devices. However, it can also be used to
* manage the mode keeping and recovery of non-redundant devices
* otherwise be needed for the handling of redundant devices.
*
* The template class monitors mode and health state of its children
* and checks availability of devices on every detected change.
@ -27,9 +26,11 @@
*
* Important:
*
* The implementation must call #registerChild for all commanded children during initialization.
* The implementation must call registerChild(object_id_t child)
* for all commanded children during initialization.
* The implementation must call the initialization function of the base class.
* (This will call the function in SubsystemBase)
*
*/
class AssemblyBase : public SubsystemBase {
public:
@ -41,15 +42,14 @@ class AssemblyBase : public SubsystemBase {
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth = 8);
AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8);
virtual ~AssemblyBase();
protected:
/**
* Command children to reach [mode,submode] combination. Can be done by setting
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
* a recovery might be on-going and the device needs to be commanded to off first.
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
* or using executeTable()
* @param mode
* @param submode
* @return
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
/**
* @brief Default periodic handler
* @details
* This is the default periodic handler which will be called by the SubsystemBase
* performOperation. It performs the child transitions or reacts to changed health/mode states
* of children objects
*/
virtual void performChildOperation() override;
virtual void performChildOperation();
/**
* This function handles changed mode or health states of children
* @return
*/
bool handleChildrenChanged();
/**
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
bool handleChildrenChangedHealth();
/**
* Core transition handler. The default implementation will only do something if
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
* from the #doPerformTransition call were executed successfully.
*
* Unless a second step was requested, the function will then use #checkChildrenState to
* determine whether the target mode was reached.
*
* There is some special handling for certain (internal) modes:
* - A second step is necessary. #commandChildren will be performed again
* - The device health was overwritten. #commandChildren will be called
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
*/
virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
/**
* Calls #doStartTransition and triggers an informative event as well that the mode will
* change
* @param mode
* @param submode
*/
virtual void startTransition(Mode_t mode, Submode_t submode);
/**
* This function starts the transition by setting the internal #targetSubmode and #targetMode
* variables and then calling the #commandChildren function.
* @param mode
* @param submode
*/
virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition();
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
* Manages recovery of a device
* @return true if recovery is still ongoing, false else.
*/
virtual bool checkAndHandleRecovery();
bool checkAndHandleRecovery();
/**
* Helper method to overwrite health state of one of the children.
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
* @param objectId Must be a registered child.
*/
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
};
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@ -7,5 +7,4 @@ target_sources(
DeviceHandlerFailureIsolation.cpp
DeviceHandlerMessage.cpp
DeviceTmReportingWrapper.cpp
FreshDeviceHandlerBase.cpp
HealthDevice.cpp)

View File

@ -3,12 +3,17 @@
#include "fsfw/subsystem/SubsystemBase.h"
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
CookieIF* cookie, HasModeTreeChildrenIF& parent,
FailureIsolationBase* customFdir, size_t cmdQueueSize)
CookieIF* cookie, object_id_t hkDestination,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
object_id_t parent, FailureIsolationBase* customFdir,
size_t cmdQueueSize)
: DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
(customFdir == nullptr ? &childHandlerFdir : customFdir), cmdQueueSize),
parent(parent),
childHandlerFdir(setObjectId) {}
parentId(parent),
childHandlerFdir(setObjectId) {
this->setHkDestination(hkDestination);
this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId);
}
ChildHandlerBase::~ChildHandlerBase() {}
@ -18,5 +23,21 @@ ReturnValue_t ChildHandlerBase::initialize() {
return result;
}
return DeviceHandlerBase::connectModeTreeParent(parent);
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == NULL) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
healthHelper.setParentQueue(parentQueue);
modeHelper.setParentQueue(parentQueue);
return returnvalue::OK;
}

View File

@ -1,23 +1,22 @@
#ifndef FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
#define FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
#include <fsfw/subsystem/HasModeTreeChildrenIF.h>
#include "ChildHandlerFDIR.h"
#include "DeviceHandlerBase.h"
class ChildHandlerBase : public DeviceHandlerBase {
public:
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF* cookie,
HasModeTreeChildrenIF& parent, FailureIsolationBase* customFdir = nullptr,
size_t cmdQueueSize = 20);
object_id_t hkDestination, uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT,
FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20);
virtual ~ChildHandlerBase();
virtual ReturnValue_t initialize();
protected:
HasModeTreeChildrenIF& parent;
const uint32_t parentId;
ChildHandlerFDIR childHandlerFdir;
};

View File

@ -49,7 +49,6 @@ class DeviceCommunicationIF {
// is this needed if there is no open/close call?
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
static constexpr ReturnValue_t BUSY = MAKE_RETURN_CODE(0x07);
virtual ~DeviceCommunicationIF() {}

View File

@ -1,4 +1,4 @@
#include "DeviceHandlerBase.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h"
@ -13,7 +13,6 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
#include "fsfw/thermal/ThermalComponentIF.h"
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
@ -24,6 +23,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
CookieIF* comCookie, FailureIsolationBase* fdirInstance,
size_t cmdQueueSize)
: SystemObject(setObjectId),
mode(MODE_OFF),
submode(SUBMODE_NONE),
wiretappingMode(OFF),
storedRawData(StorageManagerIF::INVALID_ADDRESS),
deviceCommunicationId(deviceCommunication),
@ -38,13 +39,10 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
defaultFDIRUsed(fdirInstance == nullptr),
switchOffWasReported(false),
childTransitionDelay(5000),
mode(MODE_OFF),
submode(SUBMODE_NONE),
transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
insertInCommandMap(RAW_COMMAND_ID);
cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end();
@ -52,13 +50,21 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase", returnvalue::FAILED,
"Invalid cookie");
}
if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
}
}
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
this->hkDestination = hkDestination;
}
void DeviceHandlerBase::enableThermalModule(ThermalStateCfg cfg) { this->thermalStateCfg = cfg; }
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
lp_id_t heaterRequestPoolId,
uint32_t thermalSetId) {
thermalSet =
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
}
DeviceHandlerBase::~DeviceHandlerBase() {
if (comCookie != nullptr) {
@ -124,10 +130,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (this->fdirInstance == nullptr) {
this->fdirInstance =
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
}
communicationInterface =
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
@ -222,11 +224,12 @@ ReturnValue_t DeviceHandlerBase::initialize() {
fillCommandAndReplyMap();
if (thermalSet != nullptr) {
PoolReadGuard pg(thermalSet);
// Set temperature target state to NON_OP.
if (pg.getReadResult() == returnvalue::OK) {
result = thermalSet->read();
if (result == returnvalue::OK) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->heaterRequest.setValid(true);
thermalSet->commit();
}
}
@ -350,6 +353,7 @@ void DeviceHandlerBase::doStateMachine() {
currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(_MODE_POWER_DOWN);
callChildStatemachine();
break;
}
ReturnValue_t switchState = getStateOfSwitches();
@ -363,12 +367,13 @@ void DeviceHandlerBase::doStateMachine() {
}
} break;
case _MODE_WAIT_OFF: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (powerSwitcher == nullptr) {
setMode(MODE_OFF);
break;
}
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(MODE_ERROR_ON);
@ -376,7 +381,7 @@ void DeviceHandlerBase::doStateMachine() {
}
ReturnValue_t switchState = getStateOfSwitches();
if ((switchState == PowerSwitchIF::SWITCH_OFF) || (switchState == NO_SWITCH)) {
setMode(MODE_OFF, SUBMODE_NONE);
setMode(_MODE_SWITCH_IS_OFF);
}
} break;
case MODE_OFF:
@ -389,6 +394,9 @@ void DeviceHandlerBase::doStateMachine() {
case MODE_NORMAL:
case MODE_ERROR_ON:
break;
case _MODE_SWITCH_IS_OFF:
setMode(MODE_OFF, SUBMODE_NONE);
break;
default:
triggerEvent(OBJECT_IN_INVALID_MODE, mode, submode);
setMode(_MODE_POWER_DOWN, 0);
@ -560,40 +568,25 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
}
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
/**
* handle transition from OFF to NORMAL by continuing towards normal when ON is reached
*/
if (newMode == MODE_ON and continueToNormal) {
continueToNormal = false;
// TODO: Check whether the following two lines are okay to do so.
transitionSourceMode = MODE_ON;
transitionSourceSubMode = newSubmode;
mode = _MODE_TO_NORMAL;
return;
}
/* TODO: This will probably be done by the LocalDataPoolManager now */
// changeHK(mode, submode, false);
submode = newSubmode;
mode = newMode;
modeChanged();
setNormalDatapoolEntriesInvalid();
if (newMode == MODE_OFF) {
disableCommandsAndReplies();
}
if (!isTransitionalMode()) {
// clear this flag when a non-transitional Mode is reached to be safe
continueToNormal = false;
modeHelper.modeChanged(newMode, newSubmode);
announceMode(false);
}
Clock::getUptime(&timeoutStart);
if (mode == MODE_OFF and thermalSet != nullptr) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
}
thermalSet->heaterRequest.setValid(true);
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
}
}
/* TODO: This will probably be done by the LocalDataPoolManager now */
@ -1066,7 +1059,8 @@ Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) {
return transitionMode & ~(TRANSITION_MODE_BASE_ACTION_MASK | TRANSITION_MODE_CHILD_ACTION_MASK);
}
// SHOULDDO: throw away DHB and write a new one:
// SHOULDDO: Allow transition from OFF to NORMAL to reduce complexity in assemblies. And, by the
// way, throw away DHB and write a new one:
// - Include power and thermal completely, but more modular :-)
// - Don't use modes for state transitions, reduce FSM (Finte State Machine) complexity.
// - Modularization?
@ -1078,12 +1072,13 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
if ((mode == MODE_ERROR_ON) && (commandedMode != MODE_OFF)) {
return TRANS_NOT_ALLOWED;
}
if ((commandedMode == MODE_NORMAL) && (mode == MODE_OFF)) {
return TRANS_NOT_ALLOWED;
}
// Do not check thermal state for MODE_RAW
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
(thermalSet != nullptr)) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if ((commandedMode == MODE_ON) && (mode == MODE_OFF) and (thermalSet != nullptr)) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
@ -1096,7 +1091,6 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
}
void DeviceHandlerBase::startTransition(Mode_t commandedMode, Submode_t commandedSubmode) {
continueToNormal = false;
switch (commandedMode) {
case MODE_ON:
handleTransitionToOnMode(commandedMode, commandedSubmode);
@ -1126,9 +1120,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, Submode_t commande
case MODE_NORMAL:
if (mode != MODE_OFF) {
setTransition(MODE_NORMAL, commandedSubmode);
} else { // mode is off
continueToNormal = true;
handleTransitionToOnMode(MODE_NORMAL, commandedSubmode);
} else {
replyReturnvalueToCommand(HasModesIF::TRANS_NOT_ALLOWED);
}
break;
}
@ -1144,10 +1137,11 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
if (thermalSet != nullptr) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
thermalSet->commit();
}
}
}
@ -1285,7 +1279,6 @@ void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommand
if (iter->second.command != deviceCommandMap.end()) {
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
// This may fail, but we'll ignore the fault.
if (queueId != NO_COMMANDER) {
// This may fail, but we'll ignore the fault.
actionHelper.reportData(queueId, replyId, const_cast<SerializeIF*>(&dataSet));
@ -1464,17 +1457,15 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
uint32_t parameter) {}
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
if (thermalStateCfg.has_value()) {
localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>());
localDataPoolMap.emplace(thermalStateCfg.value().thermalRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>());
if (thermalSet != nullptr) {
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
}
return returnvalue::OK;
}
@ -1487,12 +1478,8 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
}
this->poolManager.initializeAfterTaskCreation();
if (thermalStateCfg.has_value()) {
ThermalStateCfg& cfg = thermalStateCfg.value();
thermalSet = new DeviceHandlerThermalSet(this, cfg);
}
if (setStartupImmediately) {
startTransition(MODE_ON, getInitialSubmode());
startTransition(MODE_ON, SUBMODE_NONE);
}
return returnvalue::OK;
}
@ -1579,52 +1566,3 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
}
return commandIter->second.sendReplyTo;
}
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
this->powerSwitcher = switcher;
}
Mode_t DeviceHandlerBase::getMode() { return mode; }
Submode_t DeviceHandlerBase::getSubmode() { return submode; }
void DeviceHandlerBase::disableCommandsAndReplies() {
for (auto& command : deviceCommandMap) {
if (command.second.isExecuting) {
command.second.isExecuting = false;
}
}
for (auto& reply : deviceReplyMap) {
if (!reply.second.periodic) {
if (reply.second.countdown != nullptr) {
reply.second.countdown->timeOut();
} else {
reply.second.delayCycles = 0;
}
reply.second.active = false;
}
}
}
ReturnValue_t DeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}
const HasHealthIF* DeviceHandlerBase::getOptHealthIF() const { return this; }
const HasModesIF& DeviceHandlerBase::getModeIF() const { return *this; }
ModeTreeChildIF& DeviceHandlerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t action,
ReturnValue_t result) {
auto commandIter = deviceCommandMap.find(action);
if (commandIter == deviceCommandMap.end()) {
return MessageQueueIF::NO_QUEUE;
}
commandIter->second.isExecuting = false;
actionHelper.finish(success, commandIter->second.sendReplyTo, action, result);
return returnvalue::OK;
}

View File

@ -2,7 +2,6 @@
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#include <map>
#include <optional>
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
@ -22,7 +21,6 @@
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
@ -85,8 +83,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
public HasModesIF,
public HasHealthIF,
public HasActionsIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
friend void(Factory::setStaticFrameworkObjectIds)();
@ -106,51 +102,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
void setCustomFdir(FailureIsolationBase *fdir);
void setPowerSwitcher(PowerSwitchIF *switcher);
/**
* extending the modes of DeviceHandler IF for internal state machine
*/
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c _MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c _MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c _MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
void setHkDestination(object_id_t hkDestination);
/**
@ -159,12 +110,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* The device handler will then take care of creating local pool entries
* for the device thermal state and device heating request.
* Custom local pool IDs can be assigned as well.
* @param thermalStatePoolId
* @param thermalRequestPoolId
*/
void enableThermalModule(ThermalStateCfg cfg);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
void setThermalStateRequestPoolIds(
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
/**
* @brief Helper function to ease device handler development.
* This will instruct the transition to MODE_ON immediately
@ -210,7 +162,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @param counter Specifies which Action to perform
* @return returnvalue::OK for successful execution
*/
ReturnValue_t performOperation(uint8_t counter) override;
virtual ReturnValue_t performOperation(uint8_t counter) override;
/**
* @brief Initializes the device handler
@ -220,14 +172,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* Calls fillCommandAndReplyMap().
* @return
*/
ReturnValue_t initialize() override;
virtual ReturnValue_t initialize() override;
/**
* @brief Intialization steps performed after all tasks have been created.
* This function will be called by the executing task.
* @return
*/
ReturnValue_t initializeAfterTaskCreation() override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
/** Destructor. */
virtual ~DeviceHandlerBase();
@ -244,8 +196,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual object_id_t getObjectId() const override;
/**
* This is a helper method for classes which are parent nodes in the mode tree.
* It registers the passed queue as the destination for mode and health messages.
* @param parentQueueId
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
@ -257,8 +207,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual HealthState getHealth() override;
virtual ReturnValue_t setHealth(HealthState health) override;
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues,
@ -445,8 +395,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0;
MessageQueueId_t getCommanderQueueId(DeviceCommandId_t replyId) const;
ReturnValue_t finishAction(bool success, DeviceCommandId_t action, ReturnValue_t result);
/**
* Helper function to get pending command. This is useful for devices
* like SPI sensors to identify the last sent command.
@ -515,14 +463,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @brief This is a helper method to insert replies in the reply map.
* @param deviceCommand Identifier of the reply to add.
* @param maxDelayCycles The maximum number of delay cycles the reply waits
* until it times out.
* until it times out.
* @param periodic Indicates if the command is periodic (i.e. it is sent
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* @return - @c returnvalue::OK when the command was successfully inserted,
* - @c returnvalue::FAILED else.
*/
@ -707,12 +655,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
uint32_t parameter = 0);
/**
* @brief Can be overwritten by a child to specify the initial submode when device has been set
* to startup immediately.
*/
virtual Submode_t getInitialSubmode();
protected:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
@ -742,18 +684,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
size_t rawPacketLen = 0;
/**
* Get the current mode
*
* set via setMode()
* The mode the device handler is currently in.
* This should never be changed directly but only with setMode()
*/
Mode_t getMode();
Mode_t mode;
/**
* Get the current Submode
*
* set via setMode()
* The submode the device handler is currently in.
* This should never be changed directly but only with setMode()
*/
Submode_t getSubmode();
Submode_t submode;
/** This is the counter value from performOperation(). */
uint8_t pstStep = 0;
@ -834,18 +773,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* This is used to keep track of pending replies.
*/
struct DeviceReplyInfo {
//! For Command-Reply combinations:
//! The maximum number of cycles the handler should wait for a reply
//! to this command.
//!
//! Reply Only:
//! For periodic replies, this variable will be the number of delay cycles between the replies.
//! For the non-periodic variant, this variable is not used as there is no meaningful
//! definition for delay
uint16_t maxDelayCycles;
//! This variable will be set to #maxDelayCycles if a reply is expected.
//! For non-periodic replies without a command, this variable is unused.
//! A runtime value of 0 means there is no reply is currently expected.
//! The currently remaining cycles the handler should wait for a reply,
//! 0 means there is no reply expected
uint16_t delayCycles;
size_t replyLen = 0; //!< Expected size of the reply.
//! if this is !=0, the delayCycles will not be reset to 0 but to
@ -901,7 +833,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** Pointer to the used FDIR instance. If not provided by child,
* default class is instantiated. */
FailureIsolationBase *fdirInstance;
object_id_t parent = objects::NO_OBJECT;
//! To correctly delete the default instance.
bool defaultFDIRUsed;
@ -922,8 +853,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId;
std::optional<ThermalStateCfg> thermalStateCfg;
/**
* @brief Send a reply to a received device handler command.
*
@ -944,8 +873,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW).
*
* If the transition is complete, the mode should be set to the target mode,
* which can be deduced from the current mode (which is
* [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW]) using getBaseMode()
* which can be deduced from the current mode which is
* [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW]
*
* The intended target submode is already set.
* The origin submode can be read in subModeFrom.
@ -1012,9 +941,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
LocalDataPoolManager *getHkManagerHandle() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
/**
* Returns the delay cycle count of a reply.
* A count != 0 indicates that the command is already executed.
@ -1194,22 +1120,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual ReturnValue_t doSendReadHook();
/**
* Send a RMAP getRead command.
*
* The size of the getRead command is #maxDeviceReplyLen.
* This is always executed, independently from the current mode.
*/
virtual void doSendRead(void);
/**
* Check the getRead reply and the contained data.
*
* If data was received scanForReply() and, if successful, handleReply()
* are called. If the current mode is @c MODE_RAW, the received packet
* is sent to the commanding object via commandQueue.
*/
virtual void doGetRead();
private:
/**
* State a cookie is in.
@ -1260,18 +1170,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
uint32_t childTransitionDelay;
/**
* The mode the device handler is currently in.
* This should not be changed directly but only with setMode()
*/
Mode_t mode;
/**
* The submode the device handler is currently in.
* This should not be changed directly but only with setMode()
*/
Submode_t submode;
/**
* @brief The mode the current transition originated from
*
@ -1289,15 +1187,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
Submode_t transitionSourceSubMode;
/**
* used to make the state machine continue from ON to NOMAL when
* a Device is commanded to NORMAL in OFF mode
*
* set in startTransition()
* evaluated in setMode() to continue to NORMAL when ON is reached
*/
bool continueToNormal;
/**
* read the command queue
*/
@ -1366,6 +1255,21 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - if the action was successful, the reply timout counter is initialized
*/
void doGetWrite(void);
/**
* Send a RMAP getRead command.
*
* The size of the getRead command is #maxDeviceReplyLen.
* This is always executed, independently from the current mode.
*/
void doSendRead(void);
/**
* Check the getRead reply and the contained data.
*
* If data was received scanForReply() and, if successful, handleReply()
* are called. If the current mode is @c MODE_RAW, the received packet
* is sent to the commanding object via commandQueue.
*/
void doGetRead(void);
/**
* @brief Resets replies which use a timeout to detect missed replies.
@ -1419,11 +1323,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
void printWarningOrError(sif::OutputTypes errorType, const char *functionName,
ReturnValue_t errorCode = returnvalue::FAILED,
const char *errorPrint = nullptr);
/**
* @brief Disables all commands and replies when device is set to MODE_OFF
*/
void disableCommandsAndReplies();
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -10,9 +10,8 @@
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth)
: FailureIsolationBase(owner, parent, eventQueueDepth),
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent)
: FailureIsolationBase(owner, parent),
strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS,
parameterDomainBase++),
missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS,
@ -26,16 +25,10 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
if (isFdirInActionOrAreWeFaulty(event)) {
return returnvalue::OK;
}
// As mentioned in the function documentation, no FDIR reaction are performed when the device
// is in external control.
if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) {
return returnvalue::OK;
}
ReturnValue_t result = returnvalue::FAILED;
switch (event->getEvent()) {
case HasModesIF::MODE_TRANSITION_FAILED:
case HasModesIF::OBJECT_IN_INVALID_MODE:
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
// We'll try a recovery as long as defined in MAX_REBOOT.
// Might cause some AssemblyBase cycles, so keep number low.
handleRecovery(event->getEvent());
@ -191,6 +184,15 @@ void DeviceHandlerFailureIsolation::setFdirState(FDIRState state) {
fdirState = state;
}
void DeviceHandlerFailureIsolation::triggerEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
// Do not throw error events if fdirState != none.
// This will still forward MODE and HEALTH INFO events in any case.
if (fdirState == NONE || event::getSeverity(event) == severity::INFO) {
FailureIsolationBase::triggerEvent(event, parameter1, parameter2);
}
}
bool DeviceHandlerFailureIsolation::isFdirActionInProgress() { return (fdirState != NONE); }
void DeviceHandlerFailureIsolation::startRecovery(Event reason) {

View File

@ -13,10 +13,10 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase {
friend class Heater;
public:
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth = 10);
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
~DeviceHandlerFailureIsolation();
ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
bool isFdirActionInProgress();
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper,
@ -40,19 +40,6 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase {
static const uint32_t DEFAULT_MAX_MISSED_REPLY_COUNT = 5;
static const uint32_t DEFAULT_MISSED_REPLY_TIME_MS = 10000;
/**
* This is the default implementation of the eventReceived function.
*
* It will perform recoveries or failures on a pre-defined set of events. If the user wants
* to add handling for custom events, this function should be overriden.
*
* It should be noted that the default implementation will not perform FDIR reactions if the
* handler is faulty or in external control by default. If the user commands the device
* manually, this might be related to debugging to testing the device in a low-level way. FDIR
* reactions might get in the way of this process by restarting the device or putting it in
* the faulty state. If the user still requires FDIR handling in the EXTERNAL_CONTROL case,
* this function should be overriden.
*/
virtual ReturnValue_t eventReceived(EventMessage* event);
virtual void eventConfirmed(EventMessage* event);
void wasParentsFault(EventMessage* event);

View File

@ -24,6 +24,9 @@ class DeviceHandlerIF {
static const DeviceCommandId_t RAW_COMMAND_ID = -1;
static const DeviceCommandId_t NO_COMMAND_ID = -2;
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
using dh_heater_request_t = uint8_t;
using dh_thermal_state_t = int8_t;
@ -51,6 +54,47 @@ class DeviceHandlerIF {
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
//! can be commanded, which tries to switch off the device again.
static const Mode_t MODE_ERROR_ON = 4;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, severity::LOW);
@ -65,7 +109,6 @@ class DeviceHandlerIF {
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
@ -85,7 +128,6 @@ class DeviceHandlerIF {
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8);
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
static const ReturnValue_t NON_OP_STATE_OF_CHARGE = MAKE_RETURN_CODE(0xAB);
// Standard codes used in scanForReply
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
@ -137,10 +179,4 @@ class DeviceHandlerIF {
virtual MessageQueueId_t getCommandQueue() const = 0;
};
struct ThermalStateCfg {
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID;
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID;
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID;
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */

View File

@ -7,21 +7,27 @@
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
public:
DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg)
: DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {}
DeviceHandlerThermalSet(
HasLocalDataPoolIF* hkOwner, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t heaterRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
: DeviceHandlerThermalSet(hkOwner->getObjectId(), setId, thermalStateId, heaterRequestId) {}
DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg)
: StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)),
thermalStatePoolId(cfg.thermalStatePoolId),
heaterRequestPoolId(cfg.thermalRequestPoolId) {}
DeviceHandlerThermalSet(
object_id_t deviceHandler, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalStateRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
: StaticLocalDataSet(sid_t(deviceHandler, setId)),
thermalStatePoolId(thermalStateId),
heaterRequestPoolId(thermalStateRequestId) {}
const lp_id_t thermalStatePoolId;
const lp_id_t heaterRequestPoolId;
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(sid.objectId, thermalStatePoolId, this);
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(thermalStatePoolId, sid.objectId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(heaterRequestPoolId, sid.objectId, this);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */

View File

@ -1,9 +1,9 @@
#ifndef FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_
#define FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serialize/SerializeIF.h"
#include "../action/HasActionsIF.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../serialize/SerializeIF.h"
class DeviceTmReportingWrapper : public SerializeIF {
public:

View File

@ -1,203 +0,0 @@
#include "FreshDeviceHandlerBase.h"
#include "fsfw/devicehandlers/DeviceHandlerFailureIsolation.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/subsystem/helper.h"
FreshDeviceHandlerBase::FreshDeviceHandlerBase(DhbConfig config)
: SystemObject(config.objectId),
actionHelper(this, nullptr),
modeHelper(this),
healthHelper(this, getObjectId()),
paramHelper(this),
poolManager(this, nullptr),
fdirInstance(config.fdirInstance),
defaultFdirParent(config.defaultFdirParent) {
auto mqArgs = MqArgs(config.objectId, static_cast<void*>(this));
messageQueue = QueueFactory::instance()->createMessageQueue(
config.msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
FreshDeviceHandlerBase::~FreshDeviceHandlerBase() {
QueueFactory::instance()->deleteMessageQueue(messageQueue);
if (not hasCustomFdir) {
delete fdirInstance;
}
}
[[nodiscard]] object_id_t FreshDeviceHandlerBase::getObjectId() const {
return SystemObject::getObjectId();
}
ReturnValue_t FreshDeviceHandlerBase::performOperation(uint8_t opCode) {
performDeviceOperationPreQueueHandling(opCode);
handleQueue();
fdirInstance->checkForFailures();
performDeviceOperation(opCode);
poolManager.performHkOperation();
return returnvalue::OK;
}
ReturnValue_t FreshDeviceHandlerBase::performDeviceOperationPreQueueHandling(uint8_t opCode) {
return returnvalue::OK;
}
void FreshDeviceHandlerBase::startTransition(Mode_t mode_, Submode_t submode_) {
triggerEvent(CHANGING_MODE, mode_, submode_);
// Complete mode transition immediately by default.
setMode(mode_, submode_);
}
void FreshDeviceHandlerBase::setMode(Mode_t newMode, Submode_t newSubmode) {
mode = newMode;
submode = newSubmode;
modeHelper.modeChanged(mode, submode);
modeChanged(mode, submode);
announceMode(false);
}
void FreshDeviceHandlerBase::setMode(Mode_t newMode) { setMode(newMode, submode); }
void FreshDeviceHandlerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
*mode_ = this->mode;
*submode_ = this->submode;
}
void FreshDeviceHandlerBase::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode);
}
void FreshDeviceHandlerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
[[nodiscard]] MessageQueueId_t FreshDeviceHandlerBase::getCommandQueue() const {
return messageQueue->getId();
}
ReturnValue_t FreshDeviceHandlerBase::handleQueue() {
CommandMessage command;
ReturnValue_t result;
for (result = messageQueue->receiveMessage(&command); result == returnvalue::OK;
result = messageQueue->receiveMessage(&command)) {
result = actionHelper.handleActionMessage(&command);
if (result == returnvalue::OK) {
continue;
}
result = modeHelper.handleModeCommand(&command);
if (result == returnvalue::OK) {
continue;
}
result = healthHelper.handleHealthCommand(&command);
if (result == returnvalue::OK) {
continue;
}
result = paramHelper.handleParameterMessage(&command);
if (result == returnvalue::OK) {
continue;
}
result = poolManager.handleHousekeepingMessage(&command);
if (result == returnvalue::OK) {
continue;
}
result = handleCommandMessage(&command);
if (result == returnvalue::OK) {
continue;
}
command.setToUnknownCommand();
messageQueue->reply(&command);
}
return result;
}
HasHealthIF::HealthState FreshDeviceHandlerBase::getHealth() { return healthHelper.getHealth(); }
const HasHealthIF* FreshDeviceHandlerBase::getOptHealthIF() const { return this; }
const HasModesIF& FreshDeviceHandlerBase::getModeIF() const { return *this; }
ModeTreeChildIF& FreshDeviceHandlerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t FreshDeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}
// Executable Overrides.
void FreshDeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
// Pool Manager overrides.
LocalDataPoolManager* FreshDeviceHandlerBase::getHkManagerHandle() { return &poolManager; }
[[nodiscard]] uint32_t FreshDeviceHandlerBase::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
ReturnValue_t FreshDeviceHandlerBase::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation();
}
ReturnValue_t FreshDeviceHandlerBase::setHealth(HasHealthIF::HealthState health) {
// Assembly should handle commanding to OFF.
healthHelper.setHealth(health);
return returnvalue::OK;
}
void FreshDeviceHandlerBase::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) {
fdirInstance->triggerEvent(event, parameter1, parameter2);
}
void FreshDeviceHandlerBase::forwardEvent(Event event, uint32_t parameter1,
uint32_t parameter2) const {
fdirInstance->triggerEvent(event, parameter1, parameter2);
}
void FreshDeviceHandlerBase::setToExternalControl() { setHealth(HealthState::EXTERNAL_CONTROL); }
// System Object overrides.
ReturnValue_t FreshDeviceHandlerBase::initialize() {
ReturnValue_t result = modeHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = healthHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = actionHelper.initialize(messageQueue);
if (result != returnvalue::OK) {
return result;
}
result = paramHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = poolManager.initialize(messageQueue);
if (result != returnvalue::OK) {
return result;
}
if (fdirInstance == nullptr) {
hasCustomFdir = false;
fdirInstance = new DeviceHandlerFailureIsolation(getObjectId(), defaultFdirParent);
}
result = fdirInstance->initialize();
if (result != returnvalue::OK) {
return result;
}
return SystemObject::initialize();
}
ReturnValue_t FreshDeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues,
uint16_t startAtIndex) {
ReturnValue_t result =
fdirInstance->getParameter(domainId, uniqueId, parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}
return INVALID_DOMAIN_ID;
}

View File

@ -1,167 +0,0 @@
#pragma once
#include "fsfw/action.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/fdir/FailureIsolationBase.h"
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager.h"
#include "fsfw/parameters/ParameterHelper.h"
#include "fsfw/parameters/ReceivesParameterMessagesIF.h"
#include "fsfw/retval.h"
#include "fsfw/subsystem/ModeTreeChildIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
struct DhbConfig {
explicit DhbConfig(object_id_t objectId) : objectId(objectId) {}
object_id_t objectId;
FailureIsolationBase* fdirInstance = nullptr;
object_id_t defaultFdirParent = objects::NO_OBJECT;
uint32_t msgQueueDepth = 10;
};
class FreshDeviceHandlerBase : public SystemObject,
public DeviceHandlerIF,
public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public HasActionsIF,
public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
public:
explicit FreshDeviceHandlerBase(DhbConfig config);
~FreshDeviceHandlerBase() override;
/**
* Periodic helper executed function, implemented by child class.
*/
virtual void performDeviceOperation(uint8_t opCode) = 0;
[[nodiscard]] object_id_t getObjectId() const override;
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
HasHealthIF::HealthState getHealth() override;
// Mode Tree Overrides.
[[nodiscard]] const HasHealthIF* getOptHealthIF() const override;
[[nodiscard]] const HasModesIF& getModeIF() const override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ModeTreeChildIF& getModeTreeChildIF() override;
[[nodiscard]] uint32_t getPeriodicOperationFrequency() const override;
protected:
// Pool Manager overrides.
LocalDataPoolManager* getHkManagerHandle() override;
ActionHelper actionHelper;
ModeHelper modeHelper;
HealthHelper healthHelper;
ParameterHelper paramHelper;
LocalDataPoolManager poolManager;
bool hasCustomFdir = false;
FailureIsolationBase* fdirInstance;
object_id_t defaultFdirParent;
/**
* Pointer to the task which executes this component,
* is invalid before setTaskIF was called.
*/
PeriodicTaskIF* executingTask = nullptr;
Mode_t mode = HasModesIF::MODE_UNDEFINED;
Submode_t submode = 0;
MessageQueueIF* messageQueue;
/**
* The default queue handler will process all messages for the interfaces implemented
* by this class. If there are special requirements, for example that action commands are
* received on a different queue, the user can override this function for those special
* requirements.
*/
virtual ReturnValue_t handleQueue();
// Mode Helpers.
virtual void modeChanged(Mode_t mode, Submode_t submode);
/**
* The default implementation sets the new mode immediately. If this is not applicable for
* certain modes, the user should provide a custom implementation, which performs rougly
* the same functionality of this function, when all the steps have been taken to reach the
* new mode.
*/
void startTransition(Mode_t mode, Submode_t submode) override;
virtual void setMode(Mode_t newMode, Submode_t newSubmode);
virtual void setMode(Mode_t newMode);
void getMode(Mode_t* mode, Submode_t* submode) override;
void setToExternalControl() override;
void announceMode(bool recursive) override;
// System Object overrides.
ReturnValue_t initialize() override;
/**
* Implemented by child class. Handle all command messages which are
* not health, mode, action or housekeeping messages.
* @param message
* @return
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage* message) = 0;
// HK manager abstract functions.
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override = 0;
// Mode abstract functions
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override = 0;
// Health Overrides.
ReturnValue_t setHealth(HealthState health) override;
// Action override. Forward to user.
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override = 0;
// Executable overrides.
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
/**
* This calls the FDIR instance event trigger function.
* @param event
* @param parameter1
* @param parameter2
*/
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override;
/**
* This calls the FDIR instance event forward function.
* @param event
* @param parameter1
* @param parameter2
*/
void forwardEvent(Event event, uint32_t parameter1, uint32_t parameter2) const override;
/**
* This implementation handles the FDIR parameters. The user can override this to handle
* custom parameters.
* @param domainId
* @param uniqueId
* @param parameterWrapper
* @param newValues
* @param startAtIndex
* @return
*/
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
virtual ReturnValue_t performDeviceOperationPreQueueHandling(uint8_t opCode);
private:
// Executable Overrides.
void setTaskIF(PeriodicTaskIF* task) override;
};

View File

@ -8,9 +8,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
parentQueue(parentQueue),
commandQueue(),
healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(3);
}
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
@ -29,10 +27,11 @@ ReturnValue_t HealthDevice::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (parentQueue != MessageQueueIF::NO_QUEUE) {
if (parentQueue != 0) {
return healthHelper.initialize(parentQueue);
} else {
return healthHelper.initialize();
}
return healthHelper.initialize();
}
MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); }

View File

@ -29,8 +29,10 @@ class HealthDevice : public SystemObject, public ExecutableObjectIF, public HasH
protected:
HealthState lastHealth;
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
MessageQueueId_t parentQueue;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};

View File

@ -15,12 +15,11 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
EventManager::EventManager(object_id_t setObjectId)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
EventMessage::EVENT_MESSAGE_SIZE);
}
EventManager::~EventManager() {
@ -48,21 +47,9 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
void EventManager::notifyListeners(EventMessage* message) {
lockMutex();
for (auto& listener : listenerList) {
if (listener.second.match(message)) {
ReturnValue_t result =
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " for event 0x" << std::setw(4)
<< message->getEventId() << " failed with result 0x" << std::setw(4) << result
<< std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);
#endif
}
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
if (iter->second.match(message)) {
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
}
}
unlockMutex();
@ -213,19 +200,4 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
}
}
void EventManager::printListeners() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
for (auto& listener : listenerList) {
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
}
sif::info << std::dec << std::setfill(' ');
#else
sif::printInfo("Event manager listener MQ IDs:\n");
for (auto& listener : listenerList) {
sif::printInfo("0x%08x\n", listener.first);
}
#endif
}
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */

View File

@ -21,9 +21,9 @@ extern const char* translateEvents(Event event);
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
public:
static const uint16_t DEFAULT_MAX_EVENTS_PER_CYCLE = 80;
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
EventManager(object_id_t setObjectId);
virtual ~EventManager();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
@ -44,7 +44,6 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode);
void printListeners();
protected:
MessageQueueIF* eventReportQueue = nullptr;

View File

@ -10,7 +10,7 @@ enum : uint8_t {
CDH = 28,
TCS_1 = 59,
PCDU_1 = 42,
POWER_SWITCH_IF = 43,
PCDU_2 = 43,
HEATER = 50,
T_SENSORS = 52,
FDIR = 70,
@ -33,7 +33,6 @@ enum : uint8_t {
PUS_SERVICE_23 = 103,
MGM_LIS3MDL = 106,
MGM_RM3100 = 107,
CFDP = 108,
FW_SUBSYSTEM_ID_RANGE
};

View File

@ -9,9 +9,8 @@
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
uint8_t messageDepth, uint8_t parameterDomainBase)
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventQueue =
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
}
FailureIsolationBase::~FailureIsolationBase() {
@ -62,12 +61,11 @@ ReturnValue_t FailureIsolationBase::initialize() {
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
if (parentIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FailureIsolationBase::intialize: Parent object "
<< "invalid" << std::endl;
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
#else
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
sif::error << "FailureIsolationBase::intialize: Parent object"
<< "invalid." << std::endl;
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
return returnvalue::FAILED;
@ -148,16 +146,25 @@ void FailureIsolationBase::doConfirmFault(EventMessage* event) {
ReturnValue_t FailureIsolationBase::confirmFault(EventMessage* event) { return YOUR_FAULT; }
void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) {
// By default, we trigger all events and also call the handler function to handle FDIR reactions
// which might occur due to these events. This makes all events visible. If the handling of
// FDIR reaction should be disabled, this should be done through dedicated logic inside the
// eventReceived function.
// With this mechanism, all events are disabled for a certain device.
// That's not so good for visibility.
if (isFdirDisabledForSeverity(event::getSeverity(event))) {
return;
}
EventMessage message(event, ownerId, parameter1, parameter2);
EventManagerIF::triggerEvent(&message, eventQueue->getId());
eventReceived(&message);
}
bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) { return false; }
bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) {
if ((owner != NULL) && (severity != severity::INFO)) {
if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) {
// External control disables handling of fault messages.
return true;
}
}
return false;
}
void FailureIsolationBase::throwFdirEvent(Event event, uint32_t parameter1, uint32_t parameter2) {
EventMessage message(event, ownerId, parameter1, parameter2);

View File

@ -12,12 +12,13 @@
class FailureIsolationBase : public ConfirmsFailuresIF, public HasParametersIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
//! FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
//! FDIR turns off device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
static const Event FDIR_CHANGED_STATE =
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2
//!< (oldState) to par1 (newState).
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(
2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(
3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
@ -44,13 +45,13 @@ class FailureIsolationBase : public ConfirmsFailuresIF, public HasParametersIF {
virtual void wasParentsFault(EventMessage* event);
virtual ReturnValue_t confirmFault(EventMessage* event);
virtual void decrementFaultCounters() = 0;
virtual bool isFdirDisabledForSeverity(EventSeverity_t severity);
ReturnValue_t sendConfirmationRequest(EventMessage* event,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
void throwFdirEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
private:
void doConfirmFault(EventMessage* event);
bool isFdirDisabledForSeverity(EventSeverity_t severity);
};
#endif /* FRAMEWORK_FDIR */
#endif /* FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ */

View File

@ -68,7 +68,7 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
parameterWrapper->set(faultCount);
break;
case ParameterIds::TIMEOUT:
parameterWrapper->set(timer.getTimeoutMs());
parameterWrapper->set(timer.timeout);
break;
default:
return INVALID_IDENTIFIER_ID;

View File

@ -17,7 +17,7 @@ struct FilesystemParams {
};
struct FileOpParams {
FileOpParams(const char* path, size_t opSize) : fsParams(path), size(opSize) {}
FileOpParams(const char* path, size_t size) : fsParams(path), size(size) {}
[[nodiscard]] const char* path() const { return fsParams.path; }
@ -40,7 +40,6 @@ class HasFileSystemIF {
//! [EXPORT] : P1: Can be file system specific error code
static constexpr ReturnValue_t GENERIC_FILE_ERROR = MAKE_RETURN_CODE(0);
static constexpr ReturnValue_t GENERIC_DIR_ERROR = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t FILESYSTEM_INACTIVE = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t GENERIC_RENAME_ERROR = MAKE_RETURN_CODE(3);
//! [EXPORT] : File system is currently busy
@ -74,14 +73,6 @@ class HasFileSystemIF {
return MessageQueueIF::NO_QUEUE;
}
// Get the base filename without the full directory path
virtual ReturnValue_t getBaseFilename(FilesystemParams params, char* nameBuf, size_t maxLen,
size_t& baseNameLen) = 0;
virtual bool isDirectory(const char* path) = 0;
virtual bool getFileSize(FilesystemParams params, uint64_t& fileSize) = 0;
virtual bool fileExists(FilesystemParams params) = 0;
/**

Some files were not shown because too many files have changed in this diff Show More