Merge pull request 'refactor power module' (#590) from eive/fsfw:mueller/refactor-power-switch-if-etc into development

Reviewed-on: fsfw/fsfw#590
This commit is contained in:
Steffen Gaisser 2022-05-12 18:37:45 +02:00
commit a83b86ccd2
17 changed files with 403 additions and 51 deletions

View File

@ -25,18 +25,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
- HAL Devicehandlers: Periodic printout is run-time configurable now - HAL Devicehandlers: Periodic printout is run-time configurable now
- `oneShotAction` flag in the `TestTask` class is not static anymore - `oneShotAction` flag in the `TestTask` class is not static anymore
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue - IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue
creation call. It allows passing context information and an arbitrary user argument into creation call. It allows passing context information and an arbitrary user argument into
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
- Clock:
- `timeval` to `TimeOfDay_t` ### HAL
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
- Moved the statics used by Clock in ClockCommon.cpp to this file - HAL Linux SPI: Set the Clock Default State when setting new SPI speed
- Better check for leap seconds and mode
- Added Unittests for Clock (only getter) PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
name clashes with Windows defines.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
### Time
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/584 and
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
- `timeval` to `TimeOfDay_t`
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
- Moved the statics used by Clock in ClockCommon.cpp to this file
- Better check for leap seconds
- Added Unittests for Clock (only getter)
### Power
- `PowerSwitchIF`: Remove `const` specifier from `sendSwitchCommand` and `sendFuseOnCommand` and
also specify a `ReturnValue_t` return type
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- Extend `PowerSwitcher` module to optionally check current state when calling `turnOn` or
`turnOff`. Tis can be helpful to avoid commanding switches which do not need commanding
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
## Removed ## Removed
@ -66,6 +89,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
- Added ETL dependency and improved library dependency management - Added ETL dependency and improved library dependency management
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
- Add a `DummyPowerSwitcher` module which can be useful for test setups when no PCDU is available
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- New typedef for switcher type
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- `Subsystem`: New API to add table and sequence entries - `Subsystem`: New API to add table and sequence entries
## Fixed ## Fixed

View File

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

View File

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

View File

@ -0,0 +1,38 @@
#ifndef FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_
#define FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_
#include <cstddef>
#include <vector>
#include "PowerSwitchIF.h"
#include "definitions.h"
#include "fsfw/objectmanager/SystemObject.h"
/**
* @brief This component can be used to simulate a power switcher like a
* Power Control Distribution Unit (PCDU)
* @details
* The dummy switcher will simply cache the commanded fuse and switch states and return them
* in the according switch getter functions. In that sense, it simulates an ideal PCDU.
*/
class DummyPowerSwitcher : public SystemObject, public PowerSwitchIF {
public:
DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, size_t numberOfFuses,
bool registerGlobally = true, uint32_t switchDelayMs = 5000);
void setInitialSwitcherList(std::vector<ReturnValue_t> switcherList);
void setInitialFusesList(std::vector<ReturnValue_t> switcherList);
virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override;
virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override;
virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const override;
virtual ReturnValue_t getFuseState(uint8_t fuseNr) const override;
virtual uint32_t getSwitchDelayMs(void) const override;
private:
std::vector<ReturnValue_t> switcherList;
std::vector<ReturnValue_t> fuseList;
uint32_t switchDelayMs = 5000;
};
#endif /* FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,7 +11,10 @@ target_sources(${FSFW_TEST_TGT} PRIVATE
) )
add_subdirectory(testcfg) add_subdirectory(testcfg)
add_subdirectory(mocks)
add_subdirectory(action) add_subdirectory(action)
add_subdirectory(power)
add_subdirectory(container) add_subdirectory(container)
add_subdirectory(osal) add_subdirectory(osal)
add_subdirectory(serialize) add_subdirectory(serialize)

View File

@ -0,0 +1,3 @@
target_sources(${FSFW_TEST_TGT} PRIVATE
PowerSwitcherMock.cpp
)

View File

@ -0,0 +1,77 @@
#include "PowerSwitcherMock.h"
static uint32_t SWITCH_REQUEST_UPDATE_VALUE = 0;
PowerSwitcherMock::PowerSwitcherMock() {}
ReturnValue_t PowerSwitcherMock::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
if (switchMap.count(switchNr) == 0) {
switchMap.emplace(switchNr, SwitchInfo(switchNr, onOff));
} else {
SwitchInfo& info = switchMap.at(switchNr);
info.currentState = onOff;
if (onOff == PowerSwitchIF::SWITCH_ON) {
info.timesCalledOn++;
} else {
info.timesCalledOff++;
}
}
return RETURN_OK;
}
ReturnValue_t PowerSwitcherMock::sendFuseOnCommand(uint8_t fuseNr) {
if (fuseMap.count(fuseNr) == 0) {
fuseMap.emplace(fuseNr, FuseInfo(fuseNr));
} else {
FuseInfo& info = fuseMap.at(fuseNr);
info.timesCalled++;
}
return RETURN_OK;
}
ReturnValue_t PowerSwitcherMock::getSwitchState(power::Switch_t switchNr) const {
if (switchMap.count(switchNr) == 1) {
auto& info = switchMap.at(switchNr);
SWITCH_REQUEST_UPDATE_VALUE++;
return info.currentState;
}
return RETURN_FAILED;
}
ReturnValue_t PowerSwitcherMock::getFuseState(uint8_t fuseNr) const {
if (fuseMap.count(fuseNr) == 1) {
return FUSE_ON;
} else {
return FUSE_OFF;
}
return RETURN_FAILED;
}
uint32_t PowerSwitcherMock::getSwitchDelayMs(void) const { return 5000; }
SwitchInfo::SwitchInfo() : switcher(0) {}
SwitchInfo::SwitchInfo(power::Switch_t switcher, ReturnValue_t initState)
: switcher(switcher), currentState(initState) {}
FuseInfo::FuseInfo(uint8_t fuse) : fuse(fuse) {}
void PowerSwitcherMock::getSwitchInfo(power::Switch_t switcher, SwitchInfo& info) {
if (switchMap.count(switcher) == 1) {
info = switchMap.at(switcher);
}
}
void PowerSwitcherMock::getFuseInfo(uint8_t fuse, FuseInfo& info) {
if (fuseMap.count(fuse) == 1) {
info = fuseMap.at(fuse);
}
}
uint32_t PowerSwitcherMock::getAmountSwitchStatWasRequested() {
return SWITCH_REQUEST_UPDATE_VALUE;
}
void PowerSwitcherMock::initSwitch(power::Switch_t switchNr) {
switchMap.emplace(switchNr, SwitchInfo(switchNr, PowerSwitchIF::SWITCH_OFF));
}

View File

@ -0,0 +1,52 @@
#ifndef FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_
#define FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_
#include <fsfw/power/PowerSwitchIF.h>
#include <map>
#include <utility>
struct SwitchInfo {
public:
SwitchInfo();
SwitchInfo(power::Switch_t switcher, ReturnValue_t initState);
power::Switch_t switcher;
ReturnValue_t currentState = PowerSwitchIF::SWITCH_OFF;
uint32_t timesCalledOn = 0;
uint32_t timesCalledOff = 0;
uint32_t timesStatusRequested = 0;
};
struct FuseInfo {
public:
FuseInfo(uint8_t fuse);
uint8_t fuse;
uint32_t timesCalled = 0;
};
class PowerSwitcherMock : public PowerSwitchIF {
public:
PowerSwitcherMock();
ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override;
ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override;
ReturnValue_t getSwitchState(power::Switch_t switchNr) const override;
ReturnValue_t getFuseState(uint8_t fuseNr) const override;
uint32_t getSwitchDelayMs(void) const override;
void getSwitchInfo(power::Switch_t switcher, SwitchInfo& info);
void getFuseInfo(uint8_t fuse, FuseInfo& info);
uint32_t getAmountSwitchStatWasRequested();
void initSwitch(power::Switch_t switchNr);
private:
using SwitchOnOffPair = std::pair<power::Switch_t, ReturnValue_t>;
using FuseOnOffPair = std::pair<uint8_t, ReturnValue_t>;
std::map<power::Switch_t, SwitchInfo> switchMap;
std::map<uint8_t, FuseInfo> fuseMap;
};
#endif /* FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_ */

View File

@ -0,0 +1,3 @@
target_sources(${FSFW_TEST_TGT} PRIVATE
testPowerSwitcher.cpp
)

View File

@ -0,0 +1,73 @@
#include <fsfw/power/DummyPowerSwitcher.h>
#include <fsfw/power/PowerSwitcher.h>
#include <fsfw_tests/unit/mocks/PowerSwitcherMock.h>
#include <catch2/catch_test_macros.hpp>
#include "objects/systemObjectList.h"
TEST_CASE("Power Switcher", "[power-switcher]") {
PowerSwitcherMock mock;
PowerSwitcher switcher(&mock, 1);
DummyPowerSwitcher dummySwitcher(objects::DUMMY_POWER_SWITCHER, 5, 5, false);
PowerSwitcher switcherUsingDummy(&dummySwitcher, 1);
SwitchInfo switchInfo;
mock.initSwitch(1);
SECTION("Basic Tests") {
REQUIRE(switcher.getFirstSwitch() == 1);
REQUIRE(switcher.getSecondSwitch() == power::NO_SWITCH);
// Default start state
REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF);
switcher.turnOn(true);
REQUIRE(mock.getAmountSwitchStatWasRequested() == 1);
REQUIRE(switcher.getState() == PowerSwitcher::WAIT_ON);
REQUIRE(switcher.checkSwitchState() == PowerSwitcher::IN_POWER_TRANSITION);
REQUIRE(switcher.active());
switcher.doStateMachine();
REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_ON);
mock.getSwitchInfo(1, switchInfo);
REQUIRE(switchInfo.timesCalledOn == 1);
REQUIRE(not switcher.active());
REQUIRE(mock.getAmountSwitchStatWasRequested() == 2);
REQUIRE(switcher.checkSwitchState() == HasReturnvaluesIF::RETURN_OK);
REQUIRE(mock.getAmountSwitchStatWasRequested() == 3);
switcher.turnOff(false);
REQUIRE(mock.getAmountSwitchStatWasRequested() == 3);
REQUIRE(switcher.getState() == PowerSwitcher::WAIT_OFF);
REQUIRE(switcher.active());
REQUIRE(switcher.getState() == PowerSwitcher::WAIT_OFF);
switcher.doStateMachine();
mock.getSwitchInfo(1, switchInfo);
REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF);
REQUIRE(switchInfo.timesCalledOn == 1);
REQUIRE(switchInfo.timesCalledOff == 1);
REQUIRE(not switcher.active());
REQUIRE(mock.getAmountSwitchStatWasRequested() == 4);
}
SECTION("Dummy Test") {
// Same tests, but we can't really check the dummy
REQUIRE(switcherUsingDummy.getFirstSwitch() == 1);
REQUIRE(switcherUsingDummy.getSecondSwitch() == power::NO_SWITCH);
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_OFF);
switcherUsingDummy.turnOn(true);
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_ON);
REQUIRE(switcherUsingDummy.active());
switcherUsingDummy.doStateMachine();
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_ON);
REQUIRE(not switcherUsingDummy.active());
switcherUsingDummy.turnOff(false);
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_OFF);
REQUIRE(switcherUsingDummy.active());
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_OFF);
switcherUsingDummy.doStateMachine();
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_OFF);
REQUIRE(not switcherUsingDummy.active());
}
SECTION("More Dummy Tests") {
}
}

View File

@ -21,8 +21,9 @@ enum sourceObjects : uint32_t {
HK_RECEIVER_MOCK = 22, HK_RECEIVER_MOCK = 22,
TEST_LOCAL_POOL_OWNER_BASE = 25, TEST_LOCAL_POOL_OWNER_BASE = 25,
SHARED_SET_ID = 26 SHARED_SET_ID = 26,
DUMMY_POWER_SWITCHER = 27
}; };
} }