Can I list all sensors with the same attribute value

Hey guys, creating a title was already difficult task haha

Short version of question:

I have sensors with name: “medication_med1”, “medication_med2”, etc. Every sensor have attributes pill_name, time_1, time_2, time_3 and time_4.

Is it possible to search attributes named time_* under all sensors named sensor.medication_* and list as pill_name attribute if value is “08:00:00” for example ?

template:
  sensor:
    name: "medication_med1"
    state: "{{ states('counter.medication_med1') | round(0) }}"
    attributes:
      pill_name: "Medication Med1"      
      time_1: "08:00:00"
      usage_1: "{{ 1 }}"
      note_1: >
        {{states.attributes
            | selectattr('entity_id', 'search', 'sensor.medication_')
            | selectattr('attribute_name', 'search', 'time_')
            | selectattr('attribute_value', 'eq' , 'state_attr('sensor.medication_med1', 'time_1')')
            | map('sensor_name', ') | list}}

Long version of question:

I’m trying to improve medication reminder/tracker that is running as a package(s) in Home Assistant. I have one yaml file for each kind of medication. Each yaml contains different time schedule for reminders. There is room for improvement, for example, sometimes I have to take 2 different pills at the same time and 2 reminders at the same time doesn’t always work as I’d like. Take a look at example of one file:

counter:
  medication_med1:
    initial: 20
    step: 1

template:
  sensor:
    name: "medication_med1"
    state: "{{ states('counter.medication_med1') | round(0) }}"
    attributes:
      pill_name: "Medication Med1"      
      time_1: "08:00:00"
      usage_1: "{{ 1 }}"
      note_1: >
        {{states.attributes
            | selectattr('entity_id', 'search', 'sensor.medication_')
            | selectattr('attribute_name', 'search', 'time_')
            | selectattr('attribute_value', 'eq' , 'state_attr('sensor.medication_med1', 'time_1')')
            | map('sensor_name', ') | list}}
      time_2: "20:00:00"
      usage_2: "{{ 3 }}"
      note_2: >
        {{states.attributes
            | selectattr('entity_id', 'search', 'medication_')
            | selectattr('attribute_name', 'search', 'time_')
            | selectattr('attribute_value', 'eq' , 'state_attr('sensor.medication_med1', 'time_1')')
            | map(attribute='pill_name')', ') | list}}
automation:
  - alias: "alarm_msg_1"
    trigger:
      platform: time
      at: "{{ state_attr('sensor.medication_med1', 'time_1') }}"
    condition:
     - condition: template
       value_template: "{{ as_timestamp(state_attr('notify.mobile_app_moto_g42','last_triggered')) > 1 }}"
    action:
      - service: notify.mobile_app_moto_g42
        data:
          message: "Take {{ note_1 }}"
  - alias: "alarm_msg_2"
    trigger:
      platform: time
      at: "{{ state_attr('sensor.medication_med1', 'time_2') }}"
    condition:
     - condition: template
       value_template: "{{ as_timestamp(state_attr('notify.mobile_app_moto_g42','last_triggered')) > 1 }}"
    action:
      - service: notify.mobile_app_moto_g42
        data:
          message: "Take {{ note_2 }}"

So attributes note_1 and note_2 is what I don’t know how to solve. I tried with selectattr(‘search’) and with for loop, but its not worth to post my attempts here and I’m not even sure is it even possible.

I’d like to have in note_1: Medication Med1, Medication Med4

I’m still quite new to this so all suggestions are welcome.

edit: made it more clear I hope :smiley:

Your automation has some major issues. It looks like you might have been trying to use the template editor tool to build your automation, which will not work reliably. The template editor tool does not understand YAML or the underlying criteria of a given HA integration. For example, you cannot use templates in a Time trigger. The time trigger accepts time strings like “08:00:00” or “08:00” or entity IDs of Input datetimes or sensors… that’s it. If you want to use a Time trigger you need to separate the time attributes into their own sensors with the device class set to “timestamp”. Otherwise you need a Template trigger.

I would leave the automation out of the individual packages, there’s no need to repeat it so many times when you want a single condensed notification.

automation:
  - alias: "medication_alarm_msg"
    trigger:
      platform: template
      value_template: |-
        {% set time_list = [state_attr('sensor.medication_med1', 'time_1'), 
        state_attr('sensor.medication_med1', 'time_2'),
        state_attr('sensor.medication_med2', 'time_1'),
        state_attr('sensor.medication_med2', 'time_2') ] %}
        {{ now().strftime('%H:%M:%S') in time_list }}
      variables:
        time_str: "{{now().strftime('%H:%M:%S')}}"
    condition:
      - alias: Throttle number of messages
        condition: template
        value_template: "{{ now() - this.attributes.last_triggered | default(as_datetime(0)) >= timedelta(minutes=1)  }}"
    action:
      - variables:
          note: |-
            {% for med in  states.sensor | selectattr('entity_id', 'search', 'medication_')
            | selectattr('attributes.time_1', 'defined')%}
            {{ med.attributes.pill_name if time_str in [med.attributes.time_1, med.attributes.time_2 | default(0) ] }}
            {% endfor %}
      - service: notify.mobile_app_moto_g42
        data:
          message: "Take {{note}}"
    mode: single

FWIW, I would remove the seconds from your time values (and the :%S from the strftime() functions above). Having the seconds doesn’t add anything in terms of temporal accuracy but it could cause inaccurate output if your system happens to be running a little slow. For example, if the trigger fires at 08:00:00.999 then the value of time_str gets rendered as 08:00:01, it wouldn’t match any of your dosage times. If you only compare hour and minutes, you have a lot more leeway.

1 Like

Thank you a lot! Im writing this just to say that for now.
I will take some time to play arund and test it out before I answer. Cya soon

This code:

          note: |-
            {% for med in  states.sensor | selectattr('entity_id', 'search', 'medication_')
            | selectattr('attributes.time_1', 'defined')%}
            {{ med.attributes.pill_name if time_str in [med.attributes.time_1, med.attributes.time_2 | default(0) ] }}
            {% endfor %}

is solution to my question! I’m hitting solution button right away.

My approach was definitely wrong, having one automation feels like much much better solution. You have provided more than I asked, it’s so kind of you. Thank you again! Your post made me think about whole code again and it is becoming more advanced than I expected.

Condition is stopping automation for some reason, but the code works otherwise. I couldn’t figure why yet, but honestly I removed condition for now and playing with the rest of the code.
I’m trying to figure how to define trigger value_template so it also lists times from any sensor that starts with sensor.medication_ and not just the meds I listed manually. What I’m trying to achieve is having ability to just create new yaml file for every new medication and name the sensor medication_anything. When I stop using one of them, I’d just delete yaml file for that med.
I had some extra automations around that, and I’ll start rebuilding everything. Your code is super useful and that approach will solve most of the hard work.

I’m not gonna post my whole code yet since it is still work in progress, but once I get it working I will share it here.

Thanks again and have a good one!

trigger:
  - platform: template
    value_template: |-
      {% set med_list = states.sensor | selectattr('entity_id', 'search', 'medication_')
      | selectattr('attributes.time_1', 'defined') | list %}
      {% set times_list = (med_list | map(attribute='attributes.time_1') | list
      + med_list | selectattr('attributes.time_2', 'defined')| map(attribute='attributes.time_2') | list
      )| unique | list %}
      {{ now().strftime('%H:%M:%S') in times_list }}

As above, you would need to remove the :%S from the strftime() function if you follow the earlier recommendation to change your times to just hours and minutes.

1 Like

Insane! I don’t know what I like more the community or home assistant itself. Wonderful and also solution!