Merge branch 'mueller/DeviceHandler-LocalPools' of https://egit.irs.uni-stuttgart.de/KSat/fsfw into mueller/DeviceHandler-LocalPools

This commit is contained in:
Robin Müller 2020-12-10 17:18:58 +01:00
commit 0cf9f334cc
51 changed files with 1415 additions and 831 deletions

View File

@ -15,6 +15,31 @@ a C file without issues
- The same is possible for the event reporting service (PUS5) - The same is possible for the event reporting service (PUS5)
- PUS Health Service added, which allows to command and retrieve health via PUS packets - PUS Health Service added, which allows to command and retrieve health via PUS packets
### Parameter Service
- The API of the parameter service has been changed to prevent inconsistencies
between documentation and actual code and to clarify usage.
- The parameter ID now consists of:
1. Domain ID (1 byte)
2. Unique Identifier (1 byte)
3. Linear Index (2 bytes)
The linear index can be used for arrays as well as matrices.
The parameter load command now explicitely expects the ECSS PTC and PFC
information as well as the rows and column number. Rows and column will
default to one, which is equivalent to one scalar parameter (the most
important use-case)
### File System Interface
- A new interfaces specifies the functions for a software object which exposes the file system of a given hardware to use message based file handling (e.g. PUS commanding)
### Internal Error Reporter
- The new internal error reporter uses the local data pools. The pool IDs for
the exisiting three error values and the new error set will be hardcoded for
now, the the constructor for the internal error reporter just takes an object
ID for now.
### Device Handler Base ### Device Handler Base
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important - There is an additional `PERFORM_OPERATION` step for the device handler base. It is important

View File

@ -1,16 +1,16 @@
#include "../subsystem/SubsystemBase.h"
#include "ControllerBase.h" #include "ControllerBase.h"
#include "../subsystem/SubsystemBase.h" #include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId, ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth) : size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode( SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
SUBMODE_NONE), commandQueue(NULL), modeHelper( submode(SUBMODE_NONE), modeHelper(this),
this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) { healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth); commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth);
} }
ControllerBase::~ControllerBase() { ControllerBase::~ControllerBase() {
@ -24,9 +24,9 @@ ReturnValue_t ControllerBase::initialize() {
} }
MessageQueueId_t parentQueue = 0; MessageQueueId_t parentQueue = 0;
if (parentId != 0) { if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId); SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) { if (parent == nullptr) {
return RETURN_FAILED; return RETURN_FAILED;
} }
parentQueue = parent->getCommandQueue(); parentQueue = parent->getCommandQueue();
@ -44,10 +44,6 @@ ReturnValue_t ControllerBase::initialize() {
return result; return result;
} }
result = hkSwitcher.initialize();
if (result != RETURN_OK) {
return result;
}
return RETURN_OK; return RETURN_OK;
} }
@ -56,26 +52,27 @@ MessageQueueId_t ControllerBase::getCommandQueue() const {
} }
void ControllerBase::handleQueue() { void ControllerBase::handleQueue() {
CommandMessage message; CommandMessage command;
ReturnValue_t result; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&message); result == RETURN_OK; for (result = commandQueue->receiveMessage(&command);
result = commandQueue->receiveMessage(&message)) { result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = modeHelper.handleModeCommand(&message); result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
result = healthHelper.handleHealthCommand(&message); result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
result = handleCommandMessage(&message); result = handleCommandMessage(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
message.setToUnknownCommand(); command.setToUnknownCommand();
commandQueue->reply(&message); commandQueue->reply(&command);
} }
} }
@ -106,7 +103,6 @@ void ControllerBase::announceMode(bool recursive) {
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) { ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue(); handleQueue();
hkSwitcher.performOperation();
performControlOperation(); performControlOperation();
return RETURN_OK; return RETURN_OK;
} }
@ -135,3 +131,7 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
} }
ReturnValue_t ControllerBase::initializeAfterTaskCreation() {
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,5 +1,5 @@
#ifndef CONTROLLERBASE_H_ #ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
#define CONTROLLERBASE_H_ #define FSFW_CONTROLLER_CONTROLLERBASE_H_
#include "../health/HasHealthIF.h" #include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h" #include "../health/HealthHelper.h"
@ -7,73 +7,88 @@
#include "../modes/ModeHelper.h" #include "../modes/ModeHelper.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h" #include "../tasks/ExecutableObjectIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../datapool/HkSwitchHelper.h" #include "../datapool/HkSwitchHelper.h"
/**
* @brief Generic base class for controller classes
* @details
* Implements common interfaces for controllers, which generally have
* a mode and a health state. This avoids boilerplate code.
*/
class ControllerBase: public HasModesIF, class ControllerBase: public HasModesIF,
public HasHealthIF, public HasHealthIF,
public ExecutableObjectIF, public ExecutableObjectIF,
public SystemObject, public SystemObject,
public HasReturnvaluesIF { public HasReturnvaluesIF {
public: public:
static const Mode_t MODE_NORMAL = 2; static const Mode_t MODE_NORMAL = 2;
ControllerBase(uint32_t setObjectId, uint32_t parentId, ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth = 3); size_t commandQueueDepth = 3);
virtual ~ControllerBase(); virtual ~ControllerBase();
ReturnValue_t initialize(); /** SystemObject override */
virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const; virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t performOperation(uint8_t opCode); /** HasHealthIF overrides */
virtual ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t setHealth(HealthState health); virtual HasHealthIF::HealthState getHealth() override;
virtual HasHealthIF::HealthState getHealth();
/**
* Implementation of ExecutableObjectIF function
*
* Used to setup the reference of the task, that executes this component
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF* task_);
/** ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void setTaskIF(PeriodicTaskIF* task) override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected: protected:
const uint32_t parentId;
/**
* Implemented by child class. Handle command messages which are not
* mode or health messages.
* @param message
* @return
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
/**
* Periodic helper, implemented by child class.
*/
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
const object_id_t parentId;
Mode_t mode; Mode_t mode;
Submode_t submode; Submode_t submode;
MessageQueueIF* commandQueue; MessageQueueIF* commandQueue = nullptr;
ModeHelper modeHelper; ModeHelper modeHelper;
HealthHelper healthHelper; HealthHelper healthHelper;
HkSwitchHelper hkSwitcher;
/** /**
* Pointer to the task which executes this component, is invalid before setTaskIF was called. * Pointer to the task which executes this component,
* is invalid before setTaskIF was called.
*/ */
PeriodicTaskIF* executingTask; PeriodicTaskIF* executingTask = nullptr;
void handleQueue(); /** Handle mode and health messages */
virtual void handleQueue();
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0; /** Mode helpers */
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
virtual void modeChanged(Mode_t mode, Submode_t submode); virtual void modeChanged(Mode_t mode, Submode_t submode);
virtual void startTransition(Mode_t mode, Submode_t submode); virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void getMode(Mode_t *mode, Submode_t *submode); virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual void setToExternalControl(); virtual void setToExternalControl();
virtual void announceMode(bool recursive); virtual void announceMode(bool recursive);
/** HK helpers */
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable); virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
}; };
#endif /* CONTROLLERBASE_H_ */ #endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */

View File

@ -1,10 +1,3 @@
/**
* @file MapPacketExtraction.cpp
* @brief This file defines the MapPacketExtraction class.
* @date 26.03.2013
* @author baetz
*/
#include "MapPacketExtraction.h" #include "MapPacketExtraction.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
@ -12,14 +5,14 @@
#include "../tmtcpacket/SpacePacketBase.h" #include "../tmtcpacket/SpacePacketBase.h"
#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../tmtcservices/AcceptsTelecommandsIF.h"
#include "../tmtcservices/TmTcMessage.h" #include "../tmtcservices/TmTcMessage.h"
#include <string.h> #include <cstring>
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId, MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
object_id_t setPacketDestination) : object_id_t setPacketDestination) :
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition( lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId),
packetBuffer), packetDestination(setPacketDestination), packetStore( bufferPosition(packetBuffer), packetDestination(setPacketDestination),
NULL), tcQueueId(MessageQueueIF::NO_QUEUE) { tcQueueId(MessageQueueIF::NO_QUEUE) {
memset(packetBuffer, 0, sizeof(packetBuffer)); std::memset(packetBuffer, 0, sizeof(packetBuffer));
} }
ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) { ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {

View File

@ -1,12 +1,5 @@
/** #ifndef FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
* @file MapPacketExtraction.h #define FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
* @brief This file defines the MapPacketExtraction class.
* @date 26.03.2013
* @author baetz
*/
#ifndef MAPPACKETEXTRACTION_H_
#define MAPPACKETEXTRACTION_H_
#include "MapPacketExtractionIF.h" #include "MapPacketExtractionIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
@ -20,17 +13,19 @@ class StorageManagerIF;
* The class implements the full MAP Packet Extraction functionality as described in the CCSDS * The class implements the full MAP Packet Extraction functionality as described in the CCSDS
* TC Space Data Link Protocol. It internally stores incomplete segmented packets until they are * TC Space Data Link Protocol. It internally stores incomplete segmented packets until they are
* fully received. All found packets are forwarded to a single distribution entity. * fully received. All found packets are forwarded to a single distribution entity.
* @author B. Baetz
*/ */
class MapPacketExtraction: public MapPacketExtractionIF { class MapPacketExtraction: public MapPacketExtractionIF {
private: private:
static const uint32_t MAX_PACKET_SIZE = 4096; static const uint32_t MAX_PACKET_SIZE = 4096;
uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame. uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame.
uint8_t mapId; //!< MAP ID of this MAP Channel. uint8_t mapId; //!< MAP ID of this MAP Channel.
uint32_t packetLength; //!< Complete length of the current Space Packet. uint32_t packetLength = 0; //!< Complete length of the current Space Packet.
uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer. uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer.
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer. uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
object_id_t packetDestination; object_id_t packetDestination;
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored. //!< Pointer to the store where full TC packets are stored.
StorageManagerIF* packetStore = nullptr;
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor. MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
/** /**
* Debug method to print the packet Buffer's content. * Debug method to print the packet Buffer's content.
@ -75,4 +70,4 @@ public:
uint8_t getMapId() const; uint8_t getMapId() const;
}; };
#endif /* MAPPACKETEXTRACTION_H_ */ #endif /* FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_ */

View File

@ -0,0 +1,34 @@
#ifndef FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#define FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h>
enum errorPoolIds {
TM_HITS,
QUEUE_HITS,
STORE_HITS
};
class InternalErrorDataset: public StaticLocalDataSet<3 * sizeof(uint32_t)> {
public:
static constexpr uint8_t ERROR_SET_ID = 0;
InternalErrorDataset(HasLocalDataPoolIF* owner):
StaticLocalDataSet(owner, ERROR_SET_ID) {}
InternalErrorDataset(object_id_t objectId):
StaticLocalDataSet(sid_t(objectId , ERROR_SET_ID)) {}
lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(hkManager->getOwner(),
TM_HITS, this);
lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(hkManager->getOwner(),
QUEUE_HITS, this);
lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(hkManager->getOwner(),
STORE_HITS, this);
};
#endif /* FSFW_INTERNALERROR_INTERNALERRORDATASET_H_ */

View File

@ -1,16 +1,16 @@
#include "../datapoolglob/GlobalDataSet.h"
#include "InternalErrorReporter.h" #include "InternalErrorReporter.h"
#include "../datapoolglob/GlobalPoolVariable.h" #include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) : uint32_t messageQueueDepth): SystemObject(setObjectId),
SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), commandQueue(QueueFactory::instance()->
tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0), createMessageQueue(messageQueueDepth)),
storeHits(0) { poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
@ -18,28 +18,42 @@ InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex); MutexFactory::instance()->deleteMutex(mutex);
} }
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
this->diagnosticPrintout = enable;
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT);
GlobDataSet mySet;
gp_uint32_t queueHitsInPool(queuePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t tmHitsInPool(tmPoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t storeHitsInPool(storePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
uint32_t newQueueHits = getAndResetQueueHits(); uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits(); uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits(); uint32_t newStoreHits = getAndResetStoreHits();
queueHitsInPool.value += newQueueHits; #ifdef DEBUG
tmHitsInPool.value += newTmHits; if(diagnosticPrintout) {
storeHitsInPool.value += newStoreHits; if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured!" << std::endl;
sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
}
}
#endif
mySet.commit(PoolVariableIF::VALID); internalErrorDataset.queueHits.value += newQueueHits;
internalErrorDataset.storeHits.value += newStoreHits;
internalErrorDataset.tmHits.value += newTmHits;
internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT);
poolManager.performHkOperation();
CommandMessage message;
ReturnValue_t result = commandQueue->receiveMessage(&message);
if(result != MessageQueueIF::EMPTY) {
poolManager.handleHousekeepingMessage(&message);
}
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -53,7 +67,7 @@ void InternalErrorReporter::lostTm() {
uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = queueHits; value = queueHits;
queueHits = 0; queueHits = 0;
mutex->unlockMutex(); mutex->unlockMutex();
@ -62,21 +76,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t InternalErrorReporter::getQueueHits() { uint32_t InternalErrorReporter::getQueueHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = queueHits; value = queueHits;
mutex->unlockMutex(); mutex->unlockMutex();
return value; return value;
} }
void InternalErrorReporter::incrementQueueHits() { void InternalErrorReporter::incrementQueueHits() {
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
queueHits++; queueHits++;
mutex->unlockMutex(); mutex->unlockMutex();
} }
uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = tmHits; value = tmHits;
tmHits = 0; tmHits = 0;
mutex->unlockMutex(); mutex->unlockMutex();
@ -85,14 +99,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t InternalErrorReporter::getTmHits() { uint32_t InternalErrorReporter::getTmHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = tmHits; value = tmHits;
mutex->unlockMutex(); mutex->unlockMutex();
return value; return value;
} }
void InternalErrorReporter::incrementTmHits() { void InternalErrorReporter::incrementTmHits() {
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
tmHits++; tmHits++;
mutex->unlockMutex(); mutex->unlockMutex();
} }
@ -103,7 +117,7 @@ void InternalErrorReporter::storeFull() {
uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = storeHits; value = storeHits;
storeHits = 0; storeHits = 0;
mutex->unlockMutex(); mutex->unlockMutex();
@ -112,14 +126,65 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t InternalErrorReporter::getStoreHits() { uint32_t InternalErrorReporter::getStoreHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = storeHits; value = storeHits;
mutex->unlockMutex(); mutex->unlockMutex();
return value; return value;
} }
void InternalErrorReporter::incrementStoreHits() { void InternalErrorReporter::incrementStoreHits() {
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
storeHits++; storeHits++;
mutex->unlockMutex(); mutex->unlockMutex();
} }
object_id_t InternalErrorReporter::getObjectId() const {
return SystemObject::getObjectId();
}
MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
return this->commandQueue->getId();
}
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(errorPoolIds::TM_HITS,
new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::STORE_HITS,
new PoolEntry<uint32_t>());
poolManager.subscribeForPeriodicPacket(internalErrorSid, false,
getPeriodicOperationFrequency(), true);
internalErrorDataset.setValidity(true, true);
return HasReturnvaluesIF::RETURN_OK;
}
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
return &poolManager;
}
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
LocalPoolDataSetBase* InternalErrorReporter::getDataSetHandle(sid_t sid) {
return &internalErrorDataset;
}
void InternalErrorReporter::setTaskIF(PeriodicTaskIF *task) {
this->executingTask = task;
}
ReturnValue_t InternalErrorReporter::initialize() {
ReturnValue_t result = poolManager.initialize(commandQueue);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SystemObject::initialize();
}
ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation();
}

View File

@ -1,37 +1,75 @@
#ifndef INTERNALERRORREPORTER_H_ #ifndef FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
#define INTERNALERRORREPORTER_H_ #define FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
#include "InternalErrorReporterIF.h" #include "InternalErrorReporterIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../internalError/InternalErrorDataset.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../tasks/ExecutableObjectIF.h" #include "../tasks/ExecutableObjectIF.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
/**
* @brief This class is used to track internal errors like lost telemetry,
* failed message sending or a full store.
* @details
* All functions were kept virtual so this class can be extended easily
* to store custom internal errors (e.g. communication interface errors).
*/
class InternalErrorReporter: public SystemObject, class InternalErrorReporter: public SystemObject,
public ExecutableObjectIF, public ExecutableObjectIF,
public InternalErrorReporterIF { public InternalErrorReporterIF,
public HasLocalDataPoolIF {
public: public:
InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId, static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20;
uint32_t tmPoolId, uint32_t storePoolId);
InternalErrorReporter(object_id_t setObjectId,
uint32_t messageQueueDepth = 5);
/**
* Enable diagnostic printout. Please note that this feature will
* only work if DEBUG has been supplied to the build defines.
* @param enable
*/
void setDiagnosticPrintout(bool enable);
virtual ~InternalErrorReporter(); virtual ~InternalErrorReporter();
virtual ReturnValue_t performOperation(uint8_t opCode); virtual object_id_t getObjectId() const override;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual dur_millis_t getPeriodicOperationFrequency() const override;
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void queueMessageNotSent(); virtual void queueMessageNotSent();
virtual void lostTm(); virtual void lostTm();
virtual void storeFull(); virtual void storeFull();
virtual void setTaskIF(PeriodicTaskIF* task) override;
protected: protected:
MutexIF* mutex; MessageQueueIF* commandQueue;
LocalDataPoolManager poolManager;
uint32_t queuePoolId; PeriodicTaskIF* executingTask = nullptr;
uint32_t tmPoolId; MutexIF* mutex = nullptr;
uint32_t storePoolId; sid_t internalErrorSid;
InternalErrorDataset internalErrorDataset;
uint32_t queueHits; bool diagnosticPrintout = true;
uint32_t tmHits;
uint32_t storeHits; uint32_t queueHits = 0;
uint32_t tmHits = 0;
uint32_t storeHits = 0;
uint32_t getAndResetQueueHits(); uint32_t getAndResetQueueHits();
uint32_t getQueueHits(); uint32_t getQueueHits();
@ -47,4 +85,4 @@ protected:
}; };
#endif /* INTERNALERRORREPORTER_H_ */ #endif /* FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_ */

80
memory/HasFileSystemIF.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef FSFW_MEMORY_HASFILESYSTEMIF_H_
#define FSFW_MEMORY_HASFILESYSTEMIF_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../returnvalues/FwClassIds.h"
#include "../ipc/messageQueueDefinitions.h"
#include <cstddef>
/**
* @brief Generic interface for objects which expose a file system to enable
* message based file handling.
* @author J. Meier, R. Mueller
*/
class HasFileSystemIF {
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::FILE_SYSTEM;
static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x00);
static constexpr ReturnValue_t FILE_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static constexpr ReturnValue_t FILE_LOCKED = MAKE_RETURN_CODE(0x02);
static constexpr ReturnValue_t DIRECTORY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
static constexpr ReturnValue_t DIRECTORY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x04);
static constexpr ReturnValue_t DIRECTORY_NOT_EMPTY = MAKE_RETURN_CODE(0x05);
static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_WRITE = MAKE_RETURN_CODE(0x06); //! P1: Sequence number missing
static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_READ = MAKE_RETURN_CODE(0x07); //! P1: Sequence number missing
virtual ~HasFileSystemIF() {}
/**
* Function to get the MessageQueueId_t of the implementing object
* @return MessageQueueId_t of the object
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
/**
* Generic function to append to file.
* @param dirname Directory of the file
* @param filename The filename of the file
* @param data The data to write to the file
* @param size The size of the data to write
* @param packetNumber Current packet number. Can be used to verify that
* there are no missing packets.
* @param args Any other arguments which an implementation might require.
* @param bytesWritten Actual bytes written to file
* For large files the write procedure must be split in multiple calls
* to writeToFile
*/
virtual ReturnValue_t appendToFile(const char* repositoryPath,
const char* filename, const uint8_t* data, size_t size,
uint16_t packetNumber, void* args = nullptr) = 0;
/**
* Generic function to create a new file.
* @param repositoryPath
* @param filename
* @param data
* @param size
* @param args Any other arguments which an implementation might require.
* @return
*/
virtual ReturnValue_t createFile(const char* repositoryPath,
const char* filename, const uint8_t* data = nullptr,
size_t size = 0, void* args = nullptr) = 0;
/**
* Generic function to delete a file.
* @param repositoryPath
* @param filename
* @param args
* @return
*/
virtual ReturnValue_t deleteFile(const char* repositoryPath,
const char* filename, void* args = nullptr) = 0;
};
#endif /* FSFW_MEMORY_HASFILESYSTEMIF_H_ */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ #ifndef FSFW_MONITORING_ABSLIMITMONITOR_H_
#define FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ #define FSFW_MONITORING_ABSLIMITMONITOR_H_
#include "MonitorBase.h" #include "MonitorBase.h"
#include <cmath> #include <cmath>
@ -7,9 +7,14 @@
template<typename T> template<typename T>
class AbsLimitMonitor: public MonitorBase<T> { class AbsLimitMonitor: public MonitorBase<T> {
public: public:
AbsLimitMonitor(object_id_t reporterId, uint8_t monitorId, uint32_t parameterId, AbsLimitMonitor(object_id_t reporterId, uint8_t monitorId,
uint16_t confirmationLimit, T limit, Event violationEvent = MonitoringIF::VALUE_OUT_OF_RANGE, bool aboveIsViolation = true) : gp_id_t globalPoolId, uint16_t confirmationLimit, T limit,
MonitorBase<T>(reporterId, monitorId, parameterId, confirmationLimit), limit(limit), violationEvent(violationEvent), aboveIsViolation(aboveIsViolation) { Event violationEvent = MonitoringIF::VALUE_OUT_OF_RANGE,
bool aboveIsViolation = true) :
MonitorBase<T>(reporterId, monitorId, globalPoolId,
confirmationLimit),
limit(limit), violationEvent(violationEvent),
aboveIsViolation(aboveIsViolation) {
} }
virtual ~AbsLimitMonitor() { virtual ~AbsLimitMonitor() {
} }
@ -32,8 +37,9 @@ public:
const ParameterWrapper *newValues, uint16_t startAtIndex) { const ParameterWrapper *newValues, uint16_t startAtIndex) {
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId, ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex); parameterId, parameterWrapper, newValues, startAtIndex);
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there. // We'll reuse the DOMAIN_ID of MonitorReporter,
if (result != this->INVALID_MATRIX_ID) { // as we know the parameterIds used there.
if (result != this->INVALID_IDENTIFIER_ID) {
return result; return result;
} }
switch (parameterId) { switch (parameterId) {
@ -41,7 +47,7 @@ public:
parameterWrapper->set(this->limit); parameterWrapper->set(this->limit);
break; break;
default: default:
return this->INVALID_MATRIX_ID; return this->INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -59,7 +65,9 @@ protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) { void sendTransitionEvent(T currentValue, ReturnValue_t state) {
switch (state) { switch (state) {
case MonitoringIF::OUT_OF_RANGE: case MonitoringIF::OUT_OF_RANGE:
EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->parameterId); EventManagerIF::triggerEvent(this->reportingId,
violationEvent, this->globalPoolId.objectId,
this->globalPoolId.localPoolId);
break; break;
default: default:
break; break;
@ -70,4 +78,4 @@ protected:
const bool aboveIsViolation; const bool aboveIsViolation;
}; };
#endif /* FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ */ #endif /* FSFW_MONITORING_ABSLIMITMONITOR_H_ */

View File

@ -1,11 +1,5 @@
/** #ifndef FSFW_MONITORING_HASMONITORSIF_H_
* @file HasMonitorsIF.h #define FSFW_MONITORING_HASMONITORSIF_H_
* @brief This file defines the HasMonitorsIF class.
* @date 28.07.2014
* @author baetz
*/
#ifndef HASMONITORSIF_H_
#define HASMONITORSIF_H_
#include "../events/EventReportingProxyIF.h" #include "../events/EventReportingProxyIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
@ -27,4 +21,4 @@ public:
} }
}; };
#endif /* HASMONITORSIF_H_ */ #endif /* FSFW_MONITORING_HASMONITORSIF_H_ */

View File

@ -12,13 +12,15 @@
template<typename T> template<typename T>
class LimitMonitor: public MonitorBase<T> { class LimitMonitor: public MonitorBase<T> {
public: public:
LimitMonitor(object_id_t reporterId, uint8_t monitorId, uint32_t parameterId, LimitMonitor(object_id_t reporterId, uint8_t monitorId,
uint16_t confirmationLimit, T lowerLimit, T upperLimit, gp_id_t globalPoolId, uint16_t confirmationLimit, T lowerLimit,
Event belowLowEvent = MonitoringIF::VALUE_BELOW_LOW_LIMIT, T upperLimit, Event belowLowEvent =
MonitoringIF::VALUE_BELOW_LOW_LIMIT,
Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT) : Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT) :
MonitorBase<T>(reporterId, monitorId, parameterId, confirmationLimit), lowerLimit( MonitorBase<T>(reporterId, monitorId, globalPoolId,
lowerLimit), upperLimit(upperLimit), belowLowEvent( confirmationLimit),
belowLowEvent), aboveHighEvent(aboveHighEvent) { lowerLimit(lowerLimit), upperLimit(upperLimit),
belowLowEvent(belowLowEvent), aboveHighEvent(aboveHighEvent) {
} }
virtual ~LimitMonitor() { virtual ~LimitMonitor() {
} }
@ -41,7 +43,7 @@ public:
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId, ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex); parameterId, parameterWrapper, newValues, startAtIndex);
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there. //We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
if (result != this->INVALID_MATRIX_ID) { if (result != this->INVALID_IDENTIFIER_ID) {
return result; return result;
} }
switch (parameterId) { switch (parameterId) {
@ -52,12 +54,13 @@ public:
parameterWrapper->set(this->upperLimit); parameterWrapper->set(this->upperLimit);
break; break;
default: default:
return this->INVALID_MATRIX_ID; return this->INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
bool isOutOfLimits() { bool isOutOfLimits() {
if (this->oldState == MonitoringIF::ABOVE_HIGH_LIMIT || this->oldState == MonitoringIF::BELOW_LOW_LIMIT) { if (this->oldState == MonitoringIF::ABOVE_HIGH_LIMIT or
this->oldState == MonitoringIF::BELOW_LOW_LIMIT) {
return true; return true;
} else { } else {
return false; return false;
@ -76,10 +79,12 @@ protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) { void sendTransitionEvent(T currentValue, ReturnValue_t state) {
switch (state) { switch (state) {
case MonitoringIF::BELOW_LOW_LIMIT: case MonitoringIF::BELOW_LOW_LIMIT:
EventManagerIF::triggerEvent(this->reportingId, belowLowEvent, this->parameterId); EventManagerIF::triggerEvent(this->reportingId, belowLowEvent,
this->globalPoolId.objectId, this->globalPoolId.localPoolId);
break; break;
case MonitoringIF::ABOVE_HIGH_LIMIT: case MonitoringIF::ABOVE_HIGH_LIMIT:
EventManagerIF::triggerEvent(this->reportingId, aboveHighEvent, this->parameterId); EventManagerIF::triggerEvent(this->reportingId, aboveHighEvent,
this->globalPoolId.objectId, this->globalPoolId.localPoolId);
break; break;
default: default:
break; break;

View File

@ -1,39 +1,50 @@
#ifndef MONITORBASE_H_ #ifndef FSFW_MONITORING_MONITORBASE_H_
#define MONITORBASE_H_ #define FSFW_MONITORING_MONITORBASE_H_
#include "LimitViolationReporter.h"
#include "MonitoringIF.h"
#include "MonitoringMessageContent.h"
#include "MonitorReporter.h"
#include "../datapoollocal/LocalPoolVariable.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/PIDReader.h"
#include "../monitoring/LimitViolationReporter.h"
#include "../monitoring/MonitoringIF.h"
#include "../monitoring/MonitoringMessageContent.h"
#include "../monitoring/MonitorReporter.h"
/** /**
* Base class for monitoring of parameters. * @brief Base class for monitoring of parameters.
* Can be used anywhere, specializations need to implement checkSample and should override sendTransitionEvent. * @details
* Manages state handling, enabling and disabling of events/reports and forwarding of transition * Can be used anywhere, specializations need to implement checkSample and
* reports via MonitorReporter. In addition, it provides default implementations for fetching the parameter sample from * should override sendTransitionEvent.
* the data pool and a simple confirmation counter. * Manages state handling, enabling and disabling of events/reports and
* forwarding of transition reports via MonitorReporter.
*
* In addition, it provides default implementations for fetching the
* parameter sample from the data pool and a simple confirmation counter.
*/ */
template<typename T> template<typename T>
class MonitorBase: public MonitorReporter<T> { class MonitorBase: public MonitorReporter<T> {
public: public:
MonitorBase(object_id_t reporterId, uint8_t monitorId, MonitorBase(object_id_t reporterId, uint8_t monitorId,
uint32_t parameterId, uint16_t confirmationLimit) : gp_id_t globalPoolId, uint16_t confirmationLimit):
MonitorReporter<T>(reporterId, monitorId, parameterId, confirmationLimit) { MonitorReporter<T>(reporterId, monitorId, globalPoolId,
confirmationLimit),
poolVariable(globalPoolId) {
} }
virtual ~MonitorBase() { virtual ~MonitorBase() {
} }
virtual ReturnValue_t check() { virtual ReturnValue_t check() {
//1. Fetch sample of type T, return validity. // 1. Fetch sample of type T, return validity.
T sample = 0; T sample = 0;
ReturnValue_t validity = fetchSample(&sample); ReturnValue_t validity = fetchSample(&sample);
//2. If returning from fetch != OK, parameter is invalid. Report (if oldState is != invalidity). // 2. If returning from fetch != OK, parameter is invalid.
// Report (if oldState is != invalidity).
if (validity != HasReturnvaluesIF::RETURN_OK) { if (validity != HasReturnvaluesIF::RETURN_OK) {
this->monitorStateIs(validity, sample, 0); this->monitorStateIs(validity, sample, 0);
//3. Otherwise, check sample.
} else { } else {
//3. Otherwise, check sample.
this->oldState = doCheck(sample); this->oldState = doCheck(sample);
} }
return this->oldState; return this->oldState;
@ -43,20 +54,25 @@ public:
ReturnValue_t currentState = checkSample(sample, &crossedLimit); ReturnValue_t currentState = checkSample(sample, &crossedLimit);
return this->monitorStateIs(currentState,sample, crossedLimit); return this->monitorStateIs(currentState,sample, crossedLimit);
} }
//Abstract or default.
// Abstract or default.
virtual ReturnValue_t checkSample(T sample, T* crossedLimit) = 0; virtual ReturnValue_t checkSample(T sample, T* crossedLimit) = 0;
protected: protected:
virtual ReturnValue_t fetchSample(T* sample) { virtual ReturnValue_t fetchSample(T* sample) {
GlobDataSet mySet; ReturnValue_t result = poolVariable.read();
PIDReader<T> parameter(this->parameterId, &mySet); if(result != HasReturnvaluesIF::RETURN_OK) {
mySet.read(); return result;
if (!parameter.isValid()) { }
return MonitoringIF::INVALID; if (not poolVariable.isValid()) {
} return MonitoringIF::INVALID;
*sample = parameter.value; }
return HasReturnvaluesIF::RETURN_OK; *sample = poolVariable.value;
return HasReturnvaluesIF::RETURN_OK;
} }
LocalPoolVar<T> poolVariable;
}; };
#endif /* MONITORBASE_H_ */ #endif /* FSFW_MONITORING_MONITORBASE_H_ */

View File

@ -1,10 +1,12 @@
#ifndef FRAMEWORK_MONITORING_MONITORREPORTER_H_ #ifndef FSFW_MONITORING_MONITORREPORTER_H_
#define FRAMEWORK_MONITORING_MONITORREPORTER_H_ #define FSFW_MONITORING_MONITORREPORTER_H_
#include "../events/EventManagerIF.h"
#include "LimitViolationReporter.h" #include "LimitViolationReporter.h"
#include "MonitoringIF.h" #include "MonitoringIF.h"
#include "MonitoringMessageContent.h" #include "MonitoringMessageContent.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../events/EventManagerIF.h"
#include "../parameters/HasParametersIF.h" #include "../parameters/HasParametersIF.h"
template<typename T> template<typename T>
@ -14,11 +16,14 @@ public:
static const uint8_t ENABLED = 1; static const uint8_t ENABLED = 1;
static const uint8_t DISABLED = 0; static const uint8_t DISABLED = 0;
MonitorReporter(object_id_t reportingId, uint8_t monitorId, uint32_t parameterId, uint16_t confirmationLimit) : // TODO: Adapt to use SID instead of parameter ID.
monitorId(monitorId), parameterId(parameterId), reportingId(
reportingId), oldState(MonitoringIF::UNCHECKED), reportingEnabled( MonitorReporter(object_id_t reportingId, uint8_t monitorId,
ENABLED), eventEnabled(ENABLED), currentCounter(0), confirmationLimit( gp_id_t globalPoolId, uint16_t confirmationLimit) :
confirmationLimit) { monitorId(monitorId), globalPoolId(globalPoolId),
reportingId(reportingId), oldState(MonitoringIF::UNCHECKED),
reportingEnabled(ENABLED), eventEnabled(ENABLED), currentCounter(0),
confirmationLimit(confirmationLimit) {
} }
virtual ~MonitorReporter() { virtual ~MonitorReporter() {
@ -63,7 +68,7 @@ public:
parameterWrapper->set(this->eventEnabled); parameterWrapper->set(this->eventEnabled);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -91,7 +96,7 @@ public:
protected: protected:
const uint8_t monitorId; const uint8_t monitorId;
const uint32_t parameterId; const gp_id_t globalPoolId;
object_id_t reportingId; object_id_t reportingId;
ReturnValue_t oldState; ReturnValue_t oldState;
@ -148,7 +153,8 @@ protected:
case HasReturnvaluesIF::RETURN_OK: case HasReturnvaluesIF::RETURN_OK:
break; break;
default: default:
EventManagerIF::triggerEvent(reportingId, MonitoringIF::MONITOR_CHANGED_STATE, state); EventManagerIF::triggerEvent(reportingId,
MonitoringIF::MONITOR_CHANGED_STATE, state);
break; break;
} }
} }
@ -159,14 +165,15 @@ protected:
* @param crossedLimit The limit crossed (if applicable). * @param crossedLimit The limit crossed (if applicable).
* @param state Current state the monitor is in. * @param state Current state the monitor is in.
*/ */
virtual void sendTransitionReport(T parameterValue, T crossedLimit, ReturnValue_t state) { virtual void sendTransitionReport(T parameterValue, T crossedLimit,
MonitoringReportContent<T> report(parameterId, ReturnValue_t state) {
MonitoringReportContent<T> report(globalPoolId,
parameterValue, crossedLimit, oldState, state); parameterValue, crossedLimit, oldState, state);
LimitViolationReporter::sendLimitViolationReport(&report); LimitViolationReporter::sendLimitViolationReport(&report);
} }
ReturnValue_t setToState(ReturnValue_t state) { ReturnValue_t setToState(ReturnValue_t state) {
if (oldState != state && reportingEnabled) { if (oldState != state && reportingEnabled) {
MonitoringReportContent<T> report(parameterId, 0, 0, oldState, MonitoringReportContent<T> report(globalPoolId, 0, 0, oldState,
state); state);
LimitViolationReporter::sendLimitViolationReport(&report); LimitViolationReporter::sendLimitViolationReport(&report);
oldState = state; oldState = state;
@ -175,4 +182,4 @@ protected:
} }
}; };
#endif /* FRAMEWORK_MONITORING_MONITORREPORTER_H_ */ #endif /* FSFW_MONITORING_MONITORREPORTER_H_ */

View File

@ -1,8 +1,8 @@
#ifndef MONITORINGIF_H_ #ifndef FSFW_MONITORING_MONITORINGIF_H_
#define MONITORINGIF_H_ #define FSFW_MONITORING_MONITORINGIF_H_
#include "../memory/HasMemoryIF.h"
#include "MonitoringMessage.h" #include "MonitoringMessage.h"
#include "../memory/HasMemoryIF.h"
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
class MonitoringIF : public SerializeIF { class MonitoringIF : public SerializeIF {
@ -64,4 +64,4 @@ public:
#endif /* MONITORINGIF_H_ */ #endif /* FSFW_MONITORING_MONITORINGIF_H_ */

View File

@ -3,6 +3,7 @@
#include "HasMonitorsIF.h" #include "HasMonitorsIF.h"
#include "MonitoringIF.h" #include "MonitoringIF.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerialBufferAdapter.h" #include "../serialize/SerialBufferAdapter.h"
#include "../serialize/SerialFixedArrayListAdapter.h" #include "../serialize/SerialFixedArrayListAdapter.h"
@ -16,12 +17,17 @@ void setStaticFrameworkObjectIds();
} }
//PID(uint32_t), TYPE, LIMIT_ID, value,limitValue, previous, later, timestamp //PID(uint32_t), TYPE, LIMIT_ID, value,limitValue, previous, later, timestamp
/**
* @brief Does magic.
* @tparam T
*/
template<typename T> template<typename T>
class MonitoringReportContent: public SerialLinkedListAdapter<SerializeIF> { class MonitoringReportContent: public SerialLinkedListAdapter<SerializeIF> {
friend void (Factory::setStaticFrameworkObjectIds)(); friend void (Factory::setStaticFrameworkObjectIds)();
public: public:
SerializeElement<uint8_t> monitorId; SerializeElement<uint8_t> monitorId;
SerializeElement<uint32_t> parameterId; SerializeElement<uint32_t> parameterObjectId;
SerializeElement<lp_id_t> localPoolId;
SerializeElement<T> parameterValue; SerializeElement<T> parameterValue;
SerializeElement<T> limitValue; SerializeElement<T> limitValue;
SerializeElement<ReturnValue_t> oldState; SerializeElement<ReturnValue_t> oldState;
@ -30,20 +36,23 @@ public:
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer; SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
TimeStamperIF* timeStamper; TimeStamperIF* timeStamper;
MonitoringReportContent() : MonitoringReportContent() :
SerialLinkedListAdapter<SerializeIF>( SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
LinkedElement<SerializeIF>::Iterator(&parameterId)), monitorId(0), parameterId( monitorId(0), parameterObjectId(0),
0), parameterValue(0), limitValue(0), oldState(0), newState( localPoolId(0), parameterValue(0),
0), rawTimestamp( { 0 }), timestampSerializer(rawTimestamp, limitValue(0), oldState(0), newState(0),
rawTimestamp( { 0 }), timestampSerializer(rawTimestamp,
sizeof(rawTimestamp)), timeStamper(NULL) { sizeof(rawTimestamp)), timeStamper(NULL) {
setAllNext(); setAllNext();
} }
MonitoringReportContent(uint32_t setPID, T value, T limitValue, MonitoringReportContent(gp_id_t globalPoolId, T value, T limitValue,
ReturnValue_t oldState, ReturnValue_t newState) : ReturnValue_t oldState, ReturnValue_t newState) :
SerialLinkedListAdapter<SerializeIF>( SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
LinkedElement<SerializeIF>::Iterator(&parameterId)), monitorId(0), parameterId( monitorId(0), parameterObjectId(globalPoolId.objectId),
setPID), parameterValue(value), limitValue(limitValue), oldState( localPoolId(globalPoolId.localPoolId),
oldState), newState(newState), timestampSerializer(rawTimestamp, parameterValue(value), limitValue(limitValue),
sizeof(rawTimestamp)), timeStamper(NULL) { oldState(oldState), newState(newState),
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
timeStamper(NULL) {
setAllNext(); setAllNext();
if (checkAndSetStamper()) { if (checkAndSetStamper()) {
timeStamper->addTimeStamp(rawTimestamp, sizeof(rawTimestamp)); timeStamper->addTimeStamp(rawTimestamp, sizeof(rawTimestamp));
@ -53,16 +62,16 @@ private:
static object_id_t timeStamperId; static object_id_t timeStamperId;
void setAllNext() { void setAllNext() {
parameterId.setNext(&parameterValue); parameterObjectId.setNext(&parameterValue);
parameterValue.setNext(&limitValue); parameterValue.setNext(&limitValue);
limitValue.setNext(&oldState); limitValue.setNext(&oldState);
oldState.setNext(&newState); oldState.setNext(&newState);
newState.setNext(&timestampSerializer); newState.setNext(&timestampSerializer);
} }
bool checkAndSetStamper() { bool checkAndSetStamper() {
if (timeStamper == NULL) { if (timeStamper == nullptr) {
timeStamper = objectManager->get<TimeStamperIF>( timeStamperId ); timeStamper = objectManager->get<TimeStamperIF>( timeStamperId );
if ( timeStamper == NULL ) { if ( timeStamper == nullptr ) {
sif::error << "MonitoringReportContent::checkAndSetStamper: " sif::error << "MonitoringReportContent::checkAndSetStamper: "
"Stamper not found!" << std::endl; "Stamper not found!" << std::endl;
return false; return false;

View File

@ -82,7 +82,7 @@ public:
parameterWrapper->set(limit); parameterWrapper->set(limit);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,12 +1,16 @@
#ifndef FSFW_PARAMETERS_HASPARAMETERSIF_H_ #ifndef FSFW_PARAMETERS_HASPARAMETERSIF_H_
#define FSFW_PARAMETERS_HASPARAMETERSIF_H_ #define FSFW_PARAMETERS_HASPARAMETERSIF_H_
#include "../parameters/ParameterWrapper.h" #include "ParameterWrapper.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <stdint.h> #include <cstdint>
/** Each parameter is identified with a unique parameter ID */ /**
typedef uint32_t ParameterId_t; * Each parameter is identified with a unique parameter ID
* The first byte of the parameter ID will denote the domain ID.
* The second and third byte will be the unique identifier number.
*/
using ParameterId_t = uint32_t;
/** /**
* @brief This interface is used by components which have modifiable * @brief This interface is used by components which have modifiable
@ -16,16 +20,15 @@ typedef uint32_t ParameterId_t;
* ID is the domain ID which can be used to identify unqiue spacecraft domains * ID is the domain ID which can be used to identify unqiue spacecraft domains
* (e.g. control and sensor domain in the AOCS controller). * (e.g. control and sensor domain in the AOCS controller).
* *
* The second and third byte represent the matrix ID, which can represent * The second byte is a unique identfier ID.
* a 8-bit row and column number and the last byte...
* *
* Yeah, it it matrix ID oder parameter ID now and is index a 16 bit number * The third and fourth byte can be used as a linear index for matrix or array
* of a 8 bit number now? * parameter entries.
*/ */
class HasParametersIF { class HasParametersIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_PARAMETERS_IF; static const uint8_t INTERFACE_ID = CLASS_ID::HAS_PARAMETERS_IF;
static const ReturnValue_t INVALID_MATRIX_ID = MAKE_RETURN_CODE(0x01); static const ReturnValue_t INVALID_IDENTIFIER_ID = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t INVALID_DOMAIN_ID = MAKE_RETURN_CODE(0x02); static const ReturnValue_t INVALID_DOMAIN_ID = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t INVALID_VALUE = MAKE_RETURN_CODE(0x03); static const ReturnValue_t INVALID_VALUE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_ONLY = MAKE_RETURN_CODE(0x05); static const ReturnValue_t READ_ONLY = MAKE_RETURN_CODE(0x05);
@ -34,33 +37,45 @@ public:
return id >> 24; return id >> 24;
} }
static uint16_t getMatrixId(ParameterId_t id) { static uint8_t getUniqueIdentifierId(ParameterId_t id) {
return id >> 8; return id >> 16;
} }
static uint8_t getIndex(ParameterId_t id) { /**
* Get the index of a parameter. Please note that the index is always a
* linear index. For a vector, this is straightforward.
* For a matrix, the linear indexing run from left to right, top to bottom.
* @param id
* @return
*/
static uint16_t getIndex(ParameterId_t id) {
return id; return id;
} }
static uint32_t getFullParameterId(uint8_t domainId, uint16_t parameterId, static uint32_t getFullParameterId(uint8_t domainId,
uint8_t index) { uint8_t uniqueIdentifier, uint16_t linearIndex) {
return (domainId << 24) + (parameterId << 8) + index; return (domainId << 24) + (uniqueIdentifier << 16) + linearIndex;
} }
virtual ~HasParametersIF() {} virtual ~HasParametersIF() {}
/** /**
* This is the generic function overriden by child classes to set
* parameters. To set a parameter, the parameter wrapper is used with
* a variety of set functions. The provided values can be checked with
* newValues.
* Always set parameter before checking newValues! * Always set parameter before checking newValues!
* *
* @param domainId * @param domainId
* @param parameterId * @param parameterId
* @param parameterWrapper * @param parameterWrapper
* @param newValues * @param newValues
* @param startAtIndex * @param startAtIndex Linear index, runs left to right, top to bottom for
* matrix indexes.
* @return * @return
*/ */
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId,
ParameterWrapper *parameterWrapper, uint16_t uniqueIdentifier, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) = 0; const ParameterWrapper *newValues, uint16_t startAtIndex) = 0;
}; };

View File

@ -2,131 +2,133 @@
#include "ParameterMessage.h" #include "ParameterMessage.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) : ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner):
owner(owner) {} owner(owner) {}
ParameterHelper::~ParameterHelper() { ParameterHelper::~ParameterHelper() {
} }
ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; if(storage == nullptr) {
switch (message->getCommand()) { // ParameterHelper was not initialized
case ParameterMessage::CMD_PARAMETER_DUMP: { return HasReturnvaluesIF::RETURN_FAILED;
ParameterWrapper description; }
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(message));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(message));
result = owner->getParameter(domain, parameterId,
&description, &description, 0);
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(message->getSender(),
ParameterMessage::getParameterId(message), &description);
}
}
break;
case ParameterMessage::CMD_PARAMETER_LOAD: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(message));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(message));
uint8_t index = HasParametersIF::getIndex(
ParameterMessage::getParameterId(message));
const uint8_t *storedStream = nullptr; ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
size_t storedStreamSize = 0; switch (message->getCommand()) {
result = storage->getData( case ParameterMessage::CMD_PARAMETER_DUMP: {
ParameterMessage::getStoreId(message), &storedStream, ParameterWrapper description;
&storedStreamSize); uint8_t domain = HasParametersIF::getDomain(
if (result != HasReturnvaluesIF::RETURN_OK) { ParameterMessage::getParameterId(message));
sif::error << "ParameterHelper::handleParameterMessage: Getting" uint8_t uniqueIdentifier = HasParametersIF::getUniqueIdentifierId(
" store data failed for load command." << std::endl; ParameterMessage::getParameterId(message));
break; result = owner->getParameter(domain, uniqueIdentifier,
} &description, &description, 0);
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(message->getSender(),
ParameterMessage::getParameterId(message), &description);
}
}
break;
case ParameterMessage::CMD_PARAMETER_LOAD: {
ParameterId_t parameterId = 0;
uint8_t ptc = 0;
uint8_t pfc = 0;
uint8_t rows = 0;
uint8_t columns = 0;
store_address_t storeId = ParameterMessage::getParameterLoadCommand(
message, &parameterId, &ptc, &pfc, &rows, &columns);
Type type(Type::getActualType(ptc, pfc));
ParameterWrapper streamWrapper; uint8_t domain = HasParametersIF::getDomain(parameterId);
result = streamWrapper.set(storedStream, storedStreamSize); uint8_t uniqueIdentifier = HasParametersIF::getUniqueIdentifierId(
if (result != HasReturnvaluesIF::RETURN_OK) { parameterId);
storage->deleteData(ParameterMessage::getStoreId(message)); uint16_t linearIndex = HasParametersIF::getIndex(parameterId);
break;
}
ParameterWrapper ownerWrapper; ConstStorageAccessor accessor(storeId);
result = owner->getParameter(domain, parameterId, &ownerWrapper, result = storage->getData(storeId, accessor);
&streamWrapper, index); if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "ParameterHelper::handleParameterMessage: Getting"
storage->deleteData(ParameterMessage::getStoreId(message)); << " store data failed for load command." << std::endl;
break; break;
} }
result = ownerWrapper.copyFrom(&streamWrapper, index); ParameterWrapper streamWrapper;
result = streamWrapper.set(type, rows, columns, accessor.data(),
accessor.size());
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
storage->deleteData(ParameterMessage::getStoreId(message)); ParameterWrapper ownerWrapper;
result = owner->getParameter(domain, uniqueIdentifier, &ownerWrapper,
&streamWrapper, linearIndex);
if (result == HasReturnvaluesIF::RETURN_OK) { result = ownerWrapper.copyFrom(&streamWrapper, linearIndex);
result = sendParameter(message->getSender(), if (result != HasReturnvaluesIF::RETURN_OK) {
ParameterMessage::getParameterId(message), &ownerWrapper); return result;
} }
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
if (result != HasReturnvaluesIF::RETURN_OK) { result = sendParameter(message->getSender(),
rejectCommand(message->getSender(), result, message->getCommand()); ParameterMessage::getParameterId(message), &ownerWrapper);
} break;
}
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK; if (result != HasReturnvaluesIF::RETURN_OK) {
rejectCommand(message->getSender(), result, message->getCommand());
}
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
const ParameterWrapper* description) { const ParameterWrapper* description) {
size_t serializedSize = description->getSerializedSize(); size_t serializedSize = description->getSerializedSize();
uint8_t *storeElement; uint8_t *storeElement;
store_address_t address; store_address_t address;
ReturnValue_t result = storage->getFreeElement(&address, serializedSize, ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
&storeElement); &storeElement);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
size_t storeElementSize = 0; size_t storeElementSize = 0;
result = description->serialize(&storeElement, &storeElementSize, result = description->serialize(&storeElement, &storeElementSize,
serializedSize, SerializeIF::Endianness::BIG); serializedSize, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(address); storage->deleteData(address);
return result; return result;
} }
CommandMessage reply; CommandMessage reply;
ParameterMessage::setParameterDumpReply(&reply, id, address); ParameterMessage::setParameterDumpReply(&reply, id, address);
MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t ParameterHelper::initialize() { ReturnValue_t ParameterHelper::initialize() {
ownerQueueId = owner->getCommandQueue(); ownerQueueId = owner->getCommandQueue();
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE); if (storage == nullptr) {
if (storage == NULL) { return ObjectManagerIF::CHILD_INIT_FAILED;
return HasReturnvaluesIF::RETURN_FAILED; }
} else { return HasReturnvaluesIF::RETURN_OK;
return HasReturnvaluesIF::RETURN_OK;
}
} }
void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand) { Command_t initialCommand) {
CommandMessage reply; CommandMessage reply;
reply.setReplyRejected(reason, initialCommand); reply.setReplyRejected(reason, initialCommand);
MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId);
} }

View File

@ -25,10 +25,26 @@ void ParameterMessage::setParameterDumpReply(CommandMessage* message,
} }
void ParameterMessage::setParameterLoadCommand(CommandMessage* message, void ParameterMessage::setParameterLoadCommand(CommandMessage* message,
ParameterId_t id, store_address_t storageID) { ParameterId_t id, store_address_t storeId, uint8_t ptc, uint8_t pfc,
uint8_t rows = 1, uint8_t columns = 1) {
message->setCommand(CMD_PARAMETER_LOAD); message->setCommand(CMD_PARAMETER_LOAD);
message->setParameter(id); message->setParameter(id);
message->setParameter2(storageID.raw); message->setParameter2(storeId.raw);
uint32_t packedParameterSettings = (ptc << 24) | (pfc << 16) |
(rows << 8) | columns;
message->setParameter3(packedParameterSettings);
}
store_address_t ParameterMessage::getParameterLoadCommand(
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
*parameterId = message->getParameter2();
uint32_t packedParamSettings = message->getParameter3();
*ptc = packedParamSettings >> 24 & 0xff;
*pfc = packedParamSettings >> 16 & 0xff;
*rows = packedParamSettings >> 8 & 0xff;
*columns = packedParamSettings & 0xff;
return message->getParameter2();
} }
void ParameterMessage::clear(CommandMessage* message) { void ParameterMessage::clear(CommandMessage* message) {

View File

@ -5,6 +5,20 @@
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
/**
* @brief ParameterMessage interface
* @details
* General structure of a parameter message:
* 1. 4-byte Object ID
* 2. 4-byte Parameter ID, first byte is Domain ID, second byte is unique
* identifier, third and fourth byte is linear index to start from
* 3. 4-byte Parameter Settings. First byte and second byte are the PTC and PFC
* ECSS type identifiers (see ECSS-E-ST-70-41C15 p.428 or Type class in
* globalfunctions). Third byte is the number of rows and fourth byte
* is the number of columns. For single variable parameters, this will
* be [1, 1].
*
*/
class ParameterMessage { class ParameterMessage {
private: private:
ParameterMessage(); ParameterMessage();
@ -20,8 +34,27 @@ public:
ParameterId_t id); ParameterId_t id);
static void setParameterDumpReply(CommandMessage* message, static void setParameterDumpReply(CommandMessage* message,
ParameterId_t id, store_address_t storageID); ParameterId_t id, store_address_t storageID);
/**
* Command to set a load parameter message. The CCSDS / ECSS type in
* form of a PTC and a PFC is expected. See ECSS-E-ST-70-41C15 p.428
* for all types or the Type class in globalfunctions.
* @param message
* @param id
* @param storeId
* @param ptc Type information according to CCSDS/ECSS standards
* @param pfc Type information according to CCSDS/ECSS standards
* @param rows Set number of rows in parameter set, minimum one.
* @param columns Set number of columns in parameter set, minimum one
*/
static void setParameterLoadCommand(CommandMessage* message, static void setParameterLoadCommand(CommandMessage* message,
ParameterId_t id, store_address_t storageID); ParameterId_t id, store_address_t storeId, uint8_t ptc,
uint8_t pfc, uint8_t rows, uint8_t columns);
static store_address_t getParameterLoadCommand(
const CommandMessage* message, ParameterId_t* parameterId,
uint8_t* ptc, uint8_t* pfc, uint8_t* rows, uint8_t* columns) ;
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };

View File

@ -115,7 +115,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow,
uint8_t fromColumns) { uint8_t fromColumns) {
//treat from as a continuous Stream as we copy all of it //treat from as a continuous Stream as we copy all of it
const uint8_t *fromAsStream = (const uint8_t*) from; const uint8_t *fromAsStream = reinterpret_cast<const uint8_t*>(from);
size_t streamSize = fromRows * fromColumns * sizeof(T); size_t streamSize = fromRows * fromColumns * sizeof(T);
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
@ -123,8 +123,9 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow,
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
//get the start element of this row in data //get the start element of this row in data
T *dataWithDataType = ((T*) data) uint16_t offset = (((startingRow + fromRow) *
+ (((startingRow + fromRow) * columns) + startingColumn); static_cast<uint16_t>(columns)) + startingColumn);
T *dataWithDataType = static_cast<T*>(data) + offset;
for (uint8_t fromColumn = 0; fromColumn < fromColumns; fromColumn++) { for (uint8_t fromColumn = 0; fromColumn < fromColumns; fromColumn++) {
result = SerializeAdapter::deSerialize( result = SerializeAdapter::deSerialize(
@ -159,6 +160,23 @@ ReturnValue_t ParameterWrapper::deSerialize(const uint8_t **buffer,
return copyFrom(&streamDescription, startWritingAtIndex); return copyFrom(&streamDescription, startWritingAtIndex);
} }
ReturnValue_t ParameterWrapper::set(Type type, uint8_t rows, uint8_t columns,
const void *data, size_t dataSize) {
this->type = type;
this->rows = rows;
this->columns = columns;
size_t expectedSize = type.getSize() * rows * columns;
if (expectedSize < dataSize) {
return SerializeIF::STREAM_TOO_SHORT;
}
this->data = nullptr;
this->readonlyData = data;
pointsToStream = true;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize, ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
const uint8_t **remainingStream, size_t *remainingSize) { const uint8_t **remainingStream, size_t *remainingSize) {
ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream, ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream,
@ -202,11 +220,13 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
uint16_t startWritingAtIndex) { uint16_t startWritingAtIndex) {
if (data == NULL) { // TODO: Optional diagnostic output (which can be disabled in FSFWConfig)
// to determined faulty implementations and configuration errors quickly.
if (data == nullptr) {
return READONLY; return READONLY;
} }
if (from->readonlyData == NULL) { if (from->readonlyData == nullptr) {
return SOURCE_NOT_SET; return SOURCE_NOT_SET;
} }
@ -214,9 +234,16 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
return DATATYPE_MISSMATCH; return DATATYPE_MISSMATCH;
} }
// The smallest allowed value for rows and columns is one.
if(rows == 0 or columns == 0) {
return COLUMN_OR_ROWS_ZERO;
}
//check if from fits into this //check if from fits into this
uint8_t startingRow = startWritingAtIndex / columns; uint8_t startingRow = 0;
uint8_t startingColumn = startWritingAtIndex % columns; uint8_t startingColumn = 0;
ParameterWrapper::convertLinearIndexToRowAndColumn(startWritingAtIndex,
&startingRow, &startingColumn);
if ((from->rows > (rows - startingRow)) if ((from->rows > (rows - startingRow))
|| (from->columns > (columns - startingColumn))) { || (from->columns > (columns - startingColumn))) {
@ -270,8 +297,8 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
//need a type to do arithmetic //need a type to do arithmetic
uint8_t* typedData = static_cast<uint8_t*>(data); uint8_t* typedData = static_cast<uint8_t*>(data);
for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) { for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) {
size_t offset = (((startingRow + fromRow) * columns) + size_t offset = (((startingRow + fromRow) * static_cast<uint16_t>(
startingColumn) * typeSize; columns)) + startingColumn) * typeSize;
std::memcpy(typedData + offset, from->readonlyData, std::memcpy(typedData + offset, from->readonlyData,
typeSize * from->columns); typeSize * from->columns);
} }
@ -279,3 +306,18 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
return result; return result;
} }
void ParameterWrapper::convertLinearIndexToRowAndColumn(uint16_t index,
uint8_t *row, uint8_t *column) {
if(row == nullptr or column == nullptr) {
return;
}
// Integer division.
*row = index / columns;
*column = index % columns;
}
uint16_t ParameterWrapper::convertRowAndColumnToLinearIndex(uint8_t row,
uint8_t column) {
return row * columns + column;
}

View File

@ -22,6 +22,7 @@ public:
static const ReturnValue_t SOURCE_NOT_SET = MAKE_RETURN_CODE(0x05); static const ReturnValue_t SOURCE_NOT_SET = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t OUT_OF_BOUNDS = MAKE_RETURN_CODE(0x06); static const ReturnValue_t OUT_OF_BOUNDS = MAKE_RETURN_CODE(0x06);
static const ReturnValue_t NOT_SET = MAKE_RETURN_CODE(0x07); static const ReturnValue_t NOT_SET = MAKE_RETURN_CODE(0x07);
static const ReturnValue_t COLUMN_OR_ROWS_ZERO = MAKE_RETURN_CODE(0x08);
ParameterWrapper(); ParameterWrapper();
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data); ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
@ -68,7 +69,7 @@ public:
template<typename T> template<typename T>
void set(const T *readonlyData, uint8_t rows, uint8_t columns) { void set(const T *readonlyData, uint8_t rows, uint8_t columns) {
this->data = NULL; this->data = nullptr;
this->readonlyData = readonlyData; this->readonlyData = readonlyData;
this->type = PodTypeConversion<T>::type; this->type = PodTypeConversion<T>::type;
this->rows = rows; this->rows = rows;
@ -97,14 +98,19 @@ public:
} }
template<typename T> template<typename T>
void setMatrix(T& member) { void setMatrix(T& member) {
this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); this->set(member[0], sizeof(member)/sizeof(member[0]),
sizeof(member[0])/sizeof(member[0][0]));
} }
template<typename T> template<typename T>
void setMatrix(const T& member) { void setMatrix(const T& member) {
this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); this->set(member[0], sizeof(member)/sizeof(member[0]),
sizeof(member[0])/sizeof(member[0][0]));
} }
ReturnValue_t set(Type type, uint8_t rows, uint8_t columns,
const void *data, size_t dataSize);
ReturnValue_t set(const uint8_t *stream, size_t streamSize, ReturnValue_t set(const uint8_t *stream, size_t streamSize,
const uint8_t **remainingStream = nullptr, const uint8_t **remainingStream = nullptr,
size_t *remainingSize = nullptr); size_t *remainingSize = nullptr);
@ -113,6 +119,13 @@ public:
uint16_t startWritingAtIndex); uint16_t startWritingAtIndex);
private: private:
void convertLinearIndexToRowAndColumn(uint16_t index,
uint8_t *row, uint8_t *column);
uint16_t convertRowAndColumnToLinearIndex(uint8_t row,
uint8_t column);
bool pointsToStream = false; bool pointsToStream = false;
Type type; Type type;
@ -148,9 +161,9 @@ inline ReturnValue_t ParameterWrapper::getElement(T *value, uint8_t row,
if (pointsToStream) { if (pointsToStream) {
const uint8_t *streamWithType = static_cast<const uint8_t*>(readonlyData); const uint8_t *streamWithType = static_cast<const uint8_t*>(readonlyData);
streamWithType += (row * columns + column) * type.getSize(); streamWithType += (row * columns + column) * type.getSize();
int32_t size = type.getSize(); size_t size = type.getSize();
return SerializeAdapter::deSerialize(value, &streamWithType, return SerializeAdapter::deSerialize(value, &streamWithType,
&size, true); &size, SerializeIF::Endianness::BIG);
} }
else { else {
const T *dataWithType = static_cast<const T*>(readonlyData); const T *dataWithType = static_cast<const T*>(readonlyData);

View File

@ -1,22 +1,25 @@
#include "Fuse.h"
#include "../monitoring/LimitViolationReporter.h" #include "../monitoring/LimitViolationReporter.h"
#include "../monitoring/MonitoringMessageContent.h" #include "../monitoring/MonitoringMessageContent.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../power/Fuse.h"
#include "../serialize/SerialFixedArrayListAdapter.h" #include "../serialize/SerialFixedArrayListAdapter.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
object_id_t Fuse::powerSwitchId = 0; object_id_t Fuse::powerSwitchId = 0;
Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId,
sid_t variableSet, VariableIds ids,
float maxCurrent, uint16_t confirmationCount) : float maxCurrent, uint16_t confirmationCount) :
SystemObject(fuseObjectId), oldFuseState(0), fuseId(fuseId), powerIF( SystemObject(fuseObjectId), oldFuseState(0), fuseId(fuseId),
NULL), currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount, currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount,
maxCurrent, FUSE_CURRENT_HIGH), powerMonitor(fuseObjectId, 2, maxCurrent, FUSE_CURRENT_HIGH),
GlobalDataPool::poolIdAndPositionToPid(ids.poolIdPower, 0), powerMonitor(fuseObjectId, 2, ids.poolIdPower,
confirmationCount), set(), voltage(ids.pidVoltage, &set), current( confirmationCount),
ids.pidCurrent, &set), state(ids.pidState, &set), power( set(variableSet), voltage(ids.pidVoltage, &set),
ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE), commandQueue( current(ids.pidCurrent, &set), state(ids.pidState, &set),
NULL), parameterHelper(this), healthHelper(this, fuseObjectId) { power(ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE),
parameterHelper(this), healthHelper(this, fuseObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(); commandQueue = QueueFactory::instance()->createMessageQueue();
} }
@ -75,7 +78,7 @@ ReturnValue_t Fuse::check() {
float lowLimit = 0.0; float lowLimit = 0.0;
float highLimit = RESIDUAL_POWER; float highLimit = RESIDUAL_POWER;
calculatePowerLimits(&lowLimit, &highLimit); calculatePowerLimits(&lowLimit, &highLimit);
result = powerMonitor.checkPower(power, lowLimit, highLimit); result = powerMonitor.checkPower(power.value, lowLimit, highLimit);
if (result == MonitoringIF::BELOW_LOW_LIMIT) { if (result == MonitoringIF::BELOW_LOW_LIMIT) {
reportEvents(POWER_BELOW_LOW_LIMIT); reportEvents(POWER_BELOW_LOW_LIMIT);
} else if (result == MonitoringIF::ABOVE_HIGH_LIMIT) { } else if (result == MonitoringIF::ABOVE_HIGH_LIMIT) {
@ -132,7 +135,7 @@ void Fuse::calculateFusePower() {
return; return;
} }
//Calculate fuse power. //Calculate fuse power.
power = current * voltage; power.value = current.value * voltage.value;
power.setValid(PoolVariableIF::VALID); power.setValid(PoolVariableIF::VALID);
} }
@ -190,12 +193,12 @@ void Fuse::checkFuseState() {
reportEvents(FUSE_WENT_OFF); reportEvents(FUSE_WENT_OFF);
} }
} }
oldFuseState = state; oldFuseState = state.value;
} }
float Fuse::getPower() { float Fuse::getPower() {
if (power.isValid()) { if (power.isValid()) {
return power; return power.value;
} else { } else {
return 0.0; return 0.0;
} }

View File

@ -1,17 +1,16 @@
#ifndef FUSE_H_ #ifndef FSFW_POWER_FUSE_H_
#define FUSE_H_ #define FSFW_POWER_FUSE_H_
#include "PowerComponentIF.h"
#include "PowerSwitchIF.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../datapoolglob/PIDReader.h"
#include "../devicehandlers/HealthDevice.h" #include "../devicehandlers/HealthDevice.h"
#include "../monitoring/AbsLimitMonitor.h" #include "../monitoring/AbsLimitMonitor.h"
#include "../power/PowerComponentIF.h"
#include "../power/PowerSwitchIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../parameters/ParameterHelper.h" #include "../parameters/ParameterHelper.h"
#include <list> #include <list>
#include "../datapoollocal/StaticLocalDataSet.h"
namespace Factory { namespace Factory {
void setStaticFrameworkObjectIds(); void setStaticFrameworkObjectIds();
} }
@ -26,10 +25,10 @@ private:
static constexpr float RESIDUAL_POWER = 0.005 * 28.5; //!< This is the upper limit of residual power lost by fuses and switches. Worst case is Fuse and one of two switches on. See PCDU ICD 1.9 p29 bottom static constexpr float RESIDUAL_POWER = 0.005 * 28.5; //!< This is the upper limit of residual power lost by fuses and switches. Worst case is Fuse and one of two switches on. See PCDU ICD 1.9 p29 bottom
public: public:
struct VariableIds { struct VariableIds {
uint32_t pidVoltage; gp_id_t pidVoltage;
uint32_t pidCurrent; gp_id_t pidCurrent;
uint32_t pidState; gp_id_t pidState;
uint32_t poolIdPower; gp_id_t poolIdPower;
}; };
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
@ -39,8 +38,8 @@ public:
static const Event POWER_BELOW_LOW_LIMIT = 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); //!< PSS detected a fuse that violates its limits.
typedef std::list<PowerComponentIF*> DeviceList; typedef std::list<PowerComponentIF*> DeviceList;
Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet,
float maxCurrent, uint16_t confirmationCount = 2); VariableIds ids, float maxCurrent, uint16_t confirmationCount = 2);
virtual ~Fuse(); virtual ~Fuse();
void addDevice(PowerComponentIF *set); void addDevice(PowerComponentIF *set);
float getPower(); float getPower();
@ -70,12 +69,12 @@ public:
private: private:
uint8_t oldFuseState; uint8_t oldFuseState;
uint8_t fuseId; uint8_t fuseId;
PowerSwitchIF *powerIF; //could be static in our case. PowerSwitchIF *powerIF = nullptr; //could be static in our case.
AbsLimitMonitor<float> currentLimit; AbsLimitMonitor<float> currentLimit;
class PowerMonitor: public MonitorReporter<float> { class PowerMonitor: public MonitorReporter<float> {
public: public:
template<typename ... Args> template<typename ... Args>
PowerMonitor(Args ... args) : PowerMonitor(Args ... args):
MonitorReporter<float>(std::forward<Args>(args)...) { MonitorReporter<float>(std::forward<Args>(args)...) {
} }
ReturnValue_t checkPower(float sample, float lowerLimit, ReturnValue_t checkPower(float sample, float lowerLimit,
@ -85,12 +84,14 @@ private:
}; };
PowerMonitor powerMonitor; PowerMonitor powerMonitor;
GlobDataSet set; StaticLocalDataSet<3> set;
PIDReader<float> voltage;
PIDReader<float> current; lp_var_t<float> voltage;
PIDReader<uint8_t> state; lp_var_t<float> current;
gp_float_t power; lp_var_t<uint8_t> state;
MessageQueueIF* commandQueue;
lp_var_t<float> power;
MessageQueueIF* commandQueue = nullptr;
ParameterHelper parameterHelper; ParameterHelper parameterHelper;
HealthHelper healthHelper; HealthHelper healthHelper;
static object_id_t powerSwitchId; static object_id_t powerSwitchId;
@ -103,4 +104,4 @@ private:
bool areSwitchesOfComponentOn(DeviceList::iterator iter); bool areSwitchesOfComponentOn(DeviceList::iterator iter);
}; };
#endif /* FUSE_H_ */ #endif /* FSFW_POWER_FUSE_H_ */

View File

@ -1,20 +1,15 @@
/**
* @file PowerComponent.cpp
* @brief This file defines the PowerComponent class.
* @date 28.08.2014
* @author baetz
*/
#include "PowerComponent.h" #include "PowerComponent.h"
#include "../serialize/SerializeAdapter.h"
PowerComponent::PowerComponent() : PowerComponent::PowerComponent(): switchId1(0xFF), switchId2(0xFF),
deviceObjectId(0), switchId1(0xFF), switchId2(0xFF), doIHaveTwoSwitches( doIHaveTwoSwitches(false) {
false), min(0.0), max(0.0), moduleId(0) {
} }
PowerComponent::PowerComponent(object_id_t setId, uint8_t moduleId, float min, float max,
uint8_t switchId1, bool twoSwitches, uint8_t switchId2) : PowerComponent::PowerComponent(object_id_t setId, uint8_t moduleId, float min,
deviceObjectId(setId), switchId1(switchId1), switchId2(switchId2), doIHaveTwoSwitches( float max, uint8_t switchId1, bool twoSwitches, uint8_t switchId2) :
twoSwitches), min(min), max(max), moduleId(moduleId) { deviceObjectId(setId), switchId1(switchId1), switchId2(switchId2),
doIHaveTwoSwitches(twoSwitches), min(min), max(max),
moduleId(moduleId) {
} }
ReturnValue_t PowerComponent::serialize(uint8_t** buffer, size_t* size, ReturnValue_t PowerComponent::serialize(uint8_t** buffer, size_t* size,
@ -57,7 +52,7 @@ float PowerComponent::getMax() {
} }
ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) { Endianness streamEndianness) {
ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer, ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer,
size, streamEndianness); size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -80,7 +75,7 @@ ReturnValue_t PowerComponent::getParameter(uint8_t domainId,
parameterWrapper->set<>(max); parameterWrapper->set<>(max);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,13 +1,17 @@
#ifndef POWERCOMPONENT_H_ #ifndef FSFW_POWER_POWERCOMPONENT_H_
#define POWERCOMPONENT_H_ #define FSFW_POWER_POWERCOMPONENT_H_
#include "../objectmanager/SystemObjectIF.h"
#include "PowerComponentIF.h" #include "PowerComponentIF.h"
#include "../objectmanager/frameworkObjects.h"
#include "../objectmanager/SystemObjectIF.h"
class PowerComponent: public PowerComponentIF { class PowerComponent: public PowerComponentIF {
public: public:
PowerComponent(object_id_t setId, uint8_t moduleId, float min, float max, uint8_t switchId1, PowerComponent(object_id_t setId, uint8_t moduleId, float min, float max,
bool twoSwitches = false, uint8_t switchId2 = 0xFF); uint8_t switchId1, bool twoSwitches = false,
uint8_t switchId2 = 0xFF);
virtual object_id_t getDeviceObjectId(); virtual object_id_t getDeviceObjectId();
@ -31,18 +35,18 @@ public:
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);
private: private:
const object_id_t deviceObjectId; const object_id_t deviceObjectId = objects::NO_OBJECT;
const uint8_t switchId1; const uint8_t switchId1;
const uint8_t switchId2; const uint8_t switchId2;
const bool doIHaveTwoSwitches; const bool doIHaveTwoSwitches;
float min; float min = 0.0;
float max; float max = 0.0;
uint8_t moduleId; uint8_t moduleId = 0;
PowerComponent(); PowerComponent();
}; };
#endif /* POWERCOMPONENT_H_ */ #endif /* FSFW_POWER_POWERCOMPONENT_H_ */

View File

@ -1,24 +1,23 @@
#ifndef POWERCOMPONENTIF_H_ #ifndef FSFW_POWER_POWERCOMPONENTIF_H_
#define POWERCOMPONENTIF_H_ #define FSFW_POWER_POWERCOMPONENTIF_H_
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
#include "../parameters/HasParametersIF.h" #include "../parameters/HasParametersIF.h"
#include "../objectmanager/SystemObjectIF.h"
class PowerComponentIF : public SerializeIF, public HasParametersIF { class PowerComponentIF : public SerializeIF, public HasParametersIF {
public: public:
virtual ~PowerComponentIF() { virtual ~PowerComponentIF() {}
} virtual object_id_t getDeviceObjectId() = 0;
virtual object_id_t getDeviceObjectId()=0; virtual uint8_t getSwitchId1() = 0;
virtual uint8_t getSwitchId2() = 0;
virtual uint8_t getSwitchId1()=0; virtual bool hasTwoSwitches() = 0;
virtual uint8_t getSwitchId2()=0;
virtual bool hasTwoSwitches()=0;
virtual float getMin() = 0; virtual float getMin() = 0;
virtual float getMax() = 0; virtual float getMax() = 0;
}; };
#endif /* POWERCOMPONENTIF_H_ */ #endif /* FSFW_POWER_POWERCOMPONENTIF_H_ */

View File

@ -1,14 +1,18 @@
#include "PowerSensor.h" #include "PowerSensor.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
PowerSensor::PowerSensor(object_id_t setId, VariableIds ids, PowerSensor::PowerSensor(object_id_t objectId, sid_t setId, VariableIds ids,
DefaultLimits limits, SensorEvents events, uint16_t confirmationCount) : DefaultLimits limits, SensorEvents events, uint16_t confirmationCount) :
SystemObject(setId), commandQueue(NULL), parameterHelper(this), healthHelper(this, setId), set(), current( SystemObject(objectId), parameterHelper(this),
ids.pidCurrent, &set), voltage(ids.pidVoltage, &set), power( healthHelper(this, objectId),
ids.poolIdPower, &set, PoolVariableIF::VAR_WRITE), currentLimit( powerSensorSet(setId), current(ids.pidCurrent, &powerSensorSet),
setId, MODULE_ID_CURRENT, ids.pidCurrent, confirmationCount, voltage(ids.pidVoltage, &powerSensorSet),
power(ids.poolIdPower, &powerSensorSet, PoolVariableIF::VAR_WRITE),
currentLimit(objectId, MODULE_ID_CURRENT, ids.pidCurrent, confirmationCount,
limits.currentMin, limits.currentMax, events.currentLow, limits.currentMin, limits.currentMax, events.currentLow,
events.currentHigh), voltageLimit(setId, MODULE_ID_VOLTAGE, events.currentHigh),
voltageLimit(objectId, MODULE_ID_VOLTAGE,
ids.pidVoltage, confirmationCount, limits.voltageMin, ids.pidVoltage, confirmationCount, limits.voltageMin,
limits.voltageMax, events.voltageLow, events.voltageHigh) { limits.voltageMax, events.voltageLow, events.voltageHigh) {
commandQueue = QueueFactory::instance()->createMessageQueue(); commandQueue = QueueFactory::instance()->createMessageQueue();
@ -19,13 +23,13 @@ PowerSensor::~PowerSensor() {
} }
ReturnValue_t PowerSensor::calculatePower() { ReturnValue_t PowerSensor::calculatePower() {
set.read(); powerSensorSet.read();
ReturnValue_t result1 = HasReturnvaluesIF::RETURN_FAILED; ReturnValue_t result1 = HasReturnvaluesIF::RETURN_FAILED;
ReturnValue_t result2 = HasReturnvaluesIF::RETURN_FAILED; ReturnValue_t result2 = HasReturnvaluesIF::RETURN_FAILED;
if (healthHelper.healthTable->isHealthy(getObjectId()) && voltage.isValid() if (healthHelper.healthTable->isHealthy(getObjectId()) && voltage.isValid()
&& current.isValid()) { && current.isValid()) {
result1 = voltageLimit.doCheck(voltage); result1 = voltageLimit.doCheck(voltage.value);
result2 = currentLimit.doCheck(current); result2 = currentLimit.doCheck(current.value);
} else { } else {
voltageLimit.setToInvalid(); voltageLimit.setToInvalid();
currentLimit.setToInvalid(); currentLimit.setToInvalid();
@ -37,9 +41,9 @@ ReturnValue_t PowerSensor::calculatePower() {
power.setValid(PoolVariableIF::INVALID); power.setValid(PoolVariableIF::INVALID);
} else { } else {
power.setValid(PoolVariableIF::VALID); power.setValid(PoolVariableIF::VALID);
power = current * voltage; power.value = current.value * voltage.value;
} }
set.commit(); powerSensorSet.commit();
return result1; return result1;
} }
@ -92,8 +96,8 @@ void PowerSensor::checkCommandQueue() {
} }
void PowerSensor::setDataPoolEntriesInvalid() { void PowerSensor::setDataPoolEntriesInvalid() {
set.read(); powerSensorSet.read();
set.commit(PoolVariableIF::INVALID); powerSensorSet.commit(PoolVariableIF::INVALID);
} }
float PowerSensor::getPower() { float PowerSensor::getPower() {

View File

@ -1,9 +1,7 @@
#ifndef POWERSENSOR_H_ #ifndef FSFW_POWER_POWERSENSOR_H_
#define POWERSENSOR_H_ #define FSFW_POWER_POWERSENSOR_H_
#include "../datapoolglob/GlobalDataSet.h" #include "../datapoollocal/StaticLocalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../datapoolglob/PIDReader.h"
#include "../devicehandlers/HealthDevice.h" #include "../devicehandlers/HealthDevice.h"
#include "../monitoring/LimitMonitor.h" #include "../monitoring/LimitMonitor.h"
#include "../parameters/ParameterHelper.h" #include "../parameters/ParameterHelper.h"
@ -12,15 +10,18 @@
class PowerController; class PowerController;
/**
* @brief Does magic.
*/
class PowerSensor: public SystemObject, class PowerSensor: public SystemObject,
public ReceivesParameterMessagesIF, public ReceivesParameterMessagesIF,
public HasHealthIF { public HasHealthIF {
friend class PowerController; friend class PowerController;
public: public:
struct VariableIds { struct VariableIds {
uint32_t pidCurrent; gp_id_t pidCurrent;
uint32_t pidVoltage; gp_id_t pidVoltage;
uint32_t poolIdPower; gp_id_t poolIdPower;
}; };
struct DefaultLimits { struct DefaultLimits {
float currentMin; float currentMin;
@ -34,8 +35,9 @@ public:
Event voltageLow; Event voltageLow;
Event voltageHigh; Event voltageHigh;
}; };
PowerSensor(object_id_t setId, VariableIds setIds, DefaultLimits limits, PowerSensor(object_id_t objectId, sid_t sid, VariableIds setIds,
SensorEvents events, uint16_t confirmationCount = 0); DefaultLimits limits, SensorEvents events,
uint16_t confirmationCount = 0);
virtual ~PowerSensor(); virtual ~PowerSensor();
ReturnValue_t calculatePower(); ReturnValue_t calculatePower();
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
@ -50,15 +52,19 @@ public:
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);
private: private:
MessageQueueIF* commandQueue; MessageQueueIF* commandQueue = nullptr;
ParameterHelper parameterHelper; ParameterHelper parameterHelper;
HealthHelper healthHelper; HealthHelper healthHelper;
GlobDataSet set; //GlobDataSet set;
StaticLocalDataSet<3> powerSensorSet;
//Variables in //Variables in
PIDReader<float> current; lp_var_t<float> current;
PIDReader<float> voltage; lp_var_t<float> voltage;
//PIDReader<float> current;
//PIDReader<float> voltage;
//Variables out //Variables out
gp_float_t power; lp_var_t<float> power;
//gp_float_t power;
static const uint8_t MODULE_ID_CURRENT = 1; static const uint8_t MODULE_ID_CURRENT = 1;
static const uint8_t MODULE_ID_VOLTAGE = 2; static const uint8_t MODULE_ID_VOLTAGE = 2;
@ -68,4 +74,4 @@ protected:
LimitMonitor<float> voltageLimit; LimitMonitor<float> voltageLimit;
}; };
#endif /* POWERSENSOR_H_ */ #endif /* FSFW_POWER_POWERSENSOR_H_ */

View File

@ -1,18 +1,16 @@
/** #ifndef FSFW_POWER_POWERSWITCHIF_H_
* @file PowerSwitchIF.h #define FSFW_POWER_POWERSWITCHIF_H_
* @brief This file defines the PowerSwitchIF class.
* @date 20.03.2013
* @author baetz
*/
#ifndef POWERSWITCHIF_H_
#define POWERSWITCHIF_H_
#include "../events/Event.h" #include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
/** /**
* This interface defines a connection to a device that is capable of turning on and off *
* switches of devices identified by a switch ID. * @brief This interface defines a connection to a device that is capable of
* turning on and off switches of devices identified by a switch ID.
* @details
* The virtual functions of this interface do not allow to make any assignments
* because they can be called asynchronosuly (const ending).
* @ingroup interfaces
*/ */
class PowerSwitchIF : public HasReturnvaluesIF { class PowerSwitchIF : public HasReturnvaluesIF {
public: public:
@ -72,4 +70,4 @@ public:
}; };
#endif /* POWERSWITCHIF_H_ */ #endif /* FSFW_POWER_POWERSWITCHIF_H_ */

View File

@ -1,15 +1,17 @@
#include "../objectmanager/ObjectManagerIF.h"
#include "PowerSwitcher.h" #include "PowerSwitcher.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2, PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2,
PowerSwitcher::State_t setStartState) : PowerSwitcher::State_t setStartState):
state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2), power(NULL) { state(setStartState), firstSwitch(setSwitch1),
secondSwitch(setSwitch2) {
} }
ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) { ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) {
power = objectManager->get<PowerSwitchIF>(powerSwitchId); power = objectManager->get<PowerSwitchIF>(powerSwitchId);
if (power == NULL) { if (power == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -17,19 +19,25 @@ ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) {
ReturnValue_t PowerSwitcher::getStateOfSwitches() { ReturnValue_t PowerSwitcher::getStateOfSwitches() {
SwitchReturn_t result = howManySwitches(); SwitchReturn_t result = howManySwitches();
switch (result) { switch (result) {
case ONE_SWITCH: case ONE_SWITCH:
return power->getSwitchState(firstSwitch); return power->getSwitchState(firstSwitch);
case TWO_SWITCHES: case TWO_SWITCHES: {
if ((power->getSwitchState(firstSwitch) == PowerSwitchIF::SWITCH_ON) ReturnValue_t firstSwitchState = power->getSwitchState(firstSwitch);
&& (power->getSwitchState(secondSwitch) == PowerSwitchIF::SWITCH_ON)) { ReturnValue_t secondSwitchState = power->getSwitchState(firstSwitch);
if ((firstSwitchState == PowerSwitchIF::SWITCH_ON)
&& (secondSwitchState == PowerSwitchIF::SWITCH_ON)) {
return PowerSwitchIF::SWITCH_ON; return PowerSwitchIF::SWITCH_ON;
} else if ((power->getSwitchState(firstSwitch) == PowerSwitchIF::SWITCH_OFF) }
&& (power->getSwitchState(secondSwitch) == PowerSwitchIF::SWITCH_OFF)) { else if ((firstSwitchState == PowerSwitchIF::SWITCH_OFF)
&& (secondSwitchState == PowerSwitchIF::SWITCH_OFF)) {
return PowerSwitchIF::SWITCH_OFF; return PowerSwitchIF::SWITCH_OFF;
} else { }
else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
}
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -1,10 +1,13 @@
#ifndef POWERSWITCHER_H_ #ifndef FSFW_POWER_POWERSWITCHER_H_
#define POWERSWITCHER_H_ #define FSFW_POWER_POWERSWITCHER_H_
#include "PowerSwitchIF.h" #include "PowerSwitchIF.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../timemanager/Countdown.h" #include "../timemanager/Countdown.h"
class PowerSwitcher : public HasReturnvaluesIF { class PowerSwitcher: public HasReturnvaluesIF {
public: public:
enum State_t { enum State_t {
WAIT_OFF, WAIT_OFF,
@ -16,7 +19,8 @@ public:
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, State_t setStartState = SWITCH_IS_OFF ); PowerSwitcher( uint8_t setSwitch1, uint8_t setSwitch2 = NO_SWITCH,
State_t setStartState = SWITCH_IS_OFF );
ReturnValue_t initialize(object_id_t powerSwitchId); ReturnValue_t initialize(object_id_t powerSwitchId);
void turnOn(); void turnOn();
void turnOff(); void turnOff();
@ -29,7 +33,8 @@ public:
private: private:
uint8_t firstSwitch; uint8_t firstSwitch;
uint8_t secondSwitch; uint8_t secondSwitch;
PowerSwitchIF* power; PowerSwitchIF* power = nullptr;
static const uint8_t NO_SWITCH = 0xFF; static const uint8_t NO_SWITCH = 0xFF;
enum SwitchReturn_t { enum SwitchReturn_t {
ONE_SWITCH = 1, ONE_SWITCH = 1,
@ -42,4 +47,4 @@ private:
#endif /* POWERSWITCHER_H_ */ #endif /* FSFW_POWER_POWERSWITCHER_H_ */

View File

@ -44,19 +44,19 @@ ReturnValue_t AbstractTemperatureSensor::performHealthOp() {
} }
void AbstractTemperatureSensor::handleCommandQueue() { void AbstractTemperatureSensor::handleCommandQueue() {
CommandMessage message; CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&message); ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
result = healthHelper.handleHealthCommand(&message); result = healthHelper.handleHealthCommand(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
return; return;
} }
result = parameterHelper.handleParameterMessage(&message); result = parameterHelper.handleParameterMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
return; return;
} }
message.setToUnknownCommand(); command.setToUnknownCommand();
commandQueue->reply(&message); commandQueue->reply(&command);
} }
} }

View File

@ -10,6 +10,16 @@
#include "ThermalModuleIF.h" #include "ThermalModuleIF.h"
#include "tcsDefinitions.h" #include "tcsDefinitions.h"
/**
* @defgroup thermal Thermal Components
* @brief Contains all components related to thermal tasks (sensors, heaters)
*/
/**
* @brief Base class for Temperature Sensor, implements all important interfaces.
* Please use the TemperatureSensor class to implement the actual sensors.
* @ingroup thermal
*/
class AbstractTemperatureSensor: public HasHealthIF, class AbstractTemperatureSensor: public HasHealthIF,
public SystemObject, public SystemObject,
public ExecutableObjectIF, public ExecutableObjectIF,

View File

@ -0,0 +1,22 @@
/**
* \file AcceptsThermalMessagesIF.h
*
* \date 16.02.2020
*/
#ifndef FRAMEWORK_THERMAL_ACCEPTSTHERMALMESSAGESIF_H_
#define FRAMEWORK_THERMAL_ACCEPTSTHERMALMESSAGESIF_H_
#include "../ipc/MessageQueueSenderIF.h"
class AcceptsThermalMessagesIF {
public:
/**
* @brief This is the empty virtual destructor as required for C++ interfaces.
*/
virtual ~AcceptsThermalMessagesIF() { }
virtual MessageQueueId_t getReceptionQueue() const = 0;
};
#endif /* FRAMEWORK_THERMAL_ACCEPTSTHERMALMESSAGESIF_H_ */

View File

@ -1,96 +0,0 @@
#ifndef MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_
#define MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../thermal/ThermalComponentIF.h"
#include "../thermal/AbstractTemperatureSensor.h"
#include "../thermal/ThermalModule.h"
#include "../thermal/ThermalMonitor.h"
// TODO: Documentaiton, how to use this? only use Thermal Component, which inherits core component?
class CoreComponent: public ThermalComponentIF {
public:
struct Parameters {
float lowerOpLimit;
float upperOpLimit;
float heaterOn;
float hysteresis;
float heaterSwitchoff;
};
static const uint16_t COMPONENT_TEMP_CONFIRMATION = 5;
CoreComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId,
uint32_t targetStatePoolId, uint32_t currentStatePoolId,
uint32_t requestPoolId, GlobDataSet *dataSet,
AbstractTemperatureSensor *sensor,
AbstractTemperatureSensor *firstRedundantSensor,
AbstractTemperatureSensor *secondRedundantSensor,
ThermalModuleIF *thermalModule, Parameters parameters,
Priority priority, StateRequest initialTargetState =
ThermalComponentIF::STATE_REQUEST_OPERATIONAL);
virtual ~CoreComponent();
virtual HeaterRequest performOperation(uint8_t opCode);
void markStateIgnored();
object_id_t getObjectId();
uint8_t getDomainId() const;
virtual float getLowerOpLimit();
ReturnValue_t setTargetState(int8_t newState);
virtual void setOutputInvalid();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
protected:
AbstractTemperatureSensor *sensor;
AbstractTemperatureSensor *firstRedundantSensor;
AbstractTemperatureSensor *secondRedundantSensor;
ThermalModuleIF *thermalModule;
gp_float_t temperature;
gp_int8_t targetState;
gp_int8_t currentState;
gp_uint8_t heaterRequest;
bool isHeating;
bool isSafeComponent;
float minTemp;
float maxTemp;
Parameters parameters;
ThermalMonitor temperatureMonitor;
const uint8_t domainId;
virtual float getTemperature();
virtual State getState(float temperature, Parameters parameters,
int8_t targetState);
virtual void checkLimits(State state);
virtual HeaterRequest getHeaterRequest(int8_t targetState,
float temperature, Parameters parameters);
virtual State getIgnoredState(int8_t state);
void updateMinMaxTemp();
virtual Parameters getParameters();
};
#endif /* MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ */

View File

@ -279,14 +279,14 @@ ReturnValue_t Heater::initialize() {
} }
void Heater::handleQueue() { void Heater::handleQueue() {
CommandMessage message; CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&message); ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
result = healthHelper.handleHealthCommand(&message); result = healthHelper.handleHealthCommand(&command);
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
return; return;
} }
parameterHelper.handleParameterMessage(&message); parameterHelper.handleParameterMessage(&command);
} }
} }
@ -301,7 +301,7 @@ ReturnValue_t Heater::getParameter(uint8_t domainId, uint16_t parameterId,
parameterWrapper->set(heaterOnCountdown.timeout); parameterWrapper->set(heaterOnCountdown.timeout);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,7 +1,7 @@
#ifndef REDUNDANTHEATER_H_ #ifndef REDUNDANTHEATER_H_
#define REDUNDANTHEATER_H_ #define REDUNDANTHEATER_H_
#include "Heater.h" #include "../thermal/Heater.h"
class RedundantHeater { class RedundantHeater {
public: public:
@ -10,15 +10,14 @@ public:
Parameters(uint32_t objectIdHeater0, uint32_t objectIdHeater1, Parameters(uint32_t objectIdHeater0, uint32_t objectIdHeater1,
uint8_t switch0Heater0, uint8_t switch1Heater0, uint8_t switch0Heater0, uint8_t switch1Heater0,
uint8_t switch0Heater1, uint8_t switch1Heater1) : uint8_t switch0Heater1, uint8_t switch1Heater1) :
objectIdHeater0(objectIdHeater0), objectIdHeater1( objectIdHeater0(objectIdHeater0), objectIdHeater1(objectIdHeater1),
objectIdHeater1), switch0Heater0(switch0Heater0), switch1Heater0( switch0Heater0(switch0Heater0),switch1Heater0(switch1Heater0),
switch1Heater0), switch0Heater1(switch0Heater1), switch1Heater1( switch0Heater1(switch0Heater1), switch1Heater1(switch1Heater1) {
switch1Heater1) {
} }
Parameters() : Parameters() :
objectIdHeater0(0), objectIdHeater1(0), switch0Heater0(0), switch1Heater0( objectIdHeater0(0), objectIdHeater1(0), switch0Heater0(0),
0), switch0Heater1(0), switch1Heater1(0) { switch1Heater0(0), switch0Heater1(0), switch1Heater1(0) {
} }
uint32_t objectIdHeater0; uint32_t objectIdHeater0;

View File

@ -1,40 +1,101 @@
#ifndef TEMPERATURESENSOR_H_ #ifndef TEMPERATURESENSOR_H_
#define TEMPERATURESENSOR_H_ #define TEMPERATURESENSOR_H_
#include "../datapool/DataSet.h" #include "../thermal/AbstractTemperatureSensor.h"
#include "AbstractTemperatureSensor.h" #include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../monitoring/LimitMonitor.h" #include "../monitoring/LimitMonitor.h"
template<typename T> /**
* @brief This building block handles non-linear value conversion and
* range checks for analog temperature sensors.
* @details This class can be used to perform all necessary tasks for temperature sensors.
* A sensor can be instantiated by calling the constructor.
* The temperature is calculated from an input value with
* the calculateOutputTemperature() function. Range checking and
* limit monitoring is performed automatically.
* The inputType specifies the type of the raw input while the
* limitType specifies the type of the upper and lower limit to check against.
* @ingroup thermal
*/
template<typename inputType, typename limitType = inputType>
class TemperatureSensor: public AbstractTemperatureSensor { class TemperatureSensor: public AbstractTemperatureSensor {
public: public:
/**
* This structure contains parameters required for range checking
* and the conversion from the input value to the output temperature.
* a, b and c can be any parameters required to calculate the output
* temperature from the input value, depending on the formula used.
*
* The parameters a,b and c are used in the calculateOutputTemperature() call.
*
* The lower and upper limits can be specified in any type, for example float for C values
* or any other type for raw values.
*/
struct Parameters { struct Parameters {
float a; float a;
float b; float b;
float c; float c;
T lowerLimit; limitType lowerLimit;
T upperLimit; limitType upperLimit;
float gradient; float maxGradient;
}; };
/**
* Forward declaration for explicit instantiation of used parameters.
*/
struct UsedParameters { struct UsedParameters {
UsedParameters(Parameters parameters) : UsedParameters(Parameters parameters) :
a(parameters.a), b(parameters.b), c(parameters.c), gradient( a(parameters.a), b(parameters.b), c(parameters.c),
parameters.gradient) { gradient(parameters.maxGradient) {}
}
float a; float a;
float b; float b;
float c; float c;
float gradient; float gradient;
}; };
static const uint16_t ADDRESS_A = 0; /**
static const uint16_t ADDRESS_B = 1; * Instantiate Temperature Sensor Object.
static const uint16_t ADDRESS_C = 2; * @param setObjectid objectId of the sensor object
static const uint16_t ADDRESS_GRADIENT = 3; * @param inputValue Input value which is converted to a temperature
* @param poolVariable Pool Variable to store the temperature value
* @param vectorIndex Vector Index for the sensor monitor
* @param parameters Calculation parameters, temperature limits, gradient limit
* @param datapoolId Datapool ID of the output temperature
* @param outputSet Output dataset for the output temperature to fetch it with read()
* @param thermalModule respective thermal module, if it has one
*/
TemperatureSensor(object_id_t setObjectid,
inputType *inputValue, PoolVariableIF *poolVariable,
uint8_t vectorIndex, uint32_t datapoolId, Parameters parameters = {0, 0, 0, 0, 0, 0},
GlobDataSet *outputSet = NULL, ThermalModuleIF *thermalModule = NULL) :
AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters),
inputValue(inputValue), poolVariable(poolVariable),
outputTemperature(datapoolId, outputSet, PoolVariableIF::VAR_WRITE),
sensorMonitor(setObjectid, DOMAIN_ID_SENSOR,
GlobalDataPool::poolIdAndPositionToPid(poolVariable->getDataPoolId(), vectorIndex),
DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit, parameters.upperLimit,
TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH),
oldTemperature(20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) {
}
protected:
/**
* This formula is used to calculate the temperature from an input value
* with an arbitrary type.
* A default implementation is provided but can be replaced depending
* on the required calculation.
* @param inputTemperature
* @return
*/
virtual float calculateOutputTemperature(inputType inputValue) {
return parameters.a * inputValue * inputValue
+ parameters.b * inputValue + parameters.c;
}
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.)
static const uint8_t DOMAIN_ID_SENSOR = 1;
private: private:
void setInvalid() { void setInvalid() {
outputTemperature = INVALID_TEMPERATURE; outputTemperature = INVALID_TEMPERATURE;
@ -47,22 +108,17 @@ protected:
UsedParameters parameters; UsedParameters parameters;
T *inputTemperature; inputType * inputValue;
PoolVariableIF *poolVariable; PoolVariableIF *poolVariable;
PoolVariable<float> outputTemperature; gp_float_t outputTemperature;
LimitMonitor<T> sensorMonitor; LimitMonitor<limitType> sensorMonitor;
float oldTemperature; float oldTemperature;
timeval uptimeOfOldTemperature; timeval uptimeOfOldTemperature;
virtual float calculateOutputTemperature(T inputTemperature) {
return parameters.a * inputTemperature * inputTemperature
+ parameters.b * inputTemperature + parameters.c;
}
void doChildOperation() { void doChildOperation() {
if (!poolVariable->isValid() if (!poolVariable->isValid()
|| !healthHelper.healthTable->isHealthy(getObjectId())) { || !healthHelper.healthTable->isHealthy(getObjectId())) {
@ -70,7 +126,7 @@ protected:
return; return;
} }
outputTemperature = calculateOutputTemperature(*inputTemperature); outputTemperature = calculateOutputTemperature(*inputValue);
outputTemperature.setValid(PoolVariableIF::VALID); outputTemperature.setValid(PoolVariableIF::VALID);
timeval uptime; timeval uptime;
@ -78,7 +134,7 @@ protected:
if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) { if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) {
//In theory, we could use an AbsValueMonitor to monitor the gradient. //In theory, we could use an AbsValueMonitor to monitor the gradient.
//But this would require storing the gradient in DP and quite some overhead. //But this would require storing the maxGradient in DP and quite some overhead.
//The concept of delta limits is a bit strange anyway. //The concept of delta limits is a bit strange anyway.
float deltaTime; float deltaTime;
float deltaTemp; float deltaTemp;
@ -96,8 +152,8 @@ protected:
} }
} }
//Check is done against raw limits. SHOULDDO: Why? Using °C would be more easy to handle. //Check is done against raw limits. SHOULDDO: Why? Using <EFBFBD>C would be more easy to handle.
sensorMonitor.doCheck(*inputTemperature); sensorMonitor.doCheck(outputTemperature.value);
if (sensorMonitor.isOutOfLimits()) { if (sensorMonitor.isOutOfLimits()) {
uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; uptimeOfOldTemperature.tv_sec = INVALID_UPTIME;
@ -110,23 +166,6 @@ protected:
} }
public: public:
TemperatureSensor(object_id_t setObjectid,
T *inputTemperature, PoolVariableIF *poolVariable,
uint8_t vectorIndex, Parameters parameters, uint32_t datapoolId,
DataSet *outputSet, ThermalModuleIF *thermalModule) :
AbstractTemperatureSensor(setObjectid, thermalModule), parameters(
parameters), inputTemperature(inputTemperature), poolVariable(
poolVariable), outputTemperature(datapoolId, outputSet,
PoolVariableIF::VAR_WRITE), sensorMonitor(setObjectid,
DOMAIN_ID_SENSOR,
DataPool::poolIdAndPositionToPid(
poolVariable->getDataPoolId(), vectorIndex),
DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit,
parameters.upperLimit, TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH), oldTemperature(
20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) {
}
float getTemperature() { float getTemperature() {
return outputTemperature; return outputTemperature;
} }
@ -135,6 +174,15 @@ public:
return outputTemperature.isValid(); return outputTemperature.isValid();
} }
static const uint16_t ADDRESS_A = 0;
static const uint16_t ADDRESS_B = 1;
static const uint16_t ADDRESS_C = 2;
static const uint16_t ADDRESS_GRADIENT = 3;
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.)
static const uint8_t DOMAIN_ID_SENSOR = 1;
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) { const ParameterWrapper *newValues, uint16_t startAtIndex) {
@ -160,7 +208,7 @@ public:
parameterWrapper->set(parameters.gradient); parameterWrapper->set(parameters.gradient);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,20 +1,20 @@
#include "ThermalComponent.h" #include "ThermalComponent.h"
ThermalComponent::ThermalComponent(object_id_t reportingObjectId, ThermalComponent::ThermalComponent(object_id_t reportingObjectId,
uint8_t domainId, uint32_t temperaturePoolId, uint8_t domainId, gp_id_t temperaturePoolId,
uint32_t targetStatePoolId, uint32_t currentStatePoolId, gp_id_t targetStatePoolId, gp_id_t currentStatePoolId,
uint32_t requestPoolId, GlobDataSet* dataSet, gp_id_t requestPoolId, LocalPoolDataSetBase* dataSet,
AbstractTemperatureSensor* sensor, AbstractTemperatureSensor* sensor,
AbstractTemperatureSensor* firstRedundantSensor, AbstractTemperatureSensor* firstRedundantSensor,
AbstractTemperatureSensor* secondRedundantSensor, AbstractTemperatureSensor* secondRedundantSensor,
ThermalModuleIF* thermalModule, Parameters parameters, ThermalModuleIF* thermalModule, Parameters parameters,
Priority priority) : Priority priority) :
CoreComponent(reportingObjectId, domainId, temperaturePoolId, ThermalComponentCore(reportingObjectId, domainId, temperaturePoolId,
targetStatePoolId, currentStatePoolId, requestPoolId, dataSet, targetStatePoolId, currentStatePoolId, requestPoolId, dataSet,
sensor, firstRedundantSensor, secondRedundantSensor, { parameters.lowerOpLimit, parameters.upperOpLimit,
thermalModule,{ parameters.lowerOpLimit, parameters.upperOpLimit, parameters.heaterOn, parameters.hysteresis,
parameters.heaterOn, parameters.hysteresis, parameters.heaterSwitchoff }, parameters.heaterSwitchoff },
priority, ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL), ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL),
nopParameters({ parameters.lowerNopLimit, parameters.upperNopLimit }) { nopParameters({ parameters.lowerNopLimit, parameters.upperNopLimit }) {
} }
@ -22,22 +22,22 @@ ThermalComponent::~ThermalComponent() {
} }
ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { ReturnValue_t ThermalComponent::setTargetState(int8_t newState) {
GlobDataSet mySet; targetState.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE);
gp_int8_t writableTargetState(targetState.getDataPoolId(), targetState.read();
&mySet, PoolVariableIF::VAR_READ_WRITE); if ((targetState == STATE_REQUEST_OPERATIONAL)
mySet.read(); and (newState != STATE_REQUEST_IGNORE)) {
if ((writableTargetState == STATE_REQUEST_OPERATIONAL)
&& (newState != STATE_REQUEST_IGNORE)) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
switch (newState) { switch (newState) {
case STATE_REQUEST_NON_OPERATIONAL: case STATE_REQUEST_NON_OPERATIONAL:
writableTargetState = newState; targetState = newState;
mySet.commit(PoolVariableIF::VALID); targetState.setValid(true);
targetState.commit(PoolVariableIF::VALID);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
default: default:
return CoreComponent::setTargetState(newState); return ThermalComponentCore::setTargetState(newState);
} }
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) { ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) {
@ -57,11 +57,11 @@ ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) {
} }
ThermalComponentIF::State ThermalComponent::getState(float temperature, ThermalComponentIF::State ThermalComponent::getState(float temperature,
CoreComponent::Parameters parameters, int8_t targetState) { ThermalComponentCore::Parameters parameters, int8_t targetState) {
if (temperature < nopParameters.lowerNopLimit) { if (temperature < nopParameters.lowerNopLimit) {
return OUT_OF_RANGE_LOW; return OUT_OF_RANGE_LOW;
} else { } else {
State state = CoreComponent::getState(temperature, parameters, State state = ThermalComponentCore::getState(temperature, parameters,
targetState); targetState);
if (state != NON_OPERATIONAL_HIGH if (state != NON_OPERATIONAL_HIGH
&& state != NON_OPERATIONAL_HIGH_IGNORED) { && state != NON_OPERATIONAL_HIGH_IGNORED) {
@ -78,18 +78,19 @@ ThermalComponentIF::State ThermalComponent::getState(float temperature,
} }
void ThermalComponent::checkLimits(ThermalComponentIF::State state) { void ThermalComponent::checkLimits(ThermalComponentIF::State state) {
if (targetState == STATE_REQUEST_OPERATIONAL || targetState == STATE_REQUEST_IGNORE) { if ((targetState == STATE_REQUEST_OPERATIONAL) or
CoreComponent::checkLimits(state); (targetState == STATE_REQUEST_IGNORE)) {
ThermalComponentCore::checkLimits(state);
return; return;
} }
//If component is not operational, it checks the NOP limits. // If component is not operational, it checks the NOP limits.
temperatureMonitor.translateState(state, temperature.value, temperatureMonitor.translateState(state, temperature.value,
nopParameters.lowerNopLimit, nopParameters.upperNopLimit, false); nopParameters.lowerNopLimit, nopParameters.upperNopLimit, false);
} }
ThermalComponentIF::HeaterRequest ThermalComponent::getHeaterRequest( ThermalComponentIF::HeaterRequest ThermalComponent::getHeaterRequest(
int8_t targetState, float temperature, int8_t targetState, float temperature,
CoreComponent::Parameters parameters) { ThermalComponentCore::Parameters parameters) {
if (targetState == STATE_REQUEST_IGNORE) { if (targetState == STATE_REQUEST_IGNORE) {
isHeating = false; isHeating = false;
return HEATER_DONT_CARE; return HEATER_DONT_CARE;
@ -142,16 +143,16 @@ ThermalComponentIF::State ThermalComponent::getIgnoredState(int8_t state) {
case OUT_OF_RANGE_HIGH_IGNORED: case OUT_OF_RANGE_HIGH_IGNORED:
return OUT_OF_RANGE_HIGH_IGNORED; return OUT_OF_RANGE_HIGH_IGNORED;
default: default:
return CoreComponent::getIgnoredState(state); return ThermalComponentCore::getIgnoredState(state);
} }
} }
ReturnValue_t ThermalComponent::getParameter(uint8_t domainId, ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) { const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = CoreComponent::getParameter(domainId, parameterId, ReturnValue_t result = ThermalComponentCore::getParameter(domainId, parameterId,
parameterWrapper, newValues, startAtIndex); parameterWrapper, newValues, startAtIndex);
if (result != INVALID_MATRIX_ID) { if (result != INVALID_IDENTIFIER_ID) {
return result; return result;
} }
switch (parameterId) { switch (parameterId) {
@ -162,7 +163,7 @@ ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
parameterWrapper->set(nopParameters.upperNopLimit); parameterWrapper->set(nopParameters.upperNopLimit);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,12 +1,14 @@
#ifndef THERMALCOMPONENT_H_ #ifndef FSFW_THERMAL_THERMALCOMPONENT_H_
#define THERMALCOMPONENT_H_ #define FSFW_THERMAL_THERMALCOMPONENT_H_
#include "CoreComponent.h" #include "ThermalComponentCore.h"
/** /**
* What is it. How to use * @brief
* @details
* Some more documentation.
*/ */
class ThermalComponent: public CoreComponent { class ThermalComponent: public ThermalComponentCore {
public: public:
struct Parameters { struct Parameters {
float lowerNopLimit; float lowerNopLimit;
@ -42,9 +44,10 @@ public:
* @param parameters * @param parameters
* @param priority * @param priority
*/ */
ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, ThermalComponent(object_id_t reportingObjectId, uint8_t domainId,
uint32_t targetStatePoolId, uint32_t currentStatePoolId, uint32_t requestPoolId, gp_id_t temperaturePoolId, gp_id_t targetStatePoolId,
GlobDataSet *dataSet, AbstractTemperatureSensor *sensor, gp_id_t currentStatePoolId, gp_id_t requestPoolId,
LocalPoolDataSetBase *dataSet, AbstractTemperatureSensor *sensor,
AbstractTemperatureSensor *firstRedundantSensor, AbstractTemperatureSensor *firstRedundantSensor,
AbstractTemperatureSensor *secondRedundantSensor, AbstractTemperatureSensor *secondRedundantSensor,
ThermalModuleIF *thermalModule, Parameters parameters, ThermalModuleIF *thermalModule, Parameters parameters,
@ -63,15 +66,15 @@ protected:
NopParameters nopParameters; NopParameters nopParameters;
State getState(float temperature, CoreComponent::Parameters parameters, State getState(float temperature, ThermalComponentCore::Parameters parameters,
int8_t targetState); int8_t targetState);
virtual void checkLimits(State state); virtual void checkLimits(State state);
virtual HeaterRequest getHeaterRequest(int8_t targetState, float temperature, virtual HeaterRequest getHeaterRequest(int8_t targetState, float temperature,
CoreComponent::Parameters parameters); ThermalComponentCore::Parameters parameters);
State getIgnoredState(int8_t state); State getIgnoredState(int8_t state);
}; };
#endif /* THERMALCOMPONENT_H_ */ #endif /* FSFW_THERMAL_THERMALCOMPONENT_H_ */

View File

@ -1,50 +1,73 @@
#include "CoreComponent.h" #include "ThermalComponentCore.h"
CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, ThermalComponentCore::ThermalComponentCore(object_id_t reportingObjectId,
uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint8_t domainId, gp_id_t temperaturePoolId,
uint32_t currentStatePoolId, uint32_t requestPoolId, GlobDataSet* dataSet, gp_id_t targetStatePoolId, gp_id_t currentStatePoolId,
AbstractTemperatureSensor* sensor, gp_id_t requestPoolId, LocalPoolDataSetBase* dataSet,
AbstractTemperatureSensor* firstRedundantSensor, Parameters parameters, StateRequest initialTargetState) :
AbstractTemperatureSensor* secondRedundantSensor, temperature(temperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE),
ThermalModuleIF* thermalModule, Parameters parameters, targetState(targetStatePoolId, dataSet, PoolVariableIF::VAR_READ),
Priority priority, StateRequest initialTargetState) : currentState(currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE),
sensor(sensor), firstRedundantSensor(firstRedundantSensor), secondRedundantSensor( heaterRequest(requestPoolId, dataSet, PoolVariableIF::VAR_WRITE),
secondRedundantSensor), thermalModule(thermalModule), temperature( parameters(parameters), domainId(domainId),
temperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), targetState( temperatureMonitor(reportingObjectId, domainId + 1,temperaturePoolId,
targetStatePoolId, dataSet, PoolVariableIF::VAR_READ), currentState( COMPONENT_TEMP_CONFIRMATION) {
currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE), heaterRequest(
requestPoolId, dataSet, PoolVariableIF::VAR_WRITE), isHeating(
false), isSafeComponent(priority == SAFE), minTemp(999), maxTemp(
AbstractTemperatureSensor::ZERO_KELVIN_C), parameters(
parameters), temperatureMonitor(reportingObjectId,
domainId + 1,
GlobalDataPool::poolIdAndPositionToPid(temperaturePoolId, 0),
COMPONENT_TEMP_CONFIRMATION), domainId(domainId) {
if (thermalModule != NULL) {
thermalModule->registerComponent(this, priority);
}
//Set thermal state once, then leave to operator. //Set thermal state once, then leave to operator.
GlobDataSet mySet; targetState.setReadWriteMode(PoolVariableIF::VAR_WRITE);
gp_uint8_t writableTargetState(targetStatePoolId, &mySet, ReturnValue_t result = targetState.read();
PoolVariableIF::VAR_WRITE); if(result == HasReturnvaluesIF::RETURN_OK) {
writableTargetState = initialTargetState; targetState = initialTargetState;
mySet.commit(PoolVariableIF::VALID); targetState.setValid(true);
targetState.commit();
}
targetState.setReadWriteMode(PoolVariableIF::VAR_READ);
} }
CoreComponent::~CoreComponent() { void ThermalComponentCore::addSensor(AbstractTemperatureSensor* sensor) {
this->sensor = sensor;
} }
ThermalComponentIF::HeaterRequest CoreComponent::performOperation(uint8_t opCode) { void ThermalComponentCore::addFirstRedundantSensor(
AbstractTemperatureSensor *firstRedundantSensor) {
this->firstRedundantSensor = firstRedundantSensor;
}
void ThermalComponentCore::addSecondRedundantSensor(
AbstractTemperatureSensor *secondRedundantSensor) {
this->secondRedundantSensor = secondRedundantSensor;
}
void ThermalComponentCore::addThermalModule(ThermalModule *thermalModule,
Priority priority) {
this->thermalModule = thermalModule;
if(thermalModule != nullptr) {
thermalModule->registerComponent(this, priority);
}
}
void ThermalComponentCore::setPriority(Priority priority) {
if(priority == SAFE) {
this->isSafeComponent = true;
}
}
ThermalComponentCore::~ThermalComponentCore() {
}
ThermalComponentIF::HeaterRequest ThermalComponentCore::performOperation(
uint8_t opCode) {
HeaterRequest request = HEATER_DONT_CARE; HeaterRequest request = HEATER_DONT_CARE;
//SHOULDDO: Better pass db_float_t* to getTemperature and set it invalid if invalid. //SHOULDDO: Better pass db_float_t* to getTemperature and set it invalid if invalid.
temperature = getTemperature(); temperature = getTemperature();
updateMinMaxTemp(); updateMinMaxTemp();
if ((temperature != INVALID_TEMPERATURE)) { if (temperature != INVALID_TEMPERATURE) {
temperature.setValid(PoolVariableIF::VALID); temperature.setValid(PoolVariableIF::VALID);
State state = getState(temperature, getParameters(), targetState); State state = getState(temperature.value, getParameters(),
targetState.value);
currentState = state; currentState = state;
checkLimits(state); checkLimits(state);
request = getHeaterRequest(targetState, temperature, getParameters()); request = getHeaterRequest(targetState.value, temperature.value,
getParameters());
} else { } else {
temperatureMonitor.setToInvalid(); temperatureMonitor.setToInvalid();
temperature.setValid(PoolVariableIF::INVALID); temperature.setValid(PoolVariableIF::INVALID);
@ -57,42 +80,45 @@ ThermalComponentIF::HeaterRequest CoreComponent::performOperation(uint8_t opCode
return request; return request;
} }
void CoreComponent::markStateIgnored() { void ThermalComponentCore::markStateIgnored() {
currentState = getIgnoredState(currentState); currentState = getIgnoredState(currentState.value);
} }
object_id_t CoreComponent::getObjectId() { object_id_t ThermalComponentCore::getObjectId() {
return temperatureMonitor.getReporterId(); return temperatureMonitor.getReporterId();
return 0;
} }
float CoreComponent::getLowerOpLimit() { float ThermalComponentCore::getLowerOpLimit() {
return parameters.lowerOpLimit; return parameters.lowerOpLimit;
} }
ReturnValue_t CoreComponent::setTargetState(int8_t newState) {
GlobDataSet mySet;
gp_uint8_t writableTargetState(targetState.getDataPoolId(), ReturnValue_t ThermalComponentCore::setTargetState(int8_t newState) {
&mySet, PoolVariableIF::VAR_READ_WRITE); targetState.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE);
mySet.read(); targetState.read();
if ((writableTargetState == STATE_REQUEST_OPERATIONAL) if((targetState == STATE_REQUEST_OPERATIONAL) and
&& (newState != STATE_REQUEST_IGNORE)) { (newState != STATE_REQUEST_IGNORE)) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
switch (newState) { switch (newState) {
case STATE_REQUEST_HEATING: case STATE_REQUEST_HEATING:
case STATE_REQUEST_IGNORE: case STATE_REQUEST_IGNORE:
case STATE_REQUEST_OPERATIONAL: case STATE_REQUEST_OPERATIONAL:
writableTargetState = newState; targetState = newState;
break; break;
case STATE_REQUEST_NON_OPERATIONAL: case STATE_REQUEST_NON_OPERATIONAL:
default: default:
return INVALID_TARGET_STATE; return INVALID_TARGET_STATE;
} }
mySet.commit(PoolVariableIF::VALID); targetState.setValid(true);
targetState.commit();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void CoreComponent::setOutputInvalid() { void ThermalComponentCore::setOutputInvalid() {
temperature = INVALID_TEMPERATURE; temperature = INVALID_TEMPERATURE;
temperature.setValid(PoolVariableIF::INVALID); temperature.setValid(PoolVariableIF::INVALID);
currentState.setValid(PoolVariableIF::INVALID); currentState.setValid(PoolVariableIF::INVALID);
@ -101,20 +127,22 @@ void CoreComponent::setOutputInvalid() {
temperatureMonitor.setToUnchecked(); temperatureMonitor.setToUnchecked();
} }
float CoreComponent::getTemperature() { float ThermalComponentCore::getTemperature() {
if ((sensor != NULL) && (sensor->isValid())) { if ((sensor != nullptr) && (sensor->isValid())) {
return sensor->getTemperature(); return sensor->getTemperature();
} }
if ((firstRedundantSensor != NULL) && (firstRedundantSensor->isValid())) { if ((firstRedundantSensor != nullptr) &&
(firstRedundantSensor->isValid())) {
return firstRedundantSensor->getTemperature(); return firstRedundantSensor->getTemperature();
} }
if ((secondRedundantSensor != NULL) && (secondRedundantSensor->isValid())) { if ((secondRedundantSensor != nullptr) &&
(secondRedundantSensor->isValid())) {
return secondRedundantSensor->getTemperature(); return secondRedundantSensor->getTemperature();
} }
if (thermalModule != NULL) { if (thermalModule != nullptr) {
float temperature = thermalModule->getTemperature(); float temperature = thermalModule->getTemperature();
if (temperature != ThermalModuleIF::INVALID_TEMPERATURE) { if (temperature != ThermalModuleIF::INVALID_TEMPERATURE) {
return temperature; return temperature;
@ -126,7 +154,7 @@ float CoreComponent::getTemperature() {
} }
} }
ThermalComponentIF::State CoreComponent::getState(float temperature, ThermalComponentIF::State ThermalComponentCore::getState(float temperature,
Parameters parameters, int8_t targetState) { Parameters parameters, int8_t targetState) {
ThermalComponentIF::State state; ThermalComponentIF::State state;
@ -144,14 +172,14 @@ ThermalComponentIF::State CoreComponent::getState(float temperature,
return state; return state;
} }
void CoreComponent::checkLimits(ThermalComponentIF::State state) { void ThermalComponentCore::checkLimits(ThermalComponentIF::State state) {
//Checks operational limits only. //Checks operational limits only.
temperatureMonitor.translateState(state, temperature.value, temperatureMonitor.translateState(state, temperature.value,
getParameters().lowerOpLimit, getParameters().upperOpLimit); getParameters().lowerOpLimit, getParameters().upperOpLimit);
} }
ThermalComponentIF::HeaterRequest CoreComponent::getHeaterRequest( ThermalComponentIF::HeaterRequest ThermalComponentCore::getHeaterRequest(
int8_t targetState, float temperature, Parameters parameters) { int8_t targetState, float temperature, Parameters parameters) {
if (targetState == STATE_REQUEST_IGNORE) { if (targetState == STATE_REQUEST_IGNORE) {
isHeating = false; isHeating = false;
@ -177,7 +205,7 @@ ThermalComponentIF::HeaterRequest CoreComponent::getHeaterRequest(
return HEATER_DONT_CARE; return HEATER_DONT_CARE;
} }
ThermalComponentIF::State CoreComponent::getIgnoredState(int8_t state) { ThermalComponentIF::State ThermalComponentCore::getIgnoredState(int8_t state) {
switch (state) { switch (state) {
case NON_OPERATIONAL_LOW: case NON_OPERATIONAL_LOW:
return NON_OPERATIONAL_LOW_IGNORED; return NON_OPERATIONAL_LOW_IGNORED;
@ -197,27 +225,27 @@ ThermalComponentIF::State CoreComponent::getIgnoredState(int8_t state) {
} }
} }
void CoreComponent::updateMinMaxTemp() { void ThermalComponentCore::updateMinMaxTemp() {
if (temperature == INVALID_TEMPERATURE) { if (temperature == INVALID_TEMPERATURE) {
return; return;
} }
if (temperature < minTemp) { if (temperature < minTemp) {
minTemp = temperature; minTemp = static_cast<float>(temperature);
} }
if (temperature > maxTemp) { if (temperature > maxTemp) {
maxTemp = temperature; maxTemp = static_cast<float>(temperature);
} }
} }
uint8_t CoreComponent::getDomainId() const { uint8_t ThermalComponentCore::getDomainId() const {
return domainId; return domainId;
} }
CoreComponent::Parameters CoreComponent::getParameters() { ThermalComponentCore::Parameters ThermalComponentCore::getParameters() {
return parameters; return parameters;
} }
ReturnValue_t CoreComponent::getParameter(uint8_t domainId, ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) { const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = temperatureMonitor.getParameter(domainId, ReturnValue_t result = temperatureMonitor.getParameter(domainId,
@ -251,7 +279,7 @@ ReturnValue_t CoreComponent::getParameter(uint8_t domainId,
parameterWrapper->set(parameters.upperOpLimit); parameterWrapper->set(parameters.upperOpLimit);
break; break;
default: default:
return INVALID_MATRIX_ID; return INVALID_IDENTIFIER_ID;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -0,0 +1,117 @@
#ifndef FSFW_THERMAL_THERMALCOMPONENTCORE_H_
#define FSFW_THERMAL_THERMALCOMPONENTCORE_H_
#include "ThermalMonitorReporter.h"
#include "ThermalComponentIF.h"
#include "AbstractTemperatureSensor.h"
#include "ThermalModule.h"
#include "../datapoollocal/LocalPoolVariable.h"
/**
* @brief
* @details
*/
class ThermalComponentCore: public ThermalComponentIF {
public:
struct Parameters {
float lowerOpLimit;
float upperOpLimit;
float heaterOn;
float hysteresis;
float heaterSwitchoff;
};
static const uint16_t COMPONENT_TEMP_CONFIRMATION = 5;
/**
* Some documentation
* @param reportingObjectId
* @param domainId
* @param temperaturePoolId
* @param targetStatePoolId
* @param currentStatePoolId
* @param requestPoolId
* @param dataSet
* @param parameters
* @param initialTargetState
*/
ThermalComponentCore(object_id_t reportingObjectId, uint8_t domainId,
gp_id_t temperaturePoolId, gp_id_t targetStatePoolId,
gp_id_t currentStatePoolId, gp_id_t requestPoolId,
LocalPoolDataSetBase* dataSet, Parameters parameters,
StateRequest initialTargetState =
ThermalComponentIF::STATE_REQUEST_OPERATIONAL);
void addSensor(AbstractTemperatureSensor* firstRedundantSensor);
void addFirstRedundantSensor(
AbstractTemperatureSensor* firstRedundantSensor);
void addSecondRedundantSensor(
AbstractTemperatureSensor* secondRedundantSensor);
void addThermalModule(ThermalModule* thermalModule, Priority priority);
void setPriority(Priority priority);
virtual ~ThermalComponentCore();
virtual HeaterRequest performOperation(uint8_t opCode);
void markStateIgnored();
object_id_t getObjectId();
uint8_t getDomainId() const;
virtual float getLowerOpLimit();
ReturnValue_t setTargetState(int8_t newState);
virtual void setOutputInvalid();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
protected:
AbstractTemperatureSensor *sensor = nullptr;
AbstractTemperatureSensor *firstRedundantSensor = nullptr;
AbstractTemperatureSensor *secondRedundantSensor = nullptr;
ThermalModuleIF *thermalModule = nullptr;
lp_var_t<float> temperature;
lp_var_t<int8_t> targetState;
lp_var_t<int8_t> currentState;
lp_var_t<uint8_t> heaterRequest;
bool isHeating = false;
bool isSafeComponent = false;
float minTemp = 999;
float maxTemp = AbstractTemperatureSensor::ZERO_KELVIN_C;
Parameters parameters;
const uint8_t domainId;
ThermalMonitorReporter temperatureMonitor;
virtual float getTemperature();
virtual State getState(float temperature, Parameters parameters,
int8_t targetState);
virtual void checkLimits(State state);
virtual HeaterRequest getHeaterRequest(int8_t targetState,
float temperature, Parameters parameters);
virtual State getIgnoredState(int8_t state);
void updateMinMaxTemp();
virtual Parameters getParameters();
};
#endif /* FSFW_THERMAL_THERMALCOMPONENT_CORE_H_ */

View File

@ -49,18 +49,18 @@ public:
SAFE = 0, //!< SAFE SAFE = 0, //!< SAFE
IDLE, //!< IDLE IDLE, //!< IDLE
PAYLOAD, //!< PAYLOAD PAYLOAD, //!< PAYLOAD
NUMBER_OF_PRIORITIES //!< MAX_PRIORITY NUMBER_OF_PRIORITIES //!< MAX_PRIORITY
}; };
/** /**
* The elements are ordered by priority, lowest have highest priority * The elements are ordered by priority, lowest have highest priority
*/ */
enum HeaterRequest { enum HeaterRequest {
HEATER_REQUEST_EMERGENCY_OFF = 0, //!< REQUEST_EMERGENCY_OFF HEATER_REQUEST_EMERGENCY_OFF = 0, //!< REQUEST_EMERGENCY_OFF
HEATER_REQUEST_EMERGENCY_ON, //!< REQUEST_EMERGENCY_ON HEATER_REQUEST_EMERGENCY_ON, //!< REQUEST_EMERGENCY_ON
HEATER_REQUEST_OFF, //!< REQUEST_OFF HEATER_REQUEST_OFF, //!< REQUEST_OFF
HEATER_REQUEST_ON, //!< REQUEST_ON HEATER_REQUEST_ON, //!< REQUEST_ON
HEATER_DONT_CARE //!< DONT_CARE HEATER_DONT_CARE //!< DONT_CARE
}; };
virtual ~ThermalComponentIF() { virtual ~ThermalComponentIF() {

View File

@ -1,28 +1,31 @@
#include "../monitoring/LimitViolationReporter.h"
#include "../monitoring/MonitoringMessageContent.h"
#include "ThermalModule.h" #include "ThermalModule.h"
#include "AbstractTemperatureSensor.h" #include "AbstractTemperatureSensor.h"
ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, #include "../monitoring/LimitViolationReporter.h"
uint32_t currentStatePoolId, uint32_t targetStatePoolId, #include "../monitoring/MonitoringMessageContent.h"
GlobDataSet *dataSet, Parameters parameters,
ThermalModule::ThermalModule(gp_id_t moduleTemperaturePoolId,
gp_id_t currentStatePoolId, gp_id_t targetStatePoolId,
LocalPoolDataSetBase *dataSet, Parameters parameters,
RedundantHeater::Parameters heaterParameters) : RedundantHeater::Parameters heaterParameters) :
oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( oldStrategy(ACTIVE_SINGLE), parameters(parameters),
false), parameters(parameters), moduleTemperature( moduleTemperature(moduleTemperaturePoolId, dataSet,
moduleTemperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), currentState( PoolVariableIF::VAR_WRITE),
currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE), targetState( currentState(currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE),
targetStatePoolId, dataSet, PoolVariableIF::VAR_READ) { targetState(targetStatePoolId, dataSet, PoolVariableIF::VAR_READ) {
heater = new RedundantHeater(heaterParameters); heater = new RedundantHeater(heaterParameters);
} }
ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, GlobDataSet* dataSet) : ThermalModule::ThermalModule(gp_id_t moduleTemperaturePoolId,
oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( LocalPoolDataSetBase* dataSet) :
false), parameters( { 0, 0 }), moduleTemperature( oldStrategy(ACTIVE_SINGLE), parameters( { 0, 0 }),
moduleTemperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), heater( moduleTemperature(moduleTemperaturePoolId, dataSet,
NULL), currentState(PoolVariableIF::INVALID, dataSet, PoolVariableIF::VAR_WRITE),
PoolVariableIF::VAR_WRITE), targetState(PoolVariableIF::INVALID, currentState(gp_id_t(), dataSet,
dataSet, PoolVariableIF::VAR_READ) { PoolVariableIF::VAR_WRITE),
targetState(gp_id_t(), dataSet,
PoolVariableIF::VAR_READ) {
} }
ThermalModule::~ThermalModule() { ThermalModule::~ThermalModule() {
@ -30,7 +33,7 @@ ThermalModule::~ThermalModule() {
} }
void ThermalModule::performOperation(uint8_t opCode) { void ThermalModule::performOperation(uint8_t opCode) {
if (heater != NULL) { if (heater != nullptr) {
heater->performOperation(0); heater->performOperation(0);
} }
} }
@ -42,7 +45,7 @@ void ThermalModule::performMode(Strategy strategy) {
ThermalComponentIF::HeaterRequest componentHeaterRequest = ThermalComponentIF::HeaterRequest componentHeaterRequest =
letComponentsPerformAndDeciceIfWeNeedToHeat(safeOnly); letComponentsPerformAndDeciceIfWeNeedToHeat(safeOnly);
if (heater == NULL) { if (heater == nullptr) {
informComponentsAboutHeaterState(false, NONE); informComponentsAboutHeaterState(false, NONE);
return; return;
} }
@ -53,8 +56,8 @@ void ThermalModule::performMode(Strategy strategy) {
//Components overwrite the module request. //Components overwrite the module request.
heating = ((componentHeaterRequest heating = ((componentHeaterRequest
== ThermalComponentIF::HEATER_REQUEST_ON) == ThermalComponentIF::HEATER_REQUEST_ON)
|| (componentHeaterRequest or (componentHeaterRequest
== ThermalComponentIF::HEATER_REQUEST_EMERGENCY_ON)); == ThermalComponentIF::HEATER_REQUEST_EMERGENCY_ON));
} }
bool dual = (strategy == ACTIVE_DUAL); bool dual = (strategy == ACTIVE_DUAL);
@ -76,7 +79,7 @@ void ThermalModule::performMode(Strategy strategy) {
} }
float ThermalModule::getTemperature() { float ThermalModule::getTemperature() {
return moduleTemperature; return moduleTemperature.value;
} }
void ThermalModule::registerSensor(AbstractTemperatureSensor * sensor) { void ThermalModule::registerSensor(AbstractTemperatureSensor * sensor) {
@ -85,7 +88,8 @@ void ThermalModule::registerSensor(AbstractTemperatureSensor * sensor) {
void ThermalModule::registerComponent(ThermalComponentIF* component, void ThermalModule::registerComponent(ThermalComponentIF* component,
ThermalComponentIF::Priority priority) { ThermalComponentIF::Priority priority) {
components.push_back(ComponentData( { component, priority, ThermalComponentIF::HEATER_DONT_CARE })); components.push_back(ComponentData( { component, priority,
ThermalComponentIF::HEATER_DONT_CARE }));
} }
void ThermalModule::calculateTemperature() { void ThermalModule::calculateTemperature() {
@ -94,12 +98,13 @@ void ThermalModule::calculateTemperature() {
std::list<AbstractTemperatureSensor *>::iterator iter = sensors.begin(); std::list<AbstractTemperatureSensor *>::iterator iter = sensors.begin();
for (; iter != sensors.end(); iter++) { for (; iter != sensors.end(); iter++) {
if ((*iter)->isValid()) { if ((*iter)->isValid()) {
moduleTemperature = moduleTemperature + (*iter)->getTemperature(); moduleTemperature = moduleTemperature.value +
(*iter)->getTemperature();
numberOfValidSensors++; numberOfValidSensors++;
} }
} }
if (numberOfValidSensors != 0) { if (numberOfValidSensors != 0) {
moduleTemperature = moduleTemperature / numberOfValidSensors; moduleTemperature = moduleTemperature.value / numberOfValidSensors;
moduleTemperature.setValid(PoolVariableIF::VALID); moduleTemperature.setValid(PoolVariableIF::VALID);
} else { } else {
moduleTemperature = INVALID_TEMPERATURE; moduleTemperature = INVALID_TEMPERATURE;
@ -117,9 +122,10 @@ ThermalComponentIF* ThermalModule::findComponent(object_id_t objectId) {
return NULL; return NULL;
} }
ThermalComponentIF::HeaterRequest ThermalModule::letComponentsPerformAndDeciceIfWeNeedToHeat( ThermalComponentIF::HeaterRequest
bool safeOnly) { ThermalModule::letComponentsPerformAndDeciceIfWeNeedToHeat(bool safeOnly) {
ThermalComponentIF::HeaterRequest heaterRequests[ThermalComponentIF::NUMBER_OF_PRIORITIES]; ThermalComponentIF::HeaterRequest
heaterRequests[ThermalComponentIF::NUMBER_OF_PRIORITIES];
survivalTargetTemp = -999; survivalTargetTemp = -999;
targetTemp = -999; targetTemp = -999;
@ -224,7 +230,7 @@ bool ThermalModule::calculateModuleHeaterRequestAndSetModuleStatus(
limit = survivalTargetTemp; limit = survivalTargetTemp;
} }
if (moduleTemperature >= limit) { if (moduleTemperature.value >= limit) {
currentState = OPERATIONAL; currentState = OPERATIONAL;
} else { } else {
currentState = NON_OPERATIONAL; currentState = NON_OPERATIONAL;
@ -250,15 +256,16 @@ bool ThermalModule::calculateModuleHeaterRequestAndSetModuleStatus(
} }
void ThermalModule::setHeating(bool on) { void ThermalModule::setHeating(bool on) {
GlobDataSet mySet; ReturnValue_t result = targetState.read();
gp_int8_t writableTargetState(targetState.getDataPoolId(), if(result == HasReturnvaluesIF::RETURN_OK) {
&mySet, PoolVariableIF::VAR_WRITE); if(on) {
if (on) { targetState.value = STATE_REQUEST_HEATING;
writableTargetState = STATE_REQUEST_HEATING; }
} else { else {
writableTargetState = STATE_REQUEST_PASSIVE; targetState.value = STATE_REQUEST_PASSIVE;
}
} }
mySet.commit(PoolVariableIF::VALID); targetState.setValid(true);
} }
void ThermalModule::updateTargetTemperatures(ThermalComponentIF* component, void ThermalModule::updateTargetTemperatures(ThermalComponentIF* component,

View File

@ -1,14 +1,18 @@
#ifndef THERMALMODULE_H_ #ifndef FSFW_THERMAL_THERMALMODULE_H_
#define THERMALMODULE_H_ #define FSFW_THERMAL_THERMALMODULE_H_
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../devicehandlers/HealthDevice.h"
#include "../events/EventReportingProxyIF.h"
#include "ThermalModuleIF.h" #include "ThermalModuleIF.h"
#include <list>
#include "tcsDefinitions.h" #include "tcsDefinitions.h"
#include "RedundantHeater.h" #include "RedundantHeater.h"
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalPoolVariable.h"
#include "../devicehandlers/HealthDevice.h"
#include "../events/EventReportingProxyIF.h"
#include <list>
class PowerSwitchIF; class PowerSwitchIF;
/** /**
@ -22,11 +26,12 @@ public:
float hysteresis; float hysteresis;
}; };
ThermalModule(uint32_t moduleTemperaturePoolId, uint32_t currentStatePoolId, ThermalModule(gp_id_t moduleTemperaturePoolId, gp_id_t currentStatePoolId,
uint32_t targetStatePoolId, GlobDataSet *dataSet, Parameters parameters, gp_id_t targetStatePoolId, LocalPoolDataSetBase *dataSet,
RedundantHeater::Parameters heaterParameters); Parameters parameters, RedundantHeater::Parameters heaterParameters);
ThermalModule(uint32_t moduleTemperaturePoolId, GlobDataSet *dataSet); ThermalModule(gp_id_t moduleTemperaturePoolId,
LocalPoolDataSetBase *dataSet);
virtual ~ThermalModule(); virtual ~ThermalModule();
@ -62,20 +67,20 @@ protected:
Strategy oldStrategy; Strategy oldStrategy;
float survivalTargetTemp; float survivalTargetTemp = 0.0;
float targetTemp; float targetTemp = 0.0;
bool heating; bool heating = false;
Parameters parameters; Parameters parameters;
gp_float_t moduleTemperature; lp_var_t<float> moduleTemperature;
RedundantHeater *heater; RedundantHeater *heater = nullptr;
gp_int8_t currentState; lp_var_t<int8_t> currentState;
gp_int8_t targetState; lp_var_t<int8_t> targetState;
std::list<AbstractTemperatureSensor *> sensors; std::list<AbstractTemperatureSensor *> sensors;
std::list<ComponentData> components; std::list<ComponentData> components;
@ -92,4 +97,4 @@ protected:
void updateTargetTemperatures(ThermalComponentIF *component, bool isSafe); void updateTargetTemperatures(ThermalComponentIF *component, bool isSafe);
}; };
#endif /* THERMALMODULE_H_ */ #endif /* FSFW_THERMAL_THERMALMODULE_H_ */

View File

@ -1,23 +0,0 @@
#ifndef FRAMEWORK_THERMAL_THERMALMONITOR_H_
#define FRAMEWORK_THERMAL_THERMALMONITOR_H_
#include "../monitoring/MonitorReporter.h"
#include "ThermalComponentIF.h"
class ThermalMonitor: public MonitorReporter<float> {
public:
template<typename ... Args>
ThermalMonitor(Args ... args) :
MonitorReporter<float>(std::forward<Args>(args)...) {
}
~ThermalMonitor();
ReturnValue_t translateState(ThermalComponentIF::State state, float sample,
float lowerLimit, float upperLimit, bool componentIsOperational = true);
bool isAboveHighLimit();
protected:
virtual void sendTransitionEvent(float currentValue, ReturnValue_t state);
};
#endif /* FRAMEWORK_THERMAL_THERMALMONITOR_H_ */

View File

@ -1,10 +1,12 @@
#include "ThermalMonitor.h" #include "ThermalMonitorReporter.h"
#include "ThermalComponentIF.h" #include "ThermalComponentIF.h"
#include "../monitoring/MonitoringIF.h" #include "../monitoring/MonitoringIF.h"
ThermalMonitor::~ThermalMonitor() {
ThermalMonitorReporter::~ThermalMonitorReporter() {
} }
void ThermalMonitor::sendTransitionEvent(float currentValue, void ThermalMonitorReporter::sendTransitionEvent(float currentValue,
ReturnValue_t state) { ReturnValue_t state) {
switch (state) { switch (state) {
case MonitoringIF::BELOW_LOW_LIMIT: case MonitoringIF::BELOW_LOW_LIMIT:
@ -28,7 +30,7 @@ void ThermalMonitor::sendTransitionEvent(float currentValue,
} }
} }
bool ThermalMonitor::isAboveHighLimit() { bool ThermalMonitorReporter::isAboveHighLimit() {
if (oldState == ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT) { if (oldState == ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT) {
return true; return true;
} else { } else {
@ -36,7 +38,8 @@ bool ThermalMonitor::isAboveHighLimit() {
} }
} }
ReturnValue_t ThermalMonitor::translateState(ThermalComponentIF::State state, float sample, float lowerLimit, ReturnValue_t ThermalMonitorReporter::translateState(
ThermalComponentIF::State state, float sample, float lowerLimit,
float upperLimit, bool componentIsOperational) { float upperLimit, bool componentIsOperational) {
if (ThermalComponentIF::isIgnoredState(state)) { if (ThermalComponentIF::isIgnoredState(state)) {
setToUnchecked(); setToUnchecked();
@ -44,10 +47,12 @@ ReturnValue_t ThermalMonitor::translateState(ThermalComponentIF::State state, fl
} }
switch (state) { switch (state) {
case ThermalComponentIF::OUT_OF_RANGE_LOW: case ThermalComponentIF::OUT_OF_RANGE_LOW:
return monitorStateIs(MonitoringIF::BELOW_LOW_LIMIT, sample, lowerLimit); return monitorStateIs(MonitoringIF::BELOW_LOW_LIMIT, sample,
lowerLimit);
case ThermalComponentIF::NON_OPERATIONAL_LOW: case ThermalComponentIF::NON_OPERATIONAL_LOW:
if (componentIsOperational) { if (componentIsOperational) {
return monitorStateIs(ThermalComponentIF::BELOW_OPERATIONAL_LIMIT, sample, lowerLimit); return monitorStateIs(ThermalComponentIF::BELOW_OPERATIONAL_LIMIT,
sample, lowerLimit);
} else { } else {
return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0);
} }
@ -55,12 +60,14 @@ ReturnValue_t ThermalMonitor::translateState(ThermalComponentIF::State state, fl
return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0);
case ThermalComponentIF::NON_OPERATIONAL_HIGH: case ThermalComponentIF::NON_OPERATIONAL_HIGH:
if (componentIsOperational) { if (componentIsOperational) {
return monitorStateIs(ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT, sample, upperLimit); return monitorStateIs(ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT,
sample, upperLimit);
} else { } else {
return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0);
} }
case ThermalComponentIF::OUT_OF_RANGE_HIGH: case ThermalComponentIF::OUT_OF_RANGE_HIGH:
return monitorStateIs(MonitoringIF::ABOVE_HIGH_LIMIT, sample, upperLimit); return monitorStateIs(MonitoringIF::ABOVE_HIGH_LIMIT, sample,
upperLimit);
default: default:
//Never reached, all states covered. //Never reached, all states covered.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;

View File

@ -0,0 +1,28 @@
#ifndef FSFW_THERMAL_THERMALMONITORREPORTER_H_
#define FSFW_THERMAL_THERMALMONITORREPORTER_H_
#include "ThermalComponentIF.h"
#include "../monitoring/MonitorReporter.h"
/**
* @brief Monitor Reporter implementation for thermal components.
*/
class ThermalMonitorReporter: public MonitorReporter<float> {
public:
template<typename ... Args>
ThermalMonitorReporter(Args ... args) :
MonitorReporter<float>(std::forward<Args>(args)...) {
}
~ThermalMonitorReporter();
ReturnValue_t translateState(ThermalComponentIF::State state, float sample,
float lowerLimit, float upperLimit,
bool componentIsOperational = true);
bool isAboveHighLimit();
protected:
virtual void sendTransitionEvent(float currentValue, ReturnValue_t state);
};
#endif /* FSFW_THERMAL_THERMALMONITORREPORTERREPORTER_H_ */

View File

@ -2,7 +2,7 @@
#define TCSDEFINITIONS_H_ #define TCSDEFINITIONS_H_
static const uint32_t INVALID_TEMPERATURE = 999; static const float INVALID_TEMPERATURE = 999;
#endif /* TCSDEFINITIONS_H_ */ #endif /* TCSDEFINITIONS_H_ */