Heads up: 2023.6 longer has persistent notifications in states: what to do?

markdown card in general has update issues i’ve noticed. I added my first one the other day and I have to force state changes and reload for it to “start working” after a restart of HA.

that must be a newish ‘feature’. I’ve have quite a few of them, and never saw any issue at all in that regard.
Ill keep an eye on these, and see if anything can be done

talking about that Dashboard yaml:

type: entities
title: Notification dashboard
show_header_toggle: false
state_color: true
card_mod:
  class: class-header-margin
entities:

  - entity: binary_sensor.persistent_notifications
    secondary_info: last-changed
  - entity: sensor.persistent_notifications_count
    secondary_info: last-changed
    format: relative
  - entity: sensor.persistent_notifications
    secondary_info: last-changed
  - type: custom:hui-element
    card_type: conditional
    conditions:
      - entity: binary_sensor.persistent_notifications
        state: 'on'
    card:
      type: custom:hui-element
      card_type: markdown
      card_mod:
        style: |
          ha-card {
            box-shadow: none;
            margin: 0px -16px;
          }
      content: >
        {% set count = states('sensor.persistent_notifications_count') %}
        ### {{count}} Notification{{'' if count == '1' else 's'}}:

        {% for m in state_attr('sensor.persistent_notifications','notifications') if m %}

        **{{m.title}}**{{'\n'}}
        *{{m.message}}*{{'\n'}}
        {{m.id}}{{'\n'}}
        {% endfor %}

  - type: conditional
    conditions:
      - entity: binary_sensor.persistent_notifications
        state: 'on'
    row:
      entity: script.dismiss_all_persistent_notifications #script.dismiss_all #former python
      secondary_info: last-triggered
      action_name: Wis

I could drop the bottom 2 conditional in 1 and use an entities card + plus a nice divider, but then I’d have to mod that again to not show borders/shadows etc. this was the lazy solution.

here’s the other:

  - type: custom:hui-element
    card_type: conditional
    conditions:
      - entity: binary_sensor.persistent_notifications
        state: 'on'
    card:
      type: entities
      card_mod:
        style: |
          ha-card {
            box-shadow: none;
            margin: 0px -16px;
          }
      entities:
        - type: divider
        - type: custom:hui-element
          card_type: markdown
          card_mod:
            style: |
              ha-card {
                box-shadow: none;
                margin: 0px -16px;
              }
          content: >
            {% set count = states('sensor.persistent_notifications_count') %}
            ### {{count}} Notification{{'' if count == '1' else 's'}}:

            {% for m in state_attr('sensor.persistent_notifications','notifications') if m %}

            **{{m.title}}**{{'\n'}}
            *{{m.message}}*{{'\n'}}
            {{m.id}}{{'\n'}}
            {% endfor %}

        - entity: script.dismiss_all_persistent_notifications #script.dismiss_all #former python
          secondary_info: last-triggered
          action_name: Wis

couldn’t resist and it seems less condition checking for the Frontend, so maybe just a bit more efficient

ive tested this once more, but it has unexpected result really:

 {'id': '75fa4c6be5fdc4155449eca69ac04eb4', 'title': 'Notification created at', 'message': 'Test notification containing a lot of info on noteworthy things', 'time': datetime.datetime(2023, 6, 30, 14, 51, 37, 172775, tzinfo=datetime.timezone.utc)}

compare to the now().isoformat() I used:

{'id': '62cb50577c591123c1c2c8448247203e', 'title': 'Notification title', 'message': 'Test notification containing a lot of info on noteworthy things', 'time': '2023-06-30T16:50:14.601893+02:00'}

and that throws off the template, and also the counter


.
because of:

not really unexpected, if that’s a datetime just change this

                  "time": trigger.notification.created_at.isoformat() }] }}

Can someone help me get a push if there is a failed login?

alias: Failed Login I Push Nachricht
trigger:
  - platform: state
    entity_id: persistent_notification.http_login
condition:
  - condition: template
    value_template: "{{ trigger.to_state.state != 'None' }}"
action:
  - service: notify.mobile_app_iphone_c_fischer
    data_template:
      title: "{{ states.persistent_notification.http_login.attributes.message }}"
      message: >-
        url:
        https://whatismyipaddress.com/ip/{{states.persistent_notification.http_login.attributes.message.split("from
        ")[1]}}
  - service: persistent_notification.dismiss
    data:
      notification_id: http_login
initial_state: true
mode: single

you mean smth like this:

  - alias: Notify of login persistent notifications
    id: notify_of_login_persistent_notifications
    trigger:
      platform: persistent_notification
      update_type: added
    condition:
      >
        {% set message = trigger.notification.message %}
        {{'Too many login attempts' in message or
          'invalid authentication' in message or 'login attempt' in message}}
    action:
      service: notify.system
      data:
        title: >
          {% set title = trigger.notification.title %}
            Ha Main: {{title}}
        message: >
          {% set message = trigger.notification.message %}
          {% set now = now().strftime('%d %b: %X') %}
          {% if 'Too many login attempts' in message %}
           Login notification: {{now}}: {{message}}
          {% elif 'invalid authentication' in message or 'login attempt' in message %}
            Login notification: {{now}}: {{message}}
            Track offending ip on http://www.ip-tracker.org/locator/ip-lookup.php?ip={{message.split('from ')[1]}}
          {% else %}
            Login notification other: {{now}}: {{message}}
          {% endif %}

its yet untested, only a quick rewrite for what was used before

1 Like

right, does your code work with the new beta?

but why would that make the template list individual characters, instead of the dict

1 Like

because the datetime object isn’t a basic object, so when the resolver checks the output type of the template it turns it into a string. Later on, when it runs again, you turn it into a list, which makes it look the way it does.

right, I see now the same thing happens when using only now() in the time field…
thanks

displaying in the markdown with:

created at: *{{as_timestamp(m.created_at)|timestamp_custom('%d %b: %X')}}*

to make it readable

don’t we have some crafty way of rewriting this:

              {% set new = [{
                  "id": trigger.notification.notification_id | default('TS' ~ now().timestamp()),
                  "title": trigger.notification.title | default(''),
                  "message": trigger.notification.message | default(''),
                  "created_at": trigger.notification.created_at.isoformat() }] %}

and have that built automatically based on those 4 variables?
especially since we can probably safely use:

              {% set new = [{
                  "id": trigger.notification.notification_id,
                  "title": trigger.notification.title,
                  "message": trigger.notification.message,
                  "created_at": trigger.notification.created_at.isoformat() }] %}

thats a system service, check your service tools page for available notify services in your system, and use which ever you want

1 Like

thx , it works …I found my mistake … THX!!!

Now that most functionality is correct, there is one more thing ( there always is…):

Upon restart, the notification tray is empty, and in the former implementation of Pers. notifications, the system would no longer have ‘notifying’ notifications. However, the trigger template still shows the state that it was in before restart, as it is restoring per design.

That is ok in itself, maybe even better than the core Pers. Notifications, but it is no longer in sync.

Also clearing the notifications now does Not work, and the last state remains. Apparently the ids are no longer in the system, so the clear does not know what to clear?
That could be an issue.

Wonder what to do. Maybe add homeassistant start to the triggers for the template?

That would probably make it sync . I do like the ‘memory’ it now displays though , but don’t like we can not clear …

No, adding the homeassistant start trigger is not perfect either, it now errors on:

Template variable error: 'dict object' has no attribute 'notification' when rendering '{% set msgs = this.attributes.get('notifications', []) %} {% if trigger.update_type == 'added' %} {% set new = [{ "id": trigger.notification.notification_id, "title": trigger.notification.title, "message": trigger.notification.message, "created_at": trigger.notification.created_at.isoformat() }] %} {{ msgs + new }} {% else %} {{msgs | rejectattr('id', 'eq', trigger.notification.notification_id) | list }} {% endif %}'

so apparently even the [] in the getter does not help here

  - trigger:
      - platform: homeassistant
        event: start
      - platform: persistent_notification
        update_type:
          - added
          - removed
    sensor:

      - unique_id: persistent_notifications_overview
        device_class: timestamp
        state: >
          {{now()}}
        attributes:
          notifications: >
            {% set msgs = this.attributes.get('notifications', []) %}
            {% if trigger.update_type == 'added' %}
              {% set new = [{
                  "id": trigger.notification.notification_id,
                  "title": trigger.notification.title,
                  "message": trigger.notification.message,
                  "created_at": trigger.notification.created_at.isoformat() }] %}
              {{ msgs + new }}
            {% else %}
              {{msgs | rejectattr('id', 'eq', trigger.notification.notification_id) | list }}
            {% endif %}

Never restarted my test box this many times before testing this!!

Tried to get the template trigger method working for this scenario but also failed (was favoring this approach), so returned to the automation approach and have got it working.

alias: Persistent Notification Mirror
description: ""
trigger:
  - platform: homeassistant
    event: start
    id: start
  - platform: persistent_notification
    update_type:
      - added
      - current
      - updated
    id: added
  - platform: persistent_notification
    update_type:
      - removed
    id: removed
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - added
        sequence:
          - event: message_create
            event_data:
              id: "{{ trigger.notification.notification_id }}"
              title: "{{ trigger.notification.title }}"
              message: "{{ trigger.notification.message }}"
      - conditions:
          - condition: trigger
            id:
              - removed
        sequence:
          - event: message_delete
            event_data:
              id: |
                {{ trigger.notification.notification_id }}
      - conditions:
          - condition: trigger
            id:
              - start
        sequence:
          - event: message_delete_all
            event_data: {}
mode: queued
max: 30

On restart all previous mirrored notifications are cleared and then as they come in again are recreated. Supports the Dismiss All button on the slide out Persistent Notification panel.

This works well for me, as on a restart any Persistent Notifications I’ve raised via automation are recreated anyway (e.g. device offline).

Note: perhaps its just me and my config @Mariusthvdb; but I re-raise persistent notifications with the same ID multiple times e.g.

id: ntf_device
title: One device offline
message: light.office

then again when a second device goes off line

id: ntf_device
title: Two devices offline
message: light.office and switch.playroom

In this scenario the second message replaces the first (same ID) in the Persistent Notifications and also in my mirror - I think in your current configuration you may get two occurrences of ID ntf_devices in your sensor? (which could be fine for the way your config is set up)

As a side note, has anyone noticed that the notification bell icon counter is not nicely refreshing and often needs a whole page refresh?

template config

  - trigger:
      - platform: event
        event_type:
          - message_create
          - message_delete
          - message_delete_all
    sensor:
      - name: Messages
        state: "{{ now().timestamp() | timestamp_custom() }}"
        attributes:
          messages: >
            {% set msgs = this.attributes.get('messages', []) %}
            {% if trigger.event.event_type == 'message_create' %}
              {% set msgs = msgs | rejectattr('id', 'eq', trigger.event.data.id) | list %}
              {% set new = [{
                  "id": trigger.event.data.id | default('TS' ~ now().timestamp()),
                  "title": trigger.event.data.title | default(''),
                  "message": trigger.event.data.message | default(''),
                  "time": now().isoformat() }] %}
              {{ (msgs + new) }}          
            {% elif trigger.event.event_type == 'message_delete' %}
              {% set msgs = msgs | rejectattr('id', 'eq', trigger.event.data.id) | list %}
              {{ msgs }}
            {% else %}
              {{ [] }}
            {% endif %}

For interest I have logged a bug for this. It appears if you restart the count is is being persisted unless you refresh the page - a small issue but a differing in behavior and potentially misleading following restart.

I think that is a frontend issue more than a core issue though, and yes that is new behavior. With more than the notification tray I fear, but there it is very obvious.

on the restart restore:
maybe I should add a clear notifications on Ha restart/stop.
it would be my first usage of

automation:
  trigger:
    - platform: homeassistant
      # Event can also be 'shutdown'
      event: start

so I have to ask if shutdown would also trigger on restart, which would be what Id need.

Btw, on the subject of that tray: ive always found it silly we can open that without having a single notification, only to have it show an empty half screen

You’ll have to test for your needs, but I couldn’t get the shutdown event to trigger on restart. The homeassistant.start event seems run before any notifications were getting generated so works for my needs.

thanks for the heads up, moved that issue to frontend now :slight_smile:

This is what i have now, and it works for me.

template:
  - trigger:
      - platform: persistent_notification
        update_type:
          - added
          - removed
        id: pn

      - platform: homeassistant
        event: shutdown
        id: shutdown

    sensor:
      - name: pn_messages
        state: "{{ now().timestamp() | timestamp_custom() }}"
        # state: "{{ state_attr('sensor.pn_messages', 'pn_ids') | length }}"   # not possible, also with 'this.attributes'    
        unique_id: 20230630060219
        attributes:
          pn_ids: >
            {% if trigger.id == 'pn' %}
              {% if trigger.notification.notification_id is defined %}
                {% set id = trigger.notification.notification_id %}
                {% set pn_ids = this.attributes.get('pn_ids', []) %}
                {% if trigger.update_type == 'added' %}
                  {% set new = [id] %}
                  {{ (pn_ids + new) | unique | list }}
                {% else %}                
                  {{ pn_ids | reject('equalto', id) | list }}
                {% endif %}
              {% endif %}
            {% elif trigger.id == 'shutdown' %}
              {{ [] }}
            {% endif %}

  - trigger:
      - platform: state
        entity_id: sensor.pn_messages
    sensor:
      - name: pn_count
        state: "{{ state_attr('sensor.pn_messages', 'pn_ids') | length }}"
        unique_id: 20230615210019

I need only a list for counting and testing of notifications, so a list with id’s is enough for me.
Creating/updating multiple notifications with the same id falsified the counter, so the unique filter.
Restarting HA deletes the notifications, but the attributes are restored, so the restart trigger to set an empty list.

What i can’t get to work ist the count as state or attribute, it seems it’s not possible to set this with values from the same sensor.
It’s also not possible to test for a notification that is created for the first time.
The trigger in a template is always faster than the same trigger in an automation, it always is false.

automation:
  - alias: persistent_notification_log
    id: '20230630190625'
    variables:
      pn_ids: "{{ state_attr('sensor.pn_messages', 'pn_ids') }}"
    initial_state: true
    mode: parallel
    trigger:
      - platform: persistent_notification
        update_type:
          - added
    # condition:
    #   - "{{ trigger.notification.notification_id not in pn_ids }}"    # always false
    action:
      - service: notify.pn_log
        data_template:
          message: >
            {{ now().strftime('%Y%m%d %H%M%S') }} 
            {{ trigger.notification.title }} /
            {{ trigger.notification.message }}

I’m open for improvements. :slightly_smiling_face:

1 Like

Need to test that a bit but I feel the count sensor works best a regular template and not at trigger .

Does here anyway.
Experimenting with the restart didn’t yet bring a solution as the trigger shutdown doesnt fire on restart….

update

I was so fixated on the restart event, I completely overlooked the fact I should not try to trigger off the restart/shutdown event, but simply use the start event…

  - trigger:
      - platform: homeassistant
        event: start
        id: start
      - platform: persistent_notification
        update_type:
          - added
          - removed
    sensor:

      - unique_id: persistent_notifications_overview
        device_class: timestamp
        state: >
          {{now()}}
        attributes:
          notifications: >
            {% set msgs = this.attributes.get('notifications', []) %}
            {% if trigger.update_type == 'added' %}
              {% set new = [{
                  "id": trigger.notification.notification_id,
                  "title": trigger.notification.title,
                  "message": trigger.notification.message,
                  "created_at": trigger.notification.created_at.isoformat() }] %}
              {{ msgs + new }}
            {% elif trigger.id == 'start' %}
              {{[]}}
            {% else %}
              {{msgs | rejectattr('id', 'eq', trigger.notification.notification_id) | list }}
            {% endif %}

makes it happen.
its a bit weird to see it go from a number, then restart, change to unavailable, then unknown, and then back to the number it had before (apparently from restore. Finally it is reset by the start event trigger ti an empty list, and causing the number And the binary to get the correct state. All perfect now.

excpet for the Frontend, which is still left from where it was before the restart

Scherm­afbeelding 2023-07-01 om 22.59.36

and requires a reload :wink: But thats a bug, and not to do with this template trigger

I linked your issue in the #beta channel on Discord, hoping it might be fixed before release

I’m not testing the July beta so I can’t test your latest example posted above (and answer my own question). What happens to this line when your Trigger-based Template Sensor is triggered by its first trigger (homeassistant start)?

{% if trigger.update_type == 'added' %}

Isn’t update_type exclusively a property of the second trigger (persistent_notification) and not the first trigger (homeassistant start)?

I would imagine it would cause an error message indicating the trigger object doesn’t have an update_type property.