2020-11-19 00:10:59 +01:00
|
|
|
#include "ThermalComponentCore.h"
|
|
|
|
|
|
|
|
ThermalComponentCore::ThermalComponentCore(object_id_t reportingObjectId,
|
2020-11-30 13:59:54 +01:00
|
|
|
uint8_t domainId, gp_id_t temperaturePoolId,
|
|
|
|
gp_id_t targetStatePoolId, gp_id_t currentStatePoolId,
|
2020-11-30 14:13:52 +01:00
|
|
|
gp_id_t requestPoolId, LocalPoolDataSetBase* dataSet,
|
|
|
|
Parameters parameters, StateRequest initialTargetState) :
|
2020-11-19 00:10:59 +01:00
|
|
|
temperature(temperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE),
|
|
|
|
targetState(targetStatePoolId, dataSet, PoolVariableIF::VAR_READ),
|
|
|
|
currentState(currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE),
|
|
|
|
heaterRequest(requestPoolId, dataSet, PoolVariableIF::VAR_WRITE),
|
2020-11-30 16:06:59 +01:00
|
|
|
parameters(parameters), domainId(domainId),
|
|
|
|
temperatureMonitor(reportingObjectId, domainId + 1,temperaturePoolId,
|
|
|
|
COMPONENT_TEMP_CONFIRMATION) {
|
2018-07-12 16:29:32 +02:00
|
|
|
//Set thermal state once, then leave to operator.
|
2020-11-30 16:06:59 +01:00
|
|
|
targetState.setReadWriteMode(PoolVariableIF::VAR_WRITE);
|
|
|
|
ReturnValue_t result = targetState.read();
|
|
|
|
if(result == HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
targetState = initialTargetState;
|
|
|
|
targetState.setValid(true);
|
|
|
|
targetState.commit();
|
|
|
|
}
|
|
|
|
targetState.setReadWriteMode(PoolVariableIF::VAR_READ);
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
void ThermalComponentCore::addSensor(AbstractTemperatureSensor* sensor) {
|
|
|
|
this->sensor = sensor;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
ThermalComponentCore::~ThermalComponentCore() {
|
|
|
|
}
|
|
|
|
|
|
|
|
ThermalComponentIF::HeaterRequest ThermalComponentCore::performOperation(
|
|
|
|
uint8_t opCode) {
|
2018-07-12 16:29:32 +02:00
|
|
|
HeaterRequest request = HEATER_DONT_CARE;
|
|
|
|
//SHOULDDO: Better pass db_float_t* to getTemperature and set it invalid if invalid.
|
|
|
|
temperature = getTemperature();
|
2020-11-30 16:06:59 +01:00
|
|
|
updateMinMaxTemp();
|
|
|
|
if ((temperature != INVALID_TEMPERATURE)) {
|
|
|
|
temperature.setValid(PoolVariableIF::VALID);
|
|
|
|
State state = getState(temperature.value, getParameters(),
|
|
|
|
targetState.value);
|
|
|
|
currentState = state;
|
|
|
|
checkLimits(state);
|
|
|
|
request = getHeaterRequest(targetState.value, temperature.value,
|
|
|
|
getParameters());
|
|
|
|
} else {
|
|
|
|
temperatureMonitor.setToInvalid();
|
|
|
|
temperature.setValid(PoolVariableIF::INVALID);
|
|
|
|
currentState = UNKNOWN;
|
|
|
|
request = HEATER_DONT_CARE;
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
currentState.setValid(PoolVariableIF::VALID);
|
|
|
|
heaterRequest = request;
|
|
|
|
heaterRequest.setValid(PoolVariableIF::VALID);
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
void ThermalComponentCore::markStateIgnored() {
|
2020-11-30 16:06:59 +01:00
|
|
|
currentState = getIgnoredState(currentState.value);
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
object_id_t ThermalComponentCore::getObjectId() {
|
2020-11-30 16:06:59 +01:00
|
|
|
return temperatureMonitor.getReporterId();
|
2020-11-30 14:13:52 +01:00
|
|
|
return 0;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
float ThermalComponentCore::getLowerOpLimit() {
|
2018-07-12 16:29:32 +02:00
|
|
|
return parameters.lowerOpLimit;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
ReturnValue_t ThermalComponentCore::setTargetState(int8_t newState) {
|
2020-05-17 01:17:11 +02:00
|
|
|
GlobDataSet mySet;
|
|
|
|
gp_uint8_t writableTargetState(targetState.getDataPoolId(),
|
2018-07-12 16:29:32 +02:00
|
|
|
&mySet, PoolVariableIF::VAR_READ_WRITE);
|
|
|
|
mySet.read();
|
|
|
|
if ((writableTargetState == STATE_REQUEST_OPERATIONAL)
|
|
|
|
&& (newState != STATE_REQUEST_IGNORE)) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
switch (newState) {
|
|
|
|
case STATE_REQUEST_HEATING:
|
|
|
|
case STATE_REQUEST_IGNORE:
|
|
|
|
case STATE_REQUEST_OPERATIONAL:
|
|
|
|
writableTargetState = newState;
|
|
|
|
break;
|
|
|
|
case STATE_REQUEST_NON_OPERATIONAL:
|
|
|
|
default:
|
|
|
|
return INVALID_TARGET_STATE;
|
|
|
|
}
|
|
|
|
mySet.commit(PoolVariableIF::VALID);
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
void ThermalComponentCore::setOutputInvalid() {
|
2018-07-12 16:29:32 +02:00
|
|
|
temperature = INVALID_TEMPERATURE;
|
|
|
|
temperature.setValid(PoolVariableIF::INVALID);
|
|
|
|
currentState.setValid(PoolVariableIF::INVALID);
|
|
|
|
heaterRequest = HEATER_DONT_CARE;
|
|
|
|
heaterRequest.setValid(PoolVariableIF::INVALID);
|
2020-11-30 16:06:59 +01:00
|
|
|
temperatureMonitor.setToUnchecked();
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
float ThermalComponentCore::getTemperature() {
|
|
|
|
if ((sensor != nullptr) && (sensor->isValid())) {
|
2018-07-12 16:29:32 +02:00
|
|
|
return sensor->getTemperature();
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
if ((firstRedundantSensor != nullptr) &&
|
|
|
|
(firstRedundantSensor->isValid())) {
|
2018-07-12 16:29:32 +02:00
|
|
|
return firstRedundantSensor->getTemperature();
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
if ((secondRedundantSensor != nullptr) &&
|
|
|
|
(secondRedundantSensor->isValid())) {
|
2018-07-12 16:29:32 +02:00
|
|
|
return secondRedundantSensor->getTemperature();
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
if (thermalModule != nullptr) {
|
2018-07-12 16:29:32 +02:00
|
|
|
float temperature = thermalModule->getTemperature();
|
|
|
|
if (temperature != ThermalModuleIF::INVALID_TEMPERATURE) {
|
|
|
|
return temperature;
|
|
|
|
} else {
|
|
|
|
return INVALID_TEMPERATURE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return INVALID_TEMPERATURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
ThermalComponentIF::State ThermalComponentCore::getState(float temperature,
|
2018-07-12 16:29:32 +02:00
|
|
|
Parameters parameters, int8_t targetState) {
|
|
|
|
ThermalComponentIF::State state;
|
|
|
|
|
|
|
|
if (temperature < parameters.lowerOpLimit) {
|
|
|
|
state = NON_OPERATIONAL_LOW;
|
|
|
|
} else if (temperature < parameters.upperOpLimit) {
|
|
|
|
state = OPERATIONAL;
|
|
|
|
} else {
|
|
|
|
state = NON_OPERATIONAL_HIGH;
|
|
|
|
}
|
|
|
|
if (targetState == STATE_REQUEST_IGNORE) {
|
|
|
|
state = getIgnoredState(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
void ThermalComponentCore::checkLimits(ThermalComponentIF::State state) {
|
2018-07-12 16:29:32 +02:00
|
|
|
//Checks operational limits only.
|
2020-11-30 16:06:59 +01:00
|
|
|
temperatureMonitor.translateState(state, temperature.value,
|
|
|
|
getParameters().lowerOpLimit, getParameters().upperOpLimit);
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
ThermalComponentIF::HeaterRequest ThermalComponentCore::getHeaterRequest(
|
2018-07-12 16:29:32 +02:00
|
|
|
int8_t targetState, float temperature, Parameters parameters) {
|
|
|
|
if (targetState == STATE_REQUEST_IGNORE) {
|
|
|
|
isHeating = false;
|
|
|
|
return HEATER_DONT_CARE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (temperature > parameters.upperOpLimit - parameters.heaterSwitchoff) {
|
|
|
|
isHeating = false;
|
|
|
|
return HEATER_REQUEST_EMERGENCY_OFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
float opHeaterLimit = parameters.lowerOpLimit + parameters.heaterOn;
|
|
|
|
|
|
|
|
if (isHeating) {
|
|
|
|
opHeaterLimit += parameters.hysteresis;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (temperature < opHeaterLimit) {
|
|
|
|
isHeating = true;
|
|
|
|
return HEATER_REQUEST_EMERGENCY_ON;
|
|
|
|
}
|
|
|
|
isHeating = false;
|
|
|
|
return HEATER_DONT_CARE;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
ThermalComponentIF::State ThermalComponentCore::getIgnoredState(int8_t state) {
|
2018-07-12 16:29:32 +02:00
|
|
|
switch (state) {
|
|
|
|
case NON_OPERATIONAL_LOW:
|
|
|
|
return NON_OPERATIONAL_LOW_IGNORED;
|
|
|
|
case OPERATIONAL:
|
|
|
|
return OPERATIONAL_IGNORED;
|
|
|
|
case NON_OPERATIONAL_HIGH:
|
|
|
|
return NON_OPERATIONAL_HIGH_IGNORED;
|
|
|
|
case NON_OPERATIONAL_LOW_IGNORED:
|
|
|
|
return NON_OPERATIONAL_LOW_IGNORED;
|
|
|
|
case OPERATIONAL_IGNORED:
|
|
|
|
return OPERATIONAL_IGNORED;
|
|
|
|
case NON_OPERATIONAL_HIGH_IGNORED:
|
|
|
|
return NON_OPERATIONAL_HIGH_IGNORED;
|
|
|
|
default:
|
|
|
|
case UNKNOWN:
|
|
|
|
return UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-30 16:06:59 +01:00
|
|
|
void ThermalComponentCore::updateMinMaxTemp() {
|
|
|
|
if (temperature == INVALID_TEMPERATURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (temperature < minTemp) {
|
|
|
|
minTemp = temperature.value;
|
|
|
|
}
|
|
|
|
if (temperature > maxTemp) {
|
|
|
|
maxTemp = temperature.value;
|
|
|
|
}
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
uint8_t ThermalComponentCore::getDomainId() const {
|
2018-07-12 16:29:32 +02:00
|
|
|
return domainId;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
ThermalComponentCore::Parameters ThermalComponentCore::getParameters() {
|
2018-07-12 16:29:32 +02:00
|
|
|
return parameters;
|
|
|
|
}
|
|
|
|
|
2020-11-19 00:10:59 +01:00
|
|
|
ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
|
2018-07-12 16:29:32 +02:00
|
|
|
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
|
|
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
2020-11-30 16:06:59 +01:00
|
|
|
ReturnValue_t result = temperatureMonitor.getParameter(domainId,
|
|
|
|
parameterId, parameterWrapper, newValues, startAtIndex);
|
|
|
|
if (result != INVALID_DOMAIN_ID) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (domainId != this->domainId) {
|
|
|
|
return INVALID_DOMAIN_ID;
|
|
|
|
}
|
|
|
|
switch (parameterId) {
|
|
|
|
case 0:
|
|
|
|
parameterWrapper->set(parameters.heaterOn);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
parameterWrapper->set(parameters.hysteresis);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
parameterWrapper->set(parameters.heaterSwitchoff);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
parameterWrapper->set(minTemp);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
parameterWrapper->set(maxTemp);
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
parameterWrapper->set(parameters.lowerOpLimit);
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
parameterWrapper->set(parameters.upperOpLimit);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return INVALID_IDENTIFIER_ID;
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|