Create template sensor to combine multiple entities

Here with another question on creating a Template Sensor. This time I am trying to take the status of my ZWave Lock, and my Wyze Sense Contact, and create one sensor to say the overall status of the Front Door. Here is what I have been trying:

front_door_status:
  friendly_name: "Front Door Status"
  value_template: >-
    {% if is_state('binary_sensor.wyzesense_frontdoor', 'on') %}
      Open
    {% elif is_state('lock.frontdoor', 'locked') %}
      Locked
    {% else %}
      Unlocked
    {% endif %}

So if the Wyze Contact is open, the door status shows as as open, but if its closed, then it will pull the state of the Lock to show Locked or Unlocked. How it is right now, it is only pulling the state of the Wyze Contact, and it correctly shows open, but if its closed if always reports Unlocked. Is there something here that I am missing?

{% if is_state('binary_sensor.wyzesense_frontdoor', 'on') and not is_state('lock.frontdoor', 'locked') %} 
Open
{% elif is_state('lock.frontdoor', 'locked') %} 
Locked

Sorry cant test but it would be like this… You should be able to figure it all out from this.

Okay cool, I’ll give this a shot. Seems like you are always here to make my overly complicated setup work the way I want it!

1 Like
front_door_status:
  friendly_name: "Front Door Status"
  value_template: >-
    {% if is_state('binary_sensor.wyzesense_frontdoor', 'off') and not is_state('lock.frontdoor', 'unlocked') %}
      Locked
    {% elif is_state('binary_sensor.wyzesense_frontdoor', 'on') and not is_state('lock.frontdoor', 'locked') %}
      Open
    {% elif is_state('binary_sensor.wyzesense_frontdoor', 'off') and not is_state('lock.frontdoor', 'locked') %}
      Unlocked
    {% else %}
      Unknown
    {% endif %}

Id go with something like this.

Mine is way over complicated as well…

2 Likes

I played with it for a bit and landed on this:

front_door_status:
  friendly_name: "Front Door Status"
  value_template: >-
    {% if is_state('binary_sensor.wyzesense_frontdoor', 'off') and is_state('lock.front_door', 'locked') %} 
      Locked
    {% elif is_state('binary_sensor.wyzesense_frontdoor', 'off') and is_state('lock.front_door', 'unlocked') %}
      Closed, Unlocked
    {% elif is_state('binary_sensor.wyzesense_frontdoor', 'on') and is_state('lock.front_door', 'unlocked') %}
      Open
    {% elif is_state('binary_sensor.wyzesense_frontdoor', 'on') and is_state('lock.front_door', 'locked') %}
      Open, Locked
    {% else %}
      Unknown
    {% endif %}

We actually both did the Unknown at the end unbeknownst to each other, but it works. Mostly I just used AND instead of AND NOT, but it reacts the way I intended, so whatever

1 Like

ya I like to make it overly complicated with ‘and not’

Glad its working for you.

Oh I see, you just flipped the Locked and Unlocked outputs to make the AND NOT work. I didn’t notice that before. But yeah it’s working great, and now I know how that works and can add unnecessary logic to other places. Woohoo!

1 Like

I have been trying to copy the exact code here for my use case, as this seems like the best example I could find after tons of forum searching, but it always comes back as “unknown” and I am not sure what I am missing.

I have tried about 20 different variations of the template, using both the and not and using is_state and state_attr.

I have tried this as a “helper” and directly adding into my sensor.yaml file and every time, it comes back as unknown. I have added extra brackets per some other conversations, I have changed from “Open/Closed” to “on/off” and every time it just comes back as “Unknown” Not sure what I am missing…

Here is the current “state” of my template in sensor.yaml:

  - platform: template
    sensors:
      front_door_status:
        friendly_name: "Front Door Status"
        value_template: >-
          {% if ( (state_attr('lock.front_door', 'Unlocked')) and not (state_attr('binary_sensor.door_front_entry_window_door_is_open', 'Open'))) %}
            Unlocked
          {% elif ( (state_attr('lock.front_door', 'Locked')) and not (state_attr('binary_sensor.door_front_entry_window_door_is_open', 'Closed'))) %}
            Open
          {% elif ( (state_attr('lock.front_door', 'Locked')) and not (state_attr('binary_sensor.door_front_entry_window_door_is_open', 'Open'))) %}
            Unlocked
          {% else %}
            Unknown
          {% endif %}

Its been awhile, but I remember having issues with AND NOT and STATE_ATTR, which I why I landed on a solution to only use AND and IS_STATE operators.

It’s been awhile since I’ve messed with home assistant yaml, but it also looks like you have a fe extra pairs of parentheses you don’t need. Try copying mine in, and seeing if you can get changing reading from it, just replacing entity names at first, and then the readouts. Maybe you can narrow in on the issue

Let’s start with addressing the ridiculous number of brackets…
but also point out that this is the legacy template sensor, which you can still use, but should really be creating new sensors the new way.

template:
  sensor:
    - name: Front Door Status
      unique_id: front-door-status-9ff7b07a-9d76-48aa-99f8-931126715014
      state: >-
        {% if is_state('lock.front_door','unlocked') and not is_state('binary_sensor.door_front_entry_window_door_is_open','open') %}
          Unlocked
        {% elif is_state('lock.front_door','locked') and not is_state('binary_sensor.door_front_entry_window_door_is_open','closed') %}
          Open
        {% elif is_state('lock.front_door','locked') and not is_state('binary_sensor.door_front_entry_window_door_is_open','open') %}
          Unlocked
        {% else %}
          Unknown
        {% endif %}

Additional errors were, trying to use state_attr to access the STATE of the entity, and not the attributes of the entity. The use of Capital letters (Locked, Unlocked, Open, Closed) which is how they are displayed in the UI but internally they are lowercase - (locked, unlocked, open, closed)

Now let’s look again at what you were trying to achieve:

      state: >-
        {% if is_state('lock.front_door','unlocked') %}
          Unlocked
        {% elif is_state('binary_sensor.door_front_entry_window_door_is_open','open') %}
          Open
        {% elif is_state('lock.front_door','locked') and is_state('binary_sensor.door_front_entry_window_door_is_open','closed') %}
          Locked
        {% else %}
          Unknown
        {% endif %}

If the front door is unlocked, it doesn’t matter about the state of the binary sensor - it’s unlocked.
If the binary sensor is open, it doesn’t matter about the state of the front door, it’s open.
If both the front door is locked and the binary sensor is closed, then it’s locked.

Hope that helps.

Those binary sensors, might need to be changed to on for open and off for closed, I’m not sure about that part.

1 Like

Yeah, I went nuts with the brackets after reading a similar post that was suggesting it was needed - good to know about the difference between caps and not.

I do need to know if the binary sensor is open for the door, because the lock can lock when the door is open, and remain that way. (Happens more often than you would think).

What is this “new” way for creating sensors? I would rather move away from something legacy if I can.

Ah ok I understand better now, use and is_state(sensor,‘actual state’) rather than and not and looking for the opposite state, because there is no reason to do that, not is used when the state might be one of many states and you want to catch them all, except one. But this is binary sensor, so it can only have 2 possible states - on or off, open or closed.

The new way to create template sensors is under the template key, instead of

sensor:
  - platform: template

Just to clarify when not might be used:

{% set light_brightness = 50 %}
{% if states('media_player.livingroom') not in ['unknown','unavailable'] %}
  {% if states('media_player.livingroom') in ['playing','buffering'] %}
    {% set light_brightness = 10 %}
  {% endif %}
{% endif %}
{{ light_brightness }}

As you can see we are testing for every state BUT unknown and unavailable (because in this case we don’t want the lights to suddenly jump to 50% if for some reason the media_player sometimes because unknown or unavailable while we are in the middle of a movie.

Next we specifically test for playing or buffering, so the light dims while playing, or buffering (which will briefly be the case when fast forwarding or rewinding). But if we pause, then the lights will return to 50%.

I hope that gives a better idea of how the logic is used.

And for a more advanced example, this could all be done as:

"{{ 10 (if states('media_player.livingroom') not in ['unknown','unavailable'] and states('media_player.livingroom') in ['playing','buffering']) else 50 }}"
1 Like

I think I figured out what is breaking, it was something from prior I could not wrap my head around, but now it is starting to make sense. First, because the door sensor is binary, it prefers on/off to open/closed

But the bigger problem is it seems that for whatever reason, any code I write like…

This works:

{% if is_state('foo','bar') %}
  State

This works:

{% if is_state('foo','bar')  or is_state('foo_sensor','baz') %}
  Other State

This does not work:

{% if is_state('foo','bar')  and is_state('foo_sensor','baz') %}
  And Breaks Statement

This is how I got wrapped around the axle of the crazy brackets - for whatever reason and does not seem to process, whereas or works just fine.

Everything else about the provided code seems to make sense, and I can make parts of the template work in isolation, but and just seems broken for reasons I cannot fathom.

This is the post that caused me to go down the multiple brackets rabbit hole:

GOT IT!

Thanks @mobile.andrew.jones You got me down the right path.

Here is the code:

{% if ( (is_state('lock.front_door','unlocked')) and (is_state('binary_sensor.door_front_entry_window_door_is_open','off')) ) %}
  Unlocked
{% elif ( (is_state('binary_sensor.door_front_entry_window_door_is_open','on')) and (is_state('lock.front_door','locked')) ) %}
  Locked Open
{% elif ( (is_state('binary_sensor.door_front_entry_window_door_is_open','off')) and (is_state('lock.front_door','locked')) ) %}
  Locked
{% elif ( (is_state('binary_sensor.door_front_entry_window_door_is_open','on')) and (is_state('lock.front_door','unlocked')) ) %}
  Open
{% else %}
  Unknown
{% endif %}

The brackets seem to be required for the AND to work, also, under the elif statements, it seems to want the binary sensor to come first. That makes absolutely no sense to me, as it works fine for the first if statement. All I know is that this works now, so I will take it.

1 Like