diff --git a/monitoring/LimitMonitor.h b/monitoring/LimitMonitor.h index 45abe48b..c24629a3 100644 --- a/monitoring/LimitMonitor.h +++ b/monitoring/LimitMonitor.h @@ -16,12 +16,13 @@ public: uint16_t confirmationLimit, T lowerLimit, T upperLimit, Event belowLowEvent = MonitoringIF::VALUE_BELOW_LOW_LIMIT, Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT) : - MonitorBase(reporterId, monitorId, parameterId, confirmationLimit), lowerLimit( - lowerLimit), upperLimit(upperLimit), belowLowEvent( - belowLowEvent), aboveHighEvent(aboveHighEvent) { - } - virtual ~LimitMonitor() { + MonitorBase(reporterId, monitorId, parameterId, confirmationLimit), + lowerLimit(lowerLimit), upperLimit(upperLimit), belowLowEvent(belowLowEvent), + aboveHighEvent(aboveHighEvent) { } + + virtual ~LimitMonitor() {} + virtual ReturnValue_t checkSample(T sample, T* crossedLimit) { *crossedLimit = 0.0; if (sample > upperLimit) { diff --git a/thermal/TemperatureSensor.h b/thermal/TemperatureSensor.h index 2f64f772..ca0dbce6 100644 --- a/thermal/TemperatureSensor.h +++ b/thermal/TemperatureSensor.h @@ -1,105 +1,142 @@ #ifndef TEMPERATURESENSOR_H_ #define TEMPERATURESENSOR_H_ +#include #include -#include "AbstractTemperatureSensor.h" #include /** * @brief This building block handles non-linear value conversion and * range checks for analog temperature sensors. - * @details HOW TO USE + * @details This class can be used to perform all necessary tasks for temperature sensors. + * A sensor can be instantiated by calling the constructor. + * The temperature is calculated from an input value with + * the calculateOutputTemperature() function. Range checking and + * limit monitoring is performed automatically. * + * @ingroup thermal */ template class TemperatureSensor: public AbstractTemperatureSensor { public: - /** - * What are a,b and c? + * This structure contains parameters required for range checking + * and the conversion from the input value to the output temperature. + * a, b and c can be any parameters required to calculate the output + * temperature from the input value, for example parameters for the + * Callendar-Van-Dusen equation(see datasheet of used sensor / ADC) + * + * The parameters a,b and c are used in the calculateOutputTemperature() call. + * + * The lower and upper limits can be specified in °C or in the input value + * format */ struct Parameters { float a; float b; float c; - T lowerLimit; - T upperLimit; - float gradient; + float maxGradient; }; /** - * How to use me. - * @param setObjectid - * @param inputTemperature - * @param poolVariable - * @param vectorIndex - * @param parameters - * @param datapoolId - * @param outputSet - * @param thermalModule + * Forward declaration for explicit instantiation of used parameters. */ - TemperatureSensor(object_id_t setObjectid, - T *inputTemperature, PoolVariableIF *poolVariable, - uint8_t vectorIndex, Parameters parameters, uint32_t datapoolId, - DataSet *outputSet, ThermalModuleIF *thermalModule) : - - AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters), - inputTemperature(inputTemperature), poolVariable(poolVariable), - outputTemperature(datapoolId, outputSet, PoolVariableIF::VAR_WRITE), - sensorMonitor(setObjectid, DOMAIN_ID_SENSOR, - DataPool::poolIdAndPositionToPid(poolVariable->getDataPoolId(), vectorIndex), - DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit,parameters.upperLimit, - TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH), - oldTemperature(20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) { - } - struct UsedParameters { UsedParameters(Parameters parameters) : a(parameters.a), b(parameters.b), c(parameters.c), - gradient(parameters.gradient) {} + gradient(parameters.maxGradient) {} float a; float b; float c; float gradient; }; - static const uint16_t ADDRESS_A = 0; - static const uint16_t ADDRESS_B = 1; - static const uint16_t ADDRESS_C = 2; - static const uint16_t ADDRESS_GRADIENT = 3; + /** + * Constructor to check against raw input values + * @param setObjectid objectId of the sensor object + * @param inputValue Input value which is converted to a temperature + * @param poolVariable Pool Variable to store the temperature value + * @param vectorIndex Vector Index for the sensor monitor + * @param parameters Calculation parameters, temperature limits, gradient limit + * @param datapoolId Datapool ID of the output temperature + * @param outputSet Output dataset for the output temperature to fetch it with read() + * @param thermalModule respective thermal module, if it has one + */ + TemperatureSensor(object_id_t setObjectid, + T *inputValue, T lowerLimit, T upperLimit, PoolVariableIF *poolVariable, + uint8_t vectorIndex, uint32_t datapoolId, Parameters parameters = {0, 0, 0, 0}, + DataSet *outputSet = NULL, ThermalModuleIF *thermalModule = NULL) : + AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters), + inputValue(inputValue), poolVariable(poolVariable), + outputTemperature(datapoolId, outputSet, PoolVariableIF::VAR_WRITE), + oldTemperature(20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) + { + sensorMonitorRaw = new LimitMonitor(setObjectid, DOMAIN_ID_SENSOR, + DataPool::poolIdAndPositionToPid(poolVariable->getDataPoolId(), vectorIndex), + DEFAULT_CONFIRMATION_COUNT, lowerLimit, upperLimit, + TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH); + delete sensorMonitor; + } + + /** + * Constructor do check against °C values + */ + TemperatureSensor(object_id_t setObjectid, + T *inputValue, float lowerLimit, float upperLimit, PoolVariableIF *poolVariable, + uint8_t vectorIndex, uint32_t datapoolId, Parameters parameters = {0, 0, 0, 0}, + DataSet *outputSet = NULL, ThermalModuleIF *thermalModule = NULL) : + AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters), + inputValue(inputValue), poolVariable(poolVariable), + outputTemperature(datapoolId, outputSet, PoolVariableIF::VAR_WRITE), + oldTemperature(20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) + { + sensorMonitor = new LimitMonitor(setObjectid, DOMAIN_ID_SENSOR, + DataPool::poolIdAndPositionToPid(poolVariable->getDataPoolId(), vectorIndex), + DEFAULT_CONFIRMATION_COUNT, lowerLimit, upperLimit, + TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH); + delete sensorMonitorRaw; + } + +protected: + /** + * This formula is used to calculate the temperature from an input value + * with an arbitrary type. + * A default implementation is provided but can be replaced depending + * on the required calculation. + * @param inputTemperature + * @return + */ + virtual float calculateOutputTemperature(T inputValue) { + return parameters.a * inputValue * inputValue + + parameters.b * inputValue + parameters.c; + } - static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.) - static const uint8_t DOMAIN_ID_SENSOR = 1; private: void setInvalid() { outputTemperature = INVALID_TEMPERATURE; outputTemperature.setValid(false); uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; - sensorMonitor.setToInvalid(); + sensorMonitor->setToInvalid(); } protected: static const int32_t INVALID_UPTIME = 0; UsedParameters parameters; - T *inputTemperature; + T * inputValue; PoolVariableIF *poolVariable; PoolVariable outputTemperature; - LimitMonitor sensorMonitor; + LimitMonitor * sensorMonitorRaw; + LimitMonitor * sensorMonitor; float oldTemperature; timeval uptimeOfOldTemperature; - virtual float calculateOutputTemperature(T inputTemperature) { - return parameters.a * inputTemperature * inputTemperature - + parameters.b * inputTemperature + parameters.c; - } - void doChildOperation() { if (!poolVariable->isValid() || !healthHelper.healthTable->isHealthy(getObjectId())) { @@ -107,7 +144,7 @@ protected: return; } - outputTemperature = calculateOutputTemperature(*inputTemperature); + outputTemperature = calculateOutputTemperature(*inputValue); outputTemperature.setValid(PoolVariableIF::VALID); timeval uptime; @@ -115,7 +152,7 @@ protected: if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) { //In theory, we could use an AbsValueMonitor to monitor the gradient. - //But this would require storing the gradient in DP and quite some overhead. + //But this would require storing the maxGradient in DP and quite some overhead. //The concept of delta limits is a bit strange anyway. float deltaTime; float deltaTemp; @@ -133,10 +170,10 @@ protected: } } - //Check is done against raw limits. SHOULDDO: Why? Using °C would be more easy to handle. - sensorMonitor.doCheck(*inputTemperature); + //Check is done against raw limits. SHOULDDO: Why? Using °C would be more easy to handle. + sensorMonitor->doCheck(outputTemperature.value); - if (sensorMonitor.isOutOfLimits()) { + if (sensorMonitor->isOutOfLimits()) { uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; outputTemperature.setValid(PoolVariableIF::INVALID); outputTemperature = INVALID_TEMPERATURE; @@ -155,10 +192,19 @@ public: return outputTemperature.isValid(); } + static const uint16_t ADDRESS_A = 0; + static const uint16_t ADDRESS_B = 1; + static const uint16_t ADDRESS_C = 2; + static const uint16_t ADDRESS_GRADIENT = 3; + + static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.) + + static const uint8_t DOMAIN_ID_SENSOR = 1; + virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, uint16_t startAtIndex) { - ReturnValue_t result = sensorMonitor.getParameter(domainId, parameterId, + ReturnValue_t result = sensorMonitor->getParameter(domainId, parameterId, parameterWrapper, newValues, startAtIndex); if (result != INVALID_DOMAIN_ID) { return result; @@ -186,7 +232,7 @@ public: } virtual void resetOldState() { - sensorMonitor.setToUnchecked(); + sensorMonitor->setToUnchecked(); } };