I’ve come up with the following automation.
This runs at 19:30 each day and checks for any update.* entities with state=on (devices needing an update).
For each device needing an update it publishes an MQTT message to Z2M to trigger an OTA update, waits for the update to start, then waits for the update to finish before going on to the next device.
I know there may be other devices with entities of update.*, but Z2M simply ignores anything where there isn’t a matching device name or where an update isn’t required, so it works ok.
Of course, this could be run on any other time pattern, etc.
alias: Check for and trigger Z2M OTA updates
description: >-
Checks for and trigger Z2M OTA updates.
trigger:
- platform: time_pattern
minutes: "30"
hours: "19"
condition: []
action:
- variables:
update_entities: >
{{ states.update | selectattr('state', 'eq', 'on') |
map(attribute='entity_id') | list }}
alias: Get list of Z2M devices needing an update
- alias: Run OTA update on devices with updates
repeat:
sequence:
- variables:
triggered_entity: "{{ repeat.item }}"
alias: Get entity_id of this specific device
- service: mqtt.publish
metadata: {}
data:
qos: 0
retain: false
topic: zigbee2mqtt/bridge/ota_update/update
payload: "{{ states[triggered_entity].attributes.friendly_name }}"
alias: Send MQTT message to Z2M to request update
- wait_template: "{{ is_state_attr(triggered_entity, 'in_progress', true) }}"
continue_on_timeout: true
timeout: "00:01:00"
alias: Wait a minute for the Z2M update to start
- wait_template: "{{ is_state_attr(triggered_entity, 'in_progress', false) }}"
continue_on_timeout: true
timeout: "01:00:00"
alias: Wait up to 1 hour for the OTA upgrade to finish
for_each: "{{ update_entities }}"
mode: single