Automation to publish and update notification on secondary MQTT trigger (frigate)

Frigate provides a review topic to subscribe to for the purpose of sending notifications of an event that is being catalogued/processed by frigate.

The review status go from New, Update to End. It’s fairly straight forward to update the notifications via the Home assistant companion by simply retaining the tag as the review id {{ trigger.payload_json['after']['id'] }}.

I’ve been trying to extend this to pick up additional information about the series of events from another MQTT topic tracked_object_update. This is where I might find the AI descriptions for the series of events so far if they exist yet or at all.

I’ve assumed that by running my automation in parallel, that each instance is in its own scope. Also, as I understand it there is no way to globally update global variables from nested code.

The problems i’m having are:

  1. if the AI description arrived before UPDATE or END, then it gets overridden. I could solve this by ignoring UPDATE,END events, but these do provide updated snapshots etc. Would be nice to retain.
  2. if there are concurrent reviews, then I don’t always get the right description. This questions my understanding and implementation of sequencing and script mode, I have no idea how this happens and haven’t got a sure way to recreate this scenario.

What can I do to solve these issues?

  - alias: "Security: Object Detected"
    id: "HD2f4Q5RbLgXv"
    mode: parallel
    triggers:
      - trigger: mqtt
        alias: "topic published to /reviews"
        topic: "frigate/reviews"
        id: frigate-event
        payload: "alert"
        value_template: "{{ value_json['after']['severity'] }}"
    variables:
      type: "{{ trigger.payload_json['type'] }}"
      review_id: "{{ trigger.payload_json['after']['id'] }}"
      camera: "{{ trigger.payload_json['after']['camera'] }}"
      before_zones: "{{ trigger.payload_json['before']['data']['zones'] }}"
      after_zones: "{{ trigger.payload_json['after']['data']['zones'] }}"
      before_objects: "{{ trigger.payload_json['before']['data']['objects'] }}"
      after_objects: "{{ trigger.payload_json['after']['data']['objects'] }}"
      sub_labels: "{{ trigger.payload_json['after']['data']['sub_labels'] }}"
      detections: "{{ trigger.payload_json['after']['data']['detections'] }}"
      thumbnail: "https://ha.mydomain.com/api/frigate/notifications/{{detections[0]}}/thumbnail.jpg"
      snapshot: "https://ha.mydomain.com/api/frigate/notifications/{{detections[0]}}/snapshot.jpg"
      clip: "https://ha.mydomain.com/api/frigate/notifications/{{detections[0]}}/clip.mp4"
      # msg_description: "{{ type }}: {{ after_objects|join(', ')|title }} detected"
      # msg_description: "{{ type }}: rid:{{ review_id }} dids: {{ detections | join(', ') }}"
      msg_title: "{{ camera|title }} camera detected {{ after_objects|join(', ')|title }}"
    # condition: # This condition just delays getting any early notifications.
    #   - alias: Object lifecycle has ended
    #     condition: template
    #     value_template: '{{ type == "end" }}' # or before_zones | length < after_zones | length }}'
    # condition: # This would prevent the AI description from being overridden in subsequent events. 
    #   - alias: Object lifecycle has started
    #     condition: template
    #     value_template: '{{ type == "new" }}' # or before_zones | length < after_zones | length }}'
    actions:
      - parallel:
          - sequence:
              - condition: template # This might reduce duplication, as we expect the automation to fire for 'new', 'end' and each 'update'
                alias: Object lifecycle has ended
                value_template: '{{ type == "new" }}'
              # - condition: template # This might reduce duplication, but may miss updates to the description.
              #   value_template: "{{ msg_description != None }}"
              - wait_for_trigger:
                  - trigger: mqtt
                    topic: frigate/tracked_object_update
                    value_template: '{{ value_json["type"] == "description" and value_json["id"] in detections }}'
                    # variables: # does it matter where msg_description is defined?
                    #   msg_description: "{{ type }}: {{ wait.trigger.payload_json['description'] }}"
                timeout:
                  seconds: "120"
              - condition: template
                alias: Object updated
                value_template: "{{ wait.completed }}"
              - variables:
                  # msg_description: "{{ type }} update: rid:{{ review_id }} oid:{{ wait.trigger.payload_json['id'] }} dids: {{ detections | join(', ') }}"
                  msg_description: "{{ wait.trigger.payload_json['description'] }}"
              - action: notify.residents
                data:
                  title: "{{ type }}: {{ msg_title }}"
                  message: "{{ msg_description }}"
                  data:
                    group: "Security"
                    channel: "MEDIUM"
                    image: "{{ thumbnail }}"
                    tag: "{{ review_id }}"
                    entity_id: camera.{{ camera }}
                    color: "#FFFF00" # YELLOW
                    priority: "high"
                    ttl: 0
                    persistent: "false"
                    sticky: "false"
                    actions:
                      - action: "URI"
                        title: "Thumbnail"
                        uri: "{{ thumbnail }}"
                      - action: "URI"
                        title: "Image"
                        uri: "{{ snapshot }}"
                      - action: "URI"
                        title: "Video"
                        uri: "{{ clip }}"
          - sequence:
              # - condition: template
              #   value_template: "{{ msg_description != None }}"
              - action: notify.residents
                data:
                  title: "{{ type }}: {{ msg_title }}"
                  message: "{{ msg_description }}"
                  data:
                    group: "Security"
                    channel: "MEDIUM"
                    image: "{{ thumbnail }}"
                    tag: "{{ review_id }}"
                    entity_id: camera.{{ camera }}
                    color: "#FFFF00" # YELLOW
                    priority: "high"
                    ttl: 0
                    persistent: "false"
                    sticky: "false"
                    actions:
                      - action: "URI"
                        title: "Thumbnail"
                        uri: "{{ thumbnail }}"
                      - action: "URI"
                        title: "Image"
                        uri: "{{ snapshot }}"
                      - action: "URI"
                        title: "Video"
                        uri: "{{ clip }}"

Thanks

To update notification use tag in the notification action

data:
  message: your message
  data:
    tag: tag name
action: notify.mobile_app

Thanks for the reply. I do already make reference to this, and I have the equivalent already in my code.

I don’t think this is related to my issue. Is there something I’ve misunderstood in your reply?

To clarify what this automation is trying to achieve:

on a review event send a notification with as much detail as possible.
for each review event, see if there is an AI description for it, and include that in the notification.

I’m using a wait_on_trigger to block a parallel sequence until either the description is seen or timeout this is per review event, for all reviews.

Sorry. I was editing.

You can store processed message along with trigger id. Just add trigger id to beginning of text

When processing ai check stored message and if trigger ID match use previous data with new

Since it is image data maybe all must be stored and all processed but not sure how take multiple images and ask, look at these three images from an event and describe it, for example

Ultimately you must store, add method to tie events by file name or data tag in text, then send for ai process.

Thanks and sorry if was too quick to reply earlier!

are you saying that in the automation, I could store the AI description somewhere for a subsequent automation to consume? that would be a brilliant if I could do that, but I can’t find anything about that in the docs.

do you have a link?

You can store it like sensor data or as text in file
I will look for example

If this is from image, may be better to store image and process that. I think this wold need test to see which has better result

I found input_text helpers.

and then I found this thread: Trigger based template sensor to store global variables

i’m currently implementing this solution to create a variable for only the AI description. and have one notification action that reads that variable, before removing the variable.

Not quite going so well.

Using @TheFes solution was working until I changed the variable keys to be dynamic to handle concurrency. it then failed validation.

you can see my description of that issue on that thread here: Trigger based template sensor to store global variables - #43 by umbramalison

I didn’t look at input_text helpers for a similar reason that you can not create them in the automation. If I created a single helper I would have the same concurrency issues. Even if I had a schema to store multiple descriptions, I doubt it would be a good idea to have multiple automations read and writing to that helper at the same time.

Post the version of your automation that uses TheFes’s solution but fails validation (please remove any YAML comments in order to make it shorter).

Thanks for offering to take a look.
In TheFes’s global variable topic, it was identified that the errors didn’t match my assertion!
I’ve fixed the real issue in the code below, it is all working.

My issue all along was that I wrapped the variable in double curlies, inside an expression.

  - alias: "Security: Object Detected"
    id: "HD2f4Q5RbLgXv"
    mode: parallel
    triggers:
      - trigger: mqtt
        alias: "topic published to /reviews"
        topic: "frigate/reviews"
        id: frigate-event
        payload: "alert"
        value_template: "{{ value_json['after']['severity'] }}"
    variables:
      type: "{{ trigger.payload_json['type'] }}"
      review_id: "{{ trigger.payload_json['after']['id'] }}"
      camera: "{{ trigger.payload_json['after']['camera'] }}"
      before_zones: "{{ trigger.payload_json['before']['data']['zones'] }}"
      after_zones: "{{ trigger.payload_json['after']['data']['zones'] }}"
      before_objects: "{{ trigger.payload_json['before']['data']['objects'] }}"
      after_objects: "{{ trigger.payload_json['after']['data']['objects'] }}"
      sub_labels: "{{ trigger.payload_json['after']['data']['sub_labels'] }}"
      detections: "{{ trigger.payload_json['after']['data']['detections'] }}"
      thumbnail: "https://ha.mydomain.com/api/frigate/notifications/{{detections[0]}}/thumbnail.jpg"
      snapshot: "https://ha.mydomain.com/api/frigate/notifications/{{detections[0]}}/snapshot.jpg"
      clip: "https://ha.mydomain.com/api/frigate/notifications/{{detections[0]}}/clip.mp4"
      msg_description: "{{ after_objects|join(', ')|title }} detected"
      msg_title: "{{ camera|title }} camera event"
    actions:
      - parallel:
          - sequence:
              - condition: template
                alias: Object lifecycle has ended
                value_template: '{{ type == "new" }}'
              - wait_for_trigger:
                  - trigger: mqtt
                    topic: frigate/tracked_object_update
                    value_template: '{{ value_json["type"] == "description" and value_json["id"] in detections }}'
                timeout:
                  seconds: "120"
              - condition: template
                alias: Object updated
                value_template: "{{ wait.completed }}"
              - event: set_variable
                event_data:
                  key: "{{ review_id }}"
                  value: "{{ wait.trigger.payload_json['description'] }}"
                  set_timestamp: false
          - sequence:
              - action: notify.residents
                data:
                  title: "{{ msg_title }}"
                  message: "{{ msg_description }}"
                  data:
                    subtitle: "{{ state_attr('sensor.variables', 'variables')[review_id] }}"
                    subject: "{{ state_attr('sensor.variables', 'variables')[review_id] }}"
                    group: "Security"
                    channel: "MEDIUM"
                    image: "{{ thumbnail }}"
                    tag: "{{ review_id }}"
                    entity_id: camera.{{ camera }}
                    color: "#FFFF00" # YELLOW
                    ledColor: "#FFFF00" # YELLOW
                    importance: high
                    priority: "high"
                    ttl: 0
                    persistent: "false"
                    sticky: "false"
                    actions:
                      - action: "URI"
                        title: "Thumbnail"
                        uri: "{{ thumbnail }}"
                      - action: "URI"
                        title: "Image"
                        uri: "{{ snapshot }}"
                      - action: "URI"
                        title: "Video"
                        uri: "{{ clip }}"
              - condition: template
                alias: Object lifecycle has ended
                value_template: '{{ type == "end" }}'
              - event: remove_variable
                event_data:
                  key: "{{ review_id }}"