Merge remote-tracking branch 'origin/develop' into continue_tcs_tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2023-04-12 13:00:58 +02:00
commit d9e38d97ee
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
23 changed files with 408 additions and 154 deletions

View File

@ -27,6 +27,8 @@ will consitute of a breaking change warranting a new major release:
temperature for the all-ones value (0x0fff). temperature for the all-ones value (0x0fff).
- Better reply result handling for the ACS board devices. - Better reply result handling for the ACS board devices.
- ADIS1650X initial timeout handling now performed in device handler. - ADIS1650X initial timeout handling now performed in device handler.
- The RW assembly and TCS board assembly now perform proper power switch handling for their
recovery handling.
## Changed ## Changed
@ -35,6 +37,8 @@ will consitute of a breaking change warranting a new major release:
This gives other tasks some time to register the SD cards being unusable, and therefore provides This gives other tasks some time to register the SD cards being unusable, and therefore provides
a way for them to perform any re-initialization tasks necessary after SD card switches. a way for them to perform any re-initialization tasks necessary after SD card switches.
- TCS controller now only has an OFF mode and an ON mode - TCS controller now only has an OFF mode and an ON mode
- The TCS controller pauses operations related to the TCS board assembly (reading sensors and
the primary control loop) while a TCS board recovery is on-going.
- Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure - Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure
where each update has a name including the version where each update has a name including the version
- The files extracted during an update process are deleted after the update was performed to keep - The files extracted during an update process are deleted after the update was performed to keep

View File

@ -40,6 +40,7 @@
#include "mission/system/com/comModeTree.h" #include "mission/system/com/comModeTree.h"
#include "mission/system/tree/payloadModeTree.h" #include "mission/system/tree/payloadModeTree.h"
#include "mission/system/tree/tcsModeTree.h" #include "mission/system/tree/tcsModeTree.h"
#include "mission/tcs/defs.h"
void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF) { void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF) {
new ComIFDummy(objects::DUMMY_COM_IF); new ComIFDummy(objects::DUMMY_COM_IF);
@ -204,7 +205,8 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
new TemperatureSensorInserter(objects::THERMAL_TEMP_INSERTER, rtdSensorDummies, new TemperatureSensorInserter(objects::THERMAL_TEMP_INSERTER, rtdSensorDummies,
tmpSensorDummies); tmpSensorDummies);
TcsBoardAssembly* tcsBoardAssy = ObjectFactory::createTcsBoardAssy(pwrSwitcher); TcsBoardAssembly* tcsBoardAssy =
ObjectFactory::createTcsBoardAssy(pwrSwitcher, tcs::TCS_BOARD_SHORTLY_UNAVAILABLE);
for (auto& rtd : rtdSensorDummies) { for (auto& rtd : rtdSensorDummies) {
rtd.second->connectModeTreeParent(*tcsBoardAssy); rtd.second->connectModeTreeParent(*tcsBoardAssy);
} }

2
fsfw

@ -1 +1 @@
Subproject commit 285d327b97514946f0714e477289f67ee8bd413f Subproject commit ffa2fa477f105cc876264335d5b25fc9b174a181

View File

@ -29,6 +29,7 @@
#include "mission/system/acs/acsModeTree.h" #include "mission/system/acs/acsModeTree.h"
#include "mission/system/tree/payloadModeTree.h" #include "mission/system/tree/payloadModeTree.h"
#include "mission/system/tree/tcsModeTree.h" #include "mission/system/tree/tcsModeTree.h"
#include "mission/tcs/defs.h"
void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF, void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF,
PowerSwitchIF& pwrSwitcher, std::string spiDev, PowerSwitchIF& pwrSwitcher, std::string spiDev,
@ -278,7 +279,8 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF,
std::array<Max31865EiveHandler*, NUM_RTDS> rtds = {}; std::array<Max31865EiveHandler*, NUM_RTDS> rtds = {};
RtdFdir* rtdFdir = nullptr; RtdFdir* rtdFdir = nullptr;
TcsBoardAssembly* tcsBoardAss = ObjectFactory::createTcsBoardAssy(*pwrSwitcher); TcsBoardAssembly* tcsBoardAss =
ObjectFactory::createTcsBoardAssy(*pwrSwitcher, tcs::TCS_BOARD_SHORTLY_UNAVAILABLE);
// Create special low level reader communication interface // Create special low level reader communication interface
new Max31865RtdPolling(objects::SPI_RTD_COM_IF, comIF, gpioComIF); new Max31865RtdPolling(objects::SPI_RTD_COM_IF, comIF, gpioComIF);

View File

@ -1 +1,3 @@
target_sources(
${LIB_EIVE_MISSION} PRIVATE CfdpHandler.cpp)

View File

@ -0,0 +1,134 @@
#include "CfdpHandler.h"
#include "fsfw/cfdp/pdu/AckPduReader.h"
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
using namespace cfdp;
CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg)
: SystemObject(fsfwParams.objectId),
msgQueue(fsfwParams.msgQueue),
destHandler(
DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, cfdpCfg.faultHandler),
cfdpCfg.userHandler, cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList,
cfdpCfg.lostSegmentsList),
FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore,
fsfwParams.tmStore)) {
destHandler.setMsgQueue(msgQueue);
}
[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; }
[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const {
return destHandler.getDestHandlerParams().cfg.localId.getValue();
}
[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue.getId(); }
ReturnValue_t CfdpHandler::initialize() {
ReturnValue_t result = destHandler.initialize();
if (result != OK) {
return result;
}
tcStore = destHandler.getTcStore();
tmStore = destHandler.getTmStore();
return SystemObject::initialize();
}
ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) {
// TODO: Receive TC packets and route them to source and dest handler, depending on which is
// correct or more appropriate
ReturnValue_t status;
ReturnValue_t result = OK;
TmTcMessage tmtcMsg;
for (status = msgQueue.receiveMessage(&tmtcMsg); status == returnvalue::OK;
status = msgQueue.receiveMessage(&tmtcMsg)) {
result = handleCfdpPacket(tmtcMsg);
if (result != OK) {
status = result;
}
}
auto& fsmRes = destHandler.performStateMachine();
// TODO: Error handling?
while (fsmRes.callStatus == CallStatus::CALL_AGAIN) {
destHandler.performStateMachine();
// TODO: Error handling?
}
return status;
}
ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
auto accessorPair = tcStore->getData(msg.getStorageId());
if (accessorPair.first != OK) {
return accessorPair.first;
}
PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size());
ReturnValue_t result = reader.parseData();
if (result != returnvalue::OK) {
return INVALID_PDU_FORMAT;
}
// The CFDP distributor should have taken care of ensuring the destination ID is correct
PduType type = reader.getPduType();
// Only the destination handler can process these PDUs
if (type == PduType::FILE_DATA) {
// Disable auto-deletion of packet
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId());
result = destHandler.passPacket(info);
} else {
// Route depending on PDU type and directive type if applicable. It retrieves directive type
// from the raw stream for better performance (with sanity and directive code check).
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
// procedure.
// PDU header only. Invalid supplied data. A directive packet should have a valid data field
// with at least one byte being the directive code
const uint8_t* pduDataField = reader.getPduDataField();
if (pduDataField == nullptr) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast<FileDirective>(pduDataField[0]);
auto passToDestHandler = [&]() {
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId(), directive);
result = destHandler.passPacket(info);
};
auto passToSourceHandler = [&]() {
};
if (directive == FileDirective::METADATA or directive == FileDirective::EOF_DIRECTIVE or
directive == FileDirective::PROMPT) {
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
// the destination handler
passToDestHandler();
} else if (directive == FileDirective::FINISH or directive == FileDirective::NAK or
directive == FileDirective::KEEP_ALIVE) {
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
// the source handler
passToSourceHandler();
} else if (directive == FileDirective::ACK) {
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
// the source handler, for a Finished PDU, it is passed to the destination handler.
FileDirective ackedDirective;
if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) {
return INVALID_ACK_DIRECTIVE_FIELDS;
}
if (ackedDirective == FileDirective::EOF_DIRECTIVE) {
passToSourceHandler();
} else if (ackedDirective == FileDirective::FINISH) {
passToDestHandler();
}
}
}
return result;
}

View File

@ -0,0 +1,71 @@
#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#include <utility>
#include "fsfw/cfdp/handler/DestHandler.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
struct FsfwHandlerParams {
FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest,
StorageManagerIF& tcStore, StorageManagerIF& tmStore, MessageQueueIF& msgQueue)
: objectId(objectId),
vfs(vfs),
packetDest(packetDest),
tcStore(tcStore),
tmStore(tmStore),
msgQueue(msgQueue) {}
object_id_t objectId{};
HasFileSystemIF& vfs;
AcceptsTelemetryIF& packetDest;
StorageManagerIF& tcStore;
StorageManagerIF& tmStore;
MessageQueueIF& msgQueue;
};
struct CfdpHandlerCfg {
CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg,
cfdp::UserBase& userHandler, cfdp::FaultHandlerBase& userFaultHandler,
cfdp::PacketInfoListBase& packetInfo, cfdp::LostSegmentsListBase& lostSegmentsList,
cfdp::RemoteConfigTableIF& remoteCfgProvider)
: id(std::move(localId)),
indicCfg(indicationCfg),
packetInfoList(packetInfo),
lostSegmentsList(lostSegmentsList),
remoteCfgProvider(remoteCfgProvider),
userHandler(userHandler),
faultHandler(userFaultHandler) {}
cfdp::EntityId id;
cfdp::IndicationCfg indicCfg;
cfdp::PacketInfoListBase& packetInfoList;
cfdp::LostSegmentsListBase& lostSegmentsList;
cfdp::RemoteConfigTableIF& remoteCfgProvider;
cfdp::UserBase& userHandler;
cfdp::FaultHandlerBase& faultHandler;
};
class CfdpHandler : public SystemObject, public ExecutableObjectIF, public AcceptsTelecommandsIF {
public:
explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg);
[[nodiscard]] const char* getName() const override;
[[nodiscard]] uint32_t getIdentifier() const override;
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode) override;
private:
MessageQueueIF& msgQueue;
cfdp::DestHandler destHandler;
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
};
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H

View File

@ -21,7 +21,8 @@
#define LOWER_EBAND_UPPER_LIMITS 0 #define LOWER_EBAND_UPPER_LIMITS 0
#define LOWER_PLOC_UPPER_LIMITS 0 #define LOWER_PLOC_UPPER_LIMITS 0
ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater) ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater,
const std::atomic_bool& tcsBoardShortUnavailable)
: ExtendedControllerBase(objectId), : ExtendedControllerBase(objectId),
heaterHandler(heater), heaterHandler(heater),
sensorTemperatures(this), sensorTemperatures(this),
@ -66,7 +67,8 @@ ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater
susSet8(objects::SUS_8_R_LOC_XBYBZB_PT_YB), susSet8(objects::SUS_8_R_LOC_XBYBZB_PT_YB),
susSet9(objects::SUS_9_R_LOC_XBYBZB_PT_YF), susSet9(objects::SUS_9_R_LOC_XBYBZB_PT_YF),
susSet10(objects::SUS_10_N_LOC_XMYBZF_PT_ZF), susSet10(objects::SUS_10_N_LOC_XMYBZF_PT_ZF),
susSet11(objects::SUS_11_R_LOC_XBYMZB_PT_ZB) { susSet11(objects::SUS_11_R_LOC_XBYMZB_PT_ZB),
tcsBrdShortlyUnavailable(tcsBoardShortUnavailable) {
resetSensorsArray(); resetSensorsArray();
} }
@ -134,12 +136,14 @@ void ThermalController::performControlOperation() {
} }
} }
if (not tcsBrdShortlyUnavailable) {
{ {
PoolReadGuard pg(&sensorTemperatures); PoolReadGuard pg(&sensorTemperatures);
if (pg.getReadResult() == returnvalue::OK) { if (pg.getReadResult() == returnvalue::OK) {
copySensors(); copySensors();
} }
} }
}
{ {
PoolReadGuard pg(&susTemperatures); PoolReadGuard pg(&susTemperatures);
if (pg.getReadResult() == returnvalue::OK) { if (pg.getReadResult() == returnvalue::OK) {
@ -188,7 +192,7 @@ void ThermalController::performControlOperation() {
} else { } else {
transitionWhenHeatersOffCycles++; transitionWhenHeatersOffCycles++;
} }
} else if (mode != MODE_OFF) { } else if (mode != MODE_OFF and not tcsBrdShortlyUnavailable) {
performThermalModuleCtrl(heaterSwitchStateArray); performThermalModuleCtrl(heaterSwitchStateArray);
} }
} }

View File

@ -22,6 +22,7 @@
#include <mission/tcs/Tmp1075Definitions.h> #include <mission/tcs/Tmp1075Definitions.h>
#include <mission/utility/trace.h> #include <mission/utility/trace.h>
#include <atomic>
#include <list> #include <list>
/** /**
@ -101,7 +102,8 @@ class ThermalController : public ExtendedControllerBase {
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80; static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160; static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160;
ThermalController(object_id_t objectId, HeaterHandler& heater); ThermalController(object_id_t objectId, HeaterHandler& heater,
const std::atomic_bool& tcsBoardShortUnavailable);
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -188,6 +190,10 @@ class ThermalController : public ExtendedControllerBase {
susMax1227::SusDataset susSet10; susMax1227::SusDataset susSet10;
susMax1227::SusDataset susSet11; susMax1227::SusDataset susSet11;
// If the TCS board in unavailable, for example due to a recovery, skip
// some TCS controller tasks to avoid unnecessary events.
const std::atomic_bool& tcsBrdShortlyUnavailable = false;
lp_var_t<float> tempQ7s = lp_var_t<float>(objects::CORE_CONTROLLER, core::PoolIds::TEMPERATURE); lp_var_t<float> tempQ7s = lp_var_t<float>(objects::CORE_CONTROLLER, core::PoolIds::TEMPERATURE);
lp_var_t<int16_t> battTemp1 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_1); lp_var_t<int16_t> battTemp1 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_1);
lp_var_t<int16_t> battTemp2 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_2); lp_var_t<int16_t> battTemp2 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_2);

View File

@ -1,5 +1,5 @@
#include <fsfw/cfdp/CfdpDistributor.h> #include <fsfw/cfdp/CfdpDistributor.h>
#include <fsfw/cfdp/handler/CfdpHandler.h> #include <mission/cfdp/CfdpHandler.h>
#include <fsfw/cfdp/handler/RemoteConfigTableIF.h> #include <fsfw/cfdp/handler/RemoteConfigTableIF.h>
#include <fsfw/controller/ControllerBase.h> #include <fsfw/controller/ControllerBase.h>
#include <fsfw/controller/ExtendedControllerBase.h> #include <fsfw/controller/ExtendedControllerBase.h>
@ -48,6 +48,7 @@
#include "mission/system/acs/RwAssembly.h" #include "mission/system/acs/RwAssembly.h"
#include "mission/system/acs/acsModeTree.h" #include "mission/system/acs/acsModeTree.h"
#include "mission/system/tree/tcsModeTree.h" #include "mission/system/tree/tcsModeTree.h"
#include "mission/tcs/defs.h"
#include "mission/tmtc/tmFilters.h" #include "mission/tmtc/tmFilters.h"
#include "objects/systemObjectList.h" #include "objects/systemObjectList.h"
#include "tmtc/pusIds.h" #include "tmtc/pusIds.h"
@ -90,6 +91,8 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
} // namespace cfdp } // namespace cfdp
std::atomic_bool tcs::TCS_BOARD_SHORTLY_UNAVAILABLE = false;
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel, void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan, CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
StorageManagerIF** ipcStore, StorageManagerIF** tmStore, StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
@ -300,7 +303,8 @@ void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF&
} }
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler) { void ObjectFactory::createThermalController(HeaterHandler& heaterHandler) {
auto* tcsCtrl = new ThermalController(objects::THERMAL_CONTROLLER, heaterHandler); auto* tcsCtrl = new ThermalController(objects::THERMAL_CONTROLLER, heaterHandler,
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE);
tcsCtrl->connectModeTreeParent(satsystem::tcs::SUBSYSTEM); tcsCtrl->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
} }
void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch, void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,
@ -366,10 +370,12 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher,
acsAss->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM); acsAss->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
} }
TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher) { TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher,
std::atomic_bool& tcsShortlyUnavailable) {
TcsBoardHelper helper(RTD_INFOS); TcsBoardHelper helper(RTD_INFOS);
auto* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, &pwrSwitcher, auto* tcsBoardAss =
power::Switches::PDU1_CH0_TCS_BOARD_3V3, helper); new TcsBoardAssembly(objects::TCS_BOARD_ASS, &pwrSwitcher,
power::Switches::PDU1_CH0_TCS_BOARD_3V3, helper, tcsShortlyUnavailable);
tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM); tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
return tcsBoardAss; return tcsBoardAss;
} }

View File

@ -55,7 +55,8 @@ void createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,
void createSusAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 12> suses); void createSusAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 12> suses);
void createAcsBoardAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 8> assemblyDhbs, void createAcsBoardAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 8> assemblyDhbs,
ExtendedControllerBase* gpsCtrl, GpioIF* gpioComIF); ExtendedControllerBase* gpsCtrl, GpioIF* gpioComIF);
TcsBoardAssembly* createTcsBoardAssy(PowerSwitchIF& pwrSwitcher); TcsBoardAssembly* createTcsBoardAssy(PowerSwitchIF& pwrSwitcher,
std::atomic_bool& tcsShortlyUnavailable);
} // namespace ObjectFactory } // namespace ObjectFactory

View File

@ -50,6 +50,7 @@ static constexpr Event FDIR_REACTION_IGNORED = event::makeEvent(SUBSYSTEM_ID, 3,
enum class States { IDLE, SWITCHING_POWER, CHECKING_POWER, MODE_COMMANDING }; enum class States { IDLE, SWITCHING_POWER, CHECKING_POWER, MODE_COMMANDING };
enum class OpCodes { NONE, TO_OFF_DONE, TO_NOT_OFF_DONE, TIMEOUT_OCCURED }; enum class OpCodes { NONE, TO_OFF_DONE, TO_NOT_OFF_DONE, TIMEOUT_OCCURED };
enum RecoveryCustomStates { IDLE, POWER_SWITCHING_OFF, POWER_SWITCHING_ON, DONE };
} // namespace power } // namespace power
namespace duallane { namespace duallane {

View File

@ -6,5 +6,6 @@ add_subdirectory(fdir)
add_subdirectory(power) add_subdirectory(power)
target_sources( target_sources(
${LIB_EIVE_MISSION} PRIVATE systemTree.cpp DualLanePowerStateMachine.cpp ${LIB_EIVE_MISSION}
EiveSystem.cpp treeUtil.cpp) PRIVATE systemTree.cpp DualLanePowerStateMachine.cpp EiveSystem.cpp
treeUtil.cpp SharedPowerAssemblyBase.cpp)

View File

@ -0,0 +1,91 @@
#include "SharedPowerAssemblyBase.h"
SharedPowerAssemblyBase::SharedPowerAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t switchId, uint16_t cmdQueueDepth)
: AssemblyBase(objectId, cmdQueueDepth), switcher(pwrSwitcher, switchId) {}
void SharedPowerAssemblyBase::performChildOperation() {
auto state = switcher.getState();
if (state != PowerSwitcher::WAIT_OFF and state != PowerSwitcher::WAIT_ON) {
AssemblyBase::performChildOperation();
return;
}
switcher.doStateMachine();
if (state == PowerSwitcher::WAIT_OFF and switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
// Indicator that a transition to off is finished
AssemblyBase::handleModeReached();
} else if (state == PowerSwitcher::WAIT_ON and
switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
// Indicator that mode commanding can be performed now
AssemblyBase::startTransition(targetMode, targetSubmode);
}
}
void SharedPowerAssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
if (mode != MODE_OFF) {
switcher.turnOn(true);
switcher.doStateMachine();
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
AssemblyBase::startTransition(mode, submode);
} else {
// Need to wait with mode commanding until power switcher is done
targetMode = mode;
targetSubmode = submode;
}
} else {
// Perform regular mode commanding first
AssemblyBase::startTransition(mode, submode);
}
}
void SharedPowerAssemblyBase::handleModeReached() {
if (targetMode == MODE_OFF) {
switcher.turnOff(true);
switcher.doStateMachine();
// Need to wait with call to AssemblyBase::handleModeReached until power switcher is done
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
AssemblyBase::handleModeReached();
}
} else {
AssemblyBase::handleModeReached();
}
}
bool SharedPowerAssemblyBase::checkAndHandleRecovery() {
using namespace power;
if (recoveryState == RECOVERY_IDLE) {
return AssemblyBase::checkAndHandleRecovery();
}
if (customRecoveryStates == IDLE) {
switcher.turnOff();
customRecoveryStates = RecoveryCustomStates::POWER_SWITCHING_OFF;
}
if (customRecoveryStates == POWER_SWITCHING_OFF) {
switcher.doStateMachine();
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
customRecoveryStates = RecoveryCustomStates::POWER_SWITCHING_ON;
switcher.turnOn();
}
}
if (customRecoveryStates == POWER_SWITCHING_ON) {
switcher.doStateMachine();
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
customRecoveryStates = RecoveryCustomStates::DONE;
}
}
if (customRecoveryStates == DONE) {
bool pendingRecovery = AssemblyBase::checkAndHandleRecovery();
if (not pendingRecovery) {
customRecoveryStates = RecoveryCustomStates::IDLE;
}
// For a recovery on one side, only do the recovery once
for (auto& child : childrenMap) {
if (healthHelper.healthTable->getHealth(child.first) == HasHealthIF::NEEDS_RECOVERY) {
sendHealthCommand(child.second.commandQueue, HEALTHY);
child.second.healthChanged = false;
}
}
return pendingRecovery;
}
return true;
}

View File

@ -0,0 +1,27 @@
#ifndef MISSION_SYSTEM_SHAREDPOWERASSEMBLYBASE_H_
#define MISSION_SYSTEM_SHAREDPOWERASSEMBLYBASE_H_
#include <fsfw/devicehandlers/AssemblyBase.h>
#include <fsfw/power/PowerSwitcher.h>
#include <mission/power/defs.h>
/**
* Base class which contains common functions for assemblies where the power line is shared
* among the devices in the assembly.
*/
class SharedPowerAssemblyBase : public AssemblyBase {
public:
SharedPowerAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t switchId, uint16_t cmdQueueDepth = 8);
protected:
PowerSwitcher switcher;
power::RecoveryCustomStates customRecoveryStates = power::RecoveryCustomStates::IDLE;
void performChildOperation() override;
void startTransition(Mode_t mode, Submode_t submode) override;
void handleModeReached() override;
virtual bool checkAndHandleRecovery() override;
};
#endif /* MISSION_SYSTEM_SHAREDPOWERASSEMBLYBASE_H_ */

View File

@ -39,12 +39,7 @@ class DualLaneAssemblyBase : public AssemblyBase, public ConfirmsFailuresIF {
SideSwitchState sideSwitchState = SideSwitchState::NONE; SideSwitchState sideSwitchState = SideSwitchState::NONE;
duallane::Submodes targetSubmodeForSideSwitch = duallane::Submodes::B_SIDE; duallane::Submodes targetSubmodeForSideSwitch = duallane::Submodes::B_SIDE;
enum RecoveryCustomStates { power::RecoveryCustomStates customRecoveryStates = power::RecoveryCustomStates::IDLE;
IDLE,
POWER_SWITCHING_OFF,
POWER_SWITCHING_ON,
DONE
} customRecoveryStates = RecoveryCustomStates::IDLE;
MessageQueueIF* eventQueue = nullptr; MessageQueueIF* eventQueue = nullptr;

View File

@ -1,8 +1,8 @@
#include "RwAssembly.h" #include "RwAssembly.h"
RwAssembly::RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher, RwAssembly::RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switchId,
RwHelper helper) RwHelper helper)
: AssemblyBase(objectId), helper(helper), switcher(pwrSwitcher, switcher) { : SharedPowerAssemblyBase(objectId, pwrSwitcher, switchId), helper(helper) {
ModeListEntry entry; ModeListEntry entry;
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) { for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
entry.setObject(helper.rwIds[idx]); entry.setObject(helper.rwIds[idx]);
@ -12,26 +12,8 @@ RwAssembly::RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::
} }
} }
void RwAssembly::performChildOperation() {
auto state = switcher.getState();
if (state != PowerSwitcher::WAIT_OFF and state != PowerSwitcher::WAIT_ON) {
AssemblyBase::performChildOperation();
return;
}
switcher.doStateMachine();
if (state == PowerSwitcher::WAIT_OFF and switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
// Indicator that a transition to off is finished
AssemblyBase::handleModeReached();
} else if (state == PowerSwitcher::WAIT_ON and
switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
// Indicator that mode commanding can be performed now
AssemblyBase::startTransition(targetMode, targetSubmode);
}
}
ReturnValue_t RwAssembly::commandChildren(Mode_t mode, Submode_t submode) { ReturnValue_t RwAssembly::commandChildren(Mode_t mode, Submode_t submode) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
modeTransitionFailedSwitch = true;
// Initialize the mode table to ensure all devices are in a defined state // Initialize the mode table to ensure all devices are in a defined state
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) { for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
modeTable[idx].setMode(MODE_OFF); modeTable[idx].setMode(MODE_OFF);
@ -76,36 +58,6 @@ ReturnValue_t RwAssembly::isModeCombinationValid(Mode_t mode, Submode_t submode)
return HasModesIF::INVALID_MODE; return HasModesIF::INVALID_MODE;
} }
void RwAssembly::startTransition(Mode_t mode, Submode_t submode) {
if (mode != MODE_OFF) {
switcher.turnOn(true);
switcher.doStateMachine();
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
AssemblyBase::startTransition(mode, submode);
} else {
// Need to wait with mode commanding until power switcher is done
targetMode = mode;
targetSubmode = submode;
}
} else {
// Perform regular mode commanding first
AssemblyBase::startTransition(mode, submode);
}
}
void RwAssembly::handleModeReached() {
if (targetMode == MODE_OFF) {
switcher.turnOff(true);
switcher.doStateMachine();
// Need to wait with call to AssemblyBase::handleModeReached until power switcher is done
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
AssemblyBase::handleModeReached();
}
} else {
AssemblyBase::handleModeReached();
}
}
ReturnValue_t RwAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) { ReturnValue_t RwAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
object_id_t objId = 0; object_id_t objId = 0;

View File

@ -1,8 +1,8 @@
#ifndef MISSION_SYSTEM_RWASS_H_ #ifndef MISSION_SYSTEM_RWASS_H_
#define MISSION_SYSTEM_RWASS_H_ #define MISSION_SYSTEM_RWASS_H_
#include <fsfw/devicehandlers/AssemblyBase.h>
#include <fsfw/power/PowerSwitcher.h> #include <fsfw/power/PowerSwitcher.h>
#include <mission/system/SharedPowerAssemblyBase.h>
struct RwHelper { struct RwHelper {
RwHelper(std::array<object_id_t, 4> rwIds) : rwIds(rwIds) {} RwHelper(std::array<object_id_t, 4> rwIds) : rwIds(rwIds) {}
@ -10,17 +10,15 @@ struct RwHelper {
std::array<object_id_t, 4> rwIds = {}; std::array<object_id_t, 4> rwIds = {};
}; };
class RwAssembly : public AssemblyBase { class RwAssembly : public SharedPowerAssemblyBase {
public: public:
RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher, RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switchId,
RwHelper helper); RwHelper helper);
private: private:
static constexpr uint8_t NUMBER_RWS = 4; static constexpr uint8_t NUMBER_RWS = 4;
RwHelper helper; RwHelper helper;
PowerSwitcher switcher;
bool warningSwitch = true; bool warningSwitch = true;
bool modeTransitionFailedSwitch = true;
FixedArrayList<ModeListEntry, NUMBER_RWS> modeTable; FixedArrayList<ModeListEntry, NUMBER_RWS> modeTable;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -35,12 +33,9 @@ class RwAssembly : public AssemblyBase {
bool isUseable(object_id_t object, Mode_t mode); bool isUseable(object_id_t object, Mode_t mode);
// AssemblyBase implementation // AssemblyBase implementation
void performChildOperation() override;
ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override; ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override;
ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override; ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override;
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override; ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
void handleModeReached() override;
}; };
#endif /* MISSION_SYSTEM_RWASS_H_ */ #endif /* MISSION_SYSTEM_RWASS_H_ */

View File

@ -3,4 +3,4 @@
#include "eive/objects.h" #include "eive/objects.h"
RtdFdir::RtdFdir(object_id_t sensorId) RtdFdir::RtdFdir(object_id_t sensorId)
: DeviceHandlerFailureIsolation(sensorId, objects::TCS_BOARD_ASS) {} : DeviceHandlerFailureIsolation(sensorId, objects::NO_OBJECT) {}

View File

@ -4,9 +4,11 @@
#include <fsfw/ipc/QueueFactory.h> #include <fsfw/ipc/QueueFactory.h>
TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t theSwitch, TcsBoardHelper helper) power::Switch_t theSwitch, TcsBoardHelper helper,
: AssemblyBase(objectId, 24), switcher(pwrSwitcher, theSwitch), helper(helper) { std::atomic_bool& tcsShortlyUnavailable)
eventQueue = QueueFactory::instance()->createMessageQueue(24); : SharedPowerAssemblyBase(objectId, pwrSwitcher, theSwitch, 16),
helper(helper),
tcsShortlyUnavailable(tcsShortlyUnavailable) {
ModeListEntry entry; ModeListEntry entry;
for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) {
entry.setObject(helper.rtdInfos[idx].first); entry.setObject(helper.rtdInfos[idx].first);
@ -16,23 +18,6 @@ TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitc
} }
} }
void TcsBoardAssembly::performChildOperation() {
auto state = switcher.getState();
if (state != PowerSwitcher::WAIT_OFF and state != PowerSwitcher::WAIT_ON) {
AssemblyBase::performChildOperation();
return;
}
switcher.doStateMachine();
if (state == PowerSwitcher::WAIT_OFF and switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
// Indicator that a transition to off is finished
AssemblyBase::handleModeReached();
} else if (state == PowerSwitcher::WAIT_ON and
switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
// Indicator that mode commanding can be performed now
AssemblyBase::startTransition(targetMode, targetSubmode);
}
}
ReturnValue_t TcsBoardAssembly::commandChildren(Mode_t mode, Submode_t submode) { ReturnValue_t TcsBoardAssembly::commandChildren(Mode_t mode, Submode_t submode) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
// Initialize the mode table to ensure all devices are in a defined state // Initialize the mode table to ensure all devices are in a defined state
@ -50,6 +35,8 @@ ReturnValue_t TcsBoardAssembly::commandChildren(Mode_t mode, Submode_t submode)
if (mode == DeviceHandlerIF::MODE_NORMAL or mode == MODE_ON) { if (mode == DeviceHandlerIF::MODE_NORMAL or mode == MODE_ON) {
result = handleNormalOrOnModeCmd(mode, submode); result = handleNormalOrOnModeCmd(mode, submode);
} }
} else {
tcsShortlyUnavailable = true;
} }
HybridIterator<ModeListEntry> tableIter(modeTable.begin(), modeTable.end()); HybridIterator<ModeListEntry> tableIter(modeTable.begin(), modeTable.end());
executeTable(tableIter); executeTable(tableIter);
@ -94,25 +81,6 @@ ReturnValue_t TcsBoardAssembly::isModeCombinationValid(Mode_t mode, Submode_t su
return HasModesIF::INVALID_MODE; return HasModesIF::INVALID_MODE;
} }
ReturnValue_t TcsBoardAssembly::initialize() { return AssemblyBase::initialize(); }
void TcsBoardAssembly::startTransition(Mode_t mode, Submode_t submode) {
if (mode != MODE_OFF) {
switcher.turnOn(true);
switcher.doStateMachine();
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
AssemblyBase::startTransition(mode, submode);
} else {
// Need to wait with mode commanding until power switcher is done
targetMode = mode;
targetSubmode = submode;
}
} else {
// Perform regular mode commanding first
AssemblyBase::startTransition(mode, submode);
}
}
ReturnValue_t TcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) { ReturnValue_t TcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
bool needsSecondStep = false; bool needsSecondStep = false;
@ -169,21 +137,6 @@ bool TcsBoardAssembly::isUseable(object_id_t object, Mode_t mode) {
return false; return false;
} }
MessageQueueId_t TcsBoardAssembly::getEventReceptionQueue() { return eventQueue->getId(); }
void TcsBoardAssembly::handleModeReached() {
if (targetMode == MODE_OFF) {
switcher.turnOff(true);
switcher.doStateMachine();
// Need to wait with call to AssemblyBase::handleModeReached until power switcher is done
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
AssemblyBase::handleModeReached();
}
} else {
AssemblyBase::handleModeReached();
}
}
void TcsBoardAssembly::handleChildrenLostMode(ReturnValue_t result) { void TcsBoardAssembly::handleChildrenLostMode(ReturnValue_t result) {
triggerEvent(CHILDREN_LOST_MODE, result); triggerEvent(CHILDREN_LOST_MODE, result);
startTransition(mode, submode); startTransition(mode, submode);
@ -210,6 +163,12 @@ ReturnValue_t TcsBoardAssembly::checkAndHandleHealthStates(Mode_t deviceMode,
return status; return status;
} }
bool TcsBoardAssembly::checkAndHandleRecovery() {
bool recoveryPending = SharedPowerAssemblyBase::checkAndHandleRecovery();
tcsShortlyUnavailable = recoveryPending;
return recoveryPending;
}
void TcsBoardAssembly::handleModeTransitionFailed(ReturnValue_t result) { void TcsBoardAssembly::handleModeTransitionFailed(ReturnValue_t result) {
if (targetMode == MODE_OFF) { if (targetMode == MODE_OFF) {
AssemblyBase::handleModeTransitionFailed(result); AssemblyBase::handleModeTransitionFailed(result);

View File

@ -4,6 +4,10 @@
#include <fsfw/container/FixedArrayList.h> #include <fsfw/container/FixedArrayList.h>
#include <fsfw/devicehandlers/AssemblyBase.h> #include <fsfw/devicehandlers/AssemblyBase.h>
#include <fsfw/power/PowerSwitcher.h> #include <fsfw/power/PowerSwitcher.h>
#include <mission/power/defs.h>
#include <mission/system/SharedPowerAssemblyBase.h>
#include <atomic>
#include "events/subsystemIdRanges.h" #include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h" #include "returnvalues/classIds.h"
@ -15,23 +19,20 @@ struct TcsBoardHelper {
std::array<std::pair<object_id_t, std::string>, 16> rtdInfos = {}; std::array<std::pair<object_id_t, std::string>, 16> rtdInfos = {};
}; };
class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF { class TcsBoardAssembly : public SharedPowerAssemblyBase {
public: public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_BOARD_ASS; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_BOARD_ASS;
static constexpr Event CHILDREN_LOST_MODE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); static constexpr Event CHILDREN_LOST_MODE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher, TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher,
TcsBoardHelper helper); TcsBoardHelper helper, std::atomic_bool& tcsShortlyUnavailable);
ReturnValue_t initialize() override;
private: private:
static constexpr uint8_t NUMBER_RTDS = 16; static constexpr uint8_t NUMBER_RTDS = 16;
PowerSwitcher switcher;
bool warningSwitch = true; bool warningSwitch = true;
TcsBoardHelper helper; TcsBoardHelper helper;
FixedArrayList<ModeListEntry, NUMBER_RTDS> modeTable; FixedArrayList<ModeListEntry, NUMBER_RTDS> modeTable;
MessageQueueIF* eventQueue = nullptr; std::atomic_bool& tcsShortlyUnavailable;
ReturnValue_t handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode); ReturnValue_t handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode);
/** /**
@ -42,17 +43,12 @@ class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF {
*/ */
bool isUseable(object_id_t object, Mode_t mode); bool isUseable(object_id_t object, Mode_t mode);
// ConfirmFailureIF implementation
MessageQueueId_t getEventReceptionQueue() override;
// AssemblyBase implementation // AssemblyBase implementation
void performChildOperation() override;
ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override; ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override;
ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override; ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override;
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override; ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
void handleModeReached() override;
ReturnValue_t checkAndHandleHealthStates(Mode_t deviceMode, Submode_t deviceSubmode); ReturnValue_t checkAndHandleHealthStates(Mode_t deviceMode, Submode_t deviceSubmode);
bool checkAndHandleRecovery() override;
// These two overrides prevent a transition of the whole assembly back to off just because // These two overrides prevent a transition of the whole assembly back to off just because
// some devices are not working // some devices are not working

View File

@ -1,6 +1,6 @@
#ifndef MISSION_TCS_DEFS_H_ #pragma once
#define MISSION_TCS_DEFS_H_
#include <atomic>
#include <cstdint> #include <cstdint>
namespace heater { namespace heater {
@ -17,4 +17,8 @@ enum Switch : uint8_t {
}; };
} }
#endif /* MISSION_TCS_DEFS_H_ */ namespace tcs {
extern std::atomic_bool TCS_BOARD_SHORTLY_UNAVAILABLE;
}

View File

@ -15,6 +15,7 @@
TEST_CASE("Thermal Controller", "[ThermalController]") { TEST_CASE("Thermal Controller", "[ThermalController]") {
const object_id_t THERMAL_CONTROLLER_ID = 0x123; const object_id_t THERMAL_CONTROLLER_ID = 0x123;
std::atomic_bool tcsBrdShortlyUnavailable = false;
TemperatureSensorInserter::Max31865DummyMap map0; TemperatureSensorInserter::Max31865DummyMap map0;
TemperatureSensorInserter::Tmp1075DummyMap map1; TemperatureSensorInserter::Tmp1075DummyMap map1;
@ -29,7 +30,7 @@ TEST_CASE("Thermal Controller", "[ThermalController]") {
// testEnvironment::initialize(); // testEnvironment::initialize();
ThermalController controller(THERMAL_CONTROLLER_ID, *heaterHandler); ThermalController controller(THERMAL_CONTROLLER_ID, *heaterHandler, tcsBrdShortlyUnavailable);
ReturnValue_t result = controller.initialize(); ReturnValue_t result = controller.initialize();
REQUIRE(result == returnvalue::OK); REQUIRE(result == returnvalue::OK);