Script to Update all updateable devices (shelly/wled) at once

Hi all,

was very amazed, that HA now supports updating Shellies directly. What i’d like to do now is to create a script (to e.g. use in an automation) that updates all shellies (and WLED devices) at once. What i’m trying to do is create a data template, look for all button-entities and filter those whose devices class is “update”. These devices entity-id should be then put one after into a service call.

What i have so far:

alias: ShellyUpdate-Testscript
sequence:
  - service: button.press
    data_template:
      entity_id: >
        {%- for shellyupdate in states.button -%}  
          {%- if state_attr(shellyupdate.entity_id,'device_class') == 'update'  -%} 
            - {{ shellyupdate.entity_id +"\n"}} 
          {%- endif -%} 
        {%- endfor -%}
mode: single

of course, i did the coding of the loop in the developer tools, there it works as expected:

sadly, the script gives an error:

… not a valid value for dictionary value @ data[‘entity_id’]

What tiny little detail am i missing?

Thanks for your support! :slight_smile:

I don’t have any buttons, so I can’t test it fully, but I believe the tiny detail is that your YAML should look a little different. Specifically, data_template should be replaced with target.

Also, a couple notes on the template: entity_id accepts any form of a list object and, personally, I prefer the existing filters over Jinja logic.

So, I successfully ran this:

service: light.turn_on
data:
  brightness_pct: 100
target:
  entity_id: "{{ states.light | selectattr('entity_id', 'search', 'office') | map(attribute='entity_id') | list }}"

And, following suit, yours would look something like this:

service: button.press
target:
  entity_id: >
    {{
      states.button
      | selectattr('attribute.device_class', 'eq', 'update')
      | map(attribute='entity_id')
      | list
    }}

Hey! Thanks for your input. Now I get this error:

I‘ll play around with it tomorrow :slight_smile:

Maybe it is because device_class is not an attribute but a state.

Keep you updated

Thanks

Huh, all of my templates in the template editor just broke with similar errors… They all worked yesterday, I swear! :laughing: I only have one template in my editor, and I know it was working yesterday, and today it is giving me TypeError: unhashable type: 'TemplateState'.

I’m at a bit of a loss. I can’t find any info related to this and all I did in that time was update the HA OS. I didn’t see any changes in the release notes related to the template editor, and I don’t think the OS would affect that anyway. Hopefully someone comes along who knows what happened.

Does this approach help?

After i have played around with it a little bit more yesterday, this is my working code now for the script. :slight_smile:

service: button.press
target:
  entity_id: >
    {% for state in states.button %} {% if 'update' in state.entity_id %}  {{
    state.entity_id }} {% if not loop.last %}, {% endif %} {% endif %} {% endfor
    %}

@tom_l that also looks interesting, although it requires a lovelace plugin. but: a good starting point to now put this script into some automation, do auto-updates every week or show a button (which triggers al updates) once an update is available :slight_smile:

2 Likes

Doesn’t really matter now, but I just got around to “fixing” my template editor and could figure out why you saw that error: a simple typo :slight_smile: it should be attributes, not attribute.

I am 100% sure this template works, copied directly from my template editor:

{{ states.sensor | selectattr('attributes.device_class', 'eq', 'battery') | map(attribute='entity_id') | list }}

You should be able to specify any entity type or device class you want, I just don’t have any with type button or class update.

Now that both entities; firmware_update and OTA_update are deprecated and they’ve been replaced with update.entity_id_firmware_update (which is one of the hidden entities in the top pane now shown with a Shelly icon), is there an update to the scrip above that would still work to update all?

You can set up an auto-update…

If you don’t want to update other items, just select the exceptions.

https://community.home-assistant.io/t/scheduled-auto-update-for-home-assistant/459281/20

Thanks! didn’t know that existed. Will take a look.

1 Like

One suggestion…

Suggestion I made FOR UI to allow for updating ONLY core-Home Assistant This would seem to be critical if you are going to use this updater to update Shelly’s but NOT have it interfere with your docker container.

Thanks!
–Tom

Is there a way to filter only for shelly devices? When I run your script i get an error that “fritz_box_update_…” is not a valid id and i tried a “and not “fritz” in state.entity_id” filter but that doesnt work for me.

I played with the service call and if you don’t want to autoupdate but you would decide when you would install the updates for all your shelly devices it worked for me:

service: update.install
target:
  entity_id: >
    {%- for shellyupdate in states.update -%}
      {%- if state_attr(shellyupdate.entity_id, 'device_class') == 'firmware' -%}
        {%- set release_url = state_attr(shellyupdate.entity_id, 'release_url') -%}
        {%- if release_url is not none and 'shelly' in release_url and is_state(shellyupdate.entity_id, 'on') -%}
          {{ "\n" + "    - " + shellyupdate.entity_id }} 
        {%- endif -%}
      {%- endif -%}
    {%- endfor -%}

It could be even better:

service: update.install
target:
  entity_id: >
    {%- set entities = states.update
      | selectattr('attributes.device_class', 'eq', 'firmware')
      | selectattr('attributes.release_url', 'search', 'shelly')
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | list -%}
    {{ entities | join(', ') }}
1 Like

I had an issue with 'homeassistant.util.read_only_dict.ReadOnlyDict object' has no attribute 'release_url', so I had to modify your script as follows:

{%- set entities = states.update
      | selectattr('attributes.device_class', 'eq', 'firmware')
      | rejectattr('attributes.release_url', 'undefined')
      | selectattr('attributes.release_url', 'search', 'shelly')
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | list -%}

How would I craft the same thing but for pressing the “reboot” button? I tried a few things but never got it to work.