diff --git a/devicehandlers/AssemblyBase.h b/devicehandlers/AssemblyBase.h index 353d5f89..6cac81b4 100644 --- a/devicehandlers/AssemblyBase.h +++ b/devicehandlers/AssemblyBase.h @@ -24,6 +24,13 @@ * 1. check logic when active-> checkChildrenStateOn * 2. transition logic to change the mode -> commandChildren * + * Important: + * + * The implementation must call registerChild(object_id_t child) + * for all commanded children during initialization. + * The implementation must call the initialization function of the base class. + * (This will call the function in SubsystemBase) + * */ class AssemblyBase: public SubsystemBase { public: @@ -41,9 +48,6 @@ public: virtual ~AssemblyBase(); protected: - - // SHOULDDO: Change that OVERWRITE_HEALTH may be returned - // (or return internalState directly?) /** * Command children to reach [mode,submode] combination * Can be done by setting #commandsOutstanding correctly, @@ -68,6 +72,18 @@ protected: virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) = 0; + /** + * Check whether a combination of mode and submode is valid. + * + * Ground Controller like precise return values from HasModesIF. + * So, please return any of them. + * + * @param mode The targeted mode + * @param submode The targeted submmode + * @return Any information why this combination is invalid from HasModesIF + * like HasModesIF::INVALID_SUBMODE. + * On success return HasReturnvaluesIF::RETURN_OK + */ virtual ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 531a0642..1623a1ac 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -308,6 +308,14 @@ void DeviceHandlerBase::doStateMachine() { uint32_t currentUptime; Clock::getUptime(¤tUptime); if (currentUptime - timeoutStart >= childTransitionDelay) { +#if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0 + char printout[60]; + sprintf(printout, "Transition timeout (%lu) occured !", + static_cast(childTransitionDelay)); + /* Common configuration error for development, so print it */ + printWarningOrError(sif::OutputTypes::OUT_WARNING, "doStateMachine", + RETURN_FAILED, printout); +#endif triggerEvent(MODE_TRANSITION_FAILED, childTransitionFailure, 0); setMode(transitionSourceMode, transitionSourceSubMode); break; @@ -448,6 +456,15 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm } } +size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId){ + DeviceReplyIter iter = deviceReplyMap.find(commandId); + if(iter != deviceReplyMap.end()) { + return iter->second.replyLen; + }else{ + return 0; + } +} + ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) { auto replyIter = deviceReplyMap.find(deviceReply); @@ -638,16 +655,12 @@ void DeviceHandlerBase::doGetWrite() { void DeviceHandlerBase::doSendRead() { ReturnValue_t result; - size_t requestLen = 0; + size_t replyLen = 0; if(cookieInfo.pendingCommand != deviceCommandMap.end()) { - DeviceReplyIter iter = deviceReplyMap.find( - cookieInfo.pendingCommand->first); - if(iter != deviceReplyMap.end()) { - requestLen = iter->second.replyLen; - } + replyLen = getNextReplyLength(cookieInfo.pendingCommand->first); } - result = communicationInterface->requestReceiveMessage(comCookie, requestLen); + result = communicationInterface->requestReceiveMessage(comCookie, replyLen); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; @@ -1501,10 +1514,9 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, if(errorType == sif::OutputTypes::OUT_WARNING) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "DeviceHandlerBase::" << functionName << ": Object ID " - << std::hex << std::setw(8) << std::setfill('0') - << this->getObjectId() << " | " << errorPrint << std::dec - << std::setfill(' ') << std::endl; + sif::warning << "DeviceHandlerBase::" << functionName << ": Object ID 0x" << std::hex << + std::setw(8) << std::setfill('0') << this->getObjectId() << " | " << errorPrint << + std::dec << std::setfill(' ') << std::endl; #else sif::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n", functionName, this->getObjectId(), errorPrint); @@ -1512,7 +1524,7 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, } else if(errorType == sif::OutputTypes::OUT_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase::" << functionName << ": Object ID " + sif::error << "DeviceHandlerBase::" << functionName << ": Object ID 0x" << std::hex << std::setw(8) << std::setfill('0') << this->getObjectId() << " | " << errorPrint << std::dec << std::setfill(' ') << std::endl; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index d61b0407..496c08ff 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -471,13 +471,27 @@ protected: ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr, size_t replyLen = 0, bool periodic = false); + /** - * @brief A simple command to add a command to the commandList. + * @brief A simple command to add a command to the commandList. * @param deviceCommand The command to add * @return - @c RETURN_OK when the command was successfully inserted, * - @c RETURN_FAILED else. */ ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); + + /** + * @brief This function returns the reply length of the next reply to read. + * + * @param deviceCommand The command which triggered the device reply. + * + * @details The default implementation assumes only one reply is triggered by the command. In + * case the command triggers multiple replies (e.g. one acknowledgment, one data, + * and one execution status reply), this function can be overwritten to get the + * reply length of the next reply to read. + */ + virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand); + /** * @brief This is a helper method to facilitate updating entries * in the reply map. @@ -953,7 +967,7 @@ protected: * - NO_REPLY_EXPECTED if there was no reply found. This is not an * error case as many commands do not expect a reply. */ - virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator cmd, + virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command, uint8_t expectedReplies = 1, bool useAlternateId = false, DeviceCommandId_t alternateReplyID = 0); diff --git a/parameters/ParameterHelper.cpp b/parameters/ParameterHelper.cpp index 24d0b2b1..e80c2c47 100644 --- a/parameters/ParameterHelper.cpp +++ b/parameters/ParameterHelper.cpp @@ -65,6 +65,9 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { ParameterWrapper ownerWrapper; result = owner->getParameter(domain, uniqueIdentifier, &ownerWrapper, &streamWrapper, linearIndex); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } result = ownerWrapper.copyFrom(&streamWrapper, linearIndex); if (result != HasReturnvaluesIF::RETURN_OK) { diff --git a/subsystem/SubsystemBase.cpp b/subsystem/SubsystemBase.cpp index bcfa4b0e..565e0712 100644 --- a/subsystem/SubsystemBase.cpp +++ b/subsystem/SubsystemBase.cpp @@ -5,8 +5,7 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode, uint16_t commandQueueDepth) : - SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), - childrenChangedMode(false), + SystemObject(setObjectId), mode(initialMode), commandQueue(QueueFactory::instance()->createMessageQueue( commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE)), healthHelper(this, setObjectId), modeHelper(this), parentId(parent) { @@ -167,16 +166,16 @@ MessageQueueId_t SubsystemBase::getCommandQueue() const { } ReturnValue_t SubsystemBase::initialize() { - MessageQueueId_t parentQueue = 0; + MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE; ReturnValue_t result = SystemObject::initialize(); if (result != RETURN_OK) { return result; } - if (parentId != 0) { + if (parentId != objects::NO_OBJECT) { SubsystemBase *parent = objectManager->get(parentId); - if (parent == NULL) { + if (parent == nullptr) { return RETURN_FAILED; } parentQueue = parent->getCommandQueue(); diff --git a/subsystem/SubsystemBase.h b/subsystem/SubsystemBase.h index b8e4f902..6b2e9b5f 100644 --- a/subsystem/SubsystemBase.h +++ b/subsystem/SubsystemBase.h @@ -37,6 +37,17 @@ public: virtual MessageQueueId_t getCommandQueue() const override; + /** + * Function to register the child objects. + * Performs a checks if the child does implement HasHealthIF and/or HasModesIF + * + * Also adds them to the internal childrenMap. + * + * @param objectId + * @return RETURN_OK if successful + * CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF + * COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap + */ ReturnValue_t registerChild(object_id_t objectId); virtual ReturnValue_t initialize() override; @@ -56,9 +67,9 @@ protected: Mode_t mode; - Submode_t submode; + Submode_t submode = SUBMODE_NONE; - bool childrenChangedMode; + bool childrenChangedMode = false; /** * Always check this against <=0, so you are robust against too many replies