Thanks seanomat. I tried that out and handles the upper and lower thresholds. Iâm going to modify it to be a sensor by adding the logic to have above, in_range, and below as the values returned vs just on and off. Iâm controlling a fan to help offload my AC and I need to know all 3 states to turn it on and off properly (for instance if it is out of range above, I want the fan on, but If it is out of range below, the fan canât heat so I donât want to turn it on.) With your code it was easy to make it a sensor and it seems to work in the template editor. I need to collect some data and see if it turns on and off properly. Iâm not sure if using two single ended binary sensors or this single sensor is best. Gotta try it. Thanks for your help with this.
I case if your fan you could have stayed with the original template with just the upper limit, as you only need two states: ON and OFF.
I think, there is still an error in the last template.
It should be something like this (not tested!):
{% set threshold_upper = limit_upper - (hysteresis if (current_state=='off' and referenced_state>(limit_upper - hysteresis)) else -hysteresis) %}
{% set threshold_lower = limit_lower + (hysteresis if (current_state=='off' and referenced_state<(limit_lower + hysteresis)) else -hysteresis) %}
I came to the same conclusion to use a single threshold. I modified your code to this and it seems to be working.
{% set entity=states('sensor.outside_temperature')|float(0) %}
{% set hysteresis=states('input_number.inside_temp_hysteresis')|float(0) %}
{% set limit=states('sensor.inside_temperature')|float(0) + (hysteresis if this.state=='on' else -hysteresis) %}
{{ entity < limit }}
Thanks for your help
@seanomat I tested this for a while now and it works, but I wanted to do a modification but could not get the modification working.
Currently, its works as follows, assuming an inside temp of 21°C and hysteresis of 0.5°C
Trigger to off at 21.5°C (rising)
Trigger to on at 20.5°C (subsiding)
My goal is to
Trigger to off (risig temp) at 20.5°C
and
Trigger to on at 21.5°C (subsiding temp)
so exactly the other way around, switching states before it reaches the actual temperature.
However it looks like Iâm missing something. I thought I would just flip the hysteresis algebraic signs, but that does for whatever reason not work. I also tried other variants, but no luck.
Here is the snippet of what I think should work, but doesnât.
{% set limit=states('sensor.home_temperature')|float(0) + (-hysteresis if this.state=='on' else +hysteresis) %}
{{ entity < limit }}
can anyone help?
A threshold is meant to avoid flapping (frequent state changes). So the state change has to occur at the âfurtherâ limit in regard to the direction the underlying sensor is moving and there is an overlap in the middle.
What you want is the direct opposite, so this will not work.
Say the temp is 20, the state is on, the limit is 20.5.
The temp rises to 21, your limit has been reached, so the state is off, but since itâs off the limit now changes to 21.5.
Since the state is defined as entity< limit the state changes to on again. Which changes the limit again, and so on.
It seems to me you are making this more complicated then necessary.
My use case for this FR:
name: "Sun Azimuth SE"
unique_id: sun_azimuth_se
lower: '{{ states("input_number.azimuth_se_lower") }}'
upper: '{{ states("input_number.azimuth_se_upper") }}'
entity_id: sensor.sun_azimuth
- platform: threshold
name: "Sun Azimuth South"
unique_id: sun_azimuth_south
lower: '{{ states("input_number.azimuth_south_lower") }}'
upper: '{{ states("input_number.azimuth_south_upper") }}'
entity_id: sensor.sun_azimuth
- platform: threshold
name: "Sun Azimuth SW"
unique_id: sun_azimuth_sw
lower: '{{ states("input_number.azimuth_sw_lower") }}'
upper: '{{ states("input_number.azimuth_sw_upper") }}'
entity_id: sensor.sun_azimuth
rather than:
- binary_sensor:
- name: "Sun Azimuth SE"
unique_id: sun_azimuth_se
state: '{{ states( "input_number.azimuth_se_lower") < states("sensor.sun_azimuth") < states( "input_number.azimuth_se_upper") }}'
- name: "Sun Azimuth South"
unique_id: sun_azimuth_south
state: '{{ states( "input_number.azimuth_south_lower" ) < states("sensor.sun_azimuth") < states( "input_number.azimuth_south_upper" ) }}'
- name: "Sun Azimuth SW"
unique_id: sun_azimuth_sw
state: '{{ states( "input_number.azimuth_sw_lower" ) < states("sensor.sun_azimuth") < states( "input_number.azimuth_sw_upper" ) }}'
Also would like to see unique_id: added to threshold sensors.
you are absolutely right, my misjudgmentâŚ
I have kind of a workaround by adding + 1°C to the environment temperature, rather than playing wronlgy with the hysteresis +/-.
{% set entity=states('sensor.environment_temperature')|float(0) + 1 %}
That works kind of, it triggers sooner in the morning, however also later in the evening. I could create two sensors, one with and one without that â+1°Câ, and then combine the two with an automation, but ideally I wanted to create only one sensor.
Iâm not that advanced with the binary-sensors, is it possible to trigger the binary sensor from on to off when one condition (environment +1°C) would fire a on-to-off event (in the morning), and to trigger from off to on if the second condition (environment +0°C) fires off-to-on event (in the evening)?
I have illustrated this in the 3rd line on the below graphic
The code for the first line/sensor
state: |
{% set entity=states('sensor.environment_temperature')|float(0) %}
{% set hysteresis=states('input_number.environment_cold_diff')|float(0) %}
{% set limit=states('sensor.home_temperature')|float(0) + (hysteresis if this.state=='on' else -hysteresis) %}
{{ entity < limit }}
The code for the second line/sensor
state: |
{% set entity=states('sensor.environment_temperature')|float(0) + 1 %}
{% set hysteresis=states('input_number.environment_cold_diff')|float(0) %}
{% set limit=states('sensor.home_temperature')|float(0) + (hysteresis if this.state=='on' else -hysteresis) %}
{{ entity < limit }}
You donât need a hysteresis in your case:
{% set temp_home = states('sensor.home_temperature')|float(0) %}
{% set temp_env = states('sensor.environment_temperature')|float(0) %}
{% set diff = 0.5 %}
{{ (temp_env >= temp_home + diff ) or (temp_env <= temp_home - diff ) }}
This sensor will be on above 21.5 and below 20.5 provided your home_temperature is 21.0.
You might have to switch this around for your case. I am a littel confused about what you really want.
I saw your post from yesterday but you have deleted it anyway, I found a way now which works fabulous for my requirement (I definitely need the threshold, as you mentioned in your deleted post).
I have modified your sensor a bit, adding an offset to the outside temp. The threshold is set to 1°C in my case.
- binary_sensor:
- name: Inside vs outside temp
icon: mdi:thermometer-low
availability: |
{{ not false in
[states('sensor.outside_temp),
states('input_number.threshold'),
states('sensor.inside_temp')]|map('is_number')
}}
state: |
{% set hysteresis=states('input_number.threshold')|float(0) %}
{% set entity=states('sensor.outside_temp')|float(0) + states('input_number.offset')|float(0) %}
{% set limit=states('sensor.inside_temp')|float(0) + (hysteresis if this.state=='on' else -hysteresis) %}
{{ entity < limit }}
For the offset-temperature, I have created an automation, it includes also a safety margin (x2.5 instead of x2). In the morning, the offset in my case is at +2°C, which increases the outside temp artificially. In the evening, the offset is at -1°C, which decreasees the outside temp artificially.
Since there is the threshold in the binary sensor, you dont have any flapping.
alias: Offset on/off
description: ''
trigger:
- platform: template
value_template: >-
{{ (states('sensor.outside_temp')|float(0) -
states('sensor.inside_temp')|float(0)) > (2.5 *
states('input_number.threshold')|float(0)) }}
id: off
- platform: template
value_template: >-
{{ (states('sensor.inside_temp')|float(0) -
states('sensor.outside_temp')|float(0)) > (2.5 *
states('input_number.threshold')|float(0)) }}
id: on
condition: []
action:
- choose:
- conditions:
- condition: trigger
id: off
sequence:
- data_template:
value: >-
{{ states('input_number.threshold')|float(0) *
-1 }}
entity_id: input_number.offset
service: input_number.set_value
- conditions:
- condition: trigger
id: on
sequence:
- data_template:
value: >-
{{ states('input_number.threshold')|float(0) *
2 }}
entity_id: input_number.offset
service: input_number.set_value
default: []
mode: single
The only problem was, that if the outside temperature does not go below the inside temp for the defined [offset-threshold], the offset will remain as it was. For this, I have created an additional trigger at 5 AM in the above automation, which will check this, including a bit of safety margin (0.5°C):
- conditions:
- condition: trigger
id: time
- condition: template
value_template: >-
{{ (states('sensor.inside_temp')|float(0) -
states('sensor.outside_temp')|float(0)) <= (2.5 *
states('input_number.threshold')|float(0)) }}
- condition: state
entity_id: binary_sensor.invise_vs_outside_temp
state: 'on'
sequence:
- data_template:
value: >-
{{ (states('sensor.inside_temp')|float(0)
- states('sensor.outside_temp')|float(0) +
states('input_number.threshold')|float(0) +
0.5)|round(1) }}
entity_id: input_number.offset
service: input_number.set_value
This is the result (the offset would change dynamically at 5AM in this scenario, you can see inside vs outside temp was almost the same during the night):
Cheers and thanks for the help and input!
Yeah, turned out my last post created the exact loop that I described a few posts above
Yes, I guess you could solve the problem with an automation. I was hoping to to avoid that.
Ideally the automation can be eliminated, but for now, Iâm good. One could probably pack the rules for the offset into the binary sensor too, however when the outside temp is close to the inside temp on certain days, that will require the â5 AM fixâ
ok, so I think Iâve finally got it. Still have to observer though.
The logic is this:
You have three phases:
- below lower limit
- between lower limit and upper limit
- above upper limit.
Phase 1. and 3. are easy.
Phase two has two cases:
2.1. value crosses the border from outside to inside
2.2. value changes within the interval
In case 2.1. the state should toggle, no matter if it is coming from above (OFF to ON) or below (ON to OFF)
In Case 2.2 the state should stay the same it was after entering the interval, until it leaves the interval again, in which case we would be in Phase 1. or 3. again.
To achieve this we need to know, weather the previous value was inside the interval or not.
So I introduced an additional state attribute âisinâ that stores exactly that.
This is what it looks like:
state: |
{% set current_state = this.state %}
{% set base_entity = states('sensor.environment_temperature')|float(0) %}
{% set limit_upper = states('sensor.home_temperature')|float(0) + states('input_number.home_temperature_warm_diff')|float(0) %}
{% set limit_lower = states('sensor.home_temperature')|float(0) - states('input_number.home_temperature_warm_diff')|float(0) %}
{% if base_entity > limit_upper %}
on
{% elif base_entity < limit_lower %}
off
{% else %}
{% if state_attr(current_state,'isin') == 'on' %}
{{ this.state }}
{% else %}
{{ not this.state }}
{% endif %}
{% endif %}
attributes:
isin: |
{% set base_entity = states('sensor.environment_temperature')|float(0) %}
{% set limit_upper = states('sensor.home_temperature')|float(0) + states('input_number.home_temperature_warm_diff')|float(0) %}
{% set limit_lower = states('sensor.home_temperature')|float(0) - states('input_number.home_temperature_warm_diff')|float(0) %}
{{ limit_lower <= base_entity <= limit_upper }}
[EDIT 20220818] Removed Quotes from âonâ and âoffâ
that looks great too, let me try it out, will observe it for a while and report back
It works, but without hysteresis it might be flapping
the hysteresis in your code above is 'input_number.home_temperature_warm_diff'
if I got it correctly?
There is no hysteresis in the classical sense.
This still needs to be added.
In fact, there need to be two now, for both limits.
So âinput_number.home_temperature_warm_diffâ is an offset only?
I also need a threshold binary sensor and use the helper for this. In my case I need a variable lower limit with a fix threshold. First, I can not enter the variable lower direct into the helper GUI, its red and does not work.
Then I tried following in my templates.yaml file:
sensor:
- name: "Pool IST Temp"
state: >
{{ states('input_number.poolactualtemp') }}
binary_sensor:
- platform: threshold
name: "Pool Need Heat"
entity_id: sensor.pool_ist_temp
lower: {{ states(input_number.poolnominaltemp1) }}
hysteresis: 0.5
Also doesnât work.
And when I set a number for âlowerâ, quick restart is possible but after that with following error messages:
sensor:
- name: "Pool IST Temp"
state: >
{{ states('input_number.poolactualtemp') }}
binary_sensor:
- platform: threshold
name: "Pool Need Heat"
entity_id: sensor.pool_ist_temp
lower: 30
hysteresis: 0.5
Hopefully somebody can help
Thanks
You can see a working example above already in my post Use template for binary_sensor threshold? - #21 by fair_dinkum
The syntax changed slightly, so that since HA 2022.05 or 2022.06 this sensor must now be declared as a template sensor, see below.
My example uses an input helper for the threshold, so I can set a threshold directly in the UI - to be honest, I never changed it so far, but in case I would need to, there is an easy way to do so I have been using this sensor for almost 2 years and it has been working great.
template:
- binary_sensor:
- name: Inside vs outside temp
icon: mdi:thermometer-low
availability: |
{{ not false in
[states('sensor.outside_temp),
states('input_number.threshold'),
states('sensor.inside_temp')]|map('is_number')
}}
state: |
{% set hysteresis=states('input_number.threshold')|float(0) %}
{% set entity=states('sensor.outside_temp')|float(0) + states('input_number.offset')|float(0) %}
{% set limit=states('sensor.inside_temp')|float(0) + (hysteresis if this.state=='on' else -hysteresis) %}
{{ entity < limit }}
Great, thanks a lot. This is a selfmade hysteresis binary sensor, which is necessary because the built-in integration can not work with templates as limits.
I skipped the âavailabilityâ, donât know what is good for.
This is my binary sensor in templates.yaml:
- name: "Pool Wärmebedarf"
unique_id: "poolneedheat"
state: |
{% set hysteresis=0.3 %}
{% set actualtemp=states('sensor.poolactualtemp')|float(0) %}
{% set settemp=states('input_number.poolsettemp')|float(0) + (hysteresis if this.state=='on' else -hysteresis) %}
{{ actualtemp < settemp }}
The only think, unique id is always ignored, it sets a unique id derivated from the name, in my case pool_warmebedarfâŚfunny!