Get real/current value into Sensor Template at startup (not cached value) for Garage Door/Cover template

Summary: I’m trying to populate the value of a sensor template at HA startup to reflect a state based on two real sensors from a Shelly Uni device (built-in Shelly integration).

HA: 2022.5.4

Background:
I’ve created a garage door template which otherwise works well, similar to what’s referenced here: Garage door cover with two reed sensors - template question - #3 by kirijanker

Mine is created with a Shelly Uni device, which provides the switch entity and two sensor entities, one for closed state and one for open state (using magnetic reed switches).

The sensor template for the cover template provides four states based on the two device’s real sensors: open, closed, opening or closing. It works very well while HA is running, as the template sensor is updated any time the state of the real sensor changes.

Issue #1 - Trigger only on device/external sensor state changes:

When HA starts, the value of the template sensor may be incorrect if the garage door’s state has changed while HA was down. This is how other examples elsewhere are written and I haven’t noticed any with a solution.

The triggers within the template that allow setting its state during normal operation aren’t activated at startup. So the conditional expressions for the template which set the state values are never evaluated and the state is loaded from a HA cache which reflects the value before restart/shutdown

Issue #2 - Adding a trigger for Home Assistant Start:

If a homeassistant start trigger is added, the template sensor will be marked “unavailable” after startup/restart. It becomes available again with the correct state after the real sensors values are changed. This is because an error is caused evaluating to_state condition which is invalid as HA first starts up.

Required
The sensor template requires the ability to show 4 states during normal operation, Open, Closed, Opening, Closing (4 conditions). When HA starts, the real initial state of the door needs to be populated, which is either Open or Closed (2 conditions).

Code from configuration.yaml (shown with the HA start event trigger and sensor triggers):

# Garage Door Template from Shelly Uni Switch and Sensors
cover:
  - platform: template
    covers:
      garage_door:
        device_class: garage
        friendly_name: "Garage Door"
        unique_id: "shellyGarageDoor"
        value_template: '{{ states("sensor.garagedoor_status") }}'
        open_cover:
          - service: switch.turn_on
            target:
              entity_id: switch.garage_door_button
        close_cover:
          - service: switch.turn_on
            target:
              entity_id: switch.garage_door_button
        stop_cover:
          - service: switch.turn_on
            target:
              entity_id: switch.garage_door_button
        icon_template: >-
          {% if is_state('sensor.garagedoor_status', 'closed') %}
            mdi:garage
          {% elif is_state('sensor.garagedoor_status', 'closing') %}
            mdi:garage-alert
          {% elif is_state('sensor.garagedoor_status', 'opening') %}
            mdi:garage-alert
          {% else %}
            mdi:garage-open
          {% endif %}
template:
  - trigger:
      - platform: state
        entity_id:
          - binary_sensor.garage_door_open
          - binary_sensor.garage_door_closed
      - platform: homeassistant
        event: start
    sensor:
      - name: "GarageDoor_Status"
        unique_id: "shellyGarageDoor_Status"
        state: >
          {% if is_state('binary_sensor.garage_door_closed', 'on') %}
            closed
          {% elif (trigger.to_state.state == 'off' and trigger.from_state.state == 'on' and trigger.entity_id == 'binary_sensor.garage_door_open') %}
            closing
          {% elif (trigger.to_state.state == 'off' and trigger.from_state.state == 'on' and trigger.entity_id == 'binary_sensor.garage_door_closed') %}
            opening
          {% else %}
            open
          {% endif %}

That start trigger is already there (my #2 in the OP) :slight_smile:

What’s happening at startup with that trigger, is that the conditions that check to_state cause an error and stop evaluating, so the else condition is never set.

Received invalid cover is_on state: unavailable for entity cover.garage_door. Expected: open, opening, closed, closing, true, false

11:02:09 AM – (ERROR) Template

Error rendering state template for sensor.garagedoor_status: UndefinedError: ‘dict object’ has no attribute ‘to_state’

11:02:09 AM – (ERROR) Template

Template variable error: ‘dict object’ has no attribute ‘to_state’ when rendering ‘{% if (trigger.to_state.state == ‘on’ and trigger.entity_id == ‘binary_sensor.garage_door_closed’) %} closed {% elif (trigger.to_state.state == ‘off’ and trigger.from_state.state == ‘on’ and trigger.entity_id == ‘binary_sensor.garage_door_open’) %} closing {% elif (trigger.to_state.state == ‘off’ and trigger.from_state.state == ‘on’ and trigger.entity_id == ‘binary_sensor.garage_door_closed’) %} opening {% else %} open {% endif %}’

11:02:09 AM – (ERROR) helpers/template.py

The code as above in the OP, including the start trigger won’t set any value at startup due to the above errors.

But if the to_state elif conditions are removed, no error is present and the remaining conditions can be evaluated and values set.

template:
  - trigger:
      - platform: state
        entity_id:
          - binary_sensor.garage_door_open
          - binary_sensor.garage_door_closed
      - platform: homeassistant
        event: start
    sensor:
      - name: "GarageDoor_Status"
        unique_id: "shellyGarageDoor_Status"
        state: >
          {% if is_state('binary_sensor.garage_door_closed', 'on') %}
            closed
          {% else %}
            open
          {% endif %}

If I can prevent the to_state conditions from causing an error this can be solved.

The to_state conditions only need to be evaluated when the real sensors trigger. At startup the only condition that needs to be evaluated is for the close sensor. Is there an easy way to split out the HA start trigger from the sensor triggers so they can each have their own set of conditions?

Yes, which is what I’m trying to fix. It happens that I discovered this after first submitting this topic, which is why the title is more generic.

How can I maintain the ability to test for to/from triggered by the sensors, and only test sensor state triggered by startup?

Sorry, I just realized I pasted the wrong/old code block above - it was not the example that I was testing and intended to show an example of. Updated to show it functionally matches your example with different syntax & verified it works as a test - but isn’t a complete solution because it lacks the opening and closing states.

Below is what should have been the condition, as in the OP with the to/from conditions removed.

          {% if is_state('binary_sensor.garage_door_closed', 'on') %}
            closed
          {% else %}
            open
          {% endif %}

So knowing that works for just open/close, I still need to have the closing/opening states represented (but not triggered at startup)

Just reading up on how to test for triggers to isolate the if statements…

For now, my temporary solution is to trigger the state conditions after HA starts using an automation. This delays the triggering enough that no errors are caused by the to_state conditionals.

To do this, I removed the HA start trigger and added a switch entity as a trigger. In my case this is the entity of a second unused dry contact on the Shelly Uni. I’ve set it up on the Uni to automatically reset to OFF 1 second after it’s turned ON, but it would work equally well without that feature if used with a TOGGLE call. A template switch would also work instead of using a real one if needed.

So the updated sensor template is simply:

template:
  - trigger:
      - platform: state
        entity_id:
          - binary_sensor.garage_door_open
          - binary_sensor.garage_door_closed
          - switch.garage_door_refresh
    sensor:
      - name: "GarageDoor_Status"
        unique_id: "shellyGarageDoor_Status"
        state: >
          {% if is_state('binary_sensor.garage_door_closed', 'on') %}
            closed
          {% elif (trigger.to_state.state == 'off' and trigger.from_state.state == 'on' and trigger.entity_id == 'binary_sensor.garage_door_open') %}
            closing
          {% elif (trigger.to_state.state == 'off' and trigger.from_state.state == 'on' and trigger.entity_id == 'binary_sensor.garage_door_closed') %}
            opening
          {% else %}
            open
          {% endif %}

And then the automation done in the UI

alias: Garage Door Refresh
trigger:
  - platform: homeassistant
    event: start
action:
  - service: switch.turn_on
    data: {}
    target:
      entity_id: switch.garage_door_refresh
mode: single


Testing for the type of trigger in the template sensor allows applying conditions for different triggers. I’ve accomplished this with nested IFs, testing on template.platform to prevent errors when HA starts.

  1. Test on either state trigger or HA start (only need report 2 states, Open or Closed)
  2. Test only on state trigger (need to report from 4 states, Open, Closed, Opening, Closing)

This prevents error conditions when testing to_state too early in the startup process which renders the template sensor value invalid.

Here is the completed garage door template and sensor template with Open, Closed, Opening and Closing states.

# Garage Door Template from Shelly Uni Switch and Sensors
cover:
  - platform: template
    covers:
      garage_door:
        device_class: garage
        friendly_name: "Garage Door"
        unique_id: "shellyGarageDoor8787"
        value_template: '{{ states("sensor.garage_door_status") }}'
        open_cover:
          - service: switch.turn_on
            target:
              entity_id: switch.garage_door_button
        close_cover:
          - service: switch.turn_on
            target:
              entity_id: switch.garage_door_button
        stop_cover:
          - service: switch.turn_on
            target:
              entity_id: switch.garage_door_button
        icon_template: >-
          {% if is_state('sensor.garage_door_status', 'closed') %}
            mdi:garage
          {% elif is_state('sensor.garage_door_status', 'closing') %}
            mdi:garage-alert
          {% elif is_state('sensor.garage_door_status', 'opening') %}
            mdi:garage-alert
          {% else %}
            mdi:garage-open
          {% endif %}
template:
  - trigger:
      - platform: state
        entity_id:
          - binary_sensor.garage_door_open
          - binary_sensor.garage_door_closed
      - platform: homeassistant
        event: start
    sensor:
      - name: "Garage Door Status"
        unique_id: "shellyGarageDoor_Status8787"
        state: >
          {% if is_state('binary_sensor.garage_door_closed', 'on') %}
            closed
          {% elif trigger.platform != 'homeassistant' %}
            {% if (trigger.to_state.state == 'off' and trigger.from_state.state == 'on' and trigger.entity_id == 'binary_sensor.garage_door_open') %}
              closing
            {% elif (trigger.to_state.state == 'off' and trigger.from_state.state == 'on' and trigger.entity_id == 'binary_sensor.garage_door_closed') %}
              opening
            {% else %}
              open
            {% endif %}
          {% else %}
            open
          {% endif %}
1 Like

Hi,

I have the same scenario and have tried to use the above in a cover.yaml file including it in config.yaml but am getting errors, Does the above code go in one place or multiple yaml files?

I get the below error when trying to restart HA to apply new covers.yaml etc.

Failed to restart Home Assistant

The system cannot restart because the configuration is not valid: Invalid config for [cover]: required key not provided @ data[‘platform’]. Got None. (See /config/configuration.yaml, line 22).

I have the code only in config. It looks like you must have some malformed line in you config.

I’ve since added a rotary sensor, so my current code has more conditions. I’ve pasted it in another thread recently: Template cover for garage door - #41 by HVR88

Hi, I have a garage door controlled by a button open/stop/close (in loop).

I have installed two sensore (full_closed and full_opened) that already work with your garage door status.

What should i change to implement your template?