How do I set a default value for template sensor?

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.

3 Likes

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 %}

No. this will be undefined as well. You can test for that and set the state off

It seems to work well except for one thing. I don’t get it how to test if this is undefined or unknown?

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 }}
2 Likes

Hey Fez. Unfortunately that does not satisfy their requirement to default to "off’. It will be unknown until the conditions pass.

That’s why I used to: null and a default of 0 for the float filter.

Ah, I missed that requirement :slight_smile:

1 Like

Try 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) %}
          {% if producing > high %}
            on
          {% elif producing < low %}
            off
          {% else %}
            {{ 'off' if this.state == 'unknown' else this.state }}
          {% endif %}

It’s still going to take 10 minutes to go from unknown to off the first time though. Because of your delay_off.

How about this:

template:
  - trigger:
      - trigger: state
        entity_id: sensor.power_produced
        to: ~
    condition:
      - condition: or
        conditions:
          - condition: numeric state
            entity_id: sensor.power_produced
            above: 1000
          - condition: numeric state
            entity_id: sensor.power_produced
            below: 100
          - condition: state
            entity_id:  sensor.power_produced
            state:
              - unavailable
              - unknown
    binary_sensor:
      - name: Selling Power
        delay_on: 00:5:00
        delay_off: 00:10:00
        state: >
          {{ states('sensor.power_produced') | float(0) > 1000 }}

Condition can also be replaced with a templace condition

    condition:
      - condition: template
        value_template: >
          {% set prod = states('sensor.power_produced') | float('na') %}
          {{ prod == 'na' or prod > 1000 or prod < 100 }}

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 :slight_smile:

1 Like

It’s a power sensor, so 10 seconds max. Nothing compared to the 10 minute delay.

Yeah I thought about mentioning that.

Thanks a lot for your big help!