> For the complete documentation index, see [llms.txt](https://apps.developer.homey.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://apps.developer.homey.app/wireless/z-wave/z-wave-firmware-updates.md).

# Z-Wave Firmware Updates

Homey supports the Z-Wave Firmware Update Metadata Command Class. With this command class it is possible for Homey to update the firmware that is running on Z-Wave devices. Your app can provide firmware files, and Homey takes care of installing the firmware to the device.

{% hint style="warning" %}
Z-Wave firmware updates are supported since Homey firmware v13.2.0, and is available for Homey Pro (Early 2023, 2026, mini), Homey Self-Hosted Server, and Homey Cloud. You need at least Homey Mobile App v9.10.0 or higher in order to start updates.
{% endhint %}

### Getting Started <a href="#getting-started" id="getting-started"></a>

You can add firmware updates to your drivers. To do this, you'll need to gather the firmware files for your devices and create a `/drivers/<driver_id>/driver.firmware.compose.json` file. The `driver.firmware.compose.json` file contains metadata for Homey to be able to select the correct update for your devices.

For more information on the Z-Wave Firmware Update Metadata Command Class, refer to the [Z-Wave specification](https://z-wavealliance.org/development-resources-overview/specification-for-developers/).

{% hint style="info" %}
The `homey app driver firmware` Homey CLI command will take you through creating or updating the `driver.firmware.compose.json` file. (Requires `homey` v4.3.0 or higher.)
{% endhint %}

#### File Structure <a href="#file-structure" id="file-structure"></a>

The `driver.firmware.compose.json` contains the following fields:

* `updates`: A list of all firmware updates for the devices of this driver.
* `wakeInstruction`: A description of how a Sleepy End Device (e.g battery-powered devices) can be made active by the user to start the firmware update. This field is not required for non-sleepy devices (takes a [Translation Object](https://apps.developer.homey.app/~/changes/1149/the-basics/app/internationalization)).

**Updates**

Each item in `updates` describes a firmware update for specific Zigbee devices. Every update contains the following fields:

* `version`: The version of this firmware in `<major>.<minor>.<patch>` format.
* `changelog`: A brief description of the changes in this update (takes a [Translation Object](https://apps.developer.homey.app/~/changes/1149/the-basics/app/internationalization)).
* `device`: An object with the `manufacturerId`, `productTypeId` and `productId` combination that identifies the target device(s) for this update.
  * A driver can target multiple devices (see [Z-Wave Manifest](/wireless/z-wave.md#manifest)). This field allows making a firmware update only available for a specific subset of those devices.
  * Add a `hardwareVersion` field to make an update available for specific hardware versions of the device. When added, the field must match the device's reported hardware version through the Version Command Class.
* `files`: A list of firmware update files included in this update.
  * In most cases, you'll only have a single file for your update.
* `applicableTo`: A semver comparison string that determines whether the current version of the device can install this update. (E.g. `>1.2.3`).

#### Update Files

Each entry in `updates[].files` describes one firmware file. The following metadata fields are required for each file:

* `targetId`: The target chip of this file, if you have only a single file this is `0`.
* `size`: The file size in bytes.
* `name`: The file name. The file itself must be stored in `/drivers/<driver_id>/assets/firmware/<file name>`.
* `integrity`: A hash of the file in the format `<hash_name>:<hex_encoded_hash>`.
  * The following hash types are supported: `sha256`, `sha384`, `sha512`, `sha512-256`, `sha3-256`, `sha3-384`, `sha3-512`, `blake2b512`, `blake2s256`.

{% hint style="info" %}
The `homey app driver firmware` command will automatically fill in the `size`, `name`, and `integrity` fields for you. You'll have to provide the file's `targetId`.
{% endhint %}

Optionally you can add the following field to limit where a firmware update is available:

* `region`: The Z-Wave region where this file should be applied. If not set, it is applied globally.
  * Possible values are:
    * `ANZ`: Australia/New Zealand (919.8 MHz / 921.4 MHz)
    * `CN`: China (868.4 MHz)
    * `EU`: Europe (868.4 MHz / 869.85 MHz)
    * `HK`: Hong Kong (919.8 MHz)
    * `IL`: Israel (916 MHz)
    * `IN`: India (865.2 MHz)
    * `JP`: Japan (922.5 MHz / 923.9 MHz / 926.3 MHz)
    * `KR`: Korea (920.9 MHz / 921.7 MHz / 923.1 MHz)
    * `RU`: Russia (869 MHz)
    * `US`: United States of America (908.4 MHz / 916 MHz)

{% hint style="danger" %}
Not providing the region when this is required can cause Homey to install an update to a device in the wrong region, which can make the device unusable in the user's region.
{% endhint %}

The firmware file that is provided by the Homey app, should be the file that can be directly transferred to the Z-Wave device. Homey does not do any pre-processing of the file before sending it to the device. Homey cannot validate that it is a proper firmware file, because Z-Wave doesn't have a specification-defined file format for firmware files.

{% hint style="info" %}
When you upload your Homey App, the firmware files are stored separately from your App. Only when Homey starts installing an update for a device, it will download the required files.
{% endhint %}

### Example

Putting everything together, a `driver.firmware.compose.json` file with a single update will look like this:

{% code title="/driver/\<driver\_id>/driver.firmware.compose.json" %}

```json
{
  "wakeInstruction": {
    "en": "Hold the internal button for three seconds."
  },
  "updates": [
    {
      "version": "1.3.0",
      "changelog": {
        "en": "- Fixes issue X\n- Adds feature Y\n- Deprecates feature Z"
      },
      "device": {
        "manufacturerId": 1234,
        "productTypeId": [1, 2],
        "productId": [3, 4]
      },
      "files": [
        {
          "targetId": 0,
          "size": 262144,
          "name": "AwesomeSensor_v1.3.4.bin",
          "integrity": "sha256:dac89981aeb5352a8ddce9fbb5ab3ad5bff88d17e2f7937cc90947301ccfedd2"
        }
      ]
    }
  ]
}
```

{% endcode %}

#### Firmware Version <a href="#firmware-files" id="firmware-files"></a>

Homey uses the Version Command Class to determine the device's current firmware version.

* **If the device supports `VERSION_ZWAVE_SOFTWARE_GET`:** The firmware version is derived from the `Application Version` field of the `VERSION_ZWAVE_SOFTWARE_REPORT`. The version is formatted as `<byte_1>.<byte_2>.<byte_3>`.
* **If the device only supports `VERSION_GET`:** The firmware version is derived from the `Application Version` and `Application Sub Version` fields of the `VERSION_REPORT`. The patch field is always treated as `0`, resulting in the format `<application_version>.<application_sub_version>.0`.

#### Firmware Files <a href="#firmware-files" id="firmware-files"></a>

Homey Apps are responsible for delivering the correct firmware files to the appropriate devices. Before shipping a firmware update in your Homey App, ensure the following:

* **Device targeting:** Verify that each firmware file is mapped to the correct device(s). Delivering a firmware file to an incompatible device can cause irreversible damage or render it unresponsive.
* **End-to-end testing:** Test the full update flow on the intended physical hardware. Confirm that Homey can correctly initiate, transfer, and complete the firmware update process.
* **Validation before release:** Do not add a firmware update to your app until both of the above have been verified. Untested firmware updates should never reach end users.

## Update Selection

Homey will select the firmware for your device based on the following:

1. The `updates[].device` field must match the device's reported `manufacturerId`, `productTypeId`, and `productId`.
2. One of the files in an update should match the currently used Z-Wave region.
3. The device's current version should match the update's `applicableTo` field.

If multiple updates are found for the device, the update with the highest `version` field will be selected.

### Multiple Firmware Files

Some devices might require multiple firmware files for a single update (e.g. when it also needs to update the firmware of another chip in the device). If your device requires this, add multiple files to the update with different `targetId`s. Homey will automatically start sending a file for the next `targetId` after a previous one was completed.

### Update Failures <a href="#update-failures" id="update-failures"></a>

Firmware updates can fail. Homey considers an update failed in the following cases:

* **Explicit abort:** The device reports an error status during image transfer, actively aborting the update.
* **Stalled transfer:** The device stops requesting firmware chunks before the transfer is complete.
* **No reconnection:** The device fails to rejoin the Z-Wave network within the expected timeframe after a file has been fully transferred.

In all failure cases, the user will be notified via the firmware update screen and can retry the installation.
