Create dictionary from lists?

Hey guys,

I have couple of sensors that look like this:

template:
  sensor:
    - unique_id: medication_med1_orbirus
      name: "medication_med1_orbirus"
      state: ""
      attributes:
        counter: "counter.medication_orbirus"
        pill_name: "Orbirus"    
        time: "10:21"
        usage: "{{ 2 }}"

I can create multiple lists for attributes counter or usage, but I think I need a dictionary. Look at my attempt:

    action:
      - variables:
          what_counter: |-
            {% set med_list = states.sensor 
            | selectattr('entity_id', 'search', 'medication_') 
            | selectattr('attributes.time', 'eq', now().strftime('%H:%M') ) 
            | list %}
            {% set counter_list = med_list | map(attribute='attributes.counter') | list %}
            {{ counter_list }}
          what_usage: |-
            {% set med_list = states.sensor 
            | selectattr('entity_id', 'search', 'medication_') 
            | selectattr('attributes.time', 'eq', now().strftime('%H:%M') ) 
            | list %}
            {% set usage_list = med_list | map(attribute='attributes.usage') | list %}
            {{ usage_list }}
      - repeat:
          for_each: [counter_name:what_counter, usage:what_usage]
          sequence:
            - service: 
                - repeat: 
                    count: "{{ repeat.item.usage }}"
                    sequence:
                      - service: counter.decrement
                        target:
                          entity_id: "{{ repeat.item.counter_name }}"
    mode: single

So I get these lists:

what_counter: [counter.medication_orbirus, counter.medication_sukubus]
what_usage: [2, 1]

And I actually wanted something like this:

what: [orbirus:[what_counter:counter.medication_orbirus, what_usage:2], sukubus:[what_counter:counter.medication_sucubus, what_usage:1]

so I can use that in repeat automation. The goal is to change each counter by individual value (defined by attribute usage). Any suggestion is more than welcome

Check out my last post, there is a working example <3

Your actions do not show a a use for the med’s name… is it needed for something else?

If not, you should be able to use something like the following:

...
action:
  - variables:
      med_list: |-
        {{ states.sensor | selectattr('entity_id', 'search', 'medication_') 
        | selectattr('attributes.time', 'defined')
        | selectattr('attributes.time', 'eq', now().strftime('%H:%M')) | list }}
      dict_list: |-
        {% set ns = namespace(comb_array=[]) %}
        {% for med in med_list %}
        {% set ns.comb_array = ns.comb_array 
        + [ {"usage":med.attributes.usage, "counter": med.attributes.counter} ] %}
        {%endfor%}
        {{ ns.comb_array }}
  - repeat:
      for_each: "{{ dict_list }}"
      sequence:
        - variables:
            current: "{{ states(repeat.item.counter) | int(0) }}"
        - service: counter.set_value
          target:
            entity_id: "{{ repeat.item.counter }}"
          data:
            value: "{{ current - repeat.item.usage | int(0) }}"
mode: single
1 Like

Thank you again!

I had some issues with dict_list being empty, but didn’t have time to look further. Ill play with that after work later today.

Awesome!

I don’t think there was a problem with a list, but I merged them to 1 variable anyway. There was a mistake in service name, it should be counter.configure instead of counter.set_value, but that was easy even for me :smiley:

Thank you a lot Digeridrew, you are so helpful. Here is my final code:

    action:
      - variables:
          dict_list: |-
            {% set med_list = states.sensor 
            | selectattr('entity_id', 'search', 'medication_')
            | selectattr('attributes.time', 'eq', now().strftime('%H:%M') )
            | list %}
            {% set ns = namespace(comb_array=[]) %}
            {% for med in med_list %}
            {% set ns.comb_array = ns.comb_array 
            + [ {"usage":med.attributes.usage, "counter": med.attributes.counter} ] %}
            {%endfor%}
            {{ ns.comb_array }}
      - repeat:
          for_each: "{{ dict_list }}"
          sequence:
            - variables:
                current: "{{ states(repeat.item.counter) | int(0) }}"
            - service: counter.configure
              target:
                entity_id: "{{ repeat.item.counter }}"
              data:
                value: "{{ current - repeat.item.usage | int(0) }}"
    mode: single

I think I have everything now to finish my medication app and I will share it once its done. So cool !

The problem with Drews original post is that state objects cannot be serialized/unserialized in Jinja. So you had to combine them in order for it to work.

If you want to optimize the template, use the following…

          dict_list: >
            {% set ns = namespace(items=[]) %}
            {% for med in states.sensor 
              | selectattr('entity_id', 'search', 'medication_')
              | selectattr('attributes.time', 'eq', now().strftime('%H:%M') )
              | map(attribute='attributes') %}
              {% set ns.items  = ns.items + [ {"usage":med.usage, "counter": med.counter} ] %}
            {%endfor%}
            {{ ns.items }}
2 Likes

Thanks! It works, one-shot copy-paste :smiley:

I figured the counter doesn’t go below 0 with this automation. I changed from counter to input_number and its perfect now!

1 Like