Miicroo / ha-birthdays

Birthday integration for HomeAssistant
21 stars 7 forks source link

Split next birthday template when there are more then 1 birthdays on the same day. #16

Closed jonisnet closed 1 month ago

jonisnet commented 2 months ago

Hello,

First of all thanx for this great integration it was just what i was looking for and i find it a bit strange that it is not known by a lot of HA users.

That being said i'm wondering if i could get some help and maybe by doing so helping to make the integration even a bit better.

i use the integration with template and some automations but there is one action i cant figure out.

In the entitie configuration with the birthdays i added the attribute phone number so i can use this (with next birtday template) in an notify automation (HA buildin) to my phone. The notification contains an action that will forward when pushed to the person phone number on whatsapp so i can congrat them or at least the contact i'm closest with. So far so good.

When there are more then one birtdays on the same day this doesnt work well because the template can only collect all data and will list this seperated by comma. I would like to change this to something like sensor.next_birthday_1 and sensor.next_birthday_2, sensor.next_birthday_3, etc.

Does anyone know if this is possible and if so how?

Thank you advance.

Best regards Kees

Miicroo commented 1 month ago

Hi @jonisnet and thank you for the kind words!

Here is how I would do it, let me know if I have misunderstood your requirements!

First, I woukd change the example template ifrom the README to include all of the entities that you would like to push a notification to. It looks like this:

template:
  - sensor:
      - name: "Next birthday"
        state: >
          {%- set ns = namespace(days=365) -%}
          {%- for birthday in states.birthdays -%}
            {%- set daysLeft = birthday.state | int -%}
            {%- if daysLeft < ns.days -%}
              {%- set ns.days = daysLeft -%}
            {%- endif -%}
          {%- endfor -%}
          {{ ns.days }}
        attributes:
          entities: >
            {%- set ns = namespace(days=365, entities=[]) -%}
            {%- for birthday in states.birthdays -%}
              {%- set daysLeft = birthday.state | int -%}
              {%- if daysLeft < ns.days -%}
                {%- set ns.days = daysLeft -%}
              {%- endif -%}
            {%- endfor -%}
            {%- for birthday in states.birthdays -%}
              {%- set daysLeft = birthday.state | int -%}
              {%- if daysLeft == ns.days -%}
                {%- set ns.entities = ns.entities + [birthday.entity_id] -%}
              {%- endif -%}
            {%- endfor -%}

            {{ns.entities | join(', ')}}

When I run this in my test environment with the fictional characters from the README, sensor.next_birthday gives me the number of days until Bilbo and Frodo Baggins birthday, and there is a single attribute called entities which is a list with birthdays.bilbo_baggins, birthdays.frodo_baggins.

Next, we change the automation to iterate over these entities and access the information we want. I have chosen to use the persistent notification as an example, but you can switch it to any other service.

automation:
  - alias: Send notification for each birthday
    trigger:
      - platform: state
        entity_id: sensor.next_birthday
    mode: parallel
    action:
      - variables:
          # Here we get the birthdays as a list
          birthday_entities: "{{ state_attr('sensor.next_birthday', 'entities').split(', ') }}"
      - repeat:
          for_each: '{{ birthday_entities }}'
          sequence:                      
            - service: persistent_notification.create
              data:
                title: New birthday
                message: '{{ state_attr(repeat.item, "friendly_name") }} with phone number {{ state_attr(repeat.item, "phone_number") }} turns {{ state_attr(repeat.item, "age_at_next_birthday") }} today!'
                notification_id: '{{ repeat.item.split(".")[1] }}_birthday_notification'

Here we create a variable inside the action block, and iterate over each birthday entity. The magic mainly happens inside the state_attr calls, which turn the entity_id into an entity and returns the associated attributes.

Let me know if this works, or if you have any questions! 🎉

jonisnet commented 1 month ago

Hi @Miicroo,

Since there are 3 birthdays tomorrow i wanted to check it rightaway. There was only 1 change i made because i got some errors.

variables: birthday_entities: "{{ (state_attr('sensor.next_birthday', 'entities')|string).split (', ') }}" After that change it worked flawless.

Thank you very much.