How to collect information in condition, then use in action

I’m trying to implement an automation where in the condition I do a somewhat elaborate operation to collect information from the trigger state, use that compiled information as part of the condition, and then use the same data in the action.

First of all, how would I go about passing a variable from the condition phase down to the action? Apparently, if I simply assign it to a local variable, it’s not available later (I assume not the same execution scope). I tried things like assigning it to an attribute of this, but that doesn’t work either.

My other issue is with the data collection itself. What I’m trying to do is iterate over an array of objects among the attributes of the from and to state, and collect all that was changed in a certain way.

Most conveniently I would go about this using the stream/lambda function paradigm, but as far as I could tell, the latter is not available in the template language (which would be required to form the non-trivial condition for the change detection).

The next approach would be of course to declare an empty array, iterate over the observed collection, and put any found changes into that array. The issue is that apparently, an object declared outside of the loop can’t be accessed from within for some weird reason. In the dev tools template editor I get SecurityError: unsafe for the line in the loop’s body; and in an automation condition, I get Encountered unknown tag 'changes'. Jinja was looking for the following tags: 'elif' or 'else' or 'endif'.

{% 
set from_state = [
  { "name": "a", "value": "xx" },
  { "name": "b", "value": "y" },
  { "name": "c", "value": "z" },
]
-%}
{%
set to_state = [
  { "name": "a", "value": "x" },
  { "name": "b", "value": "yy" },
  { "name": "c", "value": "z" },
]
-%}
{% set changes = [] -%}
{% for item in to_state -%} 
{%   if item.value != from_state[loop.index - 1].value -%}
{%     changes.append(item) -%}
{%   endif -%}
{% endfor -%} 

something like this?

{% 
set from_state = [
  { "name": "a", "value": "xx" },
  { "name": "b", "value": "y" },
  { "name": "c", "value": "z" },
]
-%}
{%
set to_state = [
  { "name": "a", "value": "x" },
  { "name": "b", "value": "yy" },
  { "name": "c", "value": "z" },
]
-%}
{% set ns = namespace(changes = []) -%}
{% for item in to_state -%} 
{%   if item.value != from_state[loop.index - 1].value -%}
{%  set ns.changes = ns.changes + [item] %}
{%   endif -%}
{% endfor -%} 
{{ ns.changes }}

Yeah, thanks, this does indeed work. I wonder what prevents me from calling a method on a variable from outside from inside the loop, yet I can use set.

And what about my first issue?

That’s not possible. To my knowledge, you can’t define variables within an automation’s condition.

You may want to consider using trigger_variables (variables that can be defined within each trigger in the automation’s triggersection).

Thanks, yes, apparently trigger_variables is the way to go, splendid!

The only remaining thing to wonder about is that why do I need to put every statement into a separate set of {% ... %} brackets? This hardly makes any sense to me…

Jinja2 is a templating language. Jinja2 statements can be placed within text that belongs to something else (HTML, python, YAML, text, etc). The {% %} and {{ }} demarcate the Jinja2 statements (for the Jinja2 processor).

Yeah that’s clear, but when I have two subsequent statements, then there’s literally zero reason to demaracate a transition into literal text at the end of the first one, and then transition back into code before the second.

Trust me, I’ve used quite a few different templating languages, and Jinja is the first one I encounter that needs me to put every single statement within a continuous sequence of program logic between their own separate pair of code brackets.

I guess the designers of Jinja2 thought there was a good reason to demarcate each statement. You can direct your questions/concerns about their decisions in the Jinja2 GitHub repository.

Yeah, you’re probably right. I have answers to my issues I’ve had, this was just a small aside which struck me as I was trying to implement my logic.

Let me know if you need my help to implement trigger_variables

Thank you, I managed to figure it out, and it works nicely.

1 Like