Change cold_tolerance from script

Hello.

I have automated my heatpump to the point I’m seeing some interesting power savings without change in comfort (and hopefully not too much wear on tear on it either).

It is using a generic_thermostat and some hijacked IR codes. I would like to experiment some more with hot_tolerance and cold_tolerance, ideally I’d like to change these two points instead of a trip temperature, since a thermostat naturally operates by a hysteresis and these two points, not oscillating dumbly around a set point. But a user is mostly presented with a single temperature, for UX and ease-of-use reasons, and isn’t really aware of this concept.

I don’t care about ease-of-use and UX, I am aware of this concept which hass implements, and I want to control these two points instead of a single temperature. I don’t mind if I have to set a dummy temperature between them either, as long as I can control those two points.

This is my configuration

climate:
  - platform: generic_thermostat
    name: BMS12HD
    # icon: "hass:air-conditioner"
    ac_mode: true
    heater: switch.ac_compressor
    target_sensor: sensor.weighted_temperature
    target_temp: 24.3
    min_cycle_duration: 00:30:00
    keep_alive: 00:02:00
    away_temp: 26
    precision: 0.1
    min_temp: 16
    max_temp: 30
    hot_tolerance: 1.4
    cold_tolerance: 0.5

The thermostats and lovelace UIs are nice, but they only go in 0.5 degree steps anyway. I have this script when I want more precision. My sensors are a more complex setup, but the final sensor value weighs in the room I’m in and a few sensors near the ceiling and floor, so the precision I want is there.

alias: script_manually_set_ac_values
sequence:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.hyundai_bms12hd
      temperature: |
        {{ states.input_number.ac_manual_override.state | float}}
mode: single

I want to alter the hysteresis points (cold_tolerance and hot_tolerance) from a script. I can do this
by config file and restart, of course, but I want to do it dynamically, so I can eventually implement them in a more complex controller - for example taking into account running 3 hours for a -0.5 heat change, which was lost in 10 minutes.

But with a dummy test like this, it still fails:

alias: script_manually_set_ac_values
sequence:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.hyundai_bms12hd
      temperature: |
        {{ states.input_number.ac_manual_override.state | float}}
      cold_tolerance: 0.5
mode: single

And I get: Failed to call service script/manually_set_ac_values. extra keys not allowed @ data['cold_tolerance']

Just to be extra clear, I don’t want to alter the range of the sliders themselves (climate.target_temp_high and climate.target_temp_low), I want to alter the temperatures at which the generic_thermostat fires the state.cool and state.idle events.

These values correspond to target_temp - cold_tolerance and target_temp + hot_tolerance, or in my case 23.8 (24.3 - 0.5) and 25.7 (24.3+1.4). I want a way to change those 23.8 and 25.7 from a script, without rewriting my config file and restarting hass.

Thanks.

There is no service to change the cold/hot tolerance options. They are set and forget in the config.

The error is saying (correctly) that this is not a valid option for the climate.set_temperature service:

cold_tolerance: 0.5

The valid options are listed here: https://www.home-assistant.io/integrations/climate/#service-climateset_temperature

Thanks.

I understand what the error is saying, my question is “how do I implement this behaviour”, not “why doesn’t this work”.
Hass itself is obviously using this mechanism, as per github, line 471, or below. I also understand why (I’m messing with a climate object, and not accessing the generic_thermostat), but I couldn’t find any way to access the generic_thermostat object except through a climate one.

I was actually expecting an answer like a patch, a pull request, a python script or a hack of some sorts, since I couldn’t find absolutely no info about it, or at least some vague idea like “this isn’t really possible as it is now right, but here’s something you might consider”.

Is there truly no way? I’m ok with patching and hacking my installation (and can set up testing in a separate environment if need be).

            too_cold = self._target_temp >= self._cur_temp + self._cold_tolerance
            too_hot = self._cur_temp >= self._target_temp + self._hot_tolerance
            if self._is_device_active:
                if (self.ac_mode and too_cold) or (not self.ac_mode and too_hot):
                    _LOGGER.info("Turning off heater %s", self.heater_entity_id)
                    await self._async_heater_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning on heater heater %s",
                        self.heater_entity_id,
                    )
                    await self._async_heater_turn_on()
            else:
                if (self.ac_mode and too_hot) or (not self.ac_mode and too_cold):
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning off heater %s", self.heater_entity_id
                    )
                    await self._async_heater_turn_off()

So to me it seems it’s just abstracting the hysteresis behavior away behind a trip point.

Sure there’s a way if you edit the integration to provide the support you want. Just put the changed integration in config/custom_components and it will be used instead of the core integration.

…and add a version tag in the manifest.json :wink:

1 Like

Sure there’s a way if you edit the integration to provide the support you want.

Ah, onwards to hacking the source code it is!

…and add a version tag in the manifest.json

this sure would have been handy earlier, haha.

Thanks, both of you!

Uhh this function is still not possible by normal way?? :see_no_evil::see_no_evil:

Instead of tweking a generic thermostat, why not use a more advanced thermostat, like

or

Not until someone volunteers to add it and, so far, no one has.

very nice thermostats, but probably not suitable for my purpose … i need to dynamically regulate the hysteresis curve with definable temperature based on my values, maybe it’s possible here too, not sure

What are you trying to achieve by dynamically regulating the hysteresis curve? Both mentioned thermostats are PiD’s. That is a tried and tested technology to dynamically adjust heating, to reach the target efficiently, to prevent overshoot and keep to the set temperature as fluently as possible and save energy in the process.

The second one I mentioned, (but I maybe the first one too) tunes itself to the circumstances of your home and the influence of outside temperature completely automatically to optimize the heating process. It was designed for OpenTherm but I saw it could also do on/off. There’s not that much that I can imagine that adjusting the hot and cold margin yourself would be able to do better. But maybe you have a specific use case has needs I’m not aware of.

The only downside to a PiD is it can be daunting to set up initially, but an autotuning one should eliminate that problem.

https://blog.opticontrols.com/archives/344

the process may not be common. this is the burning of foam fuels, where I calculate the current calorific value, the desired temperature, which varies between two values, and the fuel delivery itself during the decrease of the heating itself, where I have to regulate the temperature during the run-down itself to switch between the heating circuits… I have already solved it and it works that … only the first option would make the job easier :slight_smile: