|
83 | 83 | CONF_MIN_CYCLE_DURATION = "min_cycle_duration" |
84 | 84 | CONF_MIN_OFF_CYCLE_DURATION = "min_off_cycle_duration" |
85 | 85 | CONF_KEEP_ALIVE = "keep_alive" |
| 86 | +CONF_FORCE_PID_REFRESH = "force_pid_refresh" |
86 | 87 | CONF_SAMPLING_PERIOD = "sampling_period" |
87 | 88 | CONF_INITIAL_HVAC_MODE = "initial_hvac_mode" |
88 | 89 | CONF_AWAY_TEMP = "away_temp" |
|
120 | 121 | vol.Optional(CONF_MIN_OFF_CYCLE_DURATION): vol.All( |
121 | 122 | cv.time_period, cv.positive_timedelta), |
122 | 123 | vol.Required(CONF_KEEP_ALIVE): vol.All(cv.time_period, cv.positive_timedelta), |
| 124 | + vol.Optional(CONF_FORCE_PID_REFRESH): vol.All(cv.time_period, cv.positive_timedelta), |
123 | 125 | vol.Optional(CONF_SAMPLING_PERIOD, default=DEFAULT_SAMPLING_PERIOD): vol.All( |
124 | 126 | cv.time_period, cv.positive_timedelta), |
125 | 127 | vol.Optional(CONF_INITIAL_HVAC_MODE): vol.In( |
@@ -172,6 +174,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= |
172 | 174 | 'min_cycle_duration': config.get(CONF_MIN_CYCLE_DURATION), |
173 | 175 | 'min_off_cycle_duration': config.get(CONF_MIN_OFF_CYCLE_DURATION), |
174 | 176 | 'keep_alive': config.get(CONF_KEEP_ALIVE), |
| 177 | + 'force_pid_refresh': config.get(CONF_FORCE_PID_REFRESH), |
175 | 178 | 'sampling_period': config.get(CONF_SAMPLING_PERIOD), |
176 | 179 | 'initial_hvac_mode': config.get(CONF_INITIAL_HVAC_MODE), |
177 | 180 | 'away_temp': config.get(CONF_AWAY_TEMP), |
@@ -239,6 +242,7 @@ def __init__(self, **kwargs): |
239 | 242 | self._unique_id = slugify(f"{DOMAIN}_{self._name}_{self._heater_entity_id}") |
240 | 243 | self._ac_mode = kwargs.get('ac_mode') |
241 | 244 | self._keep_alive = kwargs.get('keep_alive') |
| 245 | + self._force_pid_refresh = kwargs.get('force_pid_refresh') |
242 | 246 | self._sampling_period = kwargs.get('sampling_period').seconds |
243 | 247 | self._hvac_mode = kwargs.get('initial_hvac_mode', None) |
244 | 248 | self._saved_target_temp = kwargs.get('target_temp', None) or kwargs.get('away_temp', None) |
@@ -324,6 +328,8 @@ async def async_added_to_hass(self): |
324 | 328 |
|
325 | 329 | if self._keep_alive: |
326 | 330 | async_track_time_interval(self.hass, self._async_control_heating, self._keep_alive) |
| 331 | + if self._force_pid_refresh: |
| 332 | + async_track_time_interval(self.hass, self._async_pid_refresh, self._force_pid_refresh) |
327 | 333 |
|
328 | 334 | @callback |
329 | 335 | def _async_startup(event): |
@@ -685,6 +691,16 @@ def _async_update_temp(self, state): |
685 | 691 | except ValueError as ex: |
686 | 692 | _LOGGER.debug("Unable to update from sensor: %s", ex) |
687 | 693 |
|
| 694 | + async def _async_pid_refresh(self, time_func=None): |
| 695 | + """Refresh sensor state and run PID""" |
| 696 | + sensor_state = self.hass.states.get(self._sensor_entity_id) |
| 697 | + if sensor_state and sensor_state.state != STATE_UNKNOWN: |
| 698 | + self._previous_temp_time = self._cur_temp_time |
| 699 | + self._async_update_temp(sensor_state) |
| 700 | + self._cur_temp_time = time.time() |
| 701 | + _LOGGER.debug("Forcing PID refresh") |
| 702 | + await self._async_control_heating(calc_pid=True) |
| 703 | + |
688 | 704 | async def _async_control_heating(self, time_func=None, calc_pid=False): |
689 | 705 | """Run PID controller, optional autotune for faster integration""" |
690 | 706 | async with self._temp_lock: |
|
0 commit comments