adapted object factory to fsfw changes

This commit is contained in:
Jakob Meier 2021-04-24 22:54:18 +02:00
commit 52b549b97c
56 changed files with 925 additions and 746 deletions

View File

@ -184,6 +184,7 @@ endif()
target_include_directories(${LIB_FSFW_NAME} INTERFACE target_include_directories(${LIB_FSFW_NAME} INTERFACE
${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
${FSFW_CONFIG_PATH_ABSOLUTE} ${FSFW_CONFIG_PATH_ABSOLUTE}
${FSFW_ADD_INC_PATHS_ABS}
) )
# Includes path required to compile FSFW itself as well # Includes path required to compile FSFW itself as well

View File

@ -3,9 +3,9 @@
const char* const FSFW_VERSION_NAME = "ASTP"; const char* const FSFW_VERSION_NAME = "ASTP";
#define FSFW_VERSION 0 #define FSFW_VERSION 1
#define FSFW_SUBVERSION 0 #define FSFW_SUBVERSION 0
#define FSFW_REVISION 1 #define FSFW_REVISION 0

View File

@ -147,11 +147,6 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
return result; return result;
} }
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeAddress);
return result;
}
/* We don't need to report the objectId, as we receive REQUESTED data before the completion /* We don't need to report the objectId, as we receive REQUESTED data before the completion
success message. True aperiodic replies need to be reported with another dedicated message. */ success message. True aperiodic replies need to be reported with another dedicated message. */
ActionMessage::setDataReply(&reply, replyId, storeAddress); ActionMessage::setDataReply(&reply, replyId, storeAddress);

View File

@ -17,6 +17,9 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
SharedRingBuffer::~SharedRingBuffer() {
MutexFactory::instance()->deleteMutex(mutex);
}
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
this->fifoDepth = fifoDepth; this->fifoDepth = fifoDepth;

View File

@ -26,6 +26,18 @@ public:
*/ */
SharedRingBuffer(object_id_t objectId, const size_t size, SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes); bool overwriteOld, size_t maxExcessBytes);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
virtual~ SharedRingBuffer();
/** /**
* @brief This function can be used to add an optional FIFO to the class * @brief This function can be used to add an optional FIFO to the class
@ -37,16 +49,7 @@ public:
*/ */
void setToUseReceiveSizeFIFO(size_t fifoDepth); void setToUseReceiveSizeFIFO(size_t fifoDepth);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/** /**
* Unless a read-only constant value is read, all operations on the * Unless a read-only constant value is read, all operations on the

View File

@ -7,7 +7,7 @@ HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
} }
HkSwitchHelper::~HkSwitchHelper() { HkSwitchHelper::~HkSwitchHelper() {
// TODO Auto-generated destructor stub QueueFactory::instance()->deleteMessageQueue(actionQueue);
} }
ReturnValue_t HkSwitchHelper::initialize() { ReturnValue_t HkSwitchHelper::initialize() {

View File

@ -909,27 +909,29 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
errorPrint = "Unknown error"; errorPrint = "Unknown error";
} }
} }
object_id_t objectId = 0xffffffff;
if(owner != nullptr) {
objectId = owner->getObjectId();
}
if(outputType == sif::OutputTypes::OUT_WARNING) { if(outputType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::" << functionName sif::warning << "LocalDataPoolManager::" << functionName << ": Object ID 0x" <<
<< ": Object ID 0x" << std::setw(8) << std::setfill('0') std::setw(8) << std::setfill('0') << std::hex << objectId << " | " << errorPrint <<
<< std::hex << owner->getObjectId() << " | " << errorPrint std::dec << std::setfill(' ') << std::endl;
<< std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
functionName, owner->getObjectId(), errorPrint); functionName, objectId, errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} }
else if(outputType == sif::OutputTypes::OUT_ERROR) { else if(outputType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalDataPoolManager::" << functionName sif::error << "LocalDataPoolManager::" << functionName << ": Object ID 0x" <<
<< ": Object ID 0x" << std::setw(8) << std::setfill('0') std::setw(8) << std::setfill('0') << std::hex << objectId << " | " << errorPrint <<
<< std::hex << owner->getObjectId() << " | " << errorPrint std::dec << std::setfill(' ') << std::endl;
<< std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
functionName, owner->getObjectId(), errorPrint); functionName, objectId, errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} }
#endif /* #if FSFW_VERBOSE_LEVEL >= 1 */ #endif /* #if FSFW_VERBOSE_LEVEL >= 1 */

View File

@ -40,6 +40,13 @@
//! Specify whether a special mode store is used for Subsystem components. //! Specify whether a special mode store is used for Subsystem components.
#define FSFW_USE_MODESTORE 0 #define FSFW_USE_MODESTORE 0
//! Defines if the real time scheduler for linux should be used.
//! If set to 0, this will also disable priority settings for linux
//! as most systems will not allow to set nice values without privileges
//! For embedded linux system set this to 1.
//! If set to 1 the binary needs "cap_sys_nice=eip" privileges to run
#define FSFW_USE_REALTIME_FOR_LINUX 1
namespace fsfwconfig { namespace fsfwconfig {
//! Default timestamp size. The default timestamp will be an eight byte CDC //! Default timestamp size. The default timestamp will be an eight byte CDC
//! short timestamp. //! short timestamp.
@ -52,11 +59,12 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
//! Defines the FIFO depth of each commanding service base which //! Defines the FIFO depth of each commanding service base which
//! also determines how many commands a CSB service can handle in one cycle //! also determines how many commands a CSB service can handle in one cycle
//! simulataneously. This will increase the required RAM for //! simultaneously. This will increase the required RAM for
//! each CSB service ! //! each CSB service !
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6; static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124; static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
} }
#endif /* CONFIG_FSFWCONFIG_H_ */ #endif /* CONFIG_FSFWCONFIG_H_ */

View File

@ -24,6 +24,13 @@
* 1. check logic when active-> checkChildrenStateOn * 1. check logic when active-> checkChildrenStateOn
* 2. transition logic to change the mode -> commandChildren * 2. transition logic to change the mode -> commandChildren
* *
* Important:
*
* 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 { class AssemblyBase: public SubsystemBase {
public: public:
@ -41,9 +48,6 @@ public:
virtual ~AssemblyBase(); virtual ~AssemblyBase();
protected: protected:
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
// (or return internalState directly?)
/** /**
* Command children to reach [mode,submode] combination * Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly, * Can be done by setting #commandsOutstanding correctly,
@ -68,6 +72,18 @@ protected:
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
Submode_t wantedSubmode) = 0; Submode_t wantedSubmode) = 0;
/**
* Check whether a combination of mode and submode is valid.
*
* Ground Controller like precise return values from HasModesIF.
* So, please return any of them.
*
* @param mode The targeted mode
* @param submode The targeted submmode
* @return Any information why this combination is invalid from HasModesIF
* like HasModesIF::INVALID_SUBMODE.
* On success return HasReturnvaluesIF::RETURN_OK
*/
virtual ReturnValue_t isModeCombinationValid(Mode_t mode, virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
Submode_t submode) = 0; Submode_t submode) = 0;

View File

@ -1496,7 +1496,7 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
if(errorCode == ObjectManagerIF::CHILD_INIT_FAILED) { if(errorCode == ObjectManagerIF::CHILD_INIT_FAILED) {
errorPrint = "Initialization error"; errorPrint = "Initialization error";
} }
if(errorCode == HasReturnvaluesIF::RETURN_FAILED) { else if(errorCode == HasReturnvaluesIF::RETURN_FAILED) {
if(errorType == sif::OutputTypes::OUT_WARNING) { if(errorType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning"; errorPrint = "Generic Warning";
} }
@ -1508,6 +1508,9 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
errorPrint = "Unknown error"; errorPrint = "Unknown error";
} }
} }
if(functionName == nullptr) {
functionName = "unknown function";
}
if(errorType == sif::OutputTypes::OUT_WARNING) { if(errorType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -1516,7 +1519,7 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
std::dec << std::setfill(' ') << std::endl; std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n", sif::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint); functionName, this->getObjectId(), errorPrint);
#endif #endif
} }
else if(errorType == sif::OutputTypes::OUT_ERROR) { else if(errorType == sif::OutputTypes::OUT_ERROR) {
@ -1527,7 +1530,7 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
<< std::setfill(' ') << std::endl; << std::setfill(' ') << std::endl;
#else #else
sif::printError("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n", sif::printError("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint); functionName, this->getObjectId(), errorPrint);
#endif #endif
} }

View File

@ -16,9 +16,9 @@ ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
CommandMessage command; CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command); ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
healthHelper.handleHealthCommand(&command); result = healthHelper.handleHealthCommand(&command);
} }
return HasReturnvaluesIF::RETURN_OK; return result;
} }
ReturnValue_t HealthDevice::initialize() { ReturnValue_t HealthDevice::initialize() {

View File

@ -109,6 +109,6 @@ bool EventMessage::isClearedEventMessage() {
return getEvent() == INVALID_EVENT; return getEvent() == INVALID_EVENT;
} }
size_t EventMessage::getMinimumMessageSize() { size_t EventMessage::getMinimumMessageSize() const {
return EVENT_MESSAGE_SIZE; return EVENT_MESSAGE_SIZE;
} }

View File

@ -45,7 +45,7 @@ public:
protected: protected:
static const Event INVALID_EVENT = 0; static const Event INVALID_EVENT = 0;
virtual size_t getMinimumMessageSize(); virtual size_t getMinimumMessageSize() const override;
}; };

View File

@ -60,7 +60,7 @@ void arrayprinter::printHex(const uint8_t *data, size_t size,
#else #else
// General format: 0x01, 0x02, 0x03 so it is number of chars times 6 // General format: 0x01, 0x02, 0x03 so it is number of chars times 6
// plus line break plus small safety margin. // plus line break plus small safety margin.
char printBuffer[(size + 1) * 7 + 1]; char printBuffer[(size + 1) * 7 + 1] = {};
size_t currentPos = 0; size_t currentPos = 0;
for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// To avoid buffer overflows. // To avoid buffer overflows.
@ -103,7 +103,7 @@ void arrayprinter::printDec(const uint8_t *data, size_t size,
#else #else
// General format: 32, 243, -12 so it is number of chars times 5 // General format: 32, 243, -12 so it is number of chars times 5
// plus line break plus small safety margin. // plus line break plus small safety margin.
char printBuffer[(size + 1) * 5 + 1]; char printBuffer[(size + 1) * 5 + 1] = {};
size_t currentPos = 0; size_t currentPos = 0;
for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// To avoid buffer overflows. // To avoid buffer overflows.

View File

@ -68,14 +68,30 @@ void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
MutexGuard(mutex, timeoutType, mutexTimeoutMs); MutexGuard(mutex, timeoutType, mutexTimeoutMs);
size_t size = 0; size_t size = 0;
uint16_t count = healthMap.size(); uint16_t count = healthMap.size();
SerializeAdapter::serialize(&count, ReturnValue_t result = SerializeAdapter::serialize(&count,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG); &pointer, &size, maxSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "HealthTable::printAll: Serialization of health table failed" << std::endl;
#else
sif::printWarning("HealthTable::printAll: Serialization of health table failed\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return;
}
for (const auto& health: healthMap) { for (const auto& health: healthMap) {
SerializeAdapter::serialize(&health.first, result = SerializeAdapter::serialize(&health.first,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG); &pointer, &size, maxSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
uint8_t healthValue = health.second; uint8_t healthValue = health.second;
SerializeAdapter::serialize(&healthValue, &pointer, &size, result = SerializeAdapter::serialize(&healthValue, &pointer, &size,
maxSize, SerializeIF::Endianness::BIG); maxSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
} }
} }
@ -86,7 +102,7 @@ ReturnValue_t HealthTable::iterate(HealthEntry *value, bool reset) {
mapIterator = healthMap.begin(); mapIterator = healthMap.begin();
} }
if (mapIterator == healthMap.end()) { if (mapIterator == healthMap.end()) {
result = HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
*value = *mapIterator; *value = *mapIterator;
mapIterator++; mapIterator++;

View File

@ -27,7 +27,7 @@ public:
//! Returned if a reply method was called without partner //! Returned if a reply method was called without partner
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3); static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
//! Returned if the target destination is invalid. //! Returned if the target destination is invalid.
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4); static constexpr ReturnValue_t DESTINATION_INVALID = MAKE_RETURN_CODE(4);
virtual ~MessageQueueIF() {} virtual ~MessageQueueIF() {}
/** /**

View File

@ -86,3 +86,7 @@ size_t MessageQueueMessage::getMaximumMessageSize() const {
return this->MAX_MESSAGE_SIZE; return this->MAX_MESSAGE_SIZE;
} }
size_t MessageQueueMessage::getMaximumDataSize() const {
return this->MAX_DATA_SIZE;
}

View File

@ -139,6 +139,7 @@ public:
virtual void setMessageSize(size_t messageSize) override; virtual void setMessageSize(size_t messageSize) override;
virtual size_t getMinimumMessageSize() const override; virtual size_t getMinimumMessageSize() const override;
virtual size_t getMaximumMessageSize() const override; virtual size_t getMaximumMessageSize() const override;
virtual size_t getMaximumDataSize() const override;
/** /**
* @brief This is a debug method that prints the content. * @brief This is a debug method that prints the content.

View File

@ -72,6 +72,7 @@ public:
virtual void setMessageSize(size_t messageSize) = 0; virtual void setMessageSize(size_t messageSize) = 0;
virtual size_t getMinimumMessageSize() const = 0; virtual size_t getMinimumMessageSize() const = 0;
virtual size_t getMaximumMessageSize() const = 0; virtual size_t getMaximumMessageSize() const = 0;
virtual size_t getMaximumDataSize() const = 0;
}; };

View File

@ -1,35 +1,34 @@
# Check the OS_FSFW variable # Check the OS_FSFW variable
if(${OS_FSFW} STREQUAL "freertos") if(${OS_FSFW} STREQUAL "freertos")
add_subdirectory(FreeRTOS) add_subdirectory(FreeRTOS)
elseif(${OS_FSFW} STREQUAL "rtems") elseif(${OS_FSFW} STREQUAL "rtems")
add_subdirectory(rtems) add_subdirectory(rtems)
elseif(${OS_FSFW} STREQUAL "linux") elseif(${OS_FSFW} STREQUAL "linux")
add_subdirectory(linux) add_subdirectory(linux)
elseif(${OS_FSFW} STREQUAL "host") elseif(${OS_FSFW} STREQUAL "host")
add_subdirectory(host) add_subdirectory(host)
if (WIN32) if (WIN32)
add_subdirectory(windows) add_subdirectory(windows)
elseif(UNIX) elseif(UNIX)
target_sources(${LIB_FSFW_NAME} # We still need to pull in some Linux specific sources
PUBLIC target_sources(${LIB_FSFW_NAME} PUBLIC
linux/TcUnixUdpPollingTask.cpp linux/tcpipHelpers.cpp
linux/TmTcUnixUdpBridge.cpp )
) endif ()
endif ()
else() else()
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..") message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
# Not set. Assumuing this is a host build, try to determine host OS # Not set. Assumuing this is a host build, try to determine host OS
if (WIN32) if (WIN32)
add_subdirectory(host) add_subdirectory(host)
add_subdirectory(windows) add_subdirectory(windows)
elseif (UNIX) elseif (UNIX)
add_subdirectory(linux) add_subdirectory(linux)
else () else ()
# MacOS or other OSes have not been tested yet / are not supported. # MacOS or other OSes have not been tested yet / are not supported.
message(FATAL_ERROR "The host OS could not be determined! Aborting.") message(FATAL_ERROR "The host OS could not be determined! Aborting.")
endif() endif()
endif() endif()

View File

@ -111,7 +111,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
timeval* to) { timeval* to) {
struct tm time_tm; struct tm time_tm = {};
time_tm.tm_year = from->year - 1900; time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1; time_tm.tm_mon = from->month - 1;

View File

@ -135,7 +135,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
QueueHandle_t destination = nullptr; QueueHandle_t destination = nullptr;
if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) { if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) {
return MessageQueueIF::DESTINVATION_INVALID; return MessageQueueIF::DESTINATION_INVALID;
} }
else { else {
destination = reinterpret_cast<QueueHandle_t>(sendTo); destination = reinterpret_cast<QueueHandle_t>(sendTo);

View File

@ -70,6 +70,7 @@ ReturnValue_t TcpTmTcServer::initialize() {
#endif #endif
freeaddrinfo(addrResult); freeaddrinfo(addrResult);
handleError(Protocol::TCP, ErrorSources::BIND_CALL); handleError(Protocol::TCP, ErrorSources::BIND_CALL);
return HasReturnvaluesIF::RETURN_FAILED;
} }
freeaddrinfo(addrResult); freeaddrinfo(addrResult);
@ -84,8 +85,8 @@ TcpTmTcServer::~TcpTmTcServer() {
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
using namespace tcpip; using namespace tcpip;
/* If a connection is accepted, the corresponding socket will be assigned to the new socket */ /* If a connection is accepted, the corresponding socket will be assigned to the new socket */
socket_t clientSocket; socket_t clientSocket = 0;
sockaddr clientSockAddr; sockaddr clientSockAddr = {};
socklen_t connectorSockAddrLen = 0; socklen_t connectorSockAddrLen = 0;
int retval = 0; int retval = 0;
@ -101,6 +102,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
if(clientSocket == INVALID_SOCKET) { if(clientSocket == INVALID_SOCKET) {
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500); handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
closeSocket(clientSocket);
continue; continue;
}; };
@ -122,6 +124,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
/* Done, shut down connection */ /* Done, shut down connection */
retval = shutdown(clientSocket, SHUT_SEND); retval = shutdown(clientSocket, SHUT_SEND);
closeSocket(clientSocket);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -15,7 +15,7 @@
#endif #endif
//! Debugging preprocessor define. //! Debugging preprocessor define.
#define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 #define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId,
object_id_t tmtcUnixUdpBridge, size_t maxRecvSize, object_id_t tmtcUnixUdpBridge, size_t maxRecvSize,
@ -66,10 +66,13 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000);
continue; continue;
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 #if FSFW_UDP_RECV_WIRETAPPING_ENABLED == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UdpTcPollingTask::performOperation: " << bytesReceived << sif::debug << "UdpTcPollingTask::performOperation: " << bytesReceived <<
" bytes received" << std::endl; " bytes received" << std::endl;
#else
#endif #endif
#endif /* FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 */
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
if(result != HasReturnvaluesIF::RETURN_FAILED) { if(result != HasReturnvaluesIF::RETURN_FAILED) {
@ -84,7 +87,7 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) { ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
store_address_t storeId; store_address_t storeId;
#if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 #if FSFW_UDP_RECV_WIRETAPPING_ENABLED == 1
arrayprinter::print(receptionBuffer.data(), bytesRead); arrayprinter::print(receptionBuffer.data(), bytesRead);
#endif #endif

View File

@ -70,6 +70,7 @@ ReturnValue_t UdpTmTcBridge::initialize() {
hints.ai_family = AF_INET; hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP; hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE;
/* Set up UDP socket: /* Set up UDP socket:
https://en.wikipedia.org/wiki/Getaddrinfo https://en.wikipedia.org/wiki/Getaddrinfo
@ -95,6 +96,10 @@ ReturnValue_t UdpTmTcBridge::initialize() {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
#if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
tcpip::printAddress(addrResult->ai_addr);
#endif
retval = bind(serverSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen)); retval = bind(serverSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if(retval != 0) { if(retval != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -103,6 +108,7 @@ ReturnValue_t UdpTmTcBridge::initialize() {
#endif #endif
freeaddrinfo(addrResult); freeaddrinfo(addrResult);
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::BIND_CALL); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::BIND_CALL);
return HasReturnvaluesIF::RETURN_FAILED;
} }
freeaddrinfo(addrResult); freeaddrinfo(addrResult);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -120,10 +126,8 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
/* The target address can be set by different threads so this lock ensures thread-safety */ /* The target address can be set by different threads so this lock ensures thread-safety */
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 #if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
char ipAddress [15]; tcpip::printAddress(&clientAddress);
sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
#endif #endif
int bytesSent = sendto( int bytesSent = sendto(
@ -151,13 +155,11 @@ void UdpTmTcBridge::checkAndSetClientAddress(sockaddr& newAddress) {
/* The target address can be set by different threads so this lock ensures thread-safety */ /* The target address can be set by different threads so this lock ensures thread-safety */
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 #if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
char ipAddress [15]; tcpip::printAddress(&newAddress);
sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, tcpip::printAddress(&clientAddress);
&newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
sif::debug << "IP Address Old: " << inet_ntop(AF_INET,
&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
#endif #endif
registerCommConnect(); registerCommConnect();
/* Set new IP address to reply to */ /* Set new IP address to reply to */

View File

@ -1,4 +1,9 @@
#include "tcpipCommon.h" #include "tcpipCommon.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#endif
void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string &protStr, void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string &protStr,
std::string &srcString) { std::string &srcString) {
@ -34,3 +39,37 @@ void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std:
srcString = "unknown call"; srcString = "unknown call";
} }
} }
void tcpip::printAddress(struct sockaddr* addr) {
char ipAddress[INET6_ADDRSTRLEN] = {};
const char* stringPtr = NULL;
switch(addr->sa_family) {
case AF_INET: {
struct sockaddr_in *addrIn = reinterpret_cast<struct sockaddr_in*>(addr);
stringPtr = inet_ntop(AF_INET, &(addrIn->sin_addr), ipAddress, INET_ADDRSTRLEN);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addrIn = reinterpret_cast<struct sockaddr_in6*>(addr);
stringPtr = inet_ntop(AF_INET6, &(addrIn->sin6_addr), ipAddress, INET6_ADDRSTRLEN);
break;
}
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
if(stringPtr == NULL) {
sif::debug << "Could not convert IP address to text representation, error code "
<< errno << std::endl;
}
else {
sif::debug << "IP Address Sender: " << ipAddress << std::endl;
}
#else
if(stringPtr == NULL) {
sif::printDebug("Could not convert IP address to text representation, error code %d\n",
errno);
}
else {
sif::printDebug("IP Address Sender: %s\n", ipAddress);
}
#endif
}

View File

@ -4,6 +4,13 @@
#include "../../timemanager/clockDefinitions.h" #include "../../timemanager/clockDefinitions.h"
#include <string> #include <string>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#include <arpa/inet.h>
#endif
namespace tcpip { namespace tcpip {
const char* const DEFAULT_SERVER_PORT = "7301"; const char* const DEFAULT_SERVER_PORT = "7301";
@ -28,8 +35,8 @@ enum class ErrorSources {
void determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string& protStr, void determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string& protStr,
std::string& srcString); std::string& srcString);
void printAddress(struct sockaddr* addr);
} }
#endif /* FSFW_OSAL_COMMON_TCPIPCOMMON_H_ */ #endif /* FSFW_OSAL_COMMON_TCPIPCOMMON_H_ */

View File

@ -3,7 +3,7 @@
#include "../../ipc/MutexFactory.h" #include "../../ipc/MutexFactory.h"
#include "../../osal/host/Mutex.h" #include "../../osal/host/Mutex.h"
#include "../../osal/host/FixedTimeslotTask.h" #include "../../osal/host/FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
#include "../../tasks/ExecutableObjectIF.h" #include "../../tasks/ExecutableObjectIF.h"
#include <thread> #include <thread>
@ -38,7 +38,6 @@ FixedTimeslotTask::~FixedTimeslotTask(void) {
if(mainThread.joinable()) { if(mainThread.joinable()) {
mainThread.join(); mainThread.join();
} }
delete this;
} }
void FixedTimeslotTask::taskEntryPoint(void* argument) { void FixedTimeslotTask::taskEntryPoint(void* argument) {
@ -119,8 +118,11 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Component " << std::hex << componentId << sif::error << "Component " << std::hex << "0x" << componentId << "not found, "
" not found, not adding it to pst" << std::endl; "not adding it to PST.." << std::dec << std::endl;
#else
sif::printError("Component 0x%08x not found, not adding it to PST..\n",
static_cast<unsigned int>(componentId));
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -64,9 +64,8 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
return MessageQueueIF::EMPTY; return MessageQueueIF::EMPTY;
} }
MutexGuard mutexLock(queueLock, MutexIF::TimeoutType::WAITING, 20); MutexGuard mutexLock(queueLock, MutexIF::TimeoutType::WAITING, 20);
MessageQueueMessage* currentMessage = &messageQueue.front(); std::copy(messageQueue.front().data(), messageQueue.front().data() + messageSize,
std::copy(currentMessage->getBuffer(), message->getBuffer());
currentMessage->getBuffer() + messageSize, message->getBuffer());
messageQueue.pop(); messageQueue.pop();
// The last partner is the first uint32_t field in the message // The last partner is the first uint32_t field in the message
this->lastPartner = message->getSender(); this->lastPartner = message->getSender();
@ -80,7 +79,7 @@ MessageQueueId_t MessageQueue::getLastPartner() const {
ReturnValue_t MessageQueue::flush(uint32_t* count) { ReturnValue_t MessageQueue::flush(uint32_t* count) {
*count = messageQueue.size(); *count = messageQueue.size();
// Clears the queue. // Clears the queue.
messageQueue = std::queue<MessageQueueMessage>(); messageQueue = std::queue<std::vector<uint8_t>>();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -106,6 +105,9 @@ bool MessageQueue::isDefaultDestinationSet() const {
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
if(message == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
message->setSender(sentFrom); message->setSender(sentFrom);
if(message->getMessageSize() > message->getMaximumMessageSize()) { if(message->getMessageSize() > message->getMaximumMessageSize()) {
// Actually, this should never happen or an error will be emitted // Actually, this should never happen or an error will be emitted
@ -128,21 +130,10 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { if(targetQueue->messageQueue.size() < targetQueue->messageDepth) {
MutexGuard mutexLock(targetQueue->queueLock, MutexGuard mutexLock(targetQueue->queueLock, MutexIF::TimeoutType::WAITING, 20);
MutexIF::TimeoutType::WAITING, 20); targetQueue->messageQueue.push(std::vector<uint8_t>(message->getMaximumMessageSize()));
// not ideal, works for now though. memcpy(targetQueue->messageQueue.back().data(), message->getBuffer(),
MessageQueueMessage* mqmMessage = message->getMaximumMessageSize());
dynamic_cast<MessageQueueMessage*>(message);
if(message != nullptr) {
targetQueue->messageQueue.push(*mqmMessage);
}
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message"
"is not MessageQueueMessage!" << std::endl;
#endif
}
} }
else { else {
return MessageQueueIF::FULL; return MessageQueueIF::FULL;

View File

@ -212,7 +212,7 @@ protected:
//static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); //static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private: private:
std::queue<MessageQueueMessage> messageQueue; std::queue<std::vector<uint8_t>> messageQueue;
/** /**
* @brief The class stores the queue id it got assigned. * @brief The class stores the queue id it got assigned.
* If initialization fails, the queue id is set to zero. * If initialization fails, the queue id is set to zero.

View File

@ -21,7 +21,7 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority,
void (*setDeadlineMissedFunc)()) : void (*setDeadlineMissedFunc)()) :
started(false), taskName(name), period(setPeriod), started(false), taskName(name), period(setPeriod),
deadlineMissedFunc(setDeadlineMissedFunc) { deadlineMissedFunc(setDeadlineMissedFunc) {
// It is propably possible to set task priorities by using the native // It is probably possible to set task priorities by using the native
// task handles for Windows / Linux // task handles for Windows / Linux
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
#if defined(_WIN32) #if defined(_WIN32)
@ -38,7 +38,6 @@ PeriodicTask::~PeriodicTask(void) {
if(mainThread.joinable()) { if(mainThread.joinable()) {
mainThread.join(); mainThread.join();
} }
delete this;
} }
void PeriodicTask::taskEntryPoint(void* argument) { void PeriodicTask::taskEntryPoint(void* argument) {

View File

@ -10,6 +10,10 @@ QueueMapManager::QueueMapManager() {
mapLock = MutexFactory::instance()->createMutex(); mapLock = MutexFactory::instance()->createMutex();
} }
QueueMapManager::~QueueMapManager() {
MutexFactory::instance()->deleteMutex(mapLock);
}
QueueMapManager* QueueMapManager::instance() { QueueMapManager* QueueMapManager::instance() {
if (mqManagerInstance == nullptr){ if (mqManagerInstance == nullptr){
mqManagerInstance = new QueueMapManager(); mqManagerInstance = new QueueMapManager();

View File

@ -36,6 +36,8 @@ public:
private: private:
//! External instantiation is forbidden. //! External instantiation is forbidden.
QueueMapManager(); QueueMapManager();
~QueueMapManager();
uint32_t queueCounter = 0; uint32_t queueCounter = 0;
MutexIF* mapLock; MutexIF* mapLock;
QueueMap queueMap; QueueMap queueMap;

View File

@ -190,13 +190,15 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
}else if(status==0){ }
else if (status==0) {
//Success but no message received //Success but no message received
return MessageQueueIF::EMPTY; return MessageQueueIF::EMPTY;
} else { }
else {
//No message was received. Keep lastPartner anyway, I might send //No message was received. Keep lastPartner anyway, I might send
//something later. But still, delete packet content. //something later. But still, delete packet content.
memset(message->getData(), 0, message->getMaximumMessageSize()); memset(message->getData(), 0, message->getMaximumDataSize());
switch(errno){ switch(errno){
case EAGAIN: case EAGAIN:
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages
@ -371,7 +373,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
<<"mq_send to: " << sendTo << " sent from " <<"mq_send to: " << sendTo << " sent from "
<< sentFrom << std::endl; << sentFrom << std::endl;
#endif #endif
return DESTINVATION_INVALID; return DESTINATION_INVALID;
} }
case EINTR: case EINTR:
//The call was interrupted by a signal. //The call was interrupted by a signal.

View File

@ -12,54 +12,56 @@ PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_):
} }
PosixThread::~PosixThread() { PosixThread::~PosixThread() {
//No deletion and no free of Stack Pointer //No deletion and no free of Stack Pointer
} }
ReturnValue_t PosixThread::sleep(uint64_t ns) { ReturnValue_t PosixThread::sleep(uint64_t ns) {
//TODO sleep might be better with timer instead of sleep() //TODO sleep might be better with timer instead of sleep()
timespec time; timespec time;
time.tv_sec = ns/1000000000; time.tv_sec = ns/1000000000;
time.tv_nsec = ns - time.tv_sec*1e9; time.tv_nsec = ns - time.tv_sec*1e9;
//Remaining Time is not set here //Remaining Time is not set here
int status = nanosleep(&time,NULL); int status = nanosleep(&time,NULL);
if(status != 0){ if(status != 0){
switch(errno){ switch(errno){
case EINTR: case EINTR:
//The nanosleep() function was interrupted by a signal. //The nanosleep() function was interrupted by a signal.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
case EINVAL: case EINVAL:
//The rqtp argument specified a nanosecond value less than zero or //The rqtp argument specified a nanosecond value less than zero or
// greater than or equal to 1000 million. // greater than or equal to 1000 million.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void PosixThread::suspend() { void PosixThread::suspend() {
//Wait for SIGUSR1 //Wait for SIGUSR1
int caughtSig = 0; int caughtSig = 0;
sigset_t waitSignal; sigset_t waitSignal;
sigemptyset(&waitSignal); sigemptyset(&waitSignal);
sigaddset(&waitSignal, SIGUSR1); sigaddset(&waitSignal, SIGUSR1);
sigwait(&waitSignal, &caughtSig); sigwait(&waitSignal, &caughtSig);
if (caughtSig != SIGUSR1) { if (caughtSig != SIGUSR1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FixedTimeslotTask: Unknown Signal received: " << sif::error << "FixedTimeslotTask: Unknown Signal received: " <<
caughtSig << std::endl; caughtSig << std::endl;
#endif #endif
} }
} }
void PosixThread::resume(){ void PosixThread::resume(){
/* Signal the thread to start. Makes sense to call kill to start or? ;) /* Signal the thread to start. Makes sense to call kill to start or? ;)
According to POSIX raise(signal) will call pthread_kill(pthread_self(), sig), *
but as the call must be done from the thread itself this is not possible here */ * According to Posix raise(signal) will call pthread_kill(pthread_self(), sig),
pthread_kill(thread,SIGUSR1); * but as the call must be done from the thread itsself this is not possible here
*/
pthread_kill(thread,SIGUSR1);
} }
bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms, bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
@ -91,165 +93,176 @@ bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
} }
} }
/* Update the wake time ready for the next call. */ /* Update the wake time ready for the next call. */
(*prevoiusWakeTime_ms) = nextTimeToWake_ms; (*prevoiusWakeTime_ms) = nextTimeToWake_ms;
if (shouldDelay) { if (shouldDelay) {
uint64_t sleepTime = nextTimeToWake_ms - currentTime_ms; uint64_t sleepTime = nextTimeToWake_ms - currentTime_ms;
PosixThread::sleep(sleepTime * 1000000ull); PosixThread::sleep(sleepTime * 1000000ull);
return true; return true;
} }
/* We are shifting the time in case the deadline was missed like RTEMS */ //We are shifting the time in case the deadline was missed like rtems
(*prevoiusWakeTime_ms) = currentTime_ms; (*prevoiusWakeTime_ms) = currentTime_ms;
return false; return false;
} }
uint64_t PosixThread::getCurrentMonotonicTimeMs(){ uint64_t PosixThread::getCurrentMonotonicTimeMs(){
timespec timeNow; timespec timeNow;
clock_gettime(CLOCK_MONOTONIC_RAW, &timeNow); clock_gettime(CLOCK_MONOTONIC_RAW, &timeNow);
uint64_t currentTime_ms = (uint64_t) timeNow.tv_sec * 1000 uint64_t currentTime_ms = (uint64_t) timeNow.tv_sec * 1000
+ timeNow.tv_nsec / 1000000; + timeNow.tv_nsec / 1000000;
return currentTime_ms; return currentTime_ms;
} }
void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) { void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::debug << "PosixThread::createTask" << std::endl; //sif::debug << "PosixThread::createTask" << std::endl;
#endif #endif
/* /*
* The attr argument points to a pthread_attr_t structure whose contents * The attr argument points to a pthread_attr_t structure whose contents
* are used at thread creation time to determine attributes for the new are used at thread creation time to determine attributes for the new
* thread; this structure is initialized using pthread_attr_init(3) and thread; this structure is initialized using pthread_attr_init(3) and
* related functions. If attr is NULL, then the thread is created with related functions. If attr is NULL, then the thread is created with
* default attributes. default attributes.
*/ */
pthread_attr_t attributes; pthread_attr_t attributes;
int status = pthread_attr_init(&attributes); int status = pthread_attr_init(&attributes);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread attribute init failed with: " << sif::error << "Posix Thread attribute init failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
} }
void* stackPointer; void* stackPointer;
status = posix_memalign(&stackPointer, sysconf(_SC_PAGESIZE), stackSize); status = posix_memalign(&stackPointer, sysconf(_SC_PAGESIZE), stackSize);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Stack init failed with: " << sif::error << "PosixThread::createTask: Stack init failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
if(errno == ENOMEM) { if(errno == ENOMEM) {
size_t stackMb = stackSize/10e6; size_t stackMb = stackSize/10e6;
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Insufficient memory for" sif::error << "PosixThread::createTask: Insufficient memory for"
" the requested " << stackMb << " MB" << std::endl; " the requested " << stackMb << " MB" << std::endl;
#else #else
sif::printError("PosixThread::createTask: Insufficient memory for " sif::printError("PosixThread::createTask: Insufficient memory for "
"the requested %lu MB\n", static_cast<unsigned long>(stackMb)); "the requested %lu MB\n", static_cast<unsigned long>(stackMb));
#endif #endif
} }
else if(errno == EINVAL) { else if(errno == EINVAL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Wrong alignment argument!" sif::error << "PosixThread::createTask: Wrong alignment argument!"
<< std::endl; << std::endl;
#else #else
sif::printError("PosixThread::createTask: " sif::printError("PosixThread::createTask: "
"Wrong alignment argument!\n"); "Wrong alignment argument!\n");
#endif #endif
} }
return; return;
} }
status = pthread_attr_setstack(&attributes, stackPointer, stackSize); status = pthread_attr_setstack(&attributes, stackPointer, stackSize);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: pthread_attr_setstack " sif::error << "PosixThread::createTask: pthread_attr_setstack "
" failed with: " << strerror(status) << std::endl; " failed with: " << strerror(status) << std::endl;
sif::error << "Make sure the specified stack size is valid and is " sif::error << "Make sure the specified stack size is valid and is "
"larger than the minimum allowed stack size." << std::endl; "larger than the minimum allowed stack size." << std::endl;
#endif #endif
} }
status = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED); status = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread attribute setinheritsched failed with: " << sif::error << "Posix Thread attribute setinheritsched failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
} }
#ifndef FSFW_USE_REALTIME_FOR_LINUX
#error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1"
#endif
#if FSFW_USE_REALTIME_FOR_LINUX == 1
// FIFO -> This needs root privileges for the process
status = pthread_attr_setschedpolicy(&attributes,SCHED_FIFO);
if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread attribute schedule policy failed with: " <<
strerror(status) << std::endl;
#endif
}
// TODO FIFO -> This needs root privileges for the process sched_param scheduleParams;
status = pthread_attr_setschedpolicy(&attributes,SCHED_FIFO); scheduleParams.__sched_priority = priority;
if(status != 0){ status = pthread_attr_setschedparam(&attributes, &scheduleParams);
if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread attribute schedule policy failed with: " << sif::error << "Posix Thread attribute schedule params failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
} }
#endif
sched_param scheduleParams; //Set Signal Mask for suspend until startTask is called
scheduleParams.__sched_priority = priority; sigset_t waitSignal;
status = pthread_attr_setschedparam(&attributes, &scheduleParams); sigemptyset(&waitSignal);
if(status != 0){ sigaddset(&waitSignal, SIGUSR1);
status = pthread_sigmask(SIG_BLOCK, &waitSignal, NULL);
if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread attribute schedule params failed with: " << sif::error << "Posix Thread sigmask failed failed with: " <<
strerror(status) << std::endl; strerror(status) << " errno: " << strerror(errno) << std::endl;
#endif #endif
} }
//Set Signal Mask for suspend until startTask is called
sigset_t waitSignal;
sigemptyset(&waitSignal);
sigaddset(&waitSignal, SIGUSR1);
status = pthread_sigmask(SIG_BLOCK, &waitSignal, NULL);
if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread sigmask failed failed with: " <<
strerror(status) << " errno: " << strerror(errno) << std::endl;
#endif
}
status = pthread_create(&thread,&attributes,fnc_,arg_); status = pthread_create(&thread,&attributes,fnc_,arg_);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread create failed with: " << sif::error << "PosixThread::createTask: Failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
sif::error << "For FSFW_USE_REALTIME_FOR_LINUX == 1 make sure to call " <<
"\"all sudo setcap 'cap_sys_nice=eip'\" on the application or set "
"/etc/security/limit.conf" << std::endl;
#else
sif::printError("PosixThread::createTask: Create failed with: %s\n", strerror(status));
sif::printError("For FSFW_USE_REALTIME_FOR_LINUX == 1 make sure to call "
"\"all sudo setcap 'cap_sys_nice=eip'\" on the application or set "
"/etc/security/limit.conf\n");
#endif #endif
} }
status = pthread_setname_np(thread,name); status = pthread_setname_np(thread,name);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: setname failed with: " << sif::error << "PosixThread::createTask: setname failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
if(status == ERANGE) { if(status == ERANGE) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Task name length longer" sif::error << "PosixThread::createTask: Task name length longer"
" than 16 chars. Truncating.." << std::endl; " than 16 chars. Truncating.." << std::endl;
#endif #endif
name[15] = '\0'; name[15] = '\0';
status = pthread_setname_np(thread,name); status = pthread_setname_np(thread,name);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Setting name" sif::error << "PosixThread::createTask: Setting name"
" did not work.." << std::endl; " did not work.." << std::endl;
#endif #endif
} }
} }
} }
status = pthread_attr_destroy(&attributes); status = pthread_attr_destroy(&attributes);
if(status!=0){ if(status!=0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread attribute destroy failed with: " << sif::error << "Posix Thread attribute destroy failed with: " <<
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
} }
} }

View File

@ -1,5 +1,5 @@
#include "TmTcUnixUdpBridge.h" #include "TmTcUnixUdpBridge.h"
#include "tcpipHelpers.h" #include "../common/tcpipHelpers.h"
#include "../../serviceinterface/ServiceInterface.h" #include "../../serviceinterface/ServiceInterface.h"
#include "../../ipc/MutexGuard.h" #include "../../ipc/MutexGuard.h"
@ -12,7 +12,7 @@
//! Debugging preprocessor define. //! Debugging preprocessor define.
#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0 #define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0
const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT; const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort): object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort):

View File

@ -9,7 +9,7 @@
class TmTcUnixUdpBridge: class TmTcUnixUdpBridge:
public TmTcBridge { public TmTcBridge {
friend class TcUnixUdpPollingTask; friend class UdpTcPollingTask;
public: public:
/* The ports chosen here should not be used by any other process. /* The ports chosen here should not be used by any other process.

View File

@ -1,5 +1,6 @@
#include "../common/tcpipHelpers.h" #include "../common/tcpipHelpers.h"
#include "../../serviceinterface/ServiceInterface.h"
#include "../../tasks/TaskFactory.h" #include "../../tasks/TaskFactory.h"
#include <errno.h> #include <errno.h>
@ -98,8 +99,8 @@ void tcpip::handleError(Protocol protocol, ErrorSources errorSrc, dur_millis_t s
sif::warning << "tcpip::handleError: " << protocolString << " | " << errorSrcString << sif::warning << "tcpip::handleError: " << protocolString << " | " << errorSrcString <<
" | " << infoString << std::endl; " | " << infoString << std::endl;
#else #else
sif::printWarning("tcpip::handleError: %s | %s | %s\n", protocolString, sif::printWarning("tcpip::handleError: %s | %s | %s\n", protocolString.c_str(),
errorSrcString, infoString); errorSrcString.c_str(), infoString.c_str());
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
if(sleepDuration > 0) { if(sleepDuration > 0) {

View File

@ -61,7 +61,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
} else { } else {
//No message was received. Keep lastPartner anyway, I might send something later. //No message was received. Keep lastPartner anyway, I might send something later.
//But still, delete packet content. //But still, delete packet content.
memset(message->getData(), 0, message->getMaximumMessageSize()); memset(message->getData(), 0, message->getMaximumDataSize());
} }
return convertReturnCode(status); return convertReturnCode(status);
} }

View File

@ -61,8 +61,7 @@ ReturnValue_t CService200ModeCommanding::prepareCommand(
return result; return result;
} }
ModeMessage::setModeMessage(dynamic_cast<CommandMessage*>(message), ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
modeCommandPacket.getSubmode()); modeCommandPacket.getSubmode());
return result; return result;
} }

View File

@ -15,7 +15,9 @@ Service1TelecommandVerification::Service1TelecommandVerification(
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
} }
Service1TelecommandVerification::~Service1TelecommandVerification() {} Service1TelecommandVerification::~Service1TelecommandVerification() {
QueueFactory::instance()->deleteMessageQueue(tmQueue);
}
MessageQueueId_t Service1TelecommandVerification::getVerificationQueue(){ MessageQueueId_t Service1TelecommandVerification::getVerificationQueue(){
return tmQueue->getId(); return tmQueue->getId();

View File

@ -75,9 +75,8 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
#else #else
sif::printError("Service20ParameterManagement::checkInterfaceAndAcquire" sif::printError("Service20ParameterManagement::checkInterfaceAndAcquire"
"MessageQueue: Can't access object\n"); "MessageQueue: Can't access object\n");
sif::printError("Object ID: 0x%08x\n", objectId); sif::printError("Object ID: 0x%08x\n", *objectId);
sif::printError("Make sure it implements " sif::printError("Make sure it implements ReceivesParameterMessagesIF!\n");
"ReceivesParameterMessagesIF!\n");
#endif #endif
return CommandingServiceBase::INVALID_OBJECT; return CommandingServiceBase::INVALID_OBJECT;

View File

@ -15,7 +15,9 @@ Service5EventReporting::Service5EventReporting(object_id_t objectId,
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
} }
Service5EventReporting::~Service5EventReporting(){} Service5EventReporting::~Service5EventReporting() {
QueueFactory::instance()->deleteMessageQueue(eventQueue);
}
ReturnValue_t Service5EventReporting::performService() { ReturnValue_t Service5EventReporting::performService() {
EventMessage message; EventMessage message;

View File

@ -53,12 +53,14 @@ ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t Service8FunctionManagement::prepareCommand( ReturnValue_t Service8FunctionManagement::prepareCommand(
CommandMessage* message, uint8_t subservice, const uint8_t* tcData, CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
size_t tcDataLen, uint32_t* state, object_id_t objectId) { size_t tcDataLen, uint32_t* state, object_id_t objectId) {
return prepareDirectCommand(dynamic_cast<CommandMessage*>(message), return prepareDirectCommand(message, tcData, tcDataLen);
tcData, tcDataLen);
} }
ReturnValue_t Service8FunctionManagement::prepareDirectCommand( ReturnValue_t Service8FunctionManagement::prepareDirectCommand(
CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) { CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) {
if(message == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) { if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Service8FunctionManagement::prepareDirectCommand:" sif::debug << "Service8FunctionManagement::prepareDirectCommand:"

View File

@ -43,8 +43,8 @@ public:
private: private:
DirectCommand(const DirectCommand &command); DirectCommand(const DirectCommand &command);
object_id_t objectId; object_id_t objectId = 0;
ActionId_t actionId; ActionId_t actionId = 0;
uint32_t parametersSize; //!< [EXPORT] : [IGNORE] uint32_t parametersSize; //!< [EXPORT] : [IGNORE]
const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes

View File

@ -25,7 +25,7 @@ public:
} }
SerializeElement() : SerializeElement() :
LinkedElement<SerializeIF>(this) { LinkedElement<SerializeIF>(this), entry() {
} }
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,

View File

@ -5,8 +5,7 @@
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent,
Mode_t initialMode, uint16_t commandQueueDepth) : Mode_t initialMode, uint16_t commandQueueDepth) :
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), SystemObject(setObjectId), mode(initialMode),
childrenChangedMode(false),
commandQueue(QueueFactory::instance()->createMessageQueue( commandQueue(QueueFactory::instance()->createMessageQueue(
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE)), commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE)),
healthHelper(this, setObjectId), modeHelper(this), parentId(parent) { healthHelper(this, setObjectId), modeHelper(this), parentId(parent) {
@ -167,16 +166,16 @@ MessageQueueId_t SubsystemBase::getCommandQueue() const {
} }
ReturnValue_t SubsystemBase::initialize() { ReturnValue_t SubsystemBase::initialize() {
MessageQueueId_t parentQueue = 0; MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
ReturnValue_t result = SystemObject::initialize(); ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
if (parentId != 0) { if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId); SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) { if (parent == nullptr) {
return RETURN_FAILED; return RETURN_FAILED;
} }
parentQueue = parent->getCommandQueue(); parentQueue = parent->getCommandQueue();

View File

@ -37,6 +37,17 @@ public:
virtual MessageQueueId_t getCommandQueue() const override; virtual MessageQueueId_t getCommandQueue() const override;
/**
* Function to register the child objects.
* Performs a checks if the child does implement HasHealthIF and/or HasModesIF
*
* Also adds them to the internal childrenMap.
*
* @param objectId
* @return RETURN_OK if successful
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(object_id_t objectId); ReturnValue_t registerChild(object_id_t objectId);
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
@ -56,9 +67,9 @@ protected:
Mode_t mode; Mode_t mode;
Submode_t submode; Submode_t submode = SUBMODE_NONE;
bool childrenChangedMode; bool childrenChangedMode = false;
/** /**
* Always check this against <=0, so you are robust against too many replies * Always check this against <=0, so you are robust against too many replies

View File

@ -1,8 +1,10 @@
#include "CCSDSDistributor.h" #include "CCSDSDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#include "../tmtcpacket/SpacePacketBase.h" #include "../tmtcpacket/SpacePacketBase.h"
#define CCSDS_DISTRIBUTOR_DEBUGGING 0
CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid, CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
object_id_t setObjectId): object_id_t setObjectId):
TcDistributor(setObjectId), defaultApid( setDefaultApid ) { TcDistributor(setObjectId), defaultApid( setDefaultApid ) {
@ -11,26 +13,36 @@ CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
CCSDSDistributor::~CCSDSDistributor() {} CCSDSDistributor::~CCSDSDistributor() {}
TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() { TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() {
#if CCSDS_DISTRIBUTOR_DEBUGGING == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
// sif::debug << "CCSDSDistributor::selectDestination received: " << sif::debug << "CCSDSDistributor::selectDestination received: " <<
// this->currentMessage.getStorageId().pool_index << ", " << this->currentMessage.getStorageId().poolIndex << ", " <<
// this->currentMessage.getStorageId().packet_index << std::endl; this->currentMessage.getStorageId().packetIndex << std::endl;
#else
sif::printDebug("CCSDSDistributor::selectDestination received: %d, %d\n",
currentMessage.getStorageId().poolIndex, currentMessage.getStorageId().packetIndex);
#endif
#endif #endif
const uint8_t* packet = nullptr; const uint8_t* packet = nullptr;
size_t size = 0; size_t size = 0;
ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(), ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(),
&packet, &size ); &packet, &size );
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSDistributor::selectDestination: Getting data from" sif::error << "CCSDSDistributor::selectDestination: Getting data from"
" store failed!" << std::endl; " store failed!" << std::endl;
#else
sif::printError("CCSDSDistributor::selectDestination: Getting data from"
" store failed!\n");
#endif
#endif #endif
} }
SpacePacketBase currentPacket(packet); SpacePacketBase currentPacket(packet);
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 && CCSDS_DISTRIBUTOR_DEBUGGING == 1
// sif:: info << "CCSDSDistributor::selectDestination has packet with APID " sif::info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex <<
// << std::hex << currentPacket.getAPID() << std::dec << std::endl; currentPacket.getAPID() << std::dec << std::endl;
#endif #endif
TcMqMapIter position = this->queueMap.find(currentPacket.getAPID()); TcMqMapIter position = this->queueMap.find(currentPacket.getAPID());
if ( position != this->queueMap.end() ) { if ( position != this->queueMap.end() ) {
@ -76,9 +88,14 @@ ReturnValue_t CCSDSDistributor::initialize() {
ReturnValue_t status = this->TcDistributor::initialize(); ReturnValue_t status = this->TcDistributor::initialize();
this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE ); this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE );
if (this->tcStore == nullptr) { if (this->tcStore == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSDistributor::initialize: Could not initialize" sif::error << "CCSDSDistributor::initialize: Could not initialize"
" TC store!" << std::endl; " TC store!" << std::endl;
#else
sif::printError("CCSDSDistributor::initialize: Could not initialize"
" TC store!\n");
#endif
#endif #endif
status = RETURN_FAILED; status = RETURN_FAILED;
} }

View File

@ -1,22 +1,24 @@
#include "CCSDSDistributorIF.h" #include "CCSDSDistributorIF.h"
#include "PUSDistributor.h" #include "PUSDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#include "../tmtcpacket/pus/TcPacketStored.h" #include "../tmtcpacket/pus/TcPacketStored.h"
#include "../tmtcservices/PusVerificationReport.h" #include "../tmtcservices/PusVerificationReport.h"
#define PUS_DISTRIBUTOR_DEBUGGING 0
PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId,
object_id_t setPacketSource) : object_id_t setPacketSource) :
TcDistributor(setObjectId), checker(setApid), verifyChannel(), TcDistributor(setObjectId), checker(setApid), verifyChannel(),
tcStatus(RETURN_FAILED), packetSource(setPacketSource) {} tcStatus(RETURN_FAILED), packetSource(setPacketSource) {}
PUSDistributor::~PUSDistributor() {} PUSDistributor::~PUSDistributor() {}
PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 && PUS_DISTRIBUTOR_DEBUGGING == 1
// sif:: debug << "PUSDistributor::handlePacket received: " store_address_t storeId = this->currentMessage.getStorageId());
// << this->current_packet_id.store_index << ", " sif:: debug << "PUSDistributor::handlePacket received: " << storeId.poolIndex << ", " <<
// << this->current_packet_id.packet_index << std::endl; storeId.packetIndex << std::endl;
#endif #endif
TcMqMapIter queueMapIt = this->queueMap.end(); TcMqMapIter queueMapIt = this->queueMap.end();
if(this->currentPacket == nullptr) { if(this->currentPacket == nullptr) {
@ -25,15 +27,17 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId()); this->currentPacket->setStoreAddress(this->currentMessage.getStorageId());
if (currentPacket->getWholeData() != nullptr) { if (currentPacket->getWholeData() != nullptr) {
tcStatus = checker.checkPacket(currentPacket); tcStatus = checker.checkPacket(currentPacket);
#ifdef DEBUG
if(tcStatus != HasReturnvaluesIF::RETURN_OK) { if(tcStatus != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "PUSDistributor::handlePacket: Packet format " sif::debug << "PUSDistributor::handlePacket: Packet format invalid, code " <<
<< "invalid, code "<< static_cast<int>(tcStatus) static_cast<int>(tcStatus) << std::endl;
<< std::endl; #else
sif::printDebug("PUSDistributor::handlePacket: Packet format invalid, code %d\n",
static_cast<int>(tcStatus));
#endif
#endif #endif
} }
#endif
uint32_t queue_id = currentPacket->getService(); uint32_t queue_id = currentPacket->getService();
queueMapIt = this->queueMap.find(queue_id); queueMapIt = this->queueMap.find(queue_id);
} }
@ -43,11 +47,12 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
if (queueMapIt == this->queueMap.end()) { if (queueMapIt == this->queueMap.end()) {
tcStatus = DESTINATION_NOT_FOUND; tcStatus = DESTINATION_NOT_FOUND;
#ifdef DEBUG #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "PUSDistributor::handlePacket: Destination not found, " sif::debug << "PUSDistributor::handlePacket: Destination not found" << std::endl;
<< "code "<< static_cast<int>(tcStatus) << std::endl; #else
#endif sif::printDebug("PUSDistributor::handlePacket: Destination not found\n");
#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif #endif
} }
@ -62,46 +67,54 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) { ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
uint16_t serviceId = service->getIdentifier(); uint16_t serviceId = service->getIdentifier();
#if PUS_DISTRIBUTOR_DEBUGGING == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
// sif::info << "Service ID: " << (int)serviceId << std::endl; sif::info << "Service ID: " << static_cast<int>(serviceId) << std::endl;
#else
sif::printInfo("Service ID: %d\n", static_cast<int>(serviceId));
#endif #endif
MessageQueueId_t queue = service->getRequestQueue(); #endif
auto returnPair = queueMap.emplace(serviceId, queue); MessageQueueId_t queue = service->getRequestQueue();
if (not returnPair.second) { auto returnPair = queueMap.emplace(serviceId, queue);
if (not returnPair.second) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PUSDistributor::registerService: Service ID already" sif::error << "PUSDistributor::registerService: Service ID already"
" exists in map." << std::endl; " exists in map" << std::endl;
#else
sif::printError("PUSDistributor::registerService: Service ID already exists in map\n");
#endif #endif
return SERVICE_ID_ALREADY_EXISTS; #endif
} return SERVICE_ID_ALREADY_EXISTS;
return HasReturnvaluesIF::RETURN_OK; }
return HasReturnvaluesIF::RETURN_OK;
} }
MessageQueueId_t PUSDistributor::getRequestQueue() { MessageQueueId_t PUSDistributor::getRequestQueue() {
return tcQueue->getId(); return tcQueue->getId();
} }
ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) { ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) {
if (queueStatus != RETURN_OK) { if (queueStatus != RETURN_OK) {
tcStatus = queueStatus; tcStatus = queueStatus;
} }
if (tcStatus != RETURN_OK) { if (tcStatus != RETURN_OK) {
this->verifyChannel.sendFailureReport(tc_verification::ACCEPTANCE_FAILURE, this->verifyChannel.sendFailureReport(tc_verification::ACCEPTANCE_FAILURE,
currentPacket, tcStatus); currentPacket, tcStatus);
// A failed packet is deleted immediately after reporting, // A failed packet is deleted immediately after reporting,
// otherwise it will block memory. // otherwise it will block memory.
currentPacket->deletePacket(); currentPacket->deletePacket();
return RETURN_FAILED; return RETURN_FAILED;
} else { } else {
this->verifyChannel.sendSuccessReport(tc_verification::ACCEPTANCE_SUCCESS, this->verifyChannel.sendSuccessReport(tc_verification::ACCEPTANCE_SUCCESS,
currentPacket); currentPacket);
return RETURN_OK; return RETURN_OK;
} }
} }
uint16_t PUSDistributor::getIdentifier() { uint16_t PUSDistributor::getIdentifier() {
return checker.getApid(); return checker.getApid();
} }
ReturnValue_t PUSDistributor::initialize() { ReturnValue_t PUSDistributor::initialize() {
@ -111,15 +124,17 @@ ReturnValue_t PUSDistributor::initialize() {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
CCSDSDistributorIF* ccsdsDistributor = CCSDSDistributorIF* ccsdsDistributor =
objectManager->get<CCSDSDistributorIF>(packetSource); objectManager->get<CCSDSDistributorIF>(packetSource);
if (ccsdsDistributor == nullptr) { if (ccsdsDistributor == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PUSDistributor::initialize: Packet source invalid." sif::error << "PUSDistributor::initialize: Packet source invalid" << std::endl;
<< " Make sure it exists and implements CCSDSDistributorIF!" sif::error << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl;
<< std::endl; #else
sif::printError("PUSDistributor::initialize: Packet source invalid\n");
sif::printError("Make sure it exists and implements CCSDSDistributorIF\n");
#endif #endif
return RETURN_FAILED; return RETURN_FAILED;
} }
return ccsdsDistributor->registerApplication(this); return ccsdsDistributor->registerApplication(this);
} }

View File

@ -1,350 +1,352 @@
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
#include "Heater.h" #include "Heater.h"
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
#include "../power/Fuse.h" #include "../power/Fuse.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1) : Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1) :
HealthDevice(objectId, 0), internalState(STATE_OFF), powerSwitcher( HealthDevice(objectId, 0), internalState(STATE_OFF), switch0(switch0), switch1(switch1),
NULL), pcduQueueId(0), switch0(switch0), switch1(switch1), wasOn( heaterOnCountdown(10800000)/*about two orbits*/,
false), timedOut(false), reactedToBeingFaulty(false), passive( parameterHelper(this) {
false), eventQueue(NULL), heaterOnCountdown(10800000)/*about two orbits*/, parameterHelper( eventQueue = QueueFactory::instance()->createMessageQueue();
this), lastAction(CLEAR) {
eventQueue = QueueFactory::instance()->createMessageQueue();
} }
Heater::~Heater() { Heater::~Heater() {
QueueFactory::instance()->deleteMessageQueue(eventQueue); QueueFactory::instance()->deleteMessageQueue(eventQueue);
} }
ReturnValue_t Heater::set() { ReturnValue_t Heater::set() {
passive = false; passive = false;
//wait for clear before doing anything //wait for clear before doing anything
if (internalState == STATE_WAIT) { if (internalState == STATE_WAIT) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
if (healthHelper.healthTable->isHealthy(getObjectId())) { if (healthHelper.healthTable->isHealthy(getObjectId())) {
doAction(SET); doAction(SET);
if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE)){ if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE)){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} else { } else {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
} else { } else {
if (healthHelper.healthTable->isFaulty(getObjectId())) { if (healthHelper.healthTable->isFaulty(getObjectId())) {
if (!reactedToBeingFaulty) { if (!reactedToBeingFaulty) {
reactedToBeingFaulty = true; reactedToBeingFaulty = true;
doAction(CLEAR); doAction(CLEAR);
} }
} }
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
void Heater::clear(bool passive) { void Heater::clear(bool passive) {
this->passive = passive; this->passive = passive;
//Force switching off //Force switching off
if (internalState == STATE_WAIT) { if (internalState == STATE_WAIT) {
internalState = STATE_ON; internalState = STATE_ON;
} }
if (healthHelper.healthTable->isHealthy(getObjectId())) { if (healthHelper.healthTable->isHealthy(getObjectId())) {
doAction(CLEAR); doAction(CLEAR);
} else if (healthHelper.healthTable->isFaulty(getObjectId())) { } else if (healthHelper.healthTable->isFaulty(getObjectId())) {
if (!reactedToBeingFaulty) { if (!reactedToBeingFaulty) {
reactedToBeingFaulty = true; reactedToBeingFaulty = true;
doAction(CLEAR); doAction(CLEAR);
} }
} }
} }
void Heater::doAction(Action action) { void Heater::doAction(Action action) {
//only act if we are not in the right state or in a transition //only act if we are not in the right state or in a transition
if (action == SET) { if (action == SET) {
if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE) if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE)
|| (internalState == STATE_EXTERNAL_CONTROL)) { || (internalState == STATE_EXTERNAL_CONTROL)) {
switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs()); switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs());
internalState = STATE_WAIT_FOR_SWITCHES_ON; internalState = STATE_WAIT_FOR_SWITCHES_ON;
powerSwitcher->sendSwitchCommand(switch0, PowerSwitchIF::SWITCH_ON); powerSwitcher->sendSwitchCommand(switch0, PowerSwitchIF::SWITCH_ON);
powerSwitcher->sendSwitchCommand(switch1, PowerSwitchIF::SWITCH_ON); powerSwitcher->sendSwitchCommand(switch1, PowerSwitchIF::SWITCH_ON);
} }
} else { //clear } else { //clear
if ((internalState == STATE_ON) || (internalState == STATE_FAULTY) if ((internalState == STATE_ON) || (internalState == STATE_FAULTY)
|| (internalState == STATE_EXTERNAL_CONTROL)) { || (internalState == STATE_EXTERNAL_CONTROL)) {
internalState = STATE_WAIT_FOR_SWITCHES_OFF; internalState = STATE_WAIT_FOR_SWITCHES_OFF;
switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs()); switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs());
powerSwitcher->sendSwitchCommand(switch0, powerSwitcher->sendSwitchCommand(switch0,
PowerSwitchIF::SWITCH_OFF); PowerSwitchIF::SWITCH_OFF);
powerSwitcher->sendSwitchCommand(switch1, powerSwitcher->sendSwitchCommand(switch1,
PowerSwitchIF::SWITCH_OFF); PowerSwitchIF::SWITCH_OFF);
} }
} }
} }
void Heater::setPowerSwitcher(PowerSwitchIF* powerSwitch) { void Heater::setPowerSwitcher(PowerSwitchIF* powerSwitch) {
this->powerSwitcher = powerSwitch; this->powerSwitcher = powerSwitch;
} }
ReturnValue_t Heater::performOperation(uint8_t opCode) { ReturnValue_t Heater::performOperation(uint8_t opCode) {
handleQueue(); handleQueue();
handleEventQueue(); handleEventQueue();
if (!healthHelper.healthTable->isFaulty(getObjectId())) { if (!healthHelper.healthTable->isFaulty(getObjectId())) {
reactedToBeingFaulty = false; reactedToBeingFaulty = false;
} }
switch (internalState) { switch (internalState) {
case STATE_ON: case STATE_ON:
if ((powerSwitcher->getSwitchState(switch0) == PowerSwitchIF::SWITCH_OFF) if ((powerSwitcher->getSwitchState(switch0) == PowerSwitchIF::SWITCH_OFF)
|| (powerSwitcher->getSwitchState(switch1) || (powerSwitcher->getSwitchState(switch1)
== PowerSwitchIF::SWITCH_OFF)) { == PowerSwitchIF::SWITCH_OFF)) {
//switch went off on its own //switch went off on its own
//trigger event. FDIR can confirm if it is caused by MniOps and decide on the action //trigger event. FDIR can confirm if it is caused by MniOps and decide on the action
//do not trigger FD events when under external control //do not trigger FD events when under external control
if (healthHelper.getHealth() != EXTERNAL_CONTROL) { if (healthHelper.getHealth() != EXTERNAL_CONTROL) {
triggerEvent(PowerSwitchIF::SWITCH_WENT_OFF); triggerEvent(PowerSwitchIF::SWITCH_WENT_OFF);
} else { } else {
internalState = STATE_EXTERNAL_CONTROL; internalState = STATE_EXTERNAL_CONTROL;
} }
} }
break; break;
case STATE_OFF: case STATE_OFF:
//check if heater is on, ie both switches are on //check if heater is on, ie both switches are on
//if so, just command it to off, to resolve the situation or force a switch stayed on event //if so, just command it to off, to resolve the situation or force a switch stayed on event
//But, only do anything if not already faulty (state off is the stable point for being faulty) //But, only do anything if not already faulty (state off is the stable point for being faulty)
if ((!healthHelper.healthTable->isFaulty(getObjectId())) if ((!healthHelper.healthTable->isFaulty(getObjectId()))
&& (powerSwitcher->getSwitchState(switch0) && (powerSwitcher->getSwitchState(switch0)
== PowerSwitchIF::SWITCH_ON) == PowerSwitchIF::SWITCH_ON)
&& (powerSwitcher->getSwitchState(switch1) && (powerSwitcher->getSwitchState(switch1)
== PowerSwitchIF::SWITCH_ON)) { == PowerSwitchIF::SWITCH_ON)) {
//do not trigger FD events when under external control //do not trigger FD events when under external control
if (healthHelper.getHealth() != EXTERNAL_CONTROL) { if (healthHelper.getHealth() != EXTERNAL_CONTROL) {
internalState = STATE_WAIT_FOR_SWITCHES_OFF; internalState = STATE_WAIT_FOR_SWITCHES_OFF;
switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs()); switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs());
powerSwitcher->sendSwitchCommand(switch0, powerSwitcher->sendSwitchCommand(switch0,
PowerSwitchIF::SWITCH_OFF); PowerSwitchIF::SWITCH_OFF);
powerSwitcher->sendSwitchCommand(switch1, powerSwitcher->sendSwitchCommand(switch1,
PowerSwitchIF::SWITCH_OFF); PowerSwitchIF::SWITCH_OFF);
} else { } else {
internalState = STATE_EXTERNAL_CONTROL; internalState = STATE_EXTERNAL_CONTROL;
} }
} }
break; break;
case STATE_PASSIVE: case STATE_PASSIVE:
break; break;
case STATE_WAIT_FOR_SWITCHES_ON: case STATE_WAIT_FOR_SWITCHES_ON:
if (switchCountdown.hasTimedOut()) { if (switchCountdown.hasTimedOut()) {
if ((powerSwitcher->getSwitchState(switch0) if ((powerSwitcher->getSwitchState(switch0)
== PowerSwitchIF::SWITCH_OFF) == PowerSwitchIF::SWITCH_OFF)
|| (powerSwitcher->getSwitchState(switch1) || (powerSwitcher->getSwitchState(switch1)
== PowerSwitchIF::SWITCH_OFF)) { == PowerSwitchIF::SWITCH_OFF)) {
triggerEvent(HEATER_STAYED_OFF); triggerEvent(HEATER_STAYED_OFF);
internalState = STATE_WAIT_FOR_FDIR; //wait before retrying or anything internalState = STATE_WAIT_FOR_FDIR; //wait before retrying or anything
} else { } else {
triggerEvent(HEATER_ON); triggerEvent(HEATER_ON);
internalState = STATE_ON; internalState = STATE_ON;
} }
} }
break; break;
case STATE_WAIT_FOR_SWITCHES_OFF: case STATE_WAIT_FOR_SWITCHES_OFF:
if (switchCountdown.hasTimedOut()) { if (switchCountdown.hasTimedOut()) {
//only check for both being on (ie heater still on) //only check for both being on (ie heater still on)
if ((powerSwitcher->getSwitchState(switch0) if ((powerSwitcher->getSwitchState(switch0)
== PowerSwitchIF::SWITCH_ON) == PowerSwitchIF::SWITCH_ON)
&& (powerSwitcher->getSwitchState(switch1) && (powerSwitcher->getSwitchState(switch1)
== PowerSwitchIF::SWITCH_ON)) { == PowerSwitchIF::SWITCH_ON)) {
if (healthHelper.healthTable->isFaulty(getObjectId())) { if (healthHelper.healthTable->isFaulty(getObjectId())) {
if (passive) { if (passive) {
internalState = STATE_PASSIVE; internalState = STATE_PASSIVE;
} else { } else {
internalState = STATE_OFF; //just accept it internalState = STATE_OFF; //just accept it
} }
triggerEvent(HEATER_ON); //but throw an event to make it more visible triggerEvent(HEATER_ON); //but throw an event to make it more visible
break; break;
} }
triggerEvent(HEATER_STAYED_ON); triggerEvent(HEATER_STAYED_ON);
internalState = STATE_WAIT_FOR_FDIR; //wait before retrying or anything internalState = STATE_WAIT_FOR_FDIR; //wait before retrying or anything
} else { } else {
triggerEvent(HEATER_OFF); triggerEvent(HEATER_OFF);
if (passive) { if (passive) {
internalState = STATE_PASSIVE; internalState = STATE_PASSIVE;
} else { } else {
internalState = STATE_OFF; internalState = STATE_OFF;
} }
} }
} }
break; break;
default: default:
break; break;
} }
if ((powerSwitcher->getSwitchState(switch0) == PowerSwitchIF::SWITCH_ON) if ((powerSwitcher->getSwitchState(switch0) == PowerSwitchIF::SWITCH_ON)
&& (powerSwitcher->getSwitchState(switch1) && (powerSwitcher->getSwitchState(switch1)
== PowerSwitchIF::SWITCH_ON)) { == PowerSwitchIF::SWITCH_ON)) {
if (wasOn) { if (wasOn) {
if (heaterOnCountdown.hasTimedOut()) { if (heaterOnCountdown.hasTimedOut()) {
//SHOULDDO this means if a heater fails in single mode, the timeout will start again //SHOULDDO this means if a heater fails in single mode, the timeout will start again
//I am not sure if this is a bug, but atm I have no idea how to fix this and think //I am not sure if this is a bug, but atm I have no idea how to fix this and think
//it will be ok. whatcouldpossiblygowrong™ //it will be ok. whatcouldpossiblygowrong™
if (!timedOut) { if (!timedOut) {
triggerEvent(HEATER_TIMEOUT); triggerEvent(HEATER_TIMEOUT);
timedOut = true; timedOut = true;
} }
} }
} else { } else {
wasOn = true; wasOn = true;
heaterOnCountdown.resetTimer(); heaterOnCountdown.resetTimer();
timedOut = false; timedOut = false;
} }
} else { } else {
wasOn = false; wasOn = false;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void Heater::setSwitch(uint8_t number, ReturnValue_t state, void Heater::setSwitch(uint8_t number, ReturnValue_t state,
uint32_t* uptimeOfSwitching) { uint32_t* uptimeOfSwitching) {
if (powerSwitcher == NULL) { if (powerSwitcher == NULL) {
return; return;
} }
if (powerSwitcher->getSwitchState(number) == state) { if (powerSwitcher->getSwitchState(number) == state) {
*uptimeOfSwitching = INVALID_UPTIME; *uptimeOfSwitching = INVALID_UPTIME;
} else { } else {
if ((*uptimeOfSwitching == INVALID_UPTIME)) { if ((*uptimeOfSwitching == INVALID_UPTIME)) {
powerSwitcher->sendSwitchCommand(number, state); powerSwitcher->sendSwitchCommand(number, state);
Clock::getUptime(uptimeOfSwitching); Clock::getUptime(uptimeOfSwitching);
} else { } else {
uint32_t currentUptime; uint32_t currentUptime;
Clock::getUptime(&currentUptime); Clock::getUptime(&currentUptime);
if (currentUptime - *uptimeOfSwitching if (currentUptime - *uptimeOfSwitching
> powerSwitcher->getSwitchDelayMs()) { > powerSwitcher->getSwitchDelayMs()) {
*uptimeOfSwitching = INVALID_UPTIME; *uptimeOfSwitching = INVALID_UPTIME;
if (healthHelper.healthTable->isHealthy(getObjectId())) { if (healthHelper.healthTable->isHealthy(getObjectId())) {
if (state == PowerSwitchIF::SWITCH_ON) { if (state == PowerSwitchIF::SWITCH_ON) {
triggerEvent(HEATER_STAYED_OFF); triggerEvent(HEATER_STAYED_OFF);
} else { } else {
triggerEvent(HEATER_STAYED_ON); triggerEvent(HEATER_STAYED_ON);
} }
} }
//SHOULDDO MiniOps during switch timeout leads to a faulty switch }
} }
} }
}
} }
MessageQueueId_t Heater::getCommandQueue() const { MessageQueueId_t Heater::getCommandQueue() const {
return commandQueue->getId(); return commandQueue->getId();
} }
ReturnValue_t Heater::initialize() { ReturnValue_t Heater::initialize() {
ReturnValue_t result = SystemObject::initialize(); ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
EventManagerIF* manager = objectManager->get<EventManagerIF>( EventManagerIF* manager = objectManager->get<EventManagerIF>(
objects::EVENT_MANAGER); objects::EVENT_MANAGER);
if (manager == NULL) { if (manager == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
result = manager->registerListener(eventQueue->getId()); result = manager->registerListener(eventQueue->getId());
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
ConfirmsFailuresIF* pcdu = objectManager->get<ConfirmsFailuresIF>( ConfirmsFailuresIF* pcdu = objectManager->get<ConfirmsFailuresIF>(
DeviceHandlerFailureIsolation::powerConfirmationId); DeviceHandlerFailureIsolation::powerConfirmationId);
if (pcdu == NULL) { if (pcdu == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
pcduQueueId = pcdu->getEventReceptionQueue(); pcduQueueId = pcdu->getEventReceptionQueue();
result = manager->subscribeToAllEventsFrom(eventQueue->getId(), result = manager->subscribeToAllEventsFrom(eventQueue->getId(),
getObjectId()); getObjectId());
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
result = parameterHelper.initialize(); result = parameterHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
result = healthHelper.initialize(); result = healthHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void Heater::handleQueue() { void Heater::handleQueue() {
CommandMessage command; CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command); ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
result = healthHelper.handleHealthCommand(&command); result = healthHelper.handleHealthCommand(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
return; return;
} }
parameterHelper.handleParameterMessage(&command); result = parameterHelper.handleParameterMessage(&command);
} if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
}
} }
ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId, ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) { uint16_t startAtIndex) {
if (domainId != DOMAIN_ID_BASE) { if (domainId != DOMAIN_ID_BASE) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (uniqueId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(heaterOnCountdown.timeout); parameterWrapper->set(heaterOnCountdown.timeout);
break; break;
default: default:
return INVALID_IDENTIFIER_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void Heater::handleEventQueue() { void Heater::handleEventQueue() {
EventMessage event; EventMessage event;
for (ReturnValue_t result = eventQueue->receiveMessage(&event); for (ReturnValue_t result = eventQueue->receiveMessage(&event);
result == HasReturnvaluesIF::RETURN_OK; result == HasReturnvaluesIF::RETURN_OK;
result = eventQueue->receiveMessage(&event)) { result = eventQueue->receiveMessage(&event)) {
switch (event.getMessageId()) { switch (event.getMessageId()) {
case EventMessage::EVENT_MESSAGE: case EventMessage::EVENT_MESSAGE:
switch (event.getEvent()) { switch (event.getEvent()) {
case Fuse::FUSE_WENT_OFF: case Fuse::FUSE_WENT_OFF:
case HEATER_STAYED_OFF: case HEATER_STAYED_OFF:
case HEATER_STAYED_ON://Setting it faulty does not help, but we need to reach a stable state and can check for being faulty before throwing this event again. // HEATER_STAYED_ON is a setting if faulty does not help, but we need to reach a stable state and can check
if (healthHelper.healthTable->isCommandable(getObjectId())) { // for being faulty before throwing this event again.
healthHelper.setHealth(HasHealthIF::FAULTY); case HEATER_STAYED_ON:
internalState = STATE_FAULTY; if (healthHelper.healthTable->isCommandable(getObjectId())) {
} healthHelper.setHealth(HasHealthIF::FAULTY);
break; internalState = STATE_FAULTY;
case PowerSwitchIF::SWITCH_WENT_OFF: }
internalState = STATE_WAIT; break;
event.setMessageId(EventMessage::CONFIRMATION_REQUEST); case PowerSwitchIF::SWITCH_WENT_OFF:
if (pcduQueueId != 0) { internalState = STATE_WAIT;
eventQueue->sendMessage(pcduQueueId, &event); event.setMessageId(EventMessage::CONFIRMATION_REQUEST);
} else { if (pcduQueueId != 0) {
healthHelper.setHealth(HasHealthIF::FAULTY); eventQueue->sendMessage(pcduQueueId, &event);
internalState = STATE_FAULTY; } else {
} healthHelper.setHealth(HasHealthIF::FAULTY);
break; internalState = STATE_FAULTY;
default: }
return; break;
} default:
break; return;
case EventMessage::YOUR_FAULT: }
healthHelper.setHealth(HasHealthIF::FAULTY); break;
internalState = STATE_FAULTY; case EventMessage::YOUR_FAULT:
break; healthHelper.setHealth(HasHealthIF::FAULTY);
case EventMessage::MY_FAULT: internalState = STATE_FAULTY;
//do nothing, we are already in STATE_WAIT and wait for a clear() break;
break; case EventMessage::MY_FAULT:
default: //do nothing, we are already in STATE_WAIT and wait for a clear()
return; break;
} default:
} return;
}
}
} }

View File

@ -1,90 +1,93 @@
#ifndef FRAMEWORK_THERMAL_HEATER_H_ #ifndef FSFW_THERMAL_HEATER_H_
#define FRAMEWORK_THERMAL_HEATER_H_ #define FSFW_THERMAL_HEATER_H_
#include "../devicehandlers/HealthDevice.h" #include "../devicehandlers/HealthDevice.h"
#include "../parameters/ParameterHelper.h" #include "../parameters/ParameterHelper.h"
#include "../power/PowerSwitchIF.h" #include "../power/PowerSwitchIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../timemanager/Countdown.h" #include "../timemanager/Countdown.h"
#include <stdint.h> #include <cstdint>
//class RedundantHeater;
class Heater: public HealthDevice, public ReceivesParameterMessagesIF { class Heater: public HealthDevice, public ReceivesParameterMessagesIF {
friend class RedundantHeater; friend class RedundantHeater;
public: public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER;
static const Event HEATER_ON = MAKE_EVENT(0, severity::INFO); static const Event HEATER_ON = MAKE_EVENT(0, severity::INFO);
static const Event HEATER_OFF = MAKE_EVENT(1, severity::INFO); static const Event HEATER_OFF = MAKE_EVENT(1, severity::INFO);
static const Event HEATER_TIMEOUT = MAKE_EVENT(2, severity::LOW); static const Event HEATER_TIMEOUT = MAKE_EVENT(2, severity::LOW);
static const Event HEATER_STAYED_ON = MAKE_EVENT(3, severity::LOW); static const Event HEATER_STAYED_ON = MAKE_EVENT(3, severity::LOW);
static const Event HEATER_STAYED_OFF = MAKE_EVENT(4, severity::LOW); static const Event HEATER_STAYED_OFF = MAKE_EVENT(4, severity::LOW);
Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1); Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1);
virtual ~Heater(); virtual ~Heater();
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize(); ReturnValue_t initialize();
ReturnValue_t set(); ReturnValue_t set();
void clear(bool passive); void clear(bool passive);
void setPowerSwitcher(PowerSwitchIF *powerSwitch); void setPowerSwitcher(PowerSwitchIF *powerSwitch);
MessageQueueId_t getCommandQueue() const; MessageQueueId_t getCommandQueue() const;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);
protected: protected:
static const uint32_t INVALID_UPTIME = 0; static const uint32_t INVALID_UPTIME = 0;
enum InternalState { enum InternalState {
STATE_ON, STATE_ON,
STATE_OFF, STATE_OFF,
STATE_PASSIVE, STATE_PASSIVE,
STATE_WAIT_FOR_SWITCHES_ON, STATE_WAIT_FOR_SWITCHES_ON,
STATE_WAIT_FOR_SWITCHES_OFF, STATE_WAIT_FOR_SWITCHES_OFF,
STATE_WAIT_FOR_FDIR, //used to avoid doing anything until fdir decided what to do STATE_WAIT_FOR_FDIR, // Used to avoid doing anything until fdir decided what to do
STATE_FAULTY, STATE_FAULTY,
STATE_WAIT, //used when waiting for system to recover from miniops STATE_WAIT, // Used when waiting for system to recover from miniops
STATE_EXTERNAL_CONTROL //entered when under external control and a fdir reaction would be triggered. This is useful when leaving external control into an unknown state // Entered when under external control and a fdir reaction would be triggered.
//if no fdir reaction is triggered under external control the state is still ok and no need for any special treatment is needed // This is useful when leaving external control into an unknown state
} internalState; STATE_EXTERNAL_CONTROL
// If no fdir reaction is triggered under external control the state is still ok and
// no need for any special treatment is needed
} internalState;
PowerSwitchIF *powerSwitcher; PowerSwitchIF *powerSwitcher = nullptr;
MessageQueueId_t pcduQueueId; MessageQueueId_t pcduQueueId = MessageQueueIF::NO_QUEUE;
uint8_t switch0; uint8_t switch0;
uint8_t switch1; uint8_t switch1;
bool wasOn; bool wasOn = false;
bool timedOut; bool timedOut = false;
bool reactedToBeingFaulty; bool reactedToBeingFaulty = false;
bool passive; bool passive = false;
MessageQueueIF* eventQueue; MessageQueueIF* eventQueue = nullptr;
Countdown heaterOnCountdown; Countdown heaterOnCountdown;
Countdown switchCountdown; Countdown switchCountdown;
ParameterHelper parameterHelper; ParameterHelper parameterHelper;
enum Action { enum Action {
SET, CLEAR SET, CLEAR
} lastAction; } lastAction = CLEAR;
void doAction(Action action); void doAction(Action action);
void setSwitch(uint8_t number, ReturnValue_t state, void setSwitch(uint8_t number, ReturnValue_t state,
uint32_t *upTimeOfSwitching); uint32_t *upTimeOfSwitching);
void handleQueue(); void handleQueue();
void handleEventQueue(); void handleEventQueue();
}; };
#endif /* FRAMEWORK_THERMAL_HEATER_H_ */ #endif /* FSFW_THERMAL_HEATER_H_ */

View File

@ -1,11 +1,14 @@
#ifndef TEMPERATURESENSOR_H_ #ifndef FSFW_THERMAL_TEMPERATURESENSOR_H_
#define TEMPERATURESENSOR_H_ #define FSFW_THERMAL_TEMPERATURESENSOR_H_
#include "../thermal/AbstractTemperatureSensor.h" #include "tcsDefinitions.h"
#include "../datapoolglob/GlobalDataSet.h" #include "AbstractTemperatureSensor.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalPoolVariable.h"
#include "../monitoring/LimitMonitor.h" #include "../monitoring/LimitMonitor.h"
/** /**
* @brief This building block handles non-linear value conversion and * @brief This building block handles non-linear value conversion and
* range checks for analog temperature sensors. * range checks for analog temperature sensors.
@ -57,27 +60,25 @@ public:
/** /**
* Instantiate Temperature Sensor Object. * Instantiate Temperature Sensor Object.
* @param setObjectid objectId of the sensor object * @param setObjectid objectId of the sensor object
* @param inputValue Input value which is converted to a temperature * @param inputTemperature Pointer to a raw input value which is converted to an floating
* @param poolVariable Pool Variable to store the temperature value * point C output temperature
* @param vectorIndex Vector Index for the sensor monitor * @param outputGpid Global Pool ID of the output value
* @param parameters Calculation parameters, temperature limits, gradient limit * @param vectorIndex Vector Index for the sensor monitor
* @param datapoolId Datapool ID of the output temperature * @param parameters Calculation parameters, temperature limits, gradient limit
* @param outputSet Output dataset for the output temperature to fetch it with read() * @param outputSet Output dataset for the output temperature to fetch it with read()
* @param thermalModule respective thermal module, if it has one * @param thermalModule Respective thermal module, if it has one
*/ */
TemperatureSensor(object_id_t setObjectid, TemperatureSensor(object_id_t setObjectid,lp_var_t<limitType>* inputTemperature,
inputType *inputValue, PoolVariableIF *poolVariable, gp_id_t outputGpid, uint8_t vectorIndex, Parameters parameters = {0, 0, 0, 0, 0, 0},
uint8_t vectorIndex, uint32_t datapoolId, Parameters parameters = {0, 0, 0, 0, 0, 0}, LocalPoolDataSetBase *outputSet = nullptr, ThermalModuleIF *thermalModule = nullptr) :
GlobDataSet *outputSet = NULL, ThermalModuleIF *thermalModule = NULL) :
AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters), AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters),
inputValue(inputValue), poolVariable(poolVariable), inputTemperature(inputTemperature),
outputTemperature(datapoolId, outputSet, PoolVariableIF::VAR_WRITE), outputTemperature(outputGpid, outputSet, PoolVariableIF::VAR_WRITE),
sensorMonitor(setObjectid, DOMAIN_ID_SENSOR, sensorMonitor(setObjectid, DOMAIN_ID_SENSOR, outputGpid,
GlobalDataPool::poolIdAndPositionToPid(poolVariable->getDataPoolId(), vectorIndex),
DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit, parameters.upperLimit, DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit, parameters.upperLimit,
TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH), TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH),
oldTemperature(20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) { oldTemperature(20), uptimeOfOldTemperature({ thermal::INVALID_TEMPERATURE, 0 }) {
} }
@ -98,7 +99,7 @@ protected:
private: private:
void setInvalid() { void setInvalid() {
outputTemperature = INVALID_TEMPERATURE; outputTemperature = thermal::INVALID_TEMPERATURE;
outputTemperature.setValid(false); outputTemperature.setValid(false);
uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; uptimeOfOldTemperature.tv_sec = INVALID_UPTIME;
sensorMonitor.setToInvalid(); sensorMonitor.setToInvalid();
@ -108,11 +109,8 @@ protected:
UsedParameters parameters; UsedParameters parameters;
inputType * inputValue; lp_var_t<limitType>* inputTemperature;
lp_var_t<float> outputTemperature;
PoolVariableIF *poolVariable;
gp_float_t outputTemperature;
LimitMonitor<limitType> sensorMonitor; LimitMonitor<limitType> sensorMonitor;
@ -120,22 +118,27 @@ protected:
timeval uptimeOfOldTemperature; timeval uptimeOfOldTemperature;
void doChildOperation() { void doChildOperation() {
if (!poolVariable->isValid() ReturnValue_t result = inputTemperature->read(MutexIF::TimeoutType::WAITING, 20);
|| !healthHelper.healthTable->isHealthy(getObjectId())) { if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
if ((not inputTemperature->isValid()) or
(not healthHelper.healthTable->isHealthy(getObjectId()))) {
setInvalid(); setInvalid();
return; return;
} }
outputTemperature = calculateOutputTemperature(*inputValue); outputTemperature = calculateOutputTemperature(inputTemperature->value);
outputTemperature.setValid(PoolVariableIF::VALID); outputTemperature.setValid(PoolVariableIF::VALID);
timeval uptime; timeval uptime;
Clock::getUptime(&uptime); Clock::getUptime(&uptime);
if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) { if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) {
//In theory, we could use an AbsValueMonitor to monitor the gradient. // In theory, we could use an AbsValueMonitor to monitor the gradient.
//But this would require storing the maxGradient in DP and quite some overhead. // But this would require storing the maxGradient in DP and quite some overhead.
//The concept of delta limits is a bit strange anyway. // The concept of delta limits is a bit strange anyway.
float deltaTime; float deltaTime;
float deltaTemp; float deltaTemp;
@ -148,17 +151,17 @@ protected:
} }
if (parameters.gradient < deltaTemp / deltaTime) { if (parameters.gradient < deltaTemp / deltaTime) {
triggerEvent(TEMP_SENSOR_GRADIENT); triggerEvent(TEMP_SENSOR_GRADIENT);
//Don't set invalid, as we did not recognize it as invalid with full authority, let FDIR handle it // Don't set invalid, as we did not recognize it as invalid with full authority,
// let FDIR handle it
} }
} }
//Check is done against raw limits. SHOULDDO: Why? Using <20>C would be more easy to handle.
sensorMonitor.doCheck(outputTemperature.value); sensorMonitor.doCheck(outputTemperature.value);
if (sensorMonitor.isOutOfLimits()) { if (sensorMonitor.isOutOfLimits()) {
uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; uptimeOfOldTemperature.tv_sec = INVALID_UPTIME;
outputTemperature.setValid(PoolVariableIF::INVALID); outputTemperature.setValid(PoolVariableIF::INVALID);
outputTemperature = INVALID_TEMPERATURE; outputTemperature = thermal::INVALID_TEMPERATURE;
} else { } else {
oldTemperature = outputTemperature; oldTemperature = outputTemperature;
uptimeOfOldTemperature = uptime; uptimeOfOldTemperature = uptime;
@ -179,7 +182,10 @@ public:
static const uint16_t ADDRESS_C = 2; static const uint16_t ADDRESS_C = 2;
static const uint16_t ADDRESS_GRADIENT = 3; static const uint16_t ADDRESS_GRADIENT = 3;
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.) //! Changed due to issue with later temperature checking even tough the sensor monitor was
//! confirming already (Was 10 before with comment = Correlates to a 10s confirmation time.
//! Chosen rather large, should not be so bad for components and helps survive glitches.)
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1;
static const uint8_t DOMAIN_ID_SENSOR = 1; static const uint8_t DOMAIN_ID_SENSOR = 1;
@ -219,4 +225,4 @@ public:
}; };
#endif /* TEMPERATURESENSOR_H_ */ #endif /* FSFW_THERMAL_TEMPERATURESENSOR_H_ */

View File

@ -25,6 +25,6 @@ uint32_t TimeMessage::getCounterValue() {
return temp; return temp;
} }
size_t TimeMessage::getMinimumMessageSize() { size_t TimeMessage::getMinimumMessageSize() const {
return this->MAX_SIZE; return this->MAX_SIZE;
} }

View File

@ -11,7 +11,7 @@ protected:
* @brief This call always returns the same fixed size of the message. * @brief This call always returns the same fixed size of the message.
* @return Returns HEADER_SIZE + \c sizeof(timeval) + sizeof(uint32_t). * @return Returns HEADER_SIZE + \c sizeof(timeval) + sizeof(uint32_t).
*/ */
size_t getMinimumMessageSize(); size_t getMinimumMessageSize() const override;
public: public:
/** /**

View File

@ -16,7 +16,9 @@ TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
} }
TmTcBridge::~TmTcBridge() {} TmTcBridge::~TmTcBridge() {
QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue);
}
ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle( ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(
uint8_t sentPacketsPerCycle) { uint8_t sentPacketsPerCycle) {