Modify service in automation per triggered entity

Hi there,

trying to learn this system and would appreciate a pointer or where I can find the answer to this. I’ve already looked at all the questions that came up related to this topic.

I used the ring automation example for triggering saving the video when the door bell is rung and tried to figure out how to make it work across all the motion detect entities of all the ring cams and then save the respective mp4 from the URL for the specific entity where motion was detected.

For the ring cam named front, the binary sensor for motion is called binary_sensor.front_motion and basically all the binary sensors for the cams follow this pattern (binary_sensor.[front|backyard|trashcondo]_motion)

This is the trigger:

  alias: Save motion detected videos
  description: ''
  trigger:
  - platform: state
    entity_id:
    - binary_sensor.front_motion
    to: 'on'
  condition: []

which then gets expanded across multiple binary sensors like:

  entity_id:
    - binary_sensor.front_motion
    - binary_sensor.backyard_motion

Below is the basic action definition for single camera front:

service: downloader.download_file
data:
  url: "{{ state_attr('camera.front', 'video_url') }}"
  subdir: >-
    {{state_attr('camera.front', 'friendly_name')}}/{{ now().strftime('%Y.%m')
    }}
  filename: >-
    {{state_attr('camera.front', 'friendly_name')}}-{{
    now().strftime('%Y-%m-%d-at-%H-%M-%S') }}.mp4

If I instead define this automation for a bunch of motion triggers as shown above, how do I extract the correct atrribute from the entity that triggered?

What I want to happen once parsed is the following:

if binary_sensor.front_motion transitions to on, url: "{{ state_attr(‘camera.front’,‘video_url’) }}
if binary_sensor.backyard transitions to on, url: "{{ state_attr(‘camera.backyard’,‘video_url’) }}

How do I derive camera.front or camera.backyard depending on whether binary_sensor.front_motion or binary_sensor.backyard_motion was triggered?

Bonus question: Is there a less verbose way of identifying a specific set of binary_sensors than just enumerating them as above?

Thanks,
Christian

Can you show the triggers as well please?

It may be as simple as this:

service: downloader.download_file
data:
  url: "{{ state_attr(trigger.entity_id, 'video_url') }}"
  subdir: >-
    {{state_attr(trigger.entity_id, 'friendly_name')}}/{{ now().strftime('%Y.%m')
    }}
  filename: >-
    {{state_attr(trigger.entity_id, 'friendly_name')}}-{{
    now().strftime('%Y-%m-%d-at-%H-%M-%S') }}.mp4

but without seeing the triggers it is impossible to say for sure.

Apologies, I screwed up the thread creation and was editing the original when you saw the post. Hope this helps now.

FWIW, the automation I used as a scaffold for this is https://www.home-assistant.io/integrations/ring/ where the trigger is binary_sensor.front_doorbell_ring but the concept is otherwise the same.

Ok, I tried that. Modified the automation to:

alias: Save motion detected videos
description: ''
trigger:
  - platform: state
    entity_id:
      - binary_sensor.front_motion
    to: 'on'
condition: []
action:
  - service: downloader.download_file
    data:
      url: '{{ state_attr(trigger.entity_id, ''video_url'') }}'
      subdir: >-
        {{state_attr(trigger.entity_id, 'friendly_name')}}/{{
        now().strftime('%Y.%m') }}
      filename: >-
        {{state_attr(trigger.entity_id, 'friendly_name')}}-{{
        now().strftime('%Y-%m-%d-at-%H-%M-%S') }}.mp4
mode: single

And when I run the automation, nothing happens, but in traces I see the following:

Executed: December 27, 2022 at 8:00:53 PM
Error: Error rendering data template: UndefinedError: 'dict object' has no attribute 'entity_id'

Any ideas how to approach this?

Thanks,
Christian

Assuming all your binary sensors and cameras are named similarly,

e.g.

binary_sensor.front_motion -> camera.front
binary_sensor.backyard_motion -> camera.backyard
binary_sensor.driveway_motion -> camera.driveway

Then this should work (untested):

action:
  - variables:
      camera_entity: "{{ 'camera.' ~ trigger.to_state.object_id.split('_')[0] }}"
  - service: downloader.download_file
    data:
      url: "{{ state_attr(camera_entity, 'video_url') }}"
      subdir: >-
        {{state_attr(camera_entity, 'friendly_name')}}/{{ now().strftime('%Y.%m')
        }}
      filename: >-
        {{state_attr(camera_entity, 'friendly_name')}}-{{
        now().strftime('%Y-%m-%d-at-%H-%M-%S') }}.mp4

Note this entity name (with two underscores) would not work:

binary_sensor.drive_way_motion 

You would end up with:

camera.drive

instead of

camera.drive_way

If that is a problem, change the action variable to this:

action:
  - variables:
      camera_entity: "{{ 'camera.' ~ trigger.to_state.object_id|replace('_motion','') }}"
1 Like

Thank you. I was Using this

variables:
  camera_entity: '{{ ''camera.'' ~ trigger.to_state.object_id|replace(''_motion'','''') }}'

I see this in traces when I run the automation:

Executed: December 27, 2022 at 8:28:58 PM
Error: UndefinedError: 'dict object' has no attribute 'to_state'

Any ideas? How do I debug this? :slight_smile: Like stepping through this to see how these things change.

Ok, this is what I ended up with that works. Thanks for the help!

  alias: Save motion detected videos
  description: ''
  trigger:
  - platform: state
    entity_id:
    - binary_sensor.backyard_motion
    - binary_sensor.front_motion
    - binary_sensor.frontdoor_motion
    - binary_sensor.trashcondo_motion
    to: 'on'
  condition: []
  action:
  - variables:
      camera_entity: "{{ 'camera.' ~ trigger.to_state.object_id|replace('_motion','') }}"
  - service: downloader.download_file
    data:
      url: "{{ state_attr(camera_entity, 'video_url') }}"
      subdir: >-
        {{state_attr(camera_entity, 'friendly_name')}}/{{ now().strftime('%Y.%m') }}
      filename: >-
        {{state_attr(camera_entity, 'friendly_name')}}-{{ now().strftime('%Y-%m-%d-at-%H-%M-%S') }}.mp4
  mode: single

There’s no trigger data when you run it manually. Either let it trigger naturally or add a temporary time trigger or input boolean to trigger on.

2 Likes

I would not do that. The variable will be undefined.

Best to change the state of one of the binary sensors in Developer Tools → States.

1 Like

Sorry, I know that. My suggestion is rubbish. Mocking the data in the dev tools is the way to go. Thanks Tom.

2 Likes