From 6b1ff69e9c0a15ca20e903e7cd7f7d628c6c9450 Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Fri, 3 Feb 2023 10:43:58 -0500 Subject: [PATCH 1/5] Add support for zwave_js controller firmware updates --- src/data/zwave_js.ts | 28 ++++- .../zwave_js/device-actions.ts | 111 ++++++++++-------- .../dialog-zwave_js-update-firmware-node.ts | 64 ++++++---- src/translations/en.json | 9 +- 4 files changed, 131 insertions(+), 81 deletions(-) diff --git a/src/data/zwave_js.ts b/src/data/zwave_js.ts index 779566e5e86f..0953a608ea36 100644 --- a/src/data/zwave_js.ts +++ b/src/data/zwave_js.ts @@ -108,7 +108,7 @@ enum RFRegion { "Default (EU)" = 0xff, } -export enum FirmwareUpdateStatus { +export enum NodeFirmwareUpdateStatus { Error_Timeout = -1, Error_Checksum = 0, Error_TransmissionFailed = 1, @@ -124,6 +124,19 @@ export enum FirmwareUpdateStatus { OK_RestartPending = 0xff, } +export enum ControllerFirmwareUpdateStatus { + // An expected response was not received from the controller in time + Error_Timeout = 0, + /** The maximum number of retry attempts for a firmware fragments were reached */ + Error_RetryLimitReached, + /** The update was aborted by the bootloader */ + Error_Aborted, + /** This controller does not support firmware updates */ + Error_NotSupported, + + OK = 0xff, +} + export interface QRProvisioningInformation { version: QRCodeVersion; securityClasses: SecurityClass[]; @@ -322,7 +335,7 @@ export interface ZWaveJSNodeStatusUpdatedMessage { status: NodeStatus; } -export interface ZWaveJSNodeFirmwareUpdateProgressMessage { +export interface ZWaveJSFirmwareUpdateProgressMessage { event: "firmware update progress"; current_file: number; total_files: number; @@ -333,12 +346,18 @@ export interface ZWaveJSNodeFirmwareUpdateProgressMessage { export interface ZWaveJSNodeFirmwareUpdateFinishedMessage { event: "firmware update finished"; - status: FirmwareUpdateStatus; + status: NodeFirmwareUpdateStatus; success: boolean; wait_time?: number; reinterview: boolean; } +export interface ZWaveJSControllerFirmwareUpdateFinishedMessage { + event: "firmware update finished"; + status: ControllerFirmwareUpdateStatus; + success: boolean; +} + export type ZWaveJSNodeFirmwareUpdateCapabilities = | { firmware_upgradable: false } | { @@ -747,8 +766,9 @@ export const subscribeZwaveNodeFirmwareUpdate = ( device_id: string, callbackFunction: ( message: + | ZWaveJSFirmwareUpdateProgressMessage + | ZWaveJSControllerFirmwareUpdateFinishedMessage | ZWaveJSNodeFirmwareUpdateFinishedMessage - | ZWaveJSNodeFirmwareUpdateProgressMessage ) => void ): Promise => hass.connection.subscribeMessage( diff --git a/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts b/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts index a6fd80387f74..ff37acf6f9e4 100644 --- a/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts +++ b/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts @@ -43,59 +43,68 @@ export const getZwaveDeviceActions = async ( const nodeStatus = await fetchZwaveNodeStatus(hass, device.id); - if (!nodeStatus || nodeStatus.is_controller_node) { + if (!nodeStatus) { return []; } - const actions = [ - { - label: hass.localize( - "ui.panel.config.zwave_js.device_info.device_config" - ), - icon: mdiCog, - href: `/config/zwave_js/node_config/${device.id}?config_entry=${entryId}`, - }, - { - label: hass.localize( - "ui.panel.config.zwave_js.device_info.reinterview_device" - ), - icon: mdiChatQuestion, - action: () => - showZWaveJSReinterviewNodeDialog(el, { - device_id: device.id, - }), - }, - { - label: hass.localize("ui.panel.config.zwave_js.device_info.heal_node"), - icon: mdiHospitalBox, - action: () => - showZWaveJSHealNodeDialog(el, { - device, - }), - }, - { - label: hass.localize( - "ui.panel.config.zwave_js.device_info.remove_failed" - ), - icon: mdiDeleteForever, - action: () => - showZWaveJSRemoveFailedNodeDialog(el, { - device_id: device.id, - }), - }, - { - label: hass.localize( - "ui.panel.config.zwave_js.device_info.node_statistics" - ), - icon: mdiInformation, - action: () => - showZWaveJSNodeStatisticsDialog(el, { - device, - }), - }, - ]; + const actions: DeviceAction[] = []; + + if (!nodeStatus.is_controller_node) { + actions.push( + { + label: hass.localize( + "ui.panel.config.zwave_js.device_info.device_config" + ), + icon: mdiCog, + href: `/config/zwave_js/node_config/${device.id}?config_entry=${entryId}`, + }, + { + label: hass.localize( + "ui.panel.config.zwave_js.device_info.reinterview_device" + ), + icon: mdiChatQuestion, + action: () => + showZWaveJSReinterviewNodeDialog(el, { + device_id: device.id, + }), + }, + { + label: hass.localize("ui.panel.config.zwave_js.device_info.heal_node"), + icon: mdiHospitalBox, + action: () => + showZWaveJSHealNodeDialog(el, { + device, + }), + }, + { + label: hass.localize( + "ui.panel.config.zwave_js.device_info.remove_failed" + ), + icon: mdiDeleteForever, + action: () => + showZWaveJSRemoveFailedNodeDialog(el, { + device_id: device.id, + }), + }, + { + label: hass.localize( + "ui.panel.config.zwave_js.device_info.node_statistics" + ), + icon: mdiInformation, + action: () => + showZWaveJSNodeStatisticsDialog(el, { + device, + }), + } + ); + } - if (!nodeStatus.ready || !nodeStatus.has_firmware_update_cc) { + if ( + !( + nodeStatus.ready && + (nodeStatus.is_controller_node || nodeStatus.has_firmware_update_cc) + ) + ) { return actions; } @@ -117,7 +126,9 @@ export const getZwaveDeviceActions = async ( (await fetchZwaveIsNodeFirmwareUpdateInProgress(hass, device.id)) || (await showConfirmationDialog(el, { text: hass.localize( - "ui.panel.config.zwave_js.update_firmware.warning" + `ui.panel.config.zwave_js.update_firmware.${ + nodeStatus.is_controller_node ? "warning_controller" : "warning" + }` ), dismissText: hass.localize("ui.common.no"), confirmText: hass.localize("ui.common.yes"), diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts index 4c8b194b9297..bb8d722a7a54 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts @@ -15,17 +15,19 @@ import { } from "../../../../../data/device_registry"; import { abortZwaveNodeFirmwareUpdate, + ControllerFirmwareUpdateStatus, fetchZwaveIsNodeFirmwareUpdateInProgress, fetchZwaveNodeStatus, - FirmwareUpdateStatus, + NodeFirmwareUpdateStatus, NodeStatus, subscribeZwaveNodeStatus, subscribeZwaveNodeFirmwareUpdate, uploadFirmwareAndBeginUpdate, ZWaveJSNodeFirmwareUpdateFinishedMessage, - ZWaveJSNodeFirmwareUpdateProgressMessage, + ZWaveJSFirmwareUpdateProgressMessage, ZWaveJSNodeStatusUpdatedMessage, ZWaveJSNodeStatus, + ZWaveJSControllerFirmwareUpdateFinishedMessage, } from "../../../../../data/zwave_js"; import { haStyleDialog } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; @@ -44,10 +46,12 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { @state() private _uploading = false; @state() - private _updateFinishedMessage?: ZWaveJSNodeFirmwareUpdateFinishedMessage; + private _updateFinishedMessage?: + | ZWaveJSNodeFirmwareUpdateFinishedMessage + | ZWaveJSControllerFirmwareUpdateFinishedMessage; @state() - private _updateProgressMessage?: ZWaveJSNodeFirmwareUpdateProgressMessage; + private _updateProgressMessage?: ZWaveJSFirmwareUpdateProgressMessage; @state() private _updateInProgress = false; @@ -71,12 +75,11 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { public closeDialog(): void { this._unsubscribeNodeFirmwareUpdate(); this._unsubscribeNodeStatus(); - this.device = - this._updateProgressMessage = - this._updateFinishedMessage = - this._firmwareFile = - this._nodeStatus = - undefined; + this.device = undefined; + this._updateProgressMessage = undefined; + this._updateFinishedMessage = undefined; + this._firmwareFile = undefined; + this._nodeStatus = undefined; this._uploading = this._updateInProgress = false; fireEvent(this, "dialog-closed", { dialog: this.localName }); @@ -111,16 +114,20 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { )} `; - const abortFirmwareUpdateButton = html` - - ${this.hass.localize("ui.panel.config.zwave_js.update_firmware.abort")} - - `; + const abortFirmwareUpdateButton = this._nodeStatus.is_controller_node + ? html`` + : html` + + ${this.hass.localize( + "ui.panel.config.zwave_js.update_firmware.abort" + )} + + `; const status = this._updateFinishedMessage - ? FirmwareUpdateStatus[this._updateFinishedMessage.status] - .split("_")[0] - .toLowerCase() + ? this._updateFinishedMessage.success + ? "success" + : "error" : undefined; return html` @@ -210,7 +217,9 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { : html`
@@ -221,9 +230,13 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { device: html`${this._deviceName}`, message: this.hass.localize( `ui.panel.config.zwave_js.update_firmware.finished_status.${ - FirmwareUpdateStatus[ - this._updateFinishedMessage!.status - ] + this._nodeStatus.is_controller_node + ? ControllerFirmwareUpdateStatus[ + this._updateFinishedMessage!.status + ] + : NodeFirmwareUpdateStatus[ + this._updateFinishedMessage!.status + ] }` ), } @@ -231,7 +244,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement {

- ${status === "ok" + ${this._updateFinishedMessage!.success ? html`

${this.hass.localize( "ui.panel.config.zwave_js.update_firmware.finished_status.done" @@ -345,8 +358,9 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { this.device.id, ( message: + | ZWaveJSFirmwareUpdateProgressMessage + | ZWaveJSControllerFirmwareUpdateFinishedMessage | ZWaveJSNodeFirmwareUpdateFinishedMessage - | ZWaveJSNodeFirmwareUpdateProgressMessage ) => { if (message.event === "firmware update progress") { if (!this._updateFinishedMessage) { @@ -378,7 +392,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { return [ haStyleDialog, css` - .ok { + .success { color: var(--success-color); } diff --git a/src/translations/en.json b/src/translations/en.json index 86166dd30e59..d7f9077e2af5 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3687,6 +3687,7 @@ }, "update_firmware": { "title": "Update Device Firmware", + "warning_controller": "WARNING: Firmware updates can brick your controller if you do not use the right firmware files, or if you attempt to stop the firmware update before it completes. The Home Assistant and Z-Wave JS teams do not take any responsibility for any damages to your controller as a result of the firmware update and will not be able to help you if you brick your controller. Would you still like to continue?", "warning": "WARNING: Firmware updates can brick your device if you do not correctly follow the manufacturer's guidance. The Home Assistant and Z-Wave JS teams do not take any responsibility for any damages to your device as a result of the firmware update and will not be able to help you if you brick your device. Would you still like to continue?", "introduction": "Select the firmware file you would like to use to update {device}.", "upload_firmware": "Upload Firmware", @@ -3701,7 +3702,7 @@ "abort_failed": "Abort Failed", "confirm_abort": "Are you sure you want to abort the firmware update on {device}?", "finished_status": { - "ok": "Successfully updated firmware on {device}: {message}.", + "success": "Successfully updated firmware on {device}: {message}.", "error": "Unable to update firmware on {device}: {message}.", "try_again": "To attempt the firmware update again, select the new firmware file you would like to use.", "done": "The firmware update is complete! If you want to attempt another firmware update on this device, please wait until it gets re-interviewed.", @@ -3717,7 +3718,11 @@ "Error_InvalidHardwareVersion": "Invalid Hardware Version", "OK_WaitingForActivation": "Waiting for Activation", "OK_NoRestart": "No Restart", - "OK_RestartPending": "Restart Pending" + "OK_RestartPending": "Restart Pending", + "Error_RetryLimitReached": "Retry Limit Reached", + "Error_Aborted": "Update Aborted by Bootloader", + "Error_NotSupported": "Firmware Updates not Supported", + "OK": "Success" } }, "logs": { From e943cc30c5cb7796a360e3c412d353a1198e606e Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Tue, 21 Feb 2023 18:56:37 -0500 Subject: [PATCH 2/5] Update controller message --- src/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translations/en.json b/src/translations/en.json index d7f9077e2af5..19c19ad98b93 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3722,7 +3722,7 @@ "Error_RetryLimitReached": "Retry Limit Reached", "Error_Aborted": "Update Aborted by Bootloader", "Error_NotSupported": "Firmware Updates not Supported", - "OK": "Success" + "OK": "Success! Please wait for the controller to restart." } }, "logs": { From 46c0ab82b4e401b543147c8a2cb354ce3095e7bb Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Tue, 21 Feb 2023 18:57:26 -0500 Subject: [PATCH 3/5] caps --- src/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translations/en.json b/src/translations/en.json index 19c19ad98b93..a011f7eede17 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3721,7 +3721,7 @@ "OK_RestartPending": "Restart Pending", "Error_RetryLimitReached": "Retry Limit Reached", "Error_Aborted": "Update Aborted by Bootloader", - "Error_NotSupported": "Firmware Updates not Supported", + "Error_NotSupported": "Firmware Updates Not Supported", "OK": "Success! Please wait for the controller to restart." } }, From 95d021bbd9c1e7b29660ca441f05c96b6889d2d1 Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Tue, 21 Feb 2023 21:25:50 -0500 Subject: [PATCH 4/5] Move constants out of render, update strings --- .../dialog-zwave_js-update-firmware-node.ts | 35 +++++++++++-------- src/translations/en.json | 6 ++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts index bb8d722a7a54..18e158f94867 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts @@ -65,6 +65,10 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { private _deviceName?: string; + private _localizationKeySuffix = ""; + + private _abortFirmwareUpdateButton = html``; + public showDialog(params: ZWaveJSUpdateFirmwareNodeDialogParams): void { this._deviceName = computeDeviceName(params.device, this.hass!); this.device = params.device; @@ -114,16 +118,6 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { )} `; - const abortFirmwareUpdateButton = this._nodeStatus.is_controller_node - ? html`` - : html` - - ${this.hass.localize( - "ui.panel.config.zwave_js.update_firmware.abort" - )} - - `; - const status = this._updateFinishedMessage ? this._updateFinishedMessage.success ? "success" @@ -144,7 +138,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { ? html`

${this.hass.localize( - "ui.panel.config.zwave_js.update_firmware.introduction", + `ui.panel.config.zwave_js.update_firmware.introduction${this._localizationKeySuffix}`, { device: html`${this._deviceName}`, } @@ -183,7 +177,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { } )}

- ${abortFirmwareUpdateButton} + ${this._abortFirmwareUpdateButton} ` : this._updateProgressMessage && !this._updateFinishedMessage ? html` @@ -212,7 +206,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { } )}

- ${abortFirmwareUpdateButton} + ${this._abortFirmwareUpdateButton} ` : html`
@@ -247,7 +241,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { ${this._updateFinishedMessage!.success ? html`

${this.hass.localize( - "ui.panel.config.zwave_js.update_firmware.finished_status.done" + `ui.panel.config.zwave_js.update_firmware.finished_status.done${this._localizationKeySuffix}` )}

` : html`

@@ -266,6 +260,19 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { fetchZwaveNodeStatus(this.hass, this.device!.id), fetchZwaveIsNodeFirmwareUpdateInProgress(this.hass, this.device!.id), ]); + if (this._nodeStatus.is_controller_node) { + this._localizationKeySuffix = "_controller"; + this._abortFirmwareUpdateButton = html``; + } else { + this._localizationKeySuffix = ""; + this._abortFirmwareUpdateButton = html` + + ${this.hass.localize( + "ui.panel.config.zwave_js.update_firmware.abort" + )} + + `; + } if (this._updateInProgress) { this._subscribeNodeFirmwareUpdate(); } diff --git a/src/translations/en.json b/src/translations/en.json index a011f7eede17..b2d36c03371b 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3687,9 +3687,10 @@ }, "update_firmware": { "title": "Update Device Firmware", - "warning_controller": "WARNING: Firmware updates can brick your controller if you do not use the right firmware files, or if you attempt to stop the firmware update before it completes. The Home Assistant and Z-Wave JS teams do not take any responsibility for any damages to your controller as a result of the firmware update and will not be able to help you if you brick your controller. Would you still like to continue?", "warning": "WARNING: Firmware updates can brick your device if you do not correctly follow the manufacturer's guidance. The Home Assistant and Z-Wave JS teams do not take any responsibility for any damages to your device as a result of the firmware update and will not be able to help you if you brick your device. Would you still like to continue?", + "warning_controller": "WARNING: Firmware updates can brick your controller if you do not use the right firmware files, or if you attempt to stop the firmware update before it completes. The Home Assistant and Z-Wave JS teams do not take any responsibility for any damages to your controller as a result of the firmware update and will not be able to help you if you brick your controller. Would you still like to continue?", "introduction": "Select the firmware file you would like to use to update {device}.", + "introduction_controller": "Select the firmware file you would like to use to update {device}. Note that once you start a firmware update, you MUST wait for the update to complete.", "upload_firmware": "Upload Firmware", "upload_failed": "Upload Failed", "begin_update": "Begin Firmware Update", @@ -3706,6 +3707,7 @@ "error": "Unable to update firmware on {device}: {message}.", "try_again": "To attempt the firmware update again, select the new firmware file you would like to use.", "done": "The firmware update is complete! If you want to attempt another firmware update on this device, please wait until it gets re-interviewed.", + "done_controller": "The firmware update is complete! Your controller is being restarted and your network will temporarily be unavailable.", "Error_Timeout": "Timed Out", "Error_Checksum": "Checksum Error", "Error_TransmissionFailed": "Transmission Failed", @@ -3722,7 +3724,7 @@ "Error_RetryLimitReached": "Retry Limit Reached", "Error_Aborted": "Update Aborted by Bootloader", "Error_NotSupported": "Firmware Updates Not Supported", - "OK": "Success! Please wait for the controller to restart." + "OK": "Success" } }, "logs": { From 82da57fa566a3937b0f516340109c51747014556 Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Wed, 22 Feb 2023 10:45:22 -0500 Subject: [PATCH 5/5] Move vars back to render --- .../dialog-zwave_js-update-firmware-node.ts | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts index 18e158f94867..d58c1822b19c 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts @@ -65,10 +65,6 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { private _deviceName?: string; - private _localizationKeySuffix = ""; - - private _abortFirmwareUpdateButton = html``; - public showDialog(params: ZWaveJSUpdateFirmwareNodeDialogParams): void { this._deviceName = computeDeviceName(params.device, this.hass!); this.device = params.device; @@ -124,6 +120,20 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { : "error" : undefined; + const localizationKeySuffix = this._nodeStatus.is_controller_node + ? "_controller" + : ""; + + const abortFirmwareUpdateButton = this._nodeStatus.is_controller_node + ? html`` + : html` + + ${this.hass.localize( + "ui.panel.config.zwave_js.update_firmware.abort" + )} + + `; + return html` ${this.hass.localize( - `ui.panel.config.zwave_js.update_firmware.introduction${this._localizationKeySuffix}`, + `ui.panel.config.zwave_js.update_firmware.introduction${localizationKeySuffix}`, { device: html`${this._deviceName}`, } @@ -177,7 +187,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { } )}

- ${this._abortFirmwareUpdateButton} + ${abortFirmwareUpdateButton} ` : this._updateProgressMessage && !this._updateFinishedMessage ? html` @@ -206,7 +216,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { } )}

- ${this._abortFirmwareUpdateButton} + ${abortFirmwareUpdateButton} ` : html`
@@ -241,7 +251,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { ${this._updateFinishedMessage!.success ? html`

${this.hass.localize( - `ui.panel.config.zwave_js.update_firmware.finished_status.done${this._localizationKeySuffix}` + `ui.panel.config.zwave_js.update_firmware.finished_status.done${localizationKeySuffix}` )}

` : html`

@@ -260,19 +270,6 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement { fetchZwaveNodeStatus(this.hass, this.device!.id), fetchZwaveIsNodeFirmwareUpdateInProgress(this.hass, this.device!.id), ]); - if (this._nodeStatus.is_controller_node) { - this._localizationKeySuffix = "_controller"; - this._abortFirmwareUpdateButton = html``; - } else { - this._localizationKeySuffix = ""; - this._abortFirmwareUpdateButton = html` - - ${this.hass.localize( - "ui.panel.config.zwave_js.update_firmware.abort" - )} - - `; - } if (this._updateInProgress) { this._subscribeNodeFirmwareUpdate(); }