home-assistant / architecture

Repo to discuss Home Assistant architecture
313 stars 100 forks source link

Template support in matching configuration of event triggers #466

Closed OnFreund closed 1 year ago

OnFreund commented 3 years ago

Context

Following up on https://github.com/home-assistant/architecture/issues/436, I believe that having templates in the event data and context would make it significantly more powerful, especially when used with wait_for_trigger. For example, what (I believe) is a very common pattern - send an actionable notification to the app, and wait for the user to activate it - could really benefit from this (so that we only wait for the specific user that we sent the notification to).

Proposal

I propose we add template support to event triggers. The template will have the scope of the executing script/automation, so that the trigger variable will be accessible, as well as any user defined variables.

Consequences

Event triggers will become more powerful and more specific.

balloob commented 3 years ago

How are you going to keep track of the template changing the trigger values? Do you suggest to re-attach the trigger on every state change? What if the state change is also involved in the trigger, what then?

Sending something to a mobile app is great, but that starts with an action, so it belongs in a script or an automation action, so it is not a trigger. wait_for_trigger is the right solution here, not templates in triggers.

OnFreund commented 3 years ago

wait_for_trigger is the right solution here, not templates in triggers.

These are not mutually exclusive - the wait_for_trigger scenario is the one the benefits most from templates. Let's say an automation (with a parallel running mode) ran twice, resulting in sending two actionable notifications to two different users, and both instances are now waiting for a trigger. I believe that the current behavior would cause both instances to get out of the wait on the first user performing an action. Using templates, you'll be able to wait on a specific user in each instance.

How are you going to keep track of the template changing the trigger values? Do you suggest to re-attach the trigger on every state change? What if the state change is also involved in the trigger, what then?

I'm not sure the trigger needs to be re-attached. It depends on what we can get from automation_info, and when exactly the trigger is attached.

balloob commented 3 years ago

Right… so you actually want to propose we support templating for wait_for_trigger and not all triggers everywhere in Home Assistant. That's a lot smaller scope.

How do you propose the system will know if a template is to be evaluated to generate the config for wait_for_trigger instead of being a template passed to a trigger config?

The only thing that I can think of here is that we actually just pass the current variables to the wait_for_trigger, so any trigger that can consume templates can use it.

OnFreund commented 3 years ago

I think you misunderstood me. My proposal is specifically for event triggers, not all types of triggers. More specifically, it's for the use of templates in the event_data and context fields, so that you can filter an event based on runtime information, and not just static configuration.

I believe this is a way smaller scope than what you had in mind.

OnFreund commented 3 years ago

And if I understand https://github.com/home-assistant/core/blob/78a69ef2849baf6e0be4e34fdb9beb9bcdba98e8/homeassistant/helpers/script.py#L605 correctly, then async_attach_trigger is called right before the wait, which means we can evaluate the template at that point, since all the variables should have their values assigned by then.

OnFreund commented 3 years ago

Any thoughts after my clarification?

OnFreund commented 3 years ago

Trying again - any thoughts following my clarification?

balloob commented 3 years ago

How would it work? A config either takes templates and it is processed or it doesn't. When it does, we should also allow passing in variables.

OnFreund commented 3 years ago

In the same way that a value in service -> data can be either a simple value or contain templates, I'm suggesting the values in event_data and context also behave that way. If a value contains templates, they can of course include variables, and will be evaluated on the call to async_attach_trigger, which, if I understand correctly, is called just before the wait.

balloob commented 3 years ago

But templates can also be dynamic, like {{ states.light.kitchen.state == states.input_select.hello.state }}. That wouldn't work as the template won't be re-evaluated on each change.

OnFreund commented 3 years ago

You mean if the values change during the wait? That's correct, but I think we can figure out an implementation that evaluates in handle_event to account for that scenario.

balloob commented 3 years ago

Please give a YAML example how you think this should work.

OnFreund commented 3 years ago

This is the use case I had in mind. The automation can fire when any person arrives home, and then send an actionable notification (e.g. to turn on the light in that person's room) to that person's phone. It then waits for the specific person to take action (it has a parallel run mode so multiple instances can be active, each waiting for a different person).

mode: parallel
trigger:
  - entity_id: person.first
    event: enter
    platform: zone
    zone: zone.home
  - entity_id: person.second
    event: enter
    platform: zone
    zone: zone.home
action:
  - variables:
      notifiers:
        person.first: notify.first
        person.second: notify.second
  - data:
      data:
        push:
          category: ...
      message: Would you like to do something?
      title: Welcome home
    service: {{ notifiers[trigger.entity_id]}}
  - wait_for_trigger:
      - variables:
          users:
            person.first: <first_user_id>
            person.second: <second_user_id>
      - platform: event
        event_type: ios.notification_action_fired
        event_data:
          categoryName: getting_home
        context:
          user_id: {{ users[trigger.entity_id] }}
balloob commented 3 years ago

I don't see a wait_for_trigger. Please expand your example how what you're suggestion could look like.

OnFreund commented 3 years ago

The wait_for_trigger is there (after the notify). Not sure what you mean by expanding.

OnFreund commented 3 years ago

(and specifically, the use of template in wait_for_trigger is in the last line of the YAML)

OnFreund commented 3 years ago

@balloob did you get a chance to look at the example again?

balloob commented 3 years ago

I think the idea of using templates for matching is fine since it won't impact the "subscription". I think that we don't need a new "variables" block for wait_for_trigger, we can just expose existing variables.

balloob commented 3 years ago

btw didn't see the wait for trigger before because I didn't realize I could scroll 🤦

OnFreund commented 3 years ago

Yeah, I agree we don't need a new variables block - I just thought the existing implementation allows those blocks to be anywhere in an automation.

Anyway, the TODOs as I see them now:

  1. Pass some mechanism to grab the execution context with all the variables into the trigger
  2. Move the schema creation from async_attach_trigger to handle_event.
  3. Evaluate all the values before before creating the schema.

If we assume that the template values won't change during the wait, it simplifies a lot, and we can just create an evaluates schema in async_attach_trigger. Am I missing anything? I also think I'll need some guidance with 1 & 3.

balloob commented 3 years ago

We should move away from the schema. Since it's now 1 use only (because of re-evaluating templates). You could optimize it by checking if there are any templates, if not, you can stick to the schema.

OnFreund commented 3 years ago

What's a good place to look to get an understanding of how to do this?

OnFreund commented 3 years ago

i.e. an example of something similar and/or docs

emontnemery commented 3 years ago

@OnFreund I'll start working on this soon, it's sort of related to home-assistant/core#45614, unless you have something already in the works?

OnFreund commented 3 years ago

@emontnemery frankly I don't know where to start and was about to post on the forum asking for advice, so feel free to take a stab at it, and let me know how I can help.

frenck commented 1 year ago

This architecture issue is old, stale, and possibly obsolete. Things changed a lot over the years. Additionally, we have been moving to discussions for these architectural discussions.

For that reason, I'm going to close this issue.

../Frenck