Merge remote-tracking branch 'origin/eive/develop' into mueller/ipc-pass-arbitrary-args-to-mq-eive

This commit is contained in:
Robin Müller 2022-04-11 14:40:43 +02:00
commit 942d1e5e4b
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
61 changed files with 814 additions and 292 deletions

View File

@ -0,0 +1,27 @@
#ifndef FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
#define FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
#include "fsfw_hal/common/gpio/GpioIF.h"
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
/**
* @brief Additional abstraction layer for handling GPIOs.
*
* @author J. Meier
*/
class Gpio {
public:
Gpio(gpioId_t gpioId, GpioIF* gpioIF) : gpioId(gpioId), gpioIF(gpioIF) {
if (gpioIF == nullptr) {
sif::error << "Gpio::Gpio: Invalid GpioIF" << std::endl;
}
}
ReturnValue_t pullHigh() { return gpioIF->pullHigh(gpioId); }
ReturnValue_t pullLow() { return gpioIF->pullLow(gpioId); }
private:
gpioId_t gpioId = gpio::NO_GPIO;
GpioIF* gpioIF = nullptr;
};
#endif /* FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_ */

View File

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

View File

@ -12,7 +12,9 @@ object_id_t CFDPHandler::packetDestination = 0;
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist) CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
: SystemObject(setObjectId) { : SystemObject(setObjectId) {
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION); auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
distributor = dist; distributor = dist;
} }

View File

@ -13,7 +13,9 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
submode(SUBMODE_NONE), submode(SUBMODE_NONE),
modeHelper(this), modeHelper(this),
healthHelper(this, setObjectId) { healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth); auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); } ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -1,4 +1,4 @@
target_sources(${LIB_FSFW_NAME} PRIVATE target_sources(${LIB_FSFW_NAME} PRIVATE
PoolDataSetBase.cpp PoolDataSetBase.cpp
PoolEntry.cpp PoolEntry.cpp
) )

View File

@ -7,24 +7,26 @@
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
template <typename T> template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid) PoolEntry<T>::PoolEntry(uint8_t len, bool setValid): length(len), valid(setValid) {
: length(static_cast<uint8_t>(initValue.size())), valid(setValid) { this->address = new T[this->length]();
this->address = new T[this->length]; std::memset(this->address, 0, this->getByteSize());
if (initValue.size() == 0) { }
std::memset(this->address, 0, this->getByteSize());
} else { template <typename T>
std::copy(initValue.begin(), initValue.end(), this->address); PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
this->address = new T[this->length]();
if (initValues.size() > 0) {
std::copy(initValues.begin(), initValues.end(), this->address);
} }
} }
template <typename T> template <typename T>
PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid) PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid)
: length(setLength), valid(setValid) { : length(setLength), valid(setValid) {
this->address = new T[this->length]; this->address = new T[this->length]();
if (initValue != nullptr) { if (initValue != nullptr) {
std::memcpy(this->address, initValue, this->getByteSize()); std::memcpy(this->address, initValue, this->getByteSize());
} else {
std::memset(this->address, 0, this->getByteSize());
} }
} }

View File

@ -33,6 +33,9 @@ class PoolEntry : public PoolEntryIF {
"instead! The ECSS standard defines a boolean as a one bit " "instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an " "field. Therefore it is preferred to store a boolean as an "
"uint8_t"); "uint8_t");
PoolEntry(uint8_t len = 1, bool setValid = false);
/** /**
* @brief In the classe's constructor, space is allocated on the heap and * @brief In the classe's constructor, space is allocated on the heap and
* potential initialization values are copied to that space. * potential initialization values are copied to that space.
@ -49,7 +52,7 @@ class PoolEntry : public PoolEntryIF {
* @param setValid * @param setValid
* Sets the initialization flag. It is invalid by default. * Sets the initialization flag. It is invalid by default.
*/ */
PoolEntry(std::initializer_list<T> initValue = {0}, bool setValid = false); PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
/** /**
* @brief In the classe's constructor, space is allocated on the heap and * @brief In the classe's constructor, space is allocated on the heap and

View File

@ -162,6 +162,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
object_id_t getCreatorObjectId(); object_id_t getCreatorObjectId();
bool getReportingEnabled() const; bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/** /**
* Returns the current periodic HK generation interval this set * Returns the current periodic HK generation interval this set
@ -189,7 +190,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* Used for periodic generation. * Used for periodic generation.
*/ */
bool reportingEnabled = false; bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval, void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5); uint8_t nonDiagIntervalFactor = 5);

View File

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

View File

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

View File

@ -39,8 +39,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
childTransitionDelay(5000), childTransitionDelay(5000),
transitionSourceMode(_MODE_POWER_DOWN), transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) { transitionSourceSubMode(SUBMODE_NONE) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue( commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE); cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
insertInCommandMap(RAW_COMMAND_ID); insertInCommandMap(RAW_COMMAND_ID);
cookieInfo.state = COOKIE_UNUSED; cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end(); cookieInfo.pendingCommand = deviceCommandMap.end();
@ -48,9 +49,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase", printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie"); HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
} }
if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
}
} }
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) { void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
@ -126,6 +124,18 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
if (this->fdirInstance == nullptr) {
this->fdirInstance =
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
}
if (this->parent != objects::NO_OBJECT) {
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
if (modeIF != nullptr and healthIF != nullptr) {
setParentQueue(modeIF->getCommandQueue());
}
}
communicationInterface = communicationInterface =
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId); ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
@ -352,14 +362,12 @@ void DeviceHandlerBase::doStateMachine() {
} }
} break; } break;
case _MODE_WAIT_OFF: { case _MODE_WAIT_OFF: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (powerSwitcher == nullptr) { if (powerSwitcher == nullptr) {
setMode(MODE_OFF); setMode(MODE_OFF);
break; break;
} }
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(MODE_ERROR_ON); setMode(MODE_ERROR_ON);
@ -410,7 +418,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet, DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
// No need to check, as we may try to insert multiple times. // No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand); insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
if (hasDifferentReplyId) { if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic); return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
} else { } else {
@ -437,11 +445,15 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
} }
} }
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) { ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply,
DeviceCommandId_t alternativeReplyId) {
DeviceCommandInfo info; DeviceCommandInfo info;
info.expectedReplies = 0; info.expectedReplies = 0;
info.isExecuting = false; info.isExecuting = false;
info.sendReplyTo = NO_COMMANDER; info.sendReplyTo = NO_COMMANDER;
info.useAlternativeReplyId = alternativeReplyId;
info.alternativeReplyId = alternativeReplyId;
auto resultPair = deviceCommandMap.emplace(deviceCommand, info); auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
if (resultPair.second) { if (resultPair.second) {
return RETURN_OK; return RETURN_OK;
@ -451,12 +463,20 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
} }
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) { size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
DeviceReplyIter iter = deviceReplyMap.find(commandId); DeviceCommandId_t replyId = NO_COMMAND_ID;
if (iter != deviceReplyMap.end()) { DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
return iter->second.replyLen; if (command->second.useAlternativeReplyId) {
replyId = command->second.alternativeReplyId;
} else { } else {
return 0; replyId = commandId;
} }
DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles != 0) {
return iter->second.replyLen;
}
}
return 0;
} }
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
@ -651,7 +671,9 @@ void DeviceHandlerBase::doGetWrite() {
// We need to distinguish here, because a raw command never expects a reply. // We need to distinguish here, because a raw command never expects a reply.
//(Could be done in eRIRM, but then child implementations need to be careful. //(Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap(cookieInfo.pendingCommand); DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
result = enableReplyInReplyMap(command, 1, command->second.useAlternativeReplyId,
command->second.alternativeReplyId);
} else { } else {
// always generate a failure event, so that FDIR knows what's up // always generate a failure event, so that FDIR knows what's up
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first); triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);
@ -1385,6 +1407,8 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId, void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
uint32_t parameter) {} uint32_t parameter) {}
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
void DeviceHandlerBase::performOperationHook() {} void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -1407,7 +1431,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
this->poolManager.initializeAfterTaskCreation(); this->poolManager.initializeAfterTaskCreation();
if (setStartupImmediately) { if (setStartupImmediately) {
startTransition(MODE_ON, SUBMODE_NONE); startTransition(MODE_ON, getInitialSubmode());
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -1491,3 +1515,11 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
} }
return commandIter->second.sendReplyTo; return commandIter->second.sendReplyTo;
} }
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
this->powerSwitcher = switcher;
}

View File

@ -103,6 +103,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie, DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20); FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
void setCustomFdir(FailureIsolationBase *fdir);
void setParent(object_id_t parent);
void setPowerSwitcher(PowerSwitchIF *switcher);
void setHkDestination(object_id_t hkDestination); void setHkDestination(object_id_t hkDestination);
/** /**
@ -478,7 +481,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @return - @c RETURN_OK when the command was successfully inserted, * @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply = false,
DeviceCommandId_t alternativeReplyId = 0);
/** /**
* Enables a periodic reply for a given command. It sets to delay cycles to the specified * Enables a periodic reply for a given command. It sets to delay cycles to the specified
@ -647,6 +652,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0, virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
uint32_t parameter = 0); uint32_t parameter = 0);
/**
* @brief Can be overwritten by a child to specify the initial submode when device has been set
* to startup immediately.
*/
virtual Submode_t getInitialSubmode();
protected: protected:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
@ -751,6 +762,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! if this is != NO_COMMANDER, DHB was commanded externally and shall //! if this is != NO_COMMANDER, DHB was commanded externally and shall
//! report everything to commander. //! report everything to commander.
MessageQueueId_t sendReplyTo; MessageQueueId_t sendReplyTo;
bool useAlternativeReplyId;
DeviceCommandId_t alternativeReplyId;
}; };
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>; using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
/** /**
@ -818,6 +831,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** Pointer to the used FDIR instance. If not provided by child, /** Pointer to the used FDIR instance. If not provided by child,
* default class is instantiated. */ * default class is instantiated. */
FailureIsolationBase *fdirInstance; FailureIsolationBase *fdirInstance;
object_id_t parent = objects::NO_OBJECT;
//! To correctly delete the default instance. //! To correctly delete the default instance.
bool defaultFDIRUsed; bool defaultFDIRUsed;

View File

@ -29,6 +29,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
switch (event->getEvent()) { switch (event->getEvent()) {
case HasModesIF::MODE_TRANSITION_FAILED: case HasModesIF::MODE_TRANSITION_FAILED:
case HasModesIF::OBJECT_IN_INVALID_MODE: case HasModesIF::OBJECT_IN_INVALID_MODE:
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
// We'll try a recovery as long as defined in MAX_REBOOT. // We'll try a recovery as long as defined in MAX_REBOOT.
// Might cause some AssemblyBase cycles, so keep number low. // Might cause some AssemblyBase cycles, so keep number low.
handleRecovery(event->getEvent()); handleRecovery(event->getEvent());

View File

@ -109,6 +109,7 @@ class DeviceHandlerIF {
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW); static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW); static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH); static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;

View File

@ -8,7 +8,9 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
parentQueue(parentQueue), parentQueue(parentQueue),
commandQueue(), commandQueue(),
healthHelper(this, setObjectId) { healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3); auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); } HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

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

View File

@ -42,6 +42,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
object_id_t reporterFrom = 0, object_id_t reporterTo = 0, object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false); bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
void printListeners();
protected: protected:
MessageQueueIF* eventReportQueue = nullptr; MessageQueueIF* eventReportQueue = nullptr;

View File

@ -9,8 +9,9 @@
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent, FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
uint8_t messageDepth, uint8_t parameterDomainBase) uint8_t messageDepth, uint8_t parameterDomainBase)
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) { : ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
eventQueue = auto mqArgs = MqArgs(owner, static_cast<void*>(this));
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE); eventQueue = QueueFactory::instance()->createMessageQueue(
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
} }
FailureIsolationBase::~FailureIsolationBase() { FailureIsolationBase::~FailureIsolationBase() {
@ -51,11 +52,12 @@ ReturnValue_t FailureIsolationBase::initialize() {
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent); ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
if (parentIF == nullptr) { if (parentIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FailureIsolationBase::intialize: Parent object" sif::error << "FailureIsolationBase::intialize: Parent object "
<< "invalid." << std::endl; << "invalid" << std::endl;
#endif sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
#if FSFW_CPP_OSTREAM_ENABLED == 1 #else
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl; sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
return RETURN_FAILED; return RETURN_FAILED;

View File

@ -14,13 +14,12 @@ class FailureIsolationBase : public HasReturnvaluesIF,
public HasParametersIF { public HasParametersIF {
public: public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
static const Event FDIR_CHANGED_STATE = //! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2 static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
//!< (oldState) to par1 (newState). //! FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT( static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery. //! FDIR turns off device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT( static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT, FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0); uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);

View File

@ -23,19 +23,15 @@ class HasHealthIF {
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO); static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO); static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW); static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
static const Event OVERWRITING_HEALTH = //! Assembly overwrites health information of children to keep satellite alive.
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
//!< satellite alive. //! Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event TRYING_RECOVERY = static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically //! Recovery is ongoing. Comes twice during recovery.
//!< power-cycle). No parameters. //! P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_STEP = static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: //! Recovery was completed. Not necessarily successful. No parameters.
//!< 0 for the first, 1 for the second event. P2: 0 static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
static const Event RECOVERY_DONE = MAKE_EVENT(
12,
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() {} virtual ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -7,11 +7,13 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth) InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId), : SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue), poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID), internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) { internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); } InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
@ -36,15 +38,14 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) { if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "InternalErrorReporter::performOperation: Errors " sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured!" << std::endl; << "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
sif::debug << "Queue errors: " << newQueueHits << std::endl; << newStoreHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
#else #else
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n"); sif::printDebug(
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits)); "InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits)); "| %lu\n",
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits)); static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
static_cast<unsigned int>(newStoreHits));
#endif #endif
} }
} }

View File

@ -19,32 +19,33 @@ class HasModesIF {
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04); static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
static const Event CHANGING_MODE = //! An object announces changing the mode. p1: target mode. p2: target submode
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode. static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
//!< p2: target submode //! An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event MODE_INFO = MAKE_EVENT( static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
1,
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH); static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW); static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH); static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
static const Event OBJECT_IN_INVALID_MODE = //! Indicates a bug or configuration failure: Object is in a mode it should never be in.
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
//!< mode it should never be in. //! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
static const Event FORCING_MODE = MAKE_EVENT( //! p1: target mode. p2: target submode
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced, static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode //! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
static const Event MODE_CMD_REJECTED = static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1:
//!< called object id, Par2: return code.
static const Mode_t MODE_ON = //! The device is powered and ready to perform operations. In this mode, no commands are
1; //!< The device is powered and ready to perform operations. In this mode, no commands are //! sent by the device handler itself, but direct commands van be commanded and will be
//!< sent by the device handler itself, but direct commands van be commanded and will be //! interpreted
//!< interpreted static constexpr Mode_t MODE_ON = 1;
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in //! The device is powered off. The only command accepted in this mode is a mode change to on.
//!< this mode is a mode change to on. static constexpr Mode_t MODE_OFF = 0;
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
static constexpr Mode_t MODE_INVALID = -1;
static constexpr Mode_t MODE_UNDEFINED = -2;
//! To avoid checks against magic number "0".
static const Submode_t SUBMODE_NONE = 0;
virtual ~HasModesIF() {} virtual ~HasModesIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -95,13 +95,16 @@ void ObjectManager::initialize() {
for (auto const& it : objectList) { for (auto const& it : objectList) {
result = it.second->initialize(); result = it.second->initialize();
if (result != RETURN_OK) { if (result != RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
object_id_t var = it.first;
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8) sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
<< std::setfill('0') << var << std::setfill('0') << it.first << " failed to initialize with code 0x" << result
<< " failed to " << std::dec << std::setfill(' ') << std::endl;
"initialize with code 0x" #else
<< result << std::dec << std::setfill(' ') << std::endl; sif::printError(
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
it.first);
#endif
#endif #endif
errorCount++; errorCount++;
} }

View File

@ -1,4 +1,5 @@
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include <linux/sysinfo.h> #include <linux/sysinfo.h>
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
@ -7,12 +8,13 @@
#include <unistd.h> #include <unistd.h>
#include <fstream> #include <fstream>
#include <cstring>
#include "fsfw/serviceinterface/ServiceInterface.h"
uint16_t Clock::leapSeconds = 0; uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL; MutexIF* Clock::timeMutex = NULL;
void handleClockError(const char* func);
uint32_t Clock::getTicksPerSecond(void) { uint32_t Clock::getTicksPerSecond(void) {
uint32_t ticks = sysconf(_SC_CLK_TCK); uint32_t ticks = sysconf(_SC_CLK_TCK);
return ticks; return ticks;
@ -27,7 +29,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
int status = clock_settime(CLOCK_REALTIME, &timeUnix); int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) { if (status != 0) {
// TODO errno handleClockError("setClock");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -39,7 +41,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000; timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000;
int status = clock_settime(CLOCK_REALTIME, &timeUnix); int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) { if (status != 0) {
// TODO errno handleClockError("setClock");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -49,6 +51,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
timespec timeUnix; timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME, &timeUnix); int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) { if (status != 0) {
handleClockError("getClock_timeval");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
time->tv_sec = timeUnix.tv_sec; time->tv_sec = timeUnix.tv_sec;
@ -151,3 +154,15 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.; *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void handleClockError(const char* func) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::" << func << ": Failed with code " << errno << ": " << strerror(errno)
<< std::endl;
#else
sif::printWarning("Clock::%s: Failed with code %d: %s\n", func, errno, strerror(errno));
#endif
#endif
}

View File

@ -66,7 +66,7 @@ class HasParametersIF {
* @param newValues * @param newValues
* @param startAtIndex Linear index, runs left to right, top to bottom for * @param startAtIndex Linear index, runs left to right, top to bottom for
* matrix indexes. * matrix indexes.
* @return * @return RETURN_OK if parameter is valid and a set function of the parameter wrapper was called.
*/ */
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,

View File

@ -211,9 +211,13 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (data == nullptr) { if (data == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl; sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable or "
"data pointer not set"
<< std::endl;
#else #else
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n"); sif::printWarning(
"ParameterWrapper::copyFrom: Called on read-only variable "
"or data pointer not set\n");
#endif #endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */
return READONLY; return READONLY;
@ -222,9 +226,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (from->readonlyData == nullptr) { if (from->readonlyData == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl; sif::warning << "ParameterWrapper::copyFrom: Source not set" << std::endl;
#else #else
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n"); sif::printWarning("ParameterWrapper::copyFrom: Source not set\n");
#endif #endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */
return SOURCE_NOT_SET; return SOURCE_NOT_SET;
@ -233,9 +237,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (type != from->type) { if (type != from->type) {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl; sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch" << std::endl;
#else #else
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n"); sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch\n");
#endif #endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */
return DATATYPE_MISSMATCH; return DATATYPE_MISSMATCH;
@ -245,9 +249,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (rows == 0 or columns == 0) { if (rows == 0 or columns == 0) {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl; sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero" << std::endl;
#else #else
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n"); sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero\n");
#endif #endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */
return COLUMN_OR_ROWS_ZERO; return COLUMN_OR_ROWS_ZERO;

View File

@ -1,7 +1,8 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME} PRIVATE
PRIVATE Fuse.cpp
Fuse.cpp PowerComponent.cpp
PowerComponent.cpp PowerSensor.cpp
PowerSensor.cpp PowerSwitcher.cpp
PowerSwitcher.cpp DummyPowerSwitcher.cpp
PowerSwitcherComponent.cpp
) )

View File

@ -0,0 +1,46 @@
#include "DummyPowerSwitcher.h"
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
size_t numberOfFuses, uint32_t switchDelayMs)
: SystemObject(objectId),
switcherList(numberOfSwitches),
fuseList(numberOfFuses),
switchDelayMs(switchDelayMs) {}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList;
}
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
this->fuseList = fuseList;
}
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
if (switchNr < switcherList.capacity()) {
switcherList[switchNr] = onOff;
}
return RETURN_FAILED;
}
ReturnValue_t DummyPowerSwitcher::sendFuseOnCommand(uint8_t fuseNr) {
if (fuseNr < fuseList.capacity()) {
fuseList[fuseNr] = FUSE_ON;
}
return RETURN_FAILED;
}
ReturnValue_t DummyPowerSwitcher::getSwitchState(power::Switch_t switchNr) const {
if (switchNr < switcherList.capacity()) {
return switcherList[switchNr];
}
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t DummyPowerSwitcher::getFuseState(uint8_t fuseNr) const {
if (fuseNr < fuseList.capacity()) {
return fuseList[fuseNr];
}
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t DummyPowerSwitcher::getSwitchDelayMs(void) const { return switchDelayMs; }

View File

@ -0,0 +1,31 @@
#ifndef FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_
#define FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_
#include <cstddef>
#include <vector>
#include "PowerSwitchIF.h"
#include "definitions.h"
#include "fsfw/objectmanager/SystemObject.h"
class DummyPowerSwitcher : public SystemObject, public PowerSwitchIF {
public:
DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, size_t numberOfFuses,
uint32_t switchDelayMs = 5000);
void setInitialSwitcherList(std::vector<ReturnValue_t> switcherList);
void setInitialFusesList(std::vector<ReturnValue_t> switcherList);
virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override;
virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override;
virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const override;
virtual ReturnValue_t getFuseState(uint8_t fuseNr) const override;
virtual uint32_t getSwitchDelayMs(void) const override;
private:
std::vector<ReturnValue_t> switcherList;
std::vector<ReturnValue_t> fuseList;
uint32_t switchDelayMs = 5000;
};
#endif /* FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_ */

View File

@ -34,14 +34,14 @@ class Fuse : public SystemObject,
}; };
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT( //! PSS detected that current on a fuse is totally out of bounds.
1, severity::LOW); //!< PSS detected that current on a fuse is totally out of bounds. static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
static const Event FUSE_WENT_OFF = //! PSS detected a fuse that went off.
MAKE_EVENT(2, severity::LOW); //!< PSS detected a fuse that went off. static const Event FUSE_WENT_OFF = MAKE_EVENT(2, severity::LOW);
static const Event POWER_ABOVE_HIGH_LIMIT = //! PSS detected a fuse that violates its limits.
MAKE_EVENT(4, severity::LOW); //!< PSS detected a fuse that violates its limits. static const Event POWER_ABOVE_HIGH_LIMIT = MAKE_EVENT(4, severity::LOW);
static const Event POWER_BELOW_LOW_LIMIT = //! PSS detected a fuse that violates its limits.
MAKE_EVENT(5, severity::LOW); //!< PSS detected a fuse that violates its limits. static const Event POWER_BELOW_LOW_LIMIT = MAKE_EVENT(5, severity::LOW);
typedef std::list<PowerComponentIF *> DeviceList; typedef std::list<PowerComponentIF *> DeviceList;
Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids, Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,

View File

@ -15,7 +15,9 @@ PowerSensor::PowerSensor(object_id_t objectId, sid_t setId, VariableIds ids, Def
limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh), limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh),
voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount, voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount,
limits.voltageMin, limits.voltageMax, events.voltageLow, events.voltageHigh) { limits.voltageMin, limits.voltageMax, events.voltageLow, events.voltageHigh) {
commandQueue = QueueFactory::instance()->createMessageQueue(); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); } PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -3,6 +3,7 @@
#include "../events/Event.h" #include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "definitions.h"
/** /**
* *
* @brief This interface defines a connection to a device that is capable of * @brief This interface defines a connection to a device that is capable of
@ -37,11 +38,11 @@ class PowerSwitchIF : public HasReturnvaluesIF {
* @param switchNr * @param switchNr
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON * @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
*/ */
virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const = 0; virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) = 0;
/** /**
* Sends a command to the Power Unit to enable a certain fuse. * Sends a command to the Power Unit to enable a certain fuse.
*/ */
virtual void sendFuseOnCommand(uint8_t fuseNr) const = 0; virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) = 0;
/** /**
* get the state of the Switches. * get the state of the Switches.
@ -51,7 +52,7 @@ class PowerSwitchIF : public HasReturnvaluesIF {
* - @c SWITCH_OFF if the specified switch is off. * - @c SWITCH_OFF if the specified switch is off.
* - @c RETURN_FAILED if an error occured * - @c RETURN_FAILED if an error occured
*/ */
virtual ReturnValue_t getSwitchState(uint8_t switchNr) const = 0; virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0;
/** /**
* get state of a fuse. * get state of a fuse.
* @param fuseNr * @param fuseNr

View File

@ -1,19 +1,12 @@
#include "fsfw/power/PowerSwitcher.h" #include "fsfw/power/PowerSwitcher.h"
#include "definitions.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2, PowerSwitcher::PowerSwitcher(PowerSwitchIF* switcher, power::Switch_t setSwitch1,
PowerSwitcher::State_t setStartState) power::Switch_t setSwitch2, PowerSwitcher::State_t setStartState)
: state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2) {} : power(switcher), state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2) {}
ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) {
power = ObjectManager::instance()->get<PowerSwitchIF>(powerSwitchId);
if (power == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PowerSwitcher::getStateOfSwitches() { ReturnValue_t PowerSwitcher::getStateOfSwitches() {
SwitchReturn_t result = howManySwitches(); SwitchReturn_t result = howManySwitches();
@ -52,18 +45,37 @@ void PowerSwitcher::commandSwitches(ReturnValue_t onOff) {
return; return;
} }
void PowerSwitcher::turnOn() { void PowerSwitcher::turnOn(bool checkCurrentState) {
if (checkCurrentState) {
if (getStateOfSwitches() == PowerSwitchIF::SWITCH_ON) {
state = SWITCH_IS_ON;
return;
}
}
commandSwitches(PowerSwitchIF::SWITCH_ON); commandSwitches(PowerSwitchIF::SWITCH_ON);
state = WAIT_ON; state = WAIT_ON;
} }
void PowerSwitcher::turnOff() { void PowerSwitcher::turnOff(bool checkCurrentState) {
if (checkCurrentState) {
if (getStateOfSwitches() == PowerSwitchIF::SWITCH_OFF) {
state = SWITCH_IS_OFF;
return;
}
}
commandSwitches(PowerSwitchIF::SWITCH_OFF); commandSwitches(PowerSwitchIF::SWITCH_OFF);
state = WAIT_OFF; state = WAIT_OFF;
} }
bool PowerSwitcher::active() {
if (state == WAIT_OFF or state == WAIT_ON) {
return true;
}
return false;
}
PowerSwitcher::SwitchReturn_t PowerSwitcher::howManySwitches() { PowerSwitcher::SwitchReturn_t PowerSwitcher::howManySwitches() {
if (secondSwitch == NO_SWITCH) { if (secondSwitch == power::NO_SWITCH) {
return ONE_SWITCH; return ONE_SWITCH;
} else { } else {
return TWO_SWITCHES; return TWO_SWITCHES;

View File

@ -14,28 +14,28 @@ class PowerSwitcher : public HasReturnvaluesIF {
SWITCH_IS_OFF, SWITCH_IS_OFF,
SWITCH_IS_ON, SWITCH_IS_ON,
}; };
State_t state;
static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER; static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER;
static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1); static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1);
static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2); static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2);
PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2 = NO_SWITCH, PowerSwitcher(PowerSwitchIF* switcher, uint8_t setSwitch1, uint8_t setSwitch2 = power::NO_SWITCH,
State_t setStartState = SWITCH_IS_OFF); State_t setStartState = SWITCH_IS_OFF);
ReturnValue_t initialize(object_id_t powerSwitchId); void turnOn(bool checkCurrentState = true);
void turnOn(); void turnOff(bool checkCurrentState = true);
void turnOff(); bool active();
void doStateMachine(); void doStateMachine();
State_t getState(); State_t getState();
ReturnValue_t checkSwitchState(); ReturnValue_t checkSwitchState();
uint32_t getSwitchDelay(); uint32_t getSwitchDelay();
uint8_t getFirstSwitch() const; power::Switch_t getFirstSwitch() const;
uint8_t getSecondSwitch() const; power::Switch_t getSecondSwitch() const;
private: private:
uint8_t firstSwitch;
uint8_t secondSwitch;
PowerSwitchIF* power = nullptr; PowerSwitchIF* power = nullptr;
State_t state;
power::Switch_t firstSwitch = power::NO_SWITCH;
power::Switch_t secondSwitch = power::NO_SWITCH;
static const uint8_t NO_SWITCH = 0xFF;
enum SwitchReturn_t { ONE_SWITCH = 1, TWO_SWITCHES = 2 }; enum SwitchReturn_t { ONE_SWITCH = 1, TWO_SWITCHES = 2 };
ReturnValue_t getStateOfSwitches(); ReturnValue_t getStateOfSwitches();
void commandSwitches(ReturnValue_t onOff); void commandSwitches(ReturnValue_t onOff);

View File

@ -0,0 +1,108 @@
#include "PowerSwitcherComponent.h"
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t pwrSwitch)
: SystemObject(objectId), switcher(pwrSwitcher, pwrSwitch), modeHelper(this),
healthHelper(this, objectId) {
queue = QueueFactory::instance()->createMessageQueue();
}
ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
ReturnValue_t result;
CommandMessage command;
for (result = queue->receiveMessage(&command); result == RETURN_OK;
result = queue->receiveMessage(&command)) {
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
}
if(switcher.active()) {
switcher.doStateMachine();
auto currState = switcher.getState();
if (currState == PowerSwitcher::SWITCH_IS_OFF) {
setMode(MODE_OFF, 0);
} else if(currState == PowerSwitcher::SWITCH_IS_ON) {
setMode(MODE_ON, 0);
}
}
return RETURN_OK;
}
ReturnValue_t PowerSwitcherComponent::initialize() {
ReturnValue_t result = modeHelper.initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = healthHelper.initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SystemObject::initialize();
}
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const {
return queue->getId();
}
void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) {
*mode = this->mode;
*submode = this->submode;
}
ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) {
healthHelper.setHealth(health);
return RETURN_OK;
}
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
*msToReachTheMode = 5000;
if(mode != MODE_ON and mode != MODE_OFF) {
return TRANS_NOT_ALLOWED;
}
return RETURN_OK;
}
void PowerSwitcherComponent::startTransition(Mode_t mode, Submode_t submode) {
if(mode == MODE_OFF) {
switcher.turnOff(true);
switcher.doStateMachine();
if(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
setMode(MODE_OFF, 0);
}
} else if (mode == MODE_ON) {
switcher.turnOn(true);
switcher.doStateMachine();
if(switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
setMode(MODE_ON, 0);
}
}
}
void PowerSwitcherComponent::setToExternalControl() {
healthHelper.setHealth(HasHealthIF::EXTERNAL_CONTROL);
}
void PowerSwitcherComponent::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode);
}
void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) {
this->mode = newMode;
this->submode = newSubmode;
modeHelper.modeChanged(mode, submode);
announceMode(false);
}
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() {
return healthHelper.getHealth();
}

View File

@ -0,0 +1,64 @@
#ifndef _FSFW_POWER_POWERSWITCHERCOMPONENT_H_
#define _FSFW_POWER_POWERSWITCHERCOMPONENT_H_
#include <fsfw/health/HasHealthIF.h>
#include <fsfw/health/HealthHelper.h>
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/modes/ModeHelper.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/power/definitions.h>
#include <fsfw/power/PowerSwitcher.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
class PowerSwitchIF;
/**
* @brief Allows to create an power switch object with its own mode and health
* @details
* This basic component allows to create an object which is solely responsible for managing a
* switch. It also has a mode and a health by implementing the respective interface components
* which allows integrating this component into a system mode tree.
*
* Commanding this component to MODE_OFF will cause the switcher to turn the switch off while
* commanding in to MODE_ON will cause the switcher to turn the switch on.
*/
class PowerSwitcherComponent:
public SystemObject,
public HasReturnvaluesIF,
public ExecutableObjectIF,
public HasModesIF,
public HasHealthIF {
public:
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t pwrSwitch);
private:
MessageQueueIF* queue = nullptr;
PowerSwitcher switcher;
Mode_t mode = MODE_OFF;
Submode_t submode = 0;
ModeHelper modeHelper;
HealthHelper healthHelper;
void setMode(Mode_t newMode, Submode_t newSubmode);
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initialize() override;
MessageQueueId_t getCommandQueue() const override;
void getMode(Mode_t *mode, Submode_t *submode) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
void setToExternalControl() override;
void announceMode(bool recursive) override;
ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth() override;
};
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */

View File

@ -0,0 +1,13 @@
#ifndef FSFW_SRC_FSFW_POWER_DEFINITIONS_H_
#define FSFW_SRC_FSFW_POWER_DEFINITIONS_H_
#include <cstdint>
namespace power {
using Switch_t = uint8_t;
static constexpr Switch_t NO_SWITCH = 0xFF;
} // namespace power
#endif /* FSFW_SRC_FSFW_POWER_DEFINITIONS_H_ */

View File

@ -16,7 +16,9 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
apid(apid), apid(apid),
serviceId(serviceId), serviceId(serviceId),
targetDestination(targetDestination) { targetDestination(targetDestination) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
Service1TelecommandVerification::~Service1TelecommandVerification() { Service1TelecommandVerification::~Service1TelecommandVerification() {

View File

@ -214,11 +214,11 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
default: default:
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service3Housekeeping::handleReply: Invalid reply with " sif::warning << "Service3Housekeeping::handleReply: Invalid reply with "
<< "reply command " << command << "!" << std::endl; << "reply command " << command << std::endl;
#else #else
sif::printWarning( sif::printWarning(
"Service3Housekeeping::handleReply: Invalid reply with " "Service3Housekeeping::handleReply: Invalid reply with "
"reply command %hu!\n", "reply command %hu\n",
command); command);
#endif #endif
return CommandingServiceBase::INVALID_REPLY; return CommandingServiceBase::INVALID_REPLY;

View File

@ -12,7 +12,9 @@ Service5EventReporting::Service5EventReporting(object_id_t objectId, uint16_t ap
uint32_t messageQueueDepth) uint32_t messageQueueDepth)
: PusServiceBase(objectId, apid, serviceId), : PusServiceBase(objectId, apid, serviceId),
maxNumberReportsPerCycle(maxNumberReportsPerCycle) { maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
Service5EventReporting::~Service5EventReporting() { Service5EventReporting::~Service5EventReporting() {
@ -36,9 +38,6 @@ ReturnValue_t Service5EventReporting::performService() {
} }
} }
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service5EventReporting::generateEventReport: Too many events" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -87,7 +86,7 @@ ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) {
// to be registered to the event manager to listen for events. // to be registered to the event manager to listen for events.
ReturnValue_t Service5EventReporting::initialize() { ReturnValue_t Service5EventReporting::initialize() {
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER); EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (manager == NULL) { if (manager == nullptr) {
return RETURN_FAILED; return RETURN_FAILED;
} }
// register Service 5 as listener for events // register Service 5 as listener for events

View File

@ -41,7 +41,7 @@
class Service5EventReporting : public PusServiceBase { class Service5EventReporting : public PusServiceBase {
public: public:
Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId, Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId,
size_t maxNumberReportsPerCycle = 10, uint32_t messageQueueDepth = 10); size_t maxNumberReportsPerCycle, uint32_t messageQueueDepth);
virtual ~Service5EventReporting(); virtual ~Service5EventReporting();
/*** /***

View File

@ -6,10 +6,10 @@
class Service9TimeManagement : public PusServiceBase { class Service9TimeManagement : public PusServiceBase {
public: public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
static constexpr Event CLOCK_SET = //!< Clock has been set. P1: New Uptime. P2: Old Uptime
MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
static constexpr Event CLOCK_SET_FAILURE = //!< Clock could not be set. P1: Returncode.
MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode. static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, severity::LOW);
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9; static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;

View File

@ -12,8 +12,12 @@
#include "modes/ModeDefinitions.h" #include "modes/ModeDefinitions.h"
/** /**
* @brief TODO: documentation missing * @brief This class extends the SubsystemBase to perform the management of mode tables
* and mode sequences
* @details * @details
* This class is able to use mode tables and sequences to command all its children into the
* right mode. Fallback sequences can be used to handle failed transitions or have a fallback
* in case a component can't keep its current mode.
*/ */
class Subsystem : public SubsystemBase, public HasModeSequenceIF { class Subsystem : public SubsystemBase, public HasModeSequenceIF {
public: public:

View File

@ -8,11 +8,13 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t
uint16_t commandQueueDepth) uint16_t commandQueueDepth)
: SystemObject(setObjectId), : SystemObject(setObjectId),
mode(initialMode), mode(initialMode),
commandQueue(QueueFactory::instance()->createMessageQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE)),
healthHelper(this, setObjectId), healthHelper(this, setObjectId),
modeHelper(this), modeHelper(this),
parentId(parent) {} parentId(parent) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); } SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
@ -31,8 +33,9 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
info.mode = MODE_OFF; info.mode = MODE_OFF;
} }
} else { } else {
// intentional to force an initial command during system startup
info.commandQueue = child->getCommandQueue(); info.commandQueue = child->getCommandQueue();
info.mode = -1; // intentional to force an initial command during system startup info.mode = HasModesIF::MODE_UNDEFINED;
} }
info.submode = SUBMODE_NONE; info.submode = SUBMODE_NONE;

View File

@ -15,7 +15,14 @@
/** /**
* @defgroup subsystems Subsystem Objects * @defgroup subsystems Subsystem Objects
* Contains all Subsystem and Assemblies * All Subsystem and Assemblies can derive from this class. It contains helper classes to
* perform mode and health handling, which allows OBSW developers to build a mode tree for
* the whole satellite.
*
* Aside from setting up a mode tree and being able to executing mode tables, this class does not
* provide an implementation on what to do with the features. To build a mode tree, helper classes
* like the #AssemblyBase or the #Subsystem class extend and use the functionality of the base
* class.
*/ */
class SubsystemBase : public SystemObject, class SubsystemBase : public SystemObject,
public HasModesIF, public HasModesIF,
@ -96,6 +103,7 @@ class SubsystemBase : public SystemObject,
Submode_t targetSubmode); Submode_t targetSubmode);
/** /**
* This function takes care of sending all according mode commands specified inside a mode table.
* We need to know the target Submode, as children are able to inherit the submode * We need to know the target Submode, as children are able to inherit the submode
* Still, we have a default for all child implementations which do not use submode inheritance * Still, we have a default for all child implementations which do not use submode inheritance
*/ */
@ -123,11 +131,11 @@ class SubsystemBase : public SystemObject,
virtual void performChildOperation() = 0; virtual void performChildOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0; uint32_t *msToReachTheMode) override = 0;
virtual void startTransition(Mode_t mode, Submode_t submode) = 0; virtual void startTransition(Mode_t mode, Submode_t submode) override = 0;
virtual void getMode(Mode_t *mode, Submode_t *submode); virtual void getMode(Mode_t *mode, Submode_t *submode) override;
virtual void setToExternalControl(); virtual void setToExternalControl();

View File

@ -5,7 +5,9 @@
#include "fsfw/tmtcservices/TmTcMessage.h" #include "fsfw/tmtcservices/TmTcMessage.h"
TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) { TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) {
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS); auto mqArgs = MqArgs(objectId);
tcQueue = QueueFactory::instance()->createMessageQueue(
DISTRIBUTER_MAX_PACKETS, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); } TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); }

View File

@ -4,14 +4,13 @@
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid, AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
ThermalModuleIF *thermalModule) ThermalModuleIF *thermalModule)
: SystemObject(setObjectid), : SystemObject(setObjectid), healthHelper(this, setObjectid), parameterHelper(this) {
commandQueue(NULL), if (thermalModule != nullptr) {
healthHelper(this, setObjectid),
parameterHelper(this) {
if (thermalModule != NULL) {
thermalModule->registerSensor(this); thermalModule->registerSensor(this);
} }
commandQueue = QueueFactory::instance()->createMessageQueue(); auto mqArgs = MqArgs(setObjectid, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
AbstractTemperatureSensor::~AbstractTemperatureSensor() { AbstractTemperatureSensor::~AbstractTemperatureSensor() {

View File

@ -51,7 +51,7 @@ class AbstractTemperatureSensor : public HasHealthIF,
HasHealthIF::HealthState getHealth(); HasHealthIF::HealthState getHealth();
protected: protected:
MessageQueueIF* commandQueue; MessageQueueIF* commandQueue = nullptr;
HealthHelper healthHelper; HealthHelper healthHelper;
ParameterHelper parameterHelper; ParameterHelper parameterHelper;

View File

@ -12,7 +12,9 @@ Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1)
switch1(switch1), switch1(switch1),
heaterOnCountdown(10800000) /*about two orbits*/, heaterOnCountdown(10800000) /*about two orbits*/,
parameterHelper(this) { parameterHelper(this) {
eventQueue = QueueFactory::instance()->createMessageQueue(); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
Heater::~Heater() { QueueFactory::instance()->deleteMessageQueue(eventQueue); } Heater::~Heater() { QueueFactory::instance()->deleteMessageQueue(eventQueue); }

View File

@ -99,6 +99,13 @@ class Clock {
*/ */
static ReturnValue_t getDateAndTime(TimeOfDay_t *time); static ReturnValue_t getDateAndTime(TimeOfDay_t *time);
/**
* Convert to time of day struct given the POSIX timeval struct
* @param from
* @param to
* @return
*/
static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to);
/** /**
* Converts a time of day struct to POSIX seconds. * Converts a time of day struct to POSIX seconds.
* @param time The time of day as input * @param time The time of day as input

View File

@ -1,7 +1,9 @@
#include <ctime>
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval *tt) { ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
uint16_t leapSeconds; uint16_t leapSeconds;
ReturnValue_t result = getLeapSeconds(&leapSeconds); ReturnValue_t result = getLeapSeconds(&leapSeconds);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -31,7 +33,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) { ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if (timeMutex == nullptr) { if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
@ -42,9 +44,22 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
struct tm* timeInfo;
timeInfo = gmtime(&from->tv_sec);
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1;
to->day = timeInfo->tm_mday;
to->hour = timeInfo->tm_hour;
to->minute = timeInfo->tm_min;
to->second = timeInfo->tm_sec;
to->usecond = from->tv_usec;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::checkOrCreateClockMutex() { ReturnValue_t Clock::checkOrCreateClockMutex() {
if (timeMutex == nullptr) { if (timeMutex == nullptr) {
MutexFactory *mutexFactory = MutexFactory::instance(); MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == nullptr) { if (mutexFactory == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -33,50 +33,47 @@ class TmStoreBackendIF : public HasParametersIF {
static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15); static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY;
static const Event STORE_SEND_WRITE_FAILED = //! Initiating sending data to store failed. Low, par1:
MAKE_EVENT(0, severity::LOW); //!< Initiating sending data to store failed. Low, par1: //! returnCode, par2: integer (debug info)
//!< returnCode, par2: integer (debug info) static const Event STORE_SEND_WRITE_FAILED = MAKE_EVENT(0, severity::LOW);
static const Event STORE_WRITE_FAILED = MAKE_EVENT( //! Data was sent, but writing failed. Low, par1: returnCode, par2: 0
1, severity::LOW); //!< Data was sent, but writing failed. Low, par1: returnCode, par2: 0 static const Event STORE_WRITE_FAILED = MAKE_EVENT(1, severity::LOW);
static const Event STORE_SEND_READ_FAILED = //! Initiating reading data from store failed. Low, par1: returnCode, par2: 0
MAKE_EVENT(2, severity::LOW); //!< Initiating reading data from store failed. Low, par1: static const Event STORE_SEND_READ_FAILED = MAKE_EVENT(2, severity::LOW);
//!< returnCode, par2: 0 //! Data was requested, but access failed. Low, par1: returnCode, par2: 0
static const Event STORE_READ_FAILED = MAKE_EVENT( static const Event STORE_READ_FAILED = MAKE_EVENT(3, severity::LOW);
3, severity::LOW); //!< Data was requested, but access failed. Low, par1: returnCode, par2: 0 //! An unexpected TM packet or data message occurred. Low, par1: 0, par2: integer (debug info)
static const Event UNEXPECTED_MSG = static const Event UNEXPECTED_MSG = MAKE_EVENT(4, severity::LOW);
MAKE_EVENT(4, severity::LOW); //!< An unexpected TM packet or data message occurred. Low, //! Storing data failed. May simply be a full store. Low, par1: returnCode,
//!< par1: 0, par2: integer (debug info) //! par2: integer (sequence count of failed packet).
static const Event STORING_FAILED = MAKE_EVENT( static const Event STORING_FAILED = MAKE_EVENT(5, severity::LOW);
5, severity::LOW); //!< Storing data failed. May simply be a full store. Low, par1: //! Dumping retrieved data failed. Low, par1: returnCode,
//!< returnCode, par2: integer (sequence count of failed packet). //! par2: integer (sequence count of failed packet).
static const Event TM_DUMP_FAILED = static const Event TM_DUMP_FAILED = MAKE_EVENT(6, severity::LOW);
MAKE_EVENT(6, severity::LOW); //!< Dumping retrieved data failed. Low, par1: returnCode, //! Corrupted init data or read error. Low, par1: returnCode, par2: integer (debug info)
//!< par2: integer (sequence count of failed packet). //! Store was not initialized. Starts empty. Info, parameters both zero.
static const Event STORE_INIT_FAILED = static const Event STORE_INIT_FAILED = MAKE_EVENT(7, severity::LOW);
MAKE_EVENT(7, severity::LOW); //!< Corrupted init data or read error. Low, par1: returnCode, //! Data was read out, but it is inconsistent. Low par1:
//!< par2: integer (debug info) //! Memory address of corruption, par2: integer (debug info)
static const Event STORE_INIT_EMPTY = MAKE_EVENT( static const Event STORE_INIT_EMPTY = MAKE_EVENT(8, severity::INFO);
8, severity::INFO); //!< Store was not initialized. Starts empty. Info, parameters both zero.
static const Event STORE_CONTENT_CORRUPTED = static const Event STORE_CONTENT_CORRUPTED = MAKE_EVENT(9, severity::LOW);
MAKE_EVENT(9, severity::LOW); //!< Data was read out, but it is inconsistent. Low par1: //! Info event indicating the store will be initialized, either at boot or after IOB switch.
//!< Memory address of corruption, par2: integer (debug info) //! Info. pars: 0
static const Event STORE_INITIALIZE = static const Event STORE_INITIALIZE = MAKE_EVENT(10, severity::INFO);
MAKE_EVENT(10, severity::INFO); //!< Info event indicating the store will be initialized, //! Info event indicating the store was successfully initialized, either at boot or after
//!< either at boot or after IOB switch. Info. pars: 0 //! IOB switch. Info. pars: 0
static const Event INIT_DONE = MAKE_EVENT( static const Event INIT_DONE = MAKE_EVENT(11, severity::INFO);
11, severity::INFO); //!< Info event indicating the store was successfully initialized, //! Info event indicating that dumping finished successfully.
//!< either at boot or after IOB switch. Info. pars: 0 //! par1: Number of dumped packets. par2: APID/SSC (16bits each)
static const Event DUMP_FINISHED = MAKE_EVENT( static const Event DUMP_FINISHED = MAKE_EVENT(12, severity::INFO);
12, severity::INFO); //!< Info event indicating that dumping finished successfully. par1: //! Info event indicating that deletion finished successfully.
//!< Number of dumped packets. par2: APID/SSC (16bits each) //! par1:Number of deleted packets. par2: APID/SSC (16bits each)
static const Event DELETION_FINISHED = MAKE_EVENT( static const Event DELETION_FINISHED = MAKE_EVENT(13, severity::INFO);
13, severity::INFO); //!< Info event indicating that deletion finished successfully. par1: //! Info event indicating that something went wrong during deletion. pars: 0
//!< Number of deleted packets. par2: APID/SSC (16bits each) static const Event DELETION_FAILED = MAKE_EVENT(14, severity::LOW);
static const Event DELETION_FAILED = MAKE_EVENT( //! Info that the a auto catalog report failed
14, static const Event AUTO_CATALOGS_SENDING_FAILED = MAKE_EVENT(15, severity::INFO);
severity::LOW); //!< Info event indicating that something went wrong during deletion. pars: 0
static const Event AUTO_CATALOGS_SENDING_FAILED =
MAKE_EVENT(15, severity::INFO); //!< Info that the a auto catalog report failed
virtual ~TmStoreBackendIF() {} virtual ~TmStoreBackendIF() {}

View File

@ -20,8 +20,10 @@ CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t a
service(service), service(service),
timeoutSeconds(commandTimeoutSeconds), timeoutSeconds(commandTimeoutSeconds),
commandMap(numberOfParallelCommands) { commandMap(numberOfParallelCommands) {
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth); auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth); size_t mqSz = MessageQueueMessage::MAX_MESSAGE_SIZE;
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
} }
void CommandingServiceBase::setPacketSource(object_id_t packetSource) { void CommandingServiceBase::setPacketSource(object_id_t packetSource) {

View File

@ -13,7 +13,9 @@ object_id_t PusServiceBase::packetDestination = 0;
PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId) PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId)
: SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) { : SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) {
requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION); auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(
PUS_SERVICE_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
PusServiceBase::~PusServiceBase() { QueueFactory::instance()->deleteMessageQueue(requestQueue); } PusServiceBase::~PusServiceBase() { QueueFactory::instance()->deleteMessageQueue(requestQueue); }

View File

@ -19,6 +19,19 @@ class SourceSequenceCounter {
void reset(uint16_t toValue = 0) { void reset(uint16_t toValue = 0) {
sequenceCount = toValue % (SpacePacketBase::LIMIT_SEQUENCE_COUNT); sequenceCount = toValue % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
} }
SourceSequenceCounter& operator++(int) {
this->increment();
return *this;
}
SourceSequenceCounter& operator--(int) {
this->decrement();
return *this;
}
SourceSequenceCounter& operator=(const uint16_t& newCount) {
sequenceCount = newCount;
return *this;
}
operator uint16_t() { return this->get(); }
}; };
#endif /* FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ */ #endif /* FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ */

View File

@ -15,7 +15,9 @@ TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, object_i
tcDestination(tcDestination) tcDestination(tcDestination)
{ {
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); } TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
@ -172,15 +174,18 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
} }
if (tmFifo->full()) { if (tmFifo->full()) {
if (warningSwitch) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number " sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!" "of stored packet IDs reached!"
<< std::endl; << std::endl;
#else #else
sif::printWarning( sif::printWarning(
"TmTcBridge::storeDownlinkData: TM downlink max. number " "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n"); "of stored packet IDs reached!\n");
#endif #endif
warningSwitch = true;
}
if (overwriteOld) { if (overwriteOld) {
tmFifo->retrieve(&storeId); tmFifo->retrieve(&storeId);
tmStore->deleteData(storeId); tmStore->deleteData(storeId);

View File

@ -72,6 +72,8 @@ class TmTcBridge : public AcceptsTelemetryIF,
virtual uint16_t getIdentifier() override; virtual uint16_t getIdentifier() override;
virtual MessageQueueId_t getRequestQueue() override; virtual MessageQueueId_t getRequestQueue() override;
bool warningSwitch = true;
protected: protected:
//! Cached for initialize function. //! Cached for initialize function.
object_id_t tmStoreId = objects::NO_OBJECT; object_id_t tmStoreId = objects::NO_OBJECT;

View File

@ -1,8 +1,9 @@
#include "version.h" #include "version.h"
#include "fsfw/FSFWVersion.h"
#include <cstdio> #include <cstdio>
#include "fsfw/FSFWVersion.h"
#ifdef major #ifdef major
#undef major #undef major
#endif #endif

View File

@ -29,7 +29,7 @@ class Version {
} }
friend bool operator>(const Version& v1, const Version& v2) { friend bool operator>(const Version& v1, const Version& v2) {
return not (v1 < v2) and not (v1 == v2); return not(v1 < v2) and not(v1 == v2);
} }
friend bool operator<=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 < v2)); } friend bool operator<=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 < v2)); }

View File

@ -73,7 +73,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
REQUIRE(result != CommandExecutor::COMMAND_ERROR); REQUIRE(result != CommandExecutor::COMMAND_ERROR);
// This ensures that the tests do not block indefinitely // This ensures that the tests do not block indefinitely
usleep(500); usleep(500);
REQUIRE(limitIdx < 500); REQUIRE(limitIdx < 50000);
} }
limitIdx = 0; limitIdx = 0;
CHECK(bytesHaveBeenRead == true); CHECK(bytesHaveBeenRead == true);

View File

@ -17,15 +17,15 @@ TEST_CASE("Version API Tests", "[TestVersionAPI]") {
fsfw::Version v1 = fsfw::Version(1, 1, 1); fsfw::Version v1 = fsfw::Version(1, 1, 1);
fsfw::Version v2 = fsfw::Version(1, 1, 1); fsfw::Version v2 = fsfw::Version(1, 1, 1);
REQUIRE(v1 == v2); REQUIRE(v1 == v2);
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
v1.revision -= 1; v1.revision -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 >= v2)); REQUIRE(not(v1 >= v2));
REQUIRE(v1 < v2); REQUIRE(v1 < v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
v1.revision += 1; v1.revision += 1;
@ -33,60 +33,60 @@ TEST_CASE("Version API Tests", "[TestVersionAPI]") {
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 < v2); REQUIRE(v1 < v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 >= v2)); REQUIRE(not(v1 >= v2));
v1.minor += 1; v1.minor += 1;
v1.major -= 1; v1.major -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 < v2); REQUIRE(v1 < v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 >= v2)); REQUIRE(not(v1 >= v2));
v1.major += 1; v1.major += 1;
REQUIRE(v1 == v2); REQUIRE(v1 == v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 != v2)); REQUIRE(not(v1 != v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
v1.major += 1; v1.major += 1;
v1.minor -= 1; v1.minor -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 > v2); REQUIRE(v1 > v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 <= v2)); REQUIRE(not(v1 <= v2));
v1.major -= 1; v1.major -= 1;
v1.minor += 2; v1.minor += 2;
v1.revision -= 1; v1.revision -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 > v2); REQUIRE(v1 > v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 <= v2)); REQUIRE(not(v1 <= v2));
v1.minor -= 1; v1.minor -= 1;
v1.revision += 2; v1.revision += 2;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 > v2); REQUIRE(v1 > v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 <= v2)); REQUIRE(not(v1 <= v2));
v1.revision -= 1; v1.revision -= 1;
REQUIRE(v1 == v2); REQUIRE(v1 == v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 != v2)); REQUIRE(not(v1 != v2));
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "v" << fsfw::FSFW_VERSION << std::endl; sif::info << "v" << fsfw::FSFW_VERSION << std::endl;
#endif #endif
char verString[10] = {}; char verString[10] = {};
fsfw::FSFW_VERSION.getVersion(verString, sizeof(verString)); fsfw::FSFW_VERSION.getVersion(verString, sizeof(verString));
#if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_DISABLE_PRINTOUT == 0
printf("v%s\n",verString); printf("v%s\n", verString);
#endif #endif
} }