From d8d16c4d5f54562f53afcfbf6e666222c1fae34a Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Tue, 24 Oct 2023 17:16:21 -0400 Subject: [PATCH] Add Z-Wave controller hard reset device action (certification req) (#18216) Co-authored-by: Bram Kragten --- src/data/zwave_js.ts | 9 ++ .../zwave_js/device-actions.ts | 19 ++- .../dialog-zwave_js-hard-reset-controller.ts | 136 ++++++++++++++++++ ...w-dialog-zwave_js-hard-reset-controller.ts | 19 +++ ...ow-dialog-zwave_js-update-firmware-node.ts | 2 +- src/translations/en.json | 16 +++ 6 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-hard-reset-controller.ts create mode 100644 src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-hard-reset-controller.ts diff --git a/src/data/zwave_js.ts b/src/data/zwave_js.ts index 1c73185656..fd5ee1b4c2 100644 --- a/src/data/zwave_js.ts +++ b/src/data/zwave_js.ts @@ -757,6 +757,15 @@ export const fetchZwaveNodeFirmwareUpdateCapabilities = ( device_id, }); +export const hardResetController = ( + hass: HomeAssistant, + entry_id: string +): Promise => + hass.callWS({ + type: "zwave_js/hard_reset_controller", + entry_id, + }); + export const uploadFirmwareAndBeginUpdate = async ( hass: HomeAssistant, device_id: string, 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 d6d4af86de..5fcdb65851 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 @@ -19,8 +19,9 @@ import { showZWaveJSRebuildNodeRoutesDialog } from "../../../../integrations/int import { showZWaveJSNodeStatisticsDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-node-statistics"; import { showZWaveJSReinterviewNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-reinterview-node"; import { showZWaveJSRemoveFailedNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-remove-failed-node"; -import { showZWaveJUpdateFirmwareNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-update-firmware-node"; +import { showZWaveJSUpdateFirmwareNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-update-firmware-node"; import type { DeviceAction } from "../../../ha-config-device-page"; +import { showZWaveJSHardResetControllerDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-hard-reset-controller"; export const getZwaveDeviceActions = async ( el: HTMLElement, @@ -136,7 +137,7 @@ export const getZwaveDeviceActions = async ( confirmText: hass.localize("ui.common.yes"), })) ) { - showZWaveJUpdateFirmwareNodeDialog(el, { + showZWaveJSUpdateFirmwareNodeDialog(el, { device, }); } @@ -144,5 +145,19 @@ export const getZwaveDeviceActions = async ( }); } + if (nodeStatus.is_controller_node) { + actions.push({ + label: hass.localize( + "ui.panel.config.zwave_js.device_info.hard_reset_controller" + ), + icon: mdiDeleteForever, + action: async () => { + showZWaveJSHardResetControllerDialog(el, { + entryId, + }); + }, + }); + } + return actions; }; diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-hard-reset-controller.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-hard-reset-controller.ts new file mode 100644 index 0000000000..b9dee78f21 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-hard-reset-controller.ts @@ -0,0 +1,136 @@ +import { mdiCheckCircle, mdiDeleteForever, mdiRestore } from "@mdi/js"; +import "@material/mwc-button/mwc-button"; +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { fireEvent } from "../../../../../common/dom/fire_event"; +import { createCloseHeading } from "../../../../../components/ha-dialog"; +import "../../../../../components/ha-svg-icon"; +import { hardResetController } from "../../../../../data/zwave_js"; +import { haStyleDialog } from "../../../../../resources/styles"; +import { HomeAssistant } from "../../../../../types"; +import { ZWaveJSHardResetControllerDialogParams } from "./show-dialog-zwave_js-hard-reset-controller"; +import { showConfirmationDialog } from "../../../../../dialogs/generic/show-dialog-box"; +import { navigate } from "../../../../../common/navigate"; + +enum ResetStatus { + NotStarted, + InProgress, + Done, +} + +const iconMap = { + [ResetStatus.NotStarted]: mdiDeleteForever, + [ResetStatus.InProgress]: mdiRestore, + [ResetStatus.Done]: mdiCheckCircle, +}; + +@customElement("dialog-zwave_js-hard-reset-controller") +class DialogZWaveJSHardResetController extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _entryId?: string; + + @state() private _resetStatus = ResetStatus.NotStarted; + + public showDialog(params: ZWaveJSHardResetControllerDialogParams): void { + this._entryId = params.entryId; + } + + public closeDialog(): void { + this._entryId = undefined; + this._resetStatus = ResetStatus.NotStarted; + + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + protected render() { + if (!this._entryId) { + return nothing; + } + + return html` +
+
+ +
+

+ ${this.hass.localize( + `ui.panel.config.zwave_js.hard_reset_controller.${ + ResetStatus[this._resetStatus] + }.body` + )} +

+
+ ${this._resetStatus === ResetStatus.NotStarted + ? html` + ${this.hass.localize("ui.common.continue")} + + + ${this.hass.localize("ui.common.cancel")} + ` + : nothing} +
`; + } + + private async _hardResetController(): Promise { + if ( + await showConfirmationDialog(this, { + text: this.hass.localize( + `ui.panel.config.zwave_js.hard_reset_controller.confirmation` + ), + dismissText: this.hass.localize("ui.common.cancel"), + confirmText: this.hass.localize("ui.common.continue"), + destructive: true, + }) + ) { + this._resetStatus = ResetStatus.InProgress; + const deviceId = await hardResetController(this.hass, this._entryId!); + setTimeout(() => navigate(`/config/devices/device/${deviceId}`), 0); + this._resetStatus = ResetStatus.Done; + } + } + + static get styles(): CSSResultGroup { + return [ + haStyleDialog, + css` + .icon { + color: var(--label-badge-red); + } + .flex-container { + display: flex; + align-items: center; + margin-bottom: 5px; + } + + ha-svg-icon { + width: 68px; + height: 48px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-zwave_js-hard-reset-controller": DialogZWaveJSHardResetController; + } +} diff --git a/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-hard-reset-controller.ts b/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-hard-reset-controller.ts new file mode 100644 index 0000000000..fa46ec804f --- /dev/null +++ b/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-hard-reset-controller.ts @@ -0,0 +1,19 @@ +import { fireEvent } from "../../../../../common/dom/fire_event"; + +export interface ZWaveJSHardResetControllerDialogParams { + entryId: string; +} + +export const loadHardResetControllerDialog = () => + import("./dialog-zwave_js-hard-reset-controller"); + +export const showZWaveJSHardResetControllerDialog = ( + element: HTMLElement, + hardResetControllerDialogParams: ZWaveJSHardResetControllerDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-zwave_js-hard-reset-controller", + dialogImport: loadHardResetControllerDialog, + dialogParams: hardResetControllerDialogParams, + }); +}; diff --git a/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-update-firmware-node.ts index 69c7cc4729..ee3efb760e 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-update-firmware-node.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-update-firmware-node.ts @@ -8,7 +8,7 @@ export interface ZWaveJSUpdateFirmwareNodeDialogParams { export const loadUpdateFirmwareNodeDialog = () => import("./dialog-zwave_js-update-firmware-node"); -export const showZWaveJUpdateFirmwareNodeDialog = ( +export const showZWaveJSUpdateFirmwareNodeDialog = ( element: HTMLElement, updateFirmwareNodeDialogParams: ZWaveJSUpdateFirmwareNodeDialogParams ): void => { diff --git a/src/translations/en.json b/src/translations/en.json index cc1ef6e6b1..81fdeee0e3 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4030,11 +4030,27 @@ "remove_failed": "Remove failed", "update_firmware": "Update", "highest_security": "Highest security", + "hard_reset_controller": "Factory reset", "unknown": "Unknown", "zwave_plus": "Z-Wave Plus", "zwave_plus_version": "Version {version}", "node_statistics": "Statistics" }, + "hard_reset_controller": { + "NotStarted": { + "title": "Reset Controller to Factory Settings", + "body": "If you decide to move forward, you will reset your controller to factory settings. As a result, the controller will forget all devices it is paired with and all Z-Wave devices for this network will be removed from Home Assistant. If there are any devices still paired with the controller when it is reset, they will have to go through the exclusion process before they can be re-paired. Would you like to continue?" + }, + "InProgress": { + "title": "Resetting Controller", + "body": "Your controller is being reset and restarted. Wait until the process is complete before closing this dialog" + }, + "Done": { + "title": "Controller Reset Complete", + "body": "Your controller has been reset to factory settings and has been restarted! You can now close this dialog." + }, + "confirmation": "This action cannot be undone unless you have an NVM backup from your controller." + }, "node_statistics": { "title": "Device statistics", "commands_tx": {