text: #ifndef TEMPERATURESENSOR_H_
  #define TEMPERATURESENSOR_H_
  
  #include "../datapool/DataSet.h"
  #include "AbstractTemperatureSensor.h"
  #include "../monitoring/LimitMonitor.h"
  
  template<typename T>
  class TemperatureSensor: public AbstractTemperatureSensor {
  public:
  	struct Parameters {
  		float a;
  		float b;
  		float c;
  		T lowerLimit;
  		T upperLimit;
  		float gradient;
  	};
  	struct UsedParameters {
  		UsedParameters(Parameters parameters) :
  				a(parameters.a), b(parameters.b), c(parameters.c), gradient(
  						parameters.gradient) {
  		}
  		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;
  
  	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();
  	}
  protected:
  	static const int32_t INVALID_UPTIME = 0;
  
  	UsedParameters parameters;
  
  	T *inputTemperature;
  
  	PoolVariableIF *poolVariable;
  
  	PoolVariable<float> outputTemperature;
  
  	LimitMonitor<T> 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())) {
  			setInvalid();
  			return;
  		}
  
  		outputTemperature = calculateOutputTemperature(*inputTemperature);
  		outputTemperature.setValid(PoolVariableIF::VALID);
  
  		timeval uptime;
  		Clock::getUptime(&uptime);
  
  		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.
  			//The concept of delta limits is a bit strange anyway.
  			float deltaTime;
  			float deltaTemp;
  
  			deltaTime = (uptime.tv_sec + uptime.tv_usec / 1000000.)
  					- (uptimeOfOldTemperature.tv_sec
  							+ uptimeOfOldTemperature.tv_usec / 1000000.);
  			deltaTemp = oldTemperature - outputTemperature;
  			if (deltaTemp < 0) {
  				deltaTemp = -deltaTemp;
  			}
  			if (parameters.gradient < deltaTemp / deltaTime) {
  				triggerEvent(TEMP_SENSOR_GRADIENT);
  				//Don't set invalid, as we did not recognize it as invalid with full authority, let FDIR handle it
  			}
  		}
  
  		//Check is done against raw limits. SHOULDDO: Why? Using °C would be more easy to handle.
  		sensorMonitor.doCheck(*inputTemperature);
  
  		if (sensorMonitor.isOutOfLimits()) {
  			uptimeOfOldTemperature.tv_sec = INVALID_UPTIME;
  			outputTemperature.setValid(PoolVariableIF::INVALID);
  			outputTemperature = INVALID_TEMPERATURE;
  		} else {
  			oldTemperature = outputTemperature;
  			uptimeOfOldTemperature = uptime;
  		}
  	}
  
  public:
  	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 }) {
  
  	}
  
  	float getTemperature() {
  		return outputTemperature;
  	}
  
  	bool isValid() {
  		return outputTemperature.isValid();
  	}
  
  	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,
  				parameterWrapper, newValues, startAtIndex);
  		if (result != INVALID_DOMAIN_ID) {
  			return result;
  		}
  		if (domainId != this->DOMAIN_ID_BASE) {
  			return INVALID_DOMAIN_ID;
  		}
  		switch (parameterId) {
  		case ADDRESS_A:
  			parameterWrapper->set(parameters.a);
  			break;
  		case ADDRESS_B:
  			parameterWrapper->set(parameters.b);
  			break;
  		case ADDRESS_C:
  			parameterWrapper->set(parameters.c);
  			break;
  		case ADDRESS_GRADIENT:
  			parameterWrapper->set(parameters.gradient);
  			break;
  		default:
  			return INVALID_MATRIX_ID;
  		}
  		return HasReturnvaluesIF::RETURN_OK;
  	}
  
  	virtual void resetOldState() {
  		sensorMonitor.setToUnchecked();
  	}
  
  };
  
  #endif /* TEMPERATURESENSOR_H_ */
  