2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/power/Fuse.h"
|
2020-12-03 18:29:28 +01:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/ipc/QueueFactory.h"
|
2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/monitoring/LimitViolationReporter.h"
|
|
|
|
#include "fsfw/monitoring/MonitoringMessageContent.h"
|
|
|
|
#include "fsfw/objectmanager/ObjectManager.h"
|
|
|
|
#include "fsfw/serialize/SerialFixedArrayListAdapter.h"
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
object_id_t Fuse::powerSwitchId = 0;
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,
|
|
|
|
float maxCurrent, uint16_t confirmationCount)
|
|
|
|
: SystemObject(fuseObjectId),
|
|
|
|
oldFuseState(0),
|
|
|
|
fuseId(fuseId),
|
|
|
|
currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount, maxCurrent,
|
|
|
|
FUSE_CURRENT_HIGH),
|
|
|
|
powerMonitor(fuseObjectId, 2, ids.poolIdPower, confirmationCount),
|
|
|
|
set(variableSet),
|
|
|
|
voltage(ids.pidVoltage, &set),
|
|
|
|
current(ids.pidCurrent, &set),
|
|
|
|
state(ids.pidState, &set),
|
|
|
|
power(ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE),
|
|
|
|
parameterHelper(this),
|
|
|
|
healthHelper(this, fuseObjectId) {
|
|
|
|
commandQueue = QueueFactory::instance()->createMessageQueue();
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
Fuse::~Fuse() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void Fuse::addDevice(PowerComponentIF* switchSet) { devices.push_back(switchSet); }
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
ReturnValue_t Fuse::initialize() {
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t result = SystemObject::initialize();
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = parameterHelper.initialize();
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = healthHelper.initialize();
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
powerIF = ObjectManager::instance()->get<PowerSwitchIF>(powerSwitchId);
|
|
|
|
if (powerIF == NULL) {
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Fuse::calculatePowerLimits(float* low, float* high) {
|
2022-02-02 10:29:30 +01:00
|
|
|
for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) {
|
|
|
|
if (areSwitchesOfComponentOn(iter)) {
|
|
|
|
*low += (*iter)->getMin();
|
|
|
|
*high += (*iter)->getMax();
|
|
|
|
}
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Fuse::check() {
|
2022-02-02 10:29:30 +01:00
|
|
|
set.read();
|
|
|
|
if (!healthHelper.healthTable->isHealthy(getObjectId())) {
|
|
|
|
setAllMonitorsToUnchecked();
|
|
|
|
set.setValidity(false, true);
|
|
|
|
return set.commit();
|
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
ReturnValue_t result = returnvalue::OK;
|
2022-02-02 10:29:30 +01:00
|
|
|
checkFuseState();
|
|
|
|
calculateFusePower();
|
|
|
|
// Check if power is valid and if fuse state is off or invalid.
|
|
|
|
if (!power.isValid() || (state == 0) || !state.isValid()) {
|
|
|
|
result = powerMonitor.setToInvalid();
|
|
|
|
} else {
|
|
|
|
float lowLimit = 0.0;
|
|
|
|
float highLimit = RESIDUAL_POWER;
|
|
|
|
calculatePowerLimits(&lowLimit, &highLimit);
|
|
|
|
result = powerMonitor.checkPower(power.value, lowLimit, highLimit);
|
|
|
|
if (result == MonitoringIF::BELOW_LOW_LIMIT) {
|
|
|
|
reportEvents(POWER_BELOW_LOW_LIMIT);
|
|
|
|
} else if (result == MonitoringIF::ABOVE_HIGH_LIMIT) {
|
|
|
|
reportEvents(POWER_ABOVE_HIGH_LIMIT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
set.commit();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Fuse::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
|
|
|
Endianness streamEndianness) const {
|
2022-08-15 20:28:16 +02:00
|
|
|
ReturnValue_t result = returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
for (DeviceList::const_iterator iter = devices.begin(); iter != devices.end(); iter++) {
|
|
|
|
result = (*iter)->serialize(buffer, size, maxSize, streamEndianness);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-04-21 22:28:43 +02:00
|
|
|
size_t Fuse::getSerializedSize() const {
|
2022-02-02 10:29:30 +01:00
|
|
|
uint32_t size = 0;
|
|
|
|
for (DeviceList::const_iterator iter = devices.begin(); iter != devices.end(); iter++) {
|
|
|
|
size += (*iter)->getSerializedSize();
|
|
|
|
}
|
|
|
|
return size;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) {
|
2022-08-15 20:28:16 +02:00
|
|
|
ReturnValue_t result = returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) {
|
|
|
|
result = (*iter)->deSerialize(buffer, size, streamEndianness);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
uint8_t Fuse::getFuseId() const { return fuseId; }
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
void Fuse::calculateFusePower() {
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t result1 = currentLimit.check();
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result1 != returnvalue::OK || !(voltage.isValid())) {
|
2022-02-02 10:29:30 +01:00
|
|
|
power.setValid(PoolVariableIF::INVALID);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Calculate fuse power.
|
|
|
|
power.value = current.value * voltage.value;
|
|
|
|
power.setValid(PoolVariableIF::VALID);
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Fuse::performOperation(uint8_t opCode) {
|
2022-02-02 10:29:30 +01:00
|
|
|
checkCommandQueue();
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Fuse::reportEvents(Event event) {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (!powerMonitor.isEventEnabled()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) {
|
|
|
|
if (areSwitchesOfComponentOn(iter)) {
|
|
|
|
EventManagerIF::triggerEvent((*iter)->getDeviceObjectId(), event);
|
|
|
|
}
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
MessageQueueId_t Fuse::getCommandQueue() const { return commandQueue->getId(); }
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
void Fuse::setAllMonitorsToUnchecked() {
|
2022-02-02 10:29:30 +01:00
|
|
|
currentLimit.setToUnchecked();
|
|
|
|
powerMonitor.setToUnchecked();
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Fuse::checkCommandQueue() {
|
2022-02-02 10:29:30 +01:00
|
|
|
CommandMessage command;
|
|
|
|
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
result = healthHelper.handleHealthCommand(&command);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result == returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
result = parameterHelper.handleParameterMessage(&command);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result == returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
command.setToUnknownCommand();
|
|
|
|
commandQueue->reply(&command);
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Fuse::checkFuseState() {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (!state.isValid()) {
|
|
|
|
oldFuseState = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (state == 0) {
|
|
|
|
if (oldFuseState != 0) {
|
|
|
|
reportEvents(FUSE_WENT_OFF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
oldFuseState = state.value;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
float Fuse::getPower() {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (power.isValid()) {
|
|
|
|
return power.value;
|
|
|
|
} else {
|
|
|
|
return 0.0;
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Fuse::setDataPoolEntriesInvalid() {
|
2022-02-02 10:29:30 +01:00
|
|
|
set.read();
|
|
|
|
set.setValidity(false, true);
|
|
|
|
set.commit();
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2021-01-29 22:45:53 +01:00
|
|
|
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint8_t uniqueId,
|
2022-02-02 10:29:30 +01:00
|
|
|
ParameterWrapper* parameterWrapper,
|
|
|
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
|
|
|
ReturnValue_t result =
|
|
|
|
currentLimit.getParameter(domainId, uniqueId, parameterWrapper, newValues, startAtIndex);
|
|
|
|
if (result != INVALID_DOMAIN_ID) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = powerMonitor.getParameter(domainId, uniqueId, parameterWrapper, newValues, startAtIndex);
|
|
|
|
return result;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Fuse::areSwitchesOfComponentOn(DeviceList::iterator iter) {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (powerIF->getSwitchState((*iter)->getSwitchId1()) != PowerSwitchIF::SWITCH_ON) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((*iter)->hasTwoSwitches()) {
|
|
|
|
if ((powerIF->getSwitchState((*iter)->getSwitchId2()) != PowerSwitchIF::SWITCH_ON)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
bool Fuse::isPowerValid() { return power.isValid(); }
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
ReturnValue_t Fuse::setHealth(HealthState health) {
|
2022-02-02 10:29:30 +01:00
|
|
|
healthHelper.setHealth(health);
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
HasHealthIF::HealthState Fuse::getHealth() { return healthHelper.getHealth(); }
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t Fuse::PowerMonitor::checkPower(float sample, float lowerLimit, float upperLimit) {
|
|
|
|
if (sample > upperLimit) {
|
|
|
|
return this->monitorStateIs(MonitoringIF::ABOVE_HIGH_LIMIT, sample, upperLimit);
|
|
|
|
} else if (sample < lowerLimit) {
|
|
|
|
return this->monitorStateIs(MonitoringIF::BELOW_LOW_LIMIT, sample, lowerLimit);
|
|
|
|
} else {
|
2022-08-15 20:28:16 +02:00
|
|
|
return this->monitorStateIs(returnvalue::OK, sample, 0.0); // Within limits.
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|