Template error returning value from loop

I need to decide which zone to irrigate depending on which zone was irrigated the longest time ago. I have 5 gpio switches and have created 5 corresponding input_datetime helpers to store the last irrigation date for each zone. I’m trying to calculate the best number with the following template as part of a script:

    - service: input_number.set_value
      target:
        entity_id: input_number.current_zone
      data:
        value: >
          {%- set ns = namespace(bestval='3000-01-01', bestnum='' -%}
          {%- for i in states.input_datetime -%}
          {%-   if i.state|string < ns.bestval -%}
          {%-     set ns.bestval = i.state -%}
          {%-     set ns.bestnum = i.entity_id -%}
          {%-   endif -%}
          {%- endfor -%}
          {{ns.bestnum[-1:]|int|string}}

I did use the ‘namespace trick’ to modify the variable inside the jinja loop.
The template code works in the UI but fails to import as part of the script with the following error:

Invalid config for [script]: template value should be a string for dictionary value @ data['sequence'][2]['data']. Got None.

I couldn’t find any samples of loop calculations inside a script value, so not sure this is possible?

The result reported by your template was None (null object).

This line stores the input_datetime’s entity_id in ns.bestnum

{%-     set ns.bestnum = i.entity_id -%}

Can you explain what you believe this last line does?

{{ns.bestnum[-1:]|int|string}}

It appears to be attempting to convert the saved entity_id into an integer value (which makes no sense).

Forgot to mention the input_datetimes have the following entity_ids and states:

input_datetime.last_zone_1 = 2022-11-01
input_datetime.last_zone_2 = 2022-11-03
input_datetime.last_zone_3 = 2022-10-07
input_datetime.last_zone_4 = 2022-11-03
input_datetime.last_zone_5 = 2022-11-06

So {{ns.bestnum[-1:]}} should give me the last character of the entity_id - which is a number from 1 to 5. But now that you ask I realize the |int|string is actually pretty redundant :slightly_smiling_face: thanks.

OK, the additional information helps to make sense of what the last line does but the redundant filters aren’t the cause of the error message.

The following template performs the same function as yours (report the last letter of the entity_id of the input_datetime containing the oldest date). Copy-paste it into the Template Editor to confirm it reports the correct value.

{{ (states.input_datetime | sort(attribute='state')
  | map(attribute='object_id') | list | first)[-1:] }}

If you have many input_datetime entities and only want the ones that contain a date but no time, you can do this:

{{ (states.input_datetime
  | selectattr('attributes.has_date', 'eq', true)
  | selectattr('attributes.has_time', 'eq', false)
  | sort(attribute='state')
  | map(attribute='object_id') | list | first)[-1:] }}
1 Like

Amazing. Beautiful. Thank you sensei :pray:

1 Like