Template to run script

It works fine, but only if there only one task in todo-list?
What’s wrong? Is there a better way?

triggers:
  - trigger: time_pattern
    seconds: /30
conditions: []
actions:
  - action: todo.get_items
    continue_on_error: true
    target:
      entity_id: todo.auto
    data:
      status:
        - needs_action
    response_variable: items
    enabled: true
  - continue_on_error: true
    service_template: |
      {% if items['todo.auto']['items'] | count > 0 %}
        {% for item in items['todo.auto']['items'] %}
          {% if (now() >= item.due | as_datetime | as_local)  %}
              script.{{item.summary}}              
          {% endif %}
        {% endfor %} 
      {% else %}
        script.nop
      {% endif %}
mode: single

I believe you need to use the repeat for each and script.turn_on

As Hellis stated you need to use a repeat. Whether you use script.turn_on or call the scripts directly depends on whether you need them to wait between scripts.

triggers:
  - trigger: time_pattern
    seconds: /30
conditions: []
actions:
  - action: todo.get_items
    continue_on_error: true
    target:
      entity_id: todo.auto
    data:
      status:
        - needs_action
    response_variable: items
  - repeat:
      for_each: |
        {% set sum_list = items['todo.auto']['items'] 
        | map(attribute='summary') | list | default( [], true) %}
        {{ 'nop' if sum_list == [] else sum_list }} 
      sequence:
        - action: script.{{ repeat.item }}
          continue_on_error: true
mode: single
1 Like

vielen Dank!

missing: {% if (now() >= item.due | as_datetime | as_local) %}

You can add that as a template condition in the for each sequence.

i have problems with syntax for template condition, can you show me…

  - repeat:
      for_each: |
        {% set sum_list = items['todo.auto']['items'] 
        | map(attribute='summary') | list | default( [], true) %}
        {{ 'nop' if sum_list == [] else sum_list }} 
      sequence:
        - condition: template
          value_template: "{{ (now() >= repeat.item.due | as_datetime | as_local) }}"
        - action: script.{{ repeat.item }}
          continue_on_error: true

Make sure you accept Didgeridrews post and not mine.

I think the condition will skip the script part and skip to the next iteration.
But if it doesn’t then just make it an if then with a template condition.

1 Like

The condition can not work, because item.due not available, only the name of script to run. I think the condition have to be integrate in for_each but i don’t know how.

I edited the post.

EDIT: No… I see now that it maps the attribute summary so it will not have the due time. My bad.

Perhaps this could work…
I don’t have anything to test on.

  - repeat:
      for_each: |
        {% set sum_list = items['todo.auto']['items'] | selectattr('due', '>', now())
        | map(attribute='summary') | list | default( [], true) %}
        {{ 'nop' if sum_list == [] else sum_list }} 
      sequence:
        - action: script.{{ repeat.item }}
          continue_on_error: true

Fehler: TypeError: ‘>’ not supported between instances of ‘str’ and ‘datetime.datetime’

It needs to be mapped also then I guess.
Not sure how to do that. I bet Didgeridrew can, he is a lot better than me on templates.

Try this:

- repeat:
      for_each: |
        {% set sum_list = items['todo.auto']['items'] | selectattr('due', '>', now().isoformat())
        | map(attribute='summary') | list | default( [], true) %}
        {{ 'nop' if sum_list == [] else sum_list }} 
      sequence:
        - action: script.{{ repeat.item }}
          continue_on_error: true

get the error: Repeat ‘for_each’ must be a list of items

Ah right, you should just use an empty list

- repeat:
      for_each: |
        {{
          items['todo.auto']['items']
            | selectattr('due', '>', now().isoformat())
            | map(attribute='summary')
            | list
        }}
      sequence:
        - action: script.{{ repeat.item }}
          continue_on_error: true

But if you got that error that will mean that there are currently no todo items that fulfill the criteria. You should not get it with this version anymore.

Perfect, thank you very much.

I now have a new problem. I use the script shown below to add new items if they are not already included in the to-do list.
It only works for up to two items in the list. If a third item is added that is not included, nothing happens and no error occurs.

sequence:
  - variables:
      var_SearchItem: "{{ par_item }}"
      var_TimeDelta: "{{ par_timedelta }}"
      var_found: 0
  - target:
      entity_id: todo.auto
    response_variable: items
    action: todo.get_items
    data:
      status: needs_action
  - if:
      - condition: template
        value_template: "{{ items['todo.auto']['items'] | list | count > 0 }}"
    then:
      - variables:
          var_found: |
            {% for item in items['todo.auto']['items']  %}
              {% if item.summary  == var_SearchItem  %}
                1
                {% break %}
              {% else %}
                0
              {% endif %}
            {% endfor %}                    
      - if:
          - condition: template
            value_template: "{{ var_found==0 }}"
        then:
          - action: todo.add_item
            data:
              item: "{{ var_SearchItem }}"
              due_datetime: "{{ now() | as_datetime + timedelta(minutes=var_TimeDelta) }}"
            target:
              entity_id: todo.auto
    else:
      - action: todo.add_item
        data:
          item: "{{ var_SearchItem }}"
          due_datetime: "{{ now() | as_datetime + timedelta(minutes=var_TimeDelta) }}"
        target:
          entity_id: todo.auto

I’m not sure if I understand correctly when it’s working and when not? In any case, you could simplify this code.

I also wonder why you are creating new variables for already created variables… (e.g. var_SearchItem which is the same as the already existing par_item

Oh, and now() already returns a datetime object, you don’t need to use as_datetime on it.

sequence:
  - target:
      entity_id: todo.auto
    response_variable: items
    action: todo.get_items
    data:
      status: needs_action
  - if:
      - condition: template
        value_template: >
            {{
              items['todo.auto']['items']
                | selectattr('summary', 'eq', par_item)
                | list
                | count == 0
            }}  
    then:
      - action: todo.add_item
        data:
          item: "{{ par_item }}"
          due_datetime: "{{ now() + timedelta(minutes=par_timedelta) }}"
        target:
          entity_id: todo.auto

thank you very much, again, now its working :slight_smile: