Do not execute action when sensor is unavailable

Hi all,

New to HA so climbing the learning curve. After lurking the community I have managed to automate a wakeup light with my Hue lights:

Automation:

- id: wake_up_light
  alias: Wake_up Light
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.time
  condition:
  - condition: template
    value_template: '{{ now().timestamp() + 1800 > state_attr(''sensor.samsung_galaxy_s10_next_alarm'',
      ''Time in Milliseconds'') / 1000 }}

      '
  action:
  - service: script.sunrise
  mode: single

Script:

sunrise:
  mode: single
  sequence:
    - service: light.turn_on
      data:
        entity_id:
          - light.serre_2
          - light.hue_go_beneden
        xy_color: [0.67,0.39]
        brightness: 1
    - delay:
        seconds: 1
    - service: light.turn_on
      data:
        entity_id:
          - light.serre_2
          - light.hue_go_beneden
        xy_color: [0.65,0.41]
        brightness: 85
        transition: 600
    - delay:
        seconds: 600
    - service: light.turn_on
      data:
        entity_id:
          - light.serre_2
          - light.hue_go_beneden
        xy_color: [0.60,0.40]
        brightness: 170
        transition: 600
    - delay:
        seconds: 600
    - service: light.turn_on
      data:
        entity_id:
          - light.serre_2
          - light.hue_go_beneden
        xy_color: [0.48,0.40]
        brightness: 255
        transition: 600

This works, but when I don’t have set an alarm, the sensor is unavailable, which makes the following statement true:

value_template: '{{ now().timestamp() + 1800 > state_attr(''sensor.samsung_galaxy_s10_next_alarm'',
      ''Time in Milliseconds'') / 1000 }}

thus firing the sunrise script. How can I make sure that the sunrise script is not executed when my alarm sensor is unavailable? Any help is appriciated.

- id: wake_up_light
  alias: Wake_up Light
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.time
  condition:
  - condition: template
    value_template: >
      {% set t = (state_attr('sensor.samsung_galaxy_s10_next_alarm', 'Time in Milliseconds')|int) / 1000 %}
      {{ 0 < t < now().timestamp() + 1800 }}
  action:
  - service: script.sunrise
  mode: single

Reading the template from left to right:
Zero is less than t and t is less than the calculated timestamp.

In other words, t is greater than zero but less than the timestamp.

If the sensor or the attribute don’t exist, state_attr() returns None which the int filter converts to 0.

It may be more efficient to use a template trigger rather than triggering every minute. You would simply have to use as_local(states.sensor.time.last_updated).timestamp() rather than now().timestamp() in the trigger template.

- id: wake_up_light
  alias: Wake_up Light
  description: ''
  trigger:
  - platform: template
    value_template: >
      {% set t = (state_attr('sensor.samsung_galaxy_s10_next_alarm', 'Time in Milliseconds')|int) / 1000 %}
      {{ 0 < t < as_local(states.sensor.time.last_updated).timestamp() + 1800 }}
  action:
  - service: script.sunrise
  mode: single

Actually with recent changes to how now() is handled in templates you may even still be able to use that. Not sure if that update has been merged/released yet though.

Your version is shorter but both will be triggered every minute because their triggers contain sensor.time.

If your template is modified to use now() then it will also cause it to be updated every minute in 0.117.

It will be evaluated every minute but wont trigger every minute, unlike the original example.

Technically true but both perform work every minute. The first one evaluates the condition’s template, the second one evaluates the trigger’s template.

Even the first one won’t update its last_triggered time every minute because that only occurs if the action is executed.

I am running Beta 5.2 because I boot from SSD on RPi4.
The solution of @123 works, I suppose. Yesterday I forgot to reload my automations so it was pretty dark this morning. Will test again tonight.
If I understand correctly, the method of both tom_l and 123 both work, and one is not per sé better than the other?
@tom_l, Can you please explain the logic behind your script? Is as_local(states.sensor.time.last_updated).timestamp() the current time (eg 13:34) when I set alarm (eg at 07:00)?

Thank you for your help!

Put this in the developer tools template editor to see:

sensor.time = {{ states('sensor.time') }}
sensor.time last_updated = {{ as_local(states.sensor.time.last_updated) }}
sensor.time last _updated timestamp = {{ as_local(states.sensor.time.last_updated).timestamp() }}

now() = {{ now() }}
now() timestamp = {{ now().timestamp() }}

Ok, I will try that when I get home.