I’m trying to create a binary sensor which is on or off based on if I sell power or not.
The code below is a sketch of what I would like to do:
- platform: template
binary_sensor:
name: Selling Power
delay_on: 00:5:00
delay_off: 00:10:00
state: >
{% set high = 1000 %}
{% set low = 100 %}
{% set producing = states('sensor.power_produced') %}
{% if producing > high %}
on
{% endif %}
{% if producing < low %}
off
{% endif %}
I realize that if I’m selling 500 W after starting Home Assistant the sensor will not have a value. Can I set the sensor to off when Home Assistant has started to secure a value?
I read Template - Home Assistant but can not see how I can use this here.
Can this be done in a smarter way even? I’m new to template sensors.
Use a triggered template binary sensor. They are restored after a restart. This will require you use the new template format rather than the legacy template sensor platform (which you should be doing for new sensors anyway).
Your example above is a mish-mash of both legacy (“platform”) and new (“state”). That would never work.
configuration.yaml (not sensors.yaml)
template:
- trigger:
- trigger: state
entity_id: sensor.power_produced
to: ~ # trigger on all state changes, ignore attribute changes
binary_sensor:
- name: Selling Power
delay_on: 00:5:00
delay_off: 00:10:00
state: >
{% set high = 1000 %}
{% set low = 100 %}
{% set producing = states('sensor.power_produced')|float(0) %}
{% if producing > high %}
on
{% elif producing < low %}
off
{% else %}
{{ this.state }}
{% endif %}
The default state of (0) for the float filter (which you need to compare numbers, as states are strings) will also turn off your binary sensor if the producing sensor becomes unavailable.
Other issue: you need to define what happens if the sensor is not above high or below low. You did not. I did. I used {{ this.state }} which will keep the current state of the binary sensor.
My code was a sketch so a big thanks for pointing me in another direction! I need to understand the triggered template part better.
I will try this when I get home tonight.
I still do not understand how to handle when I deploy this sensor the first time. It will be undefined if sensor.power_produced is between 100 and 1000.
Maybe something like this:
template:
- trigger:
- trigger: state
entity_id: sensor.power_produced
to: ~ # trigger on all state changes, ignore attribute changes
binary_sensor:
- name: Selling Power
delay_on: 00:5:00
delay_off: 00:10:00
state: >
{% set high = 1000 %}
{% set low = 100 %}
{% set producing = states('sensor.power_produced')|float(0) %}
{% set current = {{ this.state }} %} # Is this the right way to get current state?
{% if producing > high %}
on
{% elif producing < low %}
off
{% elif current == on or current == off %}
{{ this.state }}
{% else %}
off
{% endif %}
this.state always exists, however on first genaration of the binary_sensor it will be unknown I use this as a trick to generate the entity_id I want when the entity is created
The syntax for setting current is incorrect, you are nesting templates here, you need to use {% set current = this.state %}
Also note that you can’t use YAML comments in a jinja template. If you want to add comments, use the jinja syntax for comments, which is {# this is a comment #}
Some further comments on your code above
{% elif current == on or current == off %} this is not working, you need to wrap on and off in quotes, otherwise it will try to match the current state with the variables on and off which you didn’t define.
It might be easier to add a condition, instead of using a template.
My suggestion
template:
- trigger:
- trigger: state
entity_id: sensor.power_produced
not_to: # avoid a state change if the sensor doesn't have a numeric value
- unavailable
- unknown
condition:
# only trigger when a state change is wanted
- condition: or
conditions:
- condition: numeric state
entity_id: sensor.power_produced
above: 1000
- condition: numeric state
entity_id: sensor.power_produced
below: 100
binary_sensor:
- name: Selling Power
delay_on: 00:5:00
delay_off: 00:10:00
state: >
{{ states('sensor.power_produced') | float > 1000 }}
This still requires a state change of the source sensor before the state template is rendered.
If @nikla wants the state template to be rendered as soon as the sensor is created, they can add the template reloaded event as as trigger. However, that won’t help for the delay_off you mentioned in your last post, so it will take at least 10 minutes.
But that is only a one time thing, as soon as it has a valid state, that won’t be an issue anymore as the state is restored.
You could even set it to off manually in devtools > states after it’s created