from components.pid.temp_controller_base import TempControllerBase


class TempController(TempControllerBase):
	def __init__(self, dt):
		TempControllerBase.__init__(self, dt)
		self.dt = dt
		# None until the first process() tick - rather than hardcoding a
		# starting point (e.g. 20), which would make that very first
		# tick's heatrate come out as a bogus spike whenever the real
		# starting temperature isn't actually 20 (see
		# components/sud_forecast.py's SudForecastEstimator, which builds
		# a fresh TempController on every call - unlike the real one,
		# which only ever goes through this exactly once, it has no
		# earlier ticks to have already settled past that spike by).
		self.last_theta_ist = None
		self.heatrate_ist = 0

	def process(self):
		self._require_params()

		# Process Kalman
		self.theta_ist = self.theta_ist_set
		heatrate = 0 if self.last_theta_ist is None else (self.theta_ist - self.last_theta_ist)/self.dt*60

		alpha = 0.1
		self.heatrate_ist = (1-alpha) * self.heatrate_ist + alpha*heatrate
		self.last_theta_ist = self.theta_ist

		# Compensate for max heat rate to reduce overshoot
		hold_scale = 1.0/self.heatrate_soll_set if self.heatrate_soll_set > 0 else 1.0

		self.heatrate_soll = self.heatrate_soll_set * self.pid_hold.get_y()
		theta_err = self.theta_soll_set - self.theta_ist
		heatrate_err = self.heatrate_soll - self.heatrate_ist

		diff = self.theta_soll_set - self.theta_ist
		self.process_fsm(diff)
		self.process_pid(theta_err, heatrate_err, hold_scale)
