ZHA Firmware Update Guide

I recently needed to update a few switches from an older firmware to the latest via ZHA on Home Assistant and couldn’t find a direct guide, so I wanted to contribute to the community on how I accomplished it. Please realize that I’m intentionally making this a “guide for dummies” to remove any ambiguity for non tech-savvy folk, and forgive me for some of the explanations that delve deeper into simple tasks that some of us already know.

ZHA supports OTA (Over the Air) updates for Inovelli switches, but this needs to be enabled via configuration YAML changes. From your HA install, navigate to “File editor” and ensure you’re editing the configuration.yaml file. Insert the following:

      inovelli_provider: true
      otau_directory: /config/zigpy_ota

Indentation matters with YAML, so be sure you copy and paste the literal text from above.

Then click the “Browse Filesystem” button at the top of the File editor UI, and click “New folder”. In the prompt, type zigpy_ota

What you’ve done, at this point, is configured ZHA to enable OTA updated for Inovelli switches and scan the OTA folder for matching binaries to update. All we need now is the binary to update to!

For 2.15, this is currently found in the beta folder of the inovelli github repository. While this is marked as beta, Inovelli is currently shipping new switches with this firmware (and I’m running several of them without problems) so it can be considered “production” at this point.

For firmware 2.15, use the following link: 2.15. Click “Download raw file” from the Github page, which will retrieve a file named VZM31-SN_2.15.ota

Back in Home Assistant’s File Editor, navigate to the newly created folder named zigpy_ota by clicking the Folder icon at the top and selecting the directory named that. Then click the “Upload file” icon from the same page, and select the file you downloaded from Github earlier.

Now you need to restart Home Assistant to effectively reboot ZHA to reconfigure and scan for the new OTA files for your switch. You can do this via the “Settings → System → Corner Power Icon → Restart Home Assistant”

HA will start back up and the OTA won’t happen immediately. Time for a cuppa. Eventually, your switch will start showing the firmware progress LED (displayed as a slow blink effect), assuming your switch has the Firmware progress LED setting enabled (it is by default). This update takes time: while the file is less than a megabyte, zigbee is a slow transmission protocol; give the switch around 30 minutes to update.

After the LED on the switch is done flickering a progress bar, check/refresh the device in ZHA. To check the version string, click the “hamburger” icon next to the Reconfigure text on the device page and select Manage zigbee device.

Pick the Basic “Cluster” from the dropdown that appears, and select the sw_build_id attribute. Click Read. If the device updated successfully, you should see 2.15.

At this point, your switch is on the most recent firmware. Congrats! However, you may be missing some of the new entities which recent firmwares exposes (for example, Led scaling mode). There may be a better way, but I personally just chose to remove my switches from ZHA by clicking the same “hamburger” icon mentioned above and selecting “Remove”, and then re-adding the device via ZHA (like you originally did to add it). This will cause HA to reinterview the switch and generate all new parameters as entities. This may effect existing automations/etc, so be aware before doing so (I’m not entirely sure on this part).

I hope this helps! If screenshots/etc would help anybody, or if any part is unclear, please respond to this post and I’ll gladly edit/update with additional clarification and steps and images. Happy ZHA switching!

FYI, these are enabling 2 ways of handling the updates. If you want automatic OTA updates that grab the firmware directly from Inovelli, that first line enables them. If you’re looking to push a file locally, you can leave that out or put it in but set it to the default of “inovelli_provider: false” so you don’t have your switches automatically update when you’re not expecting it. Local pushes just need that otau_directory parameter set.

You can also kick off the update sooner post-restart if you want. Grab the IEEE from the device page, go to developer tools and issuing the following to prompt it to check immediately -

service: zha.issue_zigbee_cluster_command
  ieee: "xx:xx:xx:xx:xx:xx:xx:xx"
  endpoint_id: 1
  cluster_id: 25
  cluster_type: out
  command: 0
  command_type: client
    - 0
    - 100

I was literally searching for this last night as I was running into an issue that looks like was resolved by newer firmware (I was still on the original shipping firmware).

I took a few screenshots along the way that I think might help less technical users. After work today I’ll review & clean up so you can add them if you want.

The one thing that might be good to add is that in HA the firmware version is given in hex (I assume, didn’t actually try converting it) and not decimal; ie, HA will show 0x0102020f for firmware and not 2.15.

1 Like

Yup. I’d read reports from other users that the current auto OTA update won’t pull 2.15 since it resides in the beta directory at the moment, so included the manual steps for download and placement on HA. I also wanted the inovelli_provider to be true, as I’m a weirdo who is fine with auto updates surprising me once they release. Thanks for describing this better, though, since others may not prefer that.

I also did this, and it did seem to work… the args on that payload are apparently deprecated and HA throws warnings in logs, but it did work!

The method I outline for retrieving the build_id param in the cluster bindings actually will show the decimal version number, FYI. But yup; the ZHA device page will show that hex.

I also don’t mind adding some screenshots of my own, if they help anybody. But if you already have some handy, I’d be happy to toss them into the OP on this thread! Thanks!

When I get some time I should grab the updated params and update the docs too, but yeah that’s what’s listed on the integration page :slight_smile:

Hello @justinlindh,

Thanks for this write-up. It inspired me to look into what firmware I had on my switches. Turns out, my 7 switches are running 2.11.

As a result, I followed your instructions step-by-step. Unfortunately, I ran into some hiccups. First, for months now I have had the OTA update line in the YAML set to true. However, in that time I never received and OTA update. Naturally, I tried your method of pushing them locally (download file, restarting HA, etc.). After some time, the updates were never pushed. Then I tried @chack 's solution which did initiate the update as I saw the visual prompts. Despite the warnings in the logs about the args, the updates appear to have completed.

However, I am still seeing a 2.11 firmware version even after restarting and shutting HA down completely. Would you have any idea as to what I am overlooking here? It is likely something so simply.

Thanks in advance.

[Update 9.4.23]
After some time, the updates began pushing automatically - albeit at the same time. I believe this flooded my zigbee network which resulted in numerous failures. I kept trying to cluster command approach one at a time, and eventually this method did work.

Apologies, but I just haven’t run into that specific issue yet, so I’m not entirely sure. Generally, that’s where I’d start enabling debug logging.

Reading your update, though, sounds like you were eventually able to get it working. Awesome! I hadn’t considered too many simultaneous updates to be something that could be a problem, but I’ve only updated 2 switches at a time so far. Good to know, though, since future firmware pushes might repro that same issue for me and others!

Thank you for the guide, however I would prefer to just have the update done automatically. Is there any reason 2.15 is still in beta if it is being installed in production devices?

Following up on the dev tool update code, the following is the way to format the cluster command for updating without getting the error about args being deprecated.

PLEASE NOTE - this will only work for the VZM31-SN and the file version lines up with 2.15 (only expect the last 2 characters to change for other versions), the VZM35-SN fan switch as an example uses a different image_type field. I also haven’t tested if this lets you check for a specific upgrade that may let you pick a higher version but not the newest (older versions weren’t supported by zigpy last I checked, it’s part of the firmware update validation).

service: zha.issue_zigbee_cluster_command
  ieee: "xx:xx:xx:xx:xx:xx:xx:xx"
  endpoint_id: 1
  cluster_id: 25
  cluster_type: out
  command: 0
  command_type: client
    payload_type: 0x00
    query_jitter: 100
    manufacturer_code: 4655
    image_type: 257
    new_file_version: 16908815
1 Like

In case it helps anyone, I was able to trigger my Blue 2-1 switches to check for firmware updates using ZHA Toolkit (installed via HACS), which was easier than typing in the parameters.

  1. Set up the zha > zigpy_config > ota settings in configuration.yaml as described above. (You can use inovelli_provider: false if you intend to put the new firmware in the zigpy_ota folder yourself manually. The inovelli_provider setting is for automatically pulling the updates from Inovelli servers, and last I checked a while ago, the servers were not offering the 2.15 firmware for ZHA.)
  2. Go to Developer Tools > Services and select the zha_toolkit.ota_notify service (“Trigger Device’s Firmware Update”).
  3. For “Device Reference” field, select the light.[your_switch_name]_light entity.
  4. Click “Call Service”.

No other settings or parameter changes were needed (I didn’t have to enter the image type, file version, etc.)

1 Like

Another approach which worked for me (via the zigpy GitHub docs):

From device card right from “reconfigure” the three dots, manage zigbee device, select OTA cluster (id: 0x0019), click commands, select image_notify (id: 0x0000), and mark payload_type: QueryJitter and move the query_jitter slider so its not being at default zero.

Note: Ignore “mandatory” manufacturer_code/image_type/new_file_version fields and still click grayed out “Issue Zigbee command” button.

Click Issue Zigbee command and waking up the device by clicking one button if its one sleeping device so it can receiving the command.

As of last night, firmware upgrades for Inovelli Zigbee Devices on ZHA will show on an update entity! Neat!

Is there anyway to upload local firmware vs what I’m assuming is cloud firmware with the recent home assistant update? I’m trying to upload beta firmware but getting “no ota image available” in the logs

1 Like

The devs for zigpy (what ZHA is built on) added another key/value pair to make it more difficult to enable local OTA for the time being. Not certain when that’s expected to change unfortunately, but would lean towards sticking with the more ‘official’ method for now.

This configuration still works…

      otau_directory: /some/directory/you/created 

It will consider firmware files you put in that directory

Are you updated to 2024.2.0?

Yes, but I’m not totally sure if I put the beta firmware on my fan switches before or after the update yesterday.

I’m pretty sure it would’ve been before if you aren’t certain. If you do have something else pending being updated though I’d be curious :slight_smile:

Everything is up to date for me, I’m willing to try stuff though. Just got a zigpy dev environment mostly setup too

I just installed another (older stock firmware) switch tonight. Yeah, the new ZHA upgrade support seems to have regressed the ability to flash local firmwares.


You lie, ZHA: that’s 2.08 and latest production firmware is 2.15, which is present in my zigpy_ota directory and used to trigger OTA update just fine. So yeah, the guide in the OP in this thread is likely no longer applicable and useful and we need something new to actually update to latest prod firmwares via ZHA.