Update notifications! Core, HACS, Supervisor and Addons (now a blueprint!)

I really like these notifications! Most of the updates appear on my phone when available, which allows me to install them faster.

Today I received a notification that a new supervisor update is available. When checking in HA, i also see that there is a new OS version available:

image

For the OS version, there is no notification. Are you planning to extend your notifications to include the Hass OS update also?

Here’s what I use.

Automations:

- alias: 'HassOS Stable Update Available'
  trigger:
    platform: template
    value_template: "{{ states('sensor.hassos_installed_version') != states('sensor.hassos_latest_stable_version') }}"
  condition:
  - "{{ states('sensor.hassos_latest_stable_version') not in ['unknown', 'unavailable', 'none'] }}"
  - "{{ states('sensor.hassos_installed_version') not in ['unknown', 'unavailable', 'none'] }}"
  action:
  - service: notify.telegram_system
    data:
      title: '*Information*'
      message: "Stable update for HassOS available, from v{{ states('sensor.hassos_installed_version') }} to v{{ states('sensor.hassos_latest_stable_version') }}, see https://github.com/home-assistant/operating-system/releases/tag/{{ states('sensor.hassos_latest_stable_version') }}"

- alias: 'HassOS Beta Update Available'
  trigger:
    platform: template
    value_template: "{{ states('sensor.hassos_installed_version') != states('sensor.hassos_latest_beta_version') }}"
  condition:
  - "{{ states('sensor.hassos_latest_beta_version') not in ['unknown', 'unavailable', 'none'] }}"
  - "{{ states('sensor.hassos_installed_version') not in ['unknown', 'unavailable', 'none'] }}"
  action:
  - service: notify.telegram_system
    data:
      title: '*Information*'
      message: "Beta update for HassOS available, from v{{ states('sensor.hassos_installed_version') }} to v{{ states('sensor.hassos_latest_beta_version') }}, see https://github.com/home-assistant/operating-system/releases/tag/{{ states('sensor.hassos_latest_beta_version') }}"

Sensors:

- platform: command_line
  name: HassOS Installed Version
  command: 'curl http://supervisor/host/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)"|jq ''{"hassos":.data.operating_system}'''
  value_template: "{{ value_json.hassos[18:] }}"

- platform: rest
  resource: https://version.home-assistant.io/stable.json
  name: HassOS Latest Stable Version
  value_template: '{{ value_json.hassos["intel-nuc"] }}'
  scan_interval: 3600

- platform: rest
  resource: https://version.home-assistant.io/beta.json
  name: HassOS Latest Beta Version
  value_template: '{{ value_json.hassos["intel-nuc"] }}'
  scan_interval: 3600

I use this for sensor

  - platform: command_line
    name: Updater HassOs
    command: >
      curl http://supervisor/os/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)"
      | jq '{"newest_version":.data.version_latest,"current_version":.data.version,"update_available":.data.update_available}'
    value_template: >
      {% if value_json.update_available == true %}on
      {% else %}off
      {% endif %}
    json_attributes:
      - update_available
      - newest_version
      - current_version
2 Likes

I have searched through this thread and did not find an answer.
How can I add a persistent notification to the alert, if possible.
At what point would “persistent_notification.create” be added.

alert:
  # Update is available - un-acknowledgeble, auto-dismiss, me only
  # Wait 5 minutes before first to give core config check time to run
  ha_update_available:
    name: HA has an update
    entity_id: sensor.updater_core
    state: 'on'
    can_acknowledge: false
    repeat: 
    - 5
    - 360
    skip_first: true
    title: 'Update for HA Core Available'
    message: "New version is {{ state_attr('sensor.updater_core', 'newest_version') }}. Currently on {{ state_attr('sensor.updater_core', 'current_version') }}"
    notifiers:
      - telegram_carlton
    data:
      tag: 'ha-update-available'
      url: 'http://XXX.XXX.X.XX:8123/hassio/addon/core_check_config'

Thanks

You can only use notification services from alerts so you can’t call persistent_notification.create but you can call notify.persistent_notification. It also creates a persistent notification but is an actual notification service so it can be used from alerts and things. However it doesn’t accept the notification_id input so it creates a distinct notification every time, a bit annoying.

Also the other thing is you can’t easily combine other notification services with notify.persistent_notification unfortunately. The notify.persistent_notification service is very restrictive, the only inputs it will accept are title and message. The call will fail if there is anything else, including data. So like in theory you could do this:

ha_update_available:
    name: HA has an update
    entity_id: sensor.updater_core
    state: 'on'
    can_acknowledge: false
    repeat: 
    - 5
    - 360
    skip_first: true
    title: 'Update for HA Core Available'
    message: "New version is {{ state_attr('sensor.updater_core', 'newest_version') }}. Currently on {{ state_attr('sensor.updater_core', 'current_version') }}"
    notifiers:
      - telegram_carlton
      - persistent_notification
    data:
      tag: 'ha-update-available'
      url: 'http://XXX.XXX.X.XX:8123/hassio/addon/core_check_config'

But in reality that would blow up because of the extra data that you want to pass to the telegram service, notify.persistent_notification wouldn’t accept that. So you’d either have to remove the data or make a separate alert just for making persistent notifications.

1 Like

Very well explained. Thank you for the effort.
Though as you said I could create a second alert (which I will more than likely do), but if I understand you correctly could the persistent notification be created very similar to the way telegram/pushbullet etc are created as a notification service and then added as a notifier?

Thanks for the information (forced me to learn more stuff that I never thought I needed).

I am a little confused with format of the alert notifier. I read the alert doc, and I do not believe it shows the format to use. I will edit the alert doc when it is clear to me. Do I use the notify.name, just the name or something else? i.e.

notifiers:
    - notify.pixel_xl_4

Yes. You should already see a notify.persistent_notification option on your system though, you don’t have to do anything to set that up. If you go to the services tab in developer tools it should be in the list for you to try out. And then yea you can pretty much just copy and paste the alert but replace telegram_carlton with persistent_notification (and remove the data in the new one)

You just use the name, i.e. what comes after notify.. So if you have a notification service that shows up as notify.pixel_xl_4 in your list of services then you put this in the alert:

notifiers:
- pixel_xl_4
1 Like

Thanks. Is the - under the " t" like above?

It doesn’t matter actually, whichever you prefer. With YAML when doing lists this:

notifiers:
- pixel_xl_4

and this:

notifiers:
  - pixel_xl_4

are both valid. The rules are that the - must be at least as indented as its parent (notifiers in this case) and all siblings in the array must be the same level of indent. I personally prefer to minimize the amount of indenting whenever possible but HA seems to prefer indenting the elements of the array more then the parent (as evidenced by how it handles autogenerated YAML in UI and automation/script editor). But yea, they both work, its your choice.

Thanks. And that is why I have struggled learning YAMl. Indents are important except when they are not. It would be so much easier if only one way worked.

2 Likes

I have a notify.mobile_app_andys_iphone service so i just can change ‘me’ with mobile_app_andys_iphone?

FROM:

    notifiers:
    - 'me'

TO:

    notifiers:
    - mobile_app_andys_iphone

Yep that’ll work. Or if you find it easier, can add a notify group that wraps yours like this:

notify:
  - name: me
    platform: group
    services:
      - service: mobile_app_andys_iphone

You may be interested in https://github.com/krpn/home-assistant-updates-notification

3 Likes

(Sorry, can’t post two images in the one post.)

You may be interested in https://github.com/krpn/home-assistant-updates-notification

2 Likes

Hi There,
First, I would like to thank all the contributors here for their amazing job.
I used this post as a base for my Versions Update notifications and I would like to share my solution for anyone who would like to use it.
Among the changes to the original package shared by @CentralCommand and other shares in this post:

  1. I added DeConz Updates
  2. I added the Supervisor version check (the supervisor itself, not the addons)
  3. I re-organised the sensors to a uniform reporting state
  4. I don’t like alerts, especially many of them so I created an automation for the notifications instead
  5. I created a unified sensor with all available Updates and I am using it in my automation (and the custom UI that I won’t share here because it it out of scope)
  6. fixed minor bug with the way versions are compared (used split (’ " ') instead of chars count for some network calls, wouldn’t fail when version number passes from 0.9.1 to 0.10.0 for example)

remember to update !secret github_access_token with your github account token.
So this is my new package:

# DeCONZ Firmware Updates:
sensor:
  # Deconz Firmware version Installed
  - platform: command_line
    name: DeCONZ Firmware Installed #sensor.deconz_firmware_installed
    command: 'cat /config/.storage/core.device_registry | grep -A 3 "Dresden Elektronik" | grep "sw_version"'
    scan_interval: 3600
    value_template: '{{ value.split("\"")[3] }}'
  # HACS version Installed
  - platform: command_line
    name: HACS Version Installed #sensor.hacs_version_installed
    command: 'cat /config/.storage/core.device_registry | grep -A 3 "hacs.xyz" | grep "sw_version"'
    scan_interval: 3600
    value_template: '{{ value.split("\"")[3] }}'
# Firmware-Update-Sensor for DeCONZ Dongle
  - platform: github
    access_token: !secret github_access_token
    repositories:
      - path: 'dresden-elektronik/deconz-rest-plugin'
        name: "DeCONZ Firmware Repository" #sensor.deconz_firmware_repository
      - path: 'hacs/integration'
        name: "HACS Repository" #sensor.hacs_repository
    scan_interval: 86400 #daily
  - platform: template
    sensors:
      deconz_firmware_version:
        friendly_name: "DeCONZ Firmware Version"
        value_template: >-
          {% set new = state_attr('sensor.deconz_firmware_repository', 'latest_release_tag').replace('v', '') %}
          {% if ("beta" not in new) and (new != states('binary_sensor.deconz_firmware_installed')) %}
            on
          {% else %}
            off
          {% endif %}
        attribute_templates:
          beta: >-
            {% set version = state_attr('sensor.deconz_firmware_repository', 'latest_release_tag') %}
            {% if "beta" not in version %}
              off
            {% else %}
              on
            {% endif %}
          latest_version: "{{state_attr('sensor.deconz_firmware_repository', 'latest_release_tag').replace('v', '') }}"
          current_version: "{{states('sensor.deconz_firmware_installed')}}"
      hacs_version:
        friendly_name: "Hacs Version"
        value_template: >-
          {% if (states('sensor.hacs') | int > 0) or (state_attr('sensor.hacs_repository', 'latest_release_tag') != states('sensor.hacs_version_installed')) %}
            on
          {% else %}
          off
          {% endif %}
        attribute_templates:
          latest_version: "{{state_attr('sensor.hacs_repository', 'latest_release_tag') }}"
          current_version: "{{states('sensor.hacs_version_installed')}}"
          repositories: "{{state_attr('sensor.hacs', 'repositories')}}"
#--------------------------------------------------------
  # Sensors to track updates to core components (core, audio, dns, CLI, observer and multicast)
  - platform: command_line
    name: Core Version # sensor.core_version
    command: 'curl http://supervisor/core/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version, "update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
    - latest_version
    - current_version 
  - platform: command_line
    name: HassOS Version # sensor.hassos_version
    command: 'curl http://supervisor/os/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version,"update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
      - latest_version
      - current_version
  - platform: command_line
    name: Audio Version # sensor.audio_version
    command: 'curl http://supervisor/audio/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version, "update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
    - latest_version
    - current_version
  - platform: command_line
    name: DNS Version # sensor.dns_version
    command: 'curl http://supervisor/dns/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version, "update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
    - latest_version
    - current_version
  - platform: command_line
    name: CLI Version # sensor.cli_version
    command: 'curl http://supervisor/cli/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version, "update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
    - latest_version
    - current_version
  - platform: command_line
    name: Multicast Version # sensor.multicast_version
    command: 'curl http://supervisor/multicast/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version, "update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
    - latest_version
    - current_version
  - platform: command_line
    name: Observer Version # sensor.observer_version
    command: 'curl http://supervisor/observer/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version, "update_available":.data.update_available}'''
    value_template: "{% if value_json.update_available %}on{% else %}off{% endif %}"
    scan_interval: 3600
    json_attributes:
    - latest_version
    - current_version
#--------------------------------------------------------
# Sensor to track available updates for the supervisor & supervisor addons list
  - platform: command_line
    name: Supervisor Version # sensor.supervisor_version
    command: 'curl http://supervisor/supervisor/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"latest_version":.data.version_latest,"current_version":.data.version,"update_available":.data.update_available,"addons":[.data.addons[] | select(.update_available)]}'''
    value_template: "{% if (value_json.addons | length > 0) or value_json.update_available %}on{% else %}off{% endif %}" 
    scan_interval: 3600 #check every hour (default is 60- every minute)
    json_attributes:
    - latest_version
    - current_version
    - addons

binary_sensor:
  - platform: template
    sensors:
      version_update_issues:
        friendly_name: 'Version Update Issues'
        device_class: problem
        value_template: >-
          {{ (state_attr('binary_sensor.version_update_issues', 'status')).outdated|count > 0 }}
        attribute_templates:
          status: >-
            {% set ns = namespace(outdated = [], up_to_date = [], optional_updates = []) -%}
            {%- for _updateSensor in (expand(states.sensor)|list) if _updateSensor.entity_id.endswith('_version') -%}
            {%- set _sensorName = _updateSensor.entity_id -%}
            {%- if _updateSensor.state == "on" -%}
              {%- set ns.outdated = ns.outdated + [_sensorName] -%}
            {%- else -%}
              {%- if _updateSensor.attributes.current_version!=_updateSensor.attributes.latest_version -%}
                {%- set ns.optional_updates = ns.optional_updates + [_sensorName] -%}
              {%- else -%}
                {%- set ns.up_to_date = ns.up_to_date + [_sensorName] -%}
              {%- endif -%}
            {%- endif -%}
            {% endfor %}
            {{ "{{\"up_to_date\": {}, \"optional_updates\": {}, \"outdated\": {} }}".format(ns.up_to_date, ns.optional_updates, ns.outdated) }}

And my notifications (using iOS, change the notifiers if you need):

alias: Device Health - Version Update Notification
description: ''
trigger:
  - platform: state
    entity_id: binary_sensor.version_update_issues
    to: 'on'
  - platform: time
    at: '14:00:00'
condition:
  - condition: state
    entity_id: binary_sensor.version_update_issues
    state: 'on'
action:
  - service: notify.admin_devices
    data:
      title: ⚠️Version Updates Available
      message: >-
        {%- for _updateSensor in
        states.binary_sensor.version_update_issues.attributes.status.outdated %}
          {{- "Stable Updates:" if loop.first }}
          {{- "\n "~states[_updateSensor].attributes.friendly_name ~ " [" ~ states[_updateSensor].attributes.current_version ~ "]"}}
          {%- if states[_updateSensor].attributes.current_version!=states[_updateSensor].attributes.latest_version -%}
            {{- "→["~ states[_updateSensor].attributes.latest_version ~"]"}}
          {%- endif -%}
          {%- if state_attr(_updateSensor, 'repositories') != None and state_attr(_updateSensor, 'repositories')|count > 0 -%} - repositories updates:
            {% for repository in state_attr(_updateSensor, 'repositories') %} 
              {{"\n -"~ repository.display_name }}: [{{ repository.installed_version }} ]→[ {{ repository.available_version }}]
              {% endfor %}
          {%- endif -%}
          {%- if state_attr(_updateSensor, 'addons') != None and state_attr(_updateSensor, 'addons')|count > 0-%} - addon updates:
            {% for addon in state_attr(_updateSensor, 'addons') %}
              - {{ addon.name }}: [{{ addon.version }} ]→[ {{ addon.version_latest }}]
              {% endfor %}
          {%- endif -%}
        {% endfor %} {% for _updateSensor in
        states.binary_sensor.version_update_issues.attributes.status.optional_updates
        %}
          {{- "\nOptional Updates:" if loop.first }}
          {{- "\n "~states[_updateSensor].attributes.friendly_name ~ " [" ~ states[_updateSensor].attributes.current_version ~ "]"}}
          {%- if states[_updateSensor].attributes.current_version!=states[_updateSensor].attributes.latest_version -%}
            {{- "→["~ states[_updateSensor].attributes.latest_version ~"]"}}
          {%- endif -%}
          {%- if state_attr(_updateSensor, 'repositories') != None and state_attr(_updateSensor, 'repositories')|count > 0 -%} - repositories updates:
            {% for repository in state_attr(_updateSensor, 'repositories') %} 
              {{"\n -"~ repository.display_name }}: [{{ repository.installed_version }} ]→[ {{ repository.available_version }}]
              {% endfor %}
          {%- endif -%}
          {%- if state_attr(_updateSensor, 'addons') != None and state_attr(_updateSensor, 'addons')|count > 0-%} - addon updates:
            {% for addon in state_attr(_updateSensor, 'addons') %}
              - {{ addon.name }}: [{{ addon.version }} ]→[ {{ addon.version_latest }}]
              {% endfor %}
          {%- endif -%}
        {% endfor %}
      data:
        url: /devices-health/health_panel
        push:
          thread-id: version-update-notification-group
        apns_headers:
          apns-collapse-id: version-update-issues
        presentation_options:
          - alert
mode: restart

alias: Device Health - Clear Version Update Notification
description: ''
trigger:
  - platform: state
    entity_id: binary_sensor.version_update_issues
    to: 'off'
condition: []
action:
  - service: notify.admin_devices
    data:
      title: ✅Version Updates Installed
      message: All components are up to date!
      data:
        url: /devices-health/health_panel
        push:
          thread-id: version-update-notification-group
        apns_headers:
          apns-collapse-id: version-update-issues
        presentation_options:
          - alert
mode: restart
5 Likes

Hi, I’m searching for a solution if a specific log entry is raised in log provider: host under …/hassio/system.
Is there a possibility to build a sensor that goes on if following value is in log?

cdc_acm 2-2:1.0: ttyACM0: USB ACM device

Hi everybody,

I must admit that I haven’t read the complete thread (estimated reading time: 49min - wow :slight_smile: ), so sorry if this has been asked/answered before:

Is it possible to share such an “update solution” as a Blueprint?

Best
Christian

It is shared as a package.
just create a package.device_health_notification.yaml file in your config directory and include the following ling in configuration.yaml:

packages:
    device_health_notification_pack: !include package.device_health_notification.yaml