DRYing some automations; how could I avoid duplicating this for each camera?

Hi y’all,

I’ve got several camera automations that I want to do the following:

  • Take a snapshot of the camera when motion is detected
  • Continue taking snapshots every X seconds while motion continues to be detected
  • Upload the first snapshot to discord as a notification

While I have something that works I currently have to duplicate these automations for every camera which is tedious and error prone. I’m wondering if there’s any great method for reducing this duplication.

I think in my ideal world I’d just be able to add the camera to a list of entities when adding a new one, and have everything work.

This is what I’m currently duplicating for each camera, although I might make it more complex which is what’s prompting this question:

- alias: 'Camera: Snapshot on Motion (Back Porch)'
  id: camera_snapshot_on_motion_back_porch
  trigger:
  - entity_id: binary_sensor.motion_back_porch
    platform: state
    to: 'on'
  condition: []
  action:
  - alias: 'snapshot while back porch camera is detecting motion'
    repeat:
      until:
      - condition: state
        entity_id: binary_sensor.motion_back_porch
        state: 'off'
      sequence:
      - service: input_text.set_value
        entity_id: input_text.back_porch_last_image
        data_template:
          value: '/media/camera-snapshots/back_porch_{{ now().strftime("%Y%m%dT%H%M%S") }}.jpg'
      - service: camera.snapshot
        data_template:
          entity_id: camera.back_porch
          filename: "{{ states('input_text.back_porch_last_image') }}"
      - delay: 10

- alias: 'Discord: Upload on Motion (Back Porch)'
  id: discord_upload_on_motion_back_porch
  trigger:
  - entity_id: binary_sensor.motion_back_porch
    platform: state
    to: 'on'
  condition: []
  action:
  - delay: 5  # ensure camera has had the time to snapshot
  - service: notify.discord
    data_template:
      message: "Motion on Back Porch!"
      target:
      - "111"
      data:
        images:
        - "{{ states('input_text.back_porch_last_image') }}"

My troubles are:

  • I feel like I could move the various actions into a script, and call them with the various parameters, but there’s a number of them to manage
    • camera filename prefix
    • camera entity id
    • motion sensor entity id
  • I’m not sure I can actually parameterize/templatize an entity_id, or at least couldn’t find any examples
  • I’m using an input_text to store the name of the image that should be uploaded to discord because unlike the snapshots, I only want to do that once, not every 10s

Wonder if anyone’s got some great ideas, I’m sort of stuck with the duplication for now!

Here is an example for an automation I use to send notifications and snapshots of various cameras based on which motion sensor triggered it (I don’t have camera’s for all the sensors hence the “dummy” stuff):

  - alias: AS Trespass Warning
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: 
          - input_boolean.as_alarm_test
          - binary_sensor.kitchen_door_sensor
          - binary_sensor.main_bath_window_sensor
          - binary_sensor.sunroom_door_sensor
          - binary_sensor.foyer_door_sensor
          - binary_sensor.comp_rm_motion_template
        to: 'on'
      - platform: state
        entity_id: sensor.sunroom_east_pe_beam
        to: 'OFF'
    condition:
      - condition: state
        entity_id: input_boolean.as_alarm_set
        state: 'on'
    action:
      - service: script.as_lights_save
      - service: script.as_burglar_alarm
        data:
          triggered_by: '{{ trigger.to_state.attributes.friendly_name }}'
      - delay: '00:00:05'
      - service: camera.snapshot
        data: 
          entity_id: >
            {% set mapper = {
              'binary_sensor.kitchen_door_sensor':'camera.kitchen',
              'binary_sensor.main_bath_window_sensor':'camera.dummy',
              'binary_sensor.sunroom_door_sensor':'camera.dining_room',
              'binary_sensor.foyer_door_sensor':'camera.living_room',
              'binary_sensor.comp_rm_motion_template':'camera.computer_room',
              'input_boolean.as_alarm_test':'camera.dummy',
              'sensor.sunroom_east_pe_beam':'camera.dining_room' } %}
            {{ mapper[trigger.entity_id] }}
          filename: >
            {% set mapper = {
              'binary_sensor.kitchen_door_sensor':'/config/www/snapshots/kitchen_alarm_1.jpg',
              'binary_sensor.main_bath_window_sensor':'/config/www/snapshots/dummy_alarm_1.jpg',
              'binary_sensor.sunroom_door_sensor':'/config/www/snapshots/diningroom_alarm_1.jpg',
              'binary_sensor.foyer_door_sensor':'/config/www/snapshots/livingroom_alarm_1.jpg', 'binary_sensor.comp_rm_motion_template':'/config/www/snapshots/computer_room_alarm_1.jpg',
              'input_boolean.as_alarm_test':'/config/www/snapshots/dummy_alarm_1.jpg',
              'sensor.sunroom_east_pe_beam':'/config/www/snapshots/diningroom_pe_alarm_1.jpg' } %}
            {{ mapper[trigger.entity_id] }}
      - delay: '00:00:05'
      - service: notify.pushbullet_notify
        data:
          message: 'Warning - Trespass alarm has been triggered by the {{ trigger.to_state.attributes.friendly_name }}!'
          data:
            file: >
              {% set mapper = {
                'binary_sensor.kitchen_door_sensor':'/config/www/snapshots/kitchen_alarm_1.jpg',
                'binary_sensor.main_bath_window_sensor':'/config/www/snapshots/dummy_alarm_1.jpg',
                'binary_sensor.sunroom_door_sensor':'/config/www/snapshots/diningroom_alarm_1.jpg',
                'binary_sensor.foyer_door_sensor':'/config/www/snapshots/livingroom_alarm_1.jpg', 'binary_sensor.comp_rm_motion_template':'/config/www/snapshots/computer_room_alarm_1.jpg',
                'input_boolean.as_alarm_test':'/config/www/snapshots/dummy_alarm_1.jpg',
                'sensor.sunroom_east_pe_beam':'/config/www/snapshots/diningroom_pe_alarm_1.jpg' } %}
              {{ mapper[trigger.entity_id] }}

it doesn’t handle the repeat function but you might figure that part out based on this example. It shouldn’t be too bad incorporating that feature to the above.

1 Like

FWIW, you can create a variable, containing the maps, to minimize duplication. It also makes it easier to update and maintain the (single) map.

    action:
      - variables:
          mapper: >
            { 'binary_sensor.kitchen_door_sensor': ['kitchen', 'kitchen_alarm_1'],
              'binary_sensor.main_bath_window_sensor': ['dummy', 'dummy_alarm_1'],
              'binary_sensor.sunroom_door_sensor': ['dining_room', 'diningroom_alarm_1'],
              'binary_sensor.foyer_door_sensor': ['living_room', 'livingroom_alarm_1'],
              'binary_sensor.comp_rm_motion_template': ['computer_room', 'computer_room_alarm_1'],
              'input_boolean.as_alarm_test': ['dummy', 'dummy_alarm_1'],
              'sensor.sunroom_east_pe_beam': ['dining_room', 'diningroom_pe_alarm_1'] } 
      - service: script.as_lights_save
      - service: script.as_burglar_alarm
        data:
          triggered_by: '{{ trigger.to_state.attributes.friendly_name }}'
      - delay: '00:00:05'
      - service: camera.snapshot
        data: 
          entity_id: 'camera.{{ mapper[trigger.entity_id][0] }}'
          filename: '/config/www/snapshots/{{ mapper[trigger.entity_id][1] }}.jpg'
      - delay: '00:00:05'
      - service: notify.pushbullet_notify
        data:
          message: 'Warning - Trespass alarm has been triggered by the {{ trigger.to_state.attributes.friendly_name }}!'
          data:
            file: '/config/www/snapshots/{{ mapper[trigger.entity_id][1] }}.jpg'
4 Likes

Thanks for that.

I haven’t switched any of my automations, etc to fully embrace the newer functionalities yet unless I’m writing new ones. And most of those haven’t been able to necessarily benefit from the “variables” functionality so I usually forget about it.

It looks like this one is definitely one I can see updating to use it.

I haven’t updated anything to use the new trigger “id” function yet either.

1 Like