Shortest variant to repeatedly send a message based on a status

I have automations that notify me when the cellar door is open for a certain time (1 hour, 2 hours, 4 hours, …) with an indication of the number of hours already open.

alias: Message door 1 hour open
trigger:
  - type: opened
    platform: device
    device_id: xxx
    entity_id: xxx
    domain: binary_sensor
    for:
      hours: 1
      minutes: 0
      seconds: 0
condition: []
action:
  - service: notify.telegram_ha
    data:
      message: door is one hour opend
mode: single

So far I have an individual automation for each state, but surely there must be a more elegant way? Can I use an automation to transfer the status (x hours) as a variable in the message text?

i’m sure there are lots of ways to do this. and someone will come with a more efficient way. however, here’s one way for you that combines into one automation.

description: ""
mode: single
trigger:
  - platform: state
    entity_id:
      - cover.garage_door
    for:
      hours: 1
    to: open
  - platform: state
    entity_id:
      - cover.garage_door
    for:
      hours: 2
    to: open
  - platform: state
    entity_id:
      - cover.garage_door
    for:
      hours: 4
    to: open
condition: []
action:
  - service: notify.send_message
    metadata: {}
    data:
      message: door is opened for {{ elapsed_time(trigger.to_state.last_changed) }}

btw… this converts you from using device id to entity_id… which you should generally do… here’s more info:

1 Like

This core integration was built with that purpose in mind. I’m not sure wether it re-evaluates the message each time it repeats though, but I’d expect it would:

If you use a group or tag, you can use a template to list and/or count the active group members.

1 Like
...
action:
  - service: notify.telegram_ha
    data:
      message: door is {{ time_since(now() - trigger.for) }}  opened
mode: single
3 Likes

You beat me to it!

That works. Although the middle part is always in English with this method (“Die Kellertür ist 1 hour offen”). But that doesn’t really matter.

You could use {{ ((trigger.for).total_seconds() // 3600) | int(0) }} instead. That will just return the hours as an integer.

2 Likes