diff --git a/src/data/zha.ts b/src/data/zha.ts index f989708257..e57df4078a 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -82,12 +82,17 @@ export interface ZHAGroupMember { export const reconfigureNode = ( hass: HomeAssistant, - ieeeAddress: string -): Promise => - hass.callWS({ - type: "zha/devices/reconfigure", - ieee: ieeeAddress, - }); + ieeeAddress: string, + callbackFunction: any +) => { + return hass.connection.subscribeMessage( + (message) => callbackFunction(message), + { + type: "zha/devices/reconfigure", + ieee: ieeeAddress, + } + ); +}; export const refreshTopology = (hass: HomeAssistant): Promise => hass.callWS({ diff --git a/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-actions-zha.ts b/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-actions-zha.ts index ddca57c922..4d0b380bb2 100644 --- a/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-actions-zha.ts +++ b/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-actions-zha.ts @@ -11,16 +11,13 @@ import { } from "lit-element"; import { navigate } from "../../../../../../common/navigate"; import { DeviceRegistryEntry } from "../../../../../../data/device_registry"; -import { - fetchZHADevice, - reconfigureNode, - ZHADevice, -} from "../../../../../../data/zha"; +import { fetchZHADevice, ZHADevice } from "../../../../../../data/zha"; import { showConfirmationDialog } from "../../../../../../dialogs/generic/show-dialog-box"; import { haStyle } from "../../../../../../resources/styles"; import { HomeAssistant } from "../../../../../../types"; import { showZHAClusterDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-cluster"; import { showZHADeviceZigbeeInfoDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-device-zigbee-info"; +import { showZHAReconfigureDeviceDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-reconfigure-device"; import { showZHADeviceChildrenDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-device-children"; @customElement("ha-device-actions-zha") @@ -108,7 +105,7 @@ export class HaDeviceActionsZha extends LitElement { if (!this.hass) { return; } - reconfigureNode(this.hass, this._zhaDevice!.ieee); + showZHAReconfigureDeviceDialog(this, { device: this._zhaDevice! }); } private _onAddDevicesClick() { diff --git a/src/panels/config/integrations/integration-panels/zha/dialog-zha-reconfigure-device.ts b/src/panels/config/integrations/integration-panels/zha/dialog-zha-reconfigure-device.ts new file mode 100644 index 0000000000..8e29d5af94 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/zha/dialog-zha-reconfigure-device.ts @@ -0,0 +1,153 @@ +import { + css, + CSSResult, + customElement, + html, + internalProperty, + LitElement, + property, + TemplateResult, +} from "lit-element"; +import { createCloseHeading } from "../../../../../components/ha-dialog"; +import { haStyleDialog } from "../../../../../resources/styles"; +import { HomeAssistant } from "../../../../../types"; +import { ZHAReconfigureDeviceDialogParams } from "./show-dialog-zha-reconfigure-device"; +import { IronAutogrowTextareaElement } from "@polymer/iron-autogrow-textarea"; +import "@polymer/paper-input/paper-textarea"; +import "../../../../../components/ha-circular-progress"; +import { LOG_OUTPUT, reconfigureNode } from "../../../../../data/zha"; +import { fireEvent } from "../../../../../common/dom/fire_event"; + +@customElement("dialog-zha-reconfigure-device") +class DialogZHAReconfigureDevice extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @internalProperty() private _active = false; + + @internalProperty() private _formattedEvents = ""; + + @internalProperty() + private _params: ZHAReconfigureDeviceDialogParams | undefined = undefined; + + private _subscribed?: Promise<() => Promise>; + + private _reconfigureDeviceTimeoutHandle: any = undefined; + + public async showDialog( + params: ZHAReconfigureDeviceDialogParams + ): Promise { + this._params = params; + this._subscribe(params); + } + + public closeDialog(): void { + this._unsubscribe(); + this._formattedEvents = ""; + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + protected render(): TemplateResult { + if (!this._params) { + return html``; + } + return html` + +
+ ${this._active + ? html` +

+ ${this._params?.device.user_given_name || + this._params?.device.name} +

+ + ` + : ""} +
+ + +
+ `; + } + + private _handleMessage(message: any): void { + if (message.type === LOG_OUTPUT) { + this._formattedEvents += message.log_entry.message + "\n"; + const paperTextArea = this.shadowRoot!.querySelector("paper-textarea"); + if (paperTextArea) { + const textArea = (paperTextArea.inputElement as IronAutogrowTextareaElement) + .textarea; + textArea.scrollTop = textArea.scrollHeight; + } + } + } + + private _unsubscribe(): void { + this._active = false; + if (this._reconfigureDeviceTimeoutHandle) { + clearTimeout(this._reconfigureDeviceTimeoutHandle); + } + if (this._subscribed) { + this._subscribed.then((unsub) => unsub()); + this._subscribed = undefined; + } + } + + private _subscribe(params: ZHAReconfigureDeviceDialogParams): void { + if (!this.hass) { + return; + } + this._active = true; + this._subscribed = reconfigureNode( + this.hass, + params.device.ieee, + this._handleMessage.bind(this) + ); + this._reconfigureDeviceTimeoutHandle = setTimeout( + () => this._unsubscribe(), + 60000 + ); + } + + static get styles(): CSSResult[] { + return [ + haStyleDialog, + css` + ha-circular-progress { + padding: 20px; + } + .searching { + margin-top: 20px; + display: flex; + flex-direction: column; + align-items: center; + } + .log { + padding: 16px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-zha-reconfigure-device": DialogZHAReconfigureDevice; + } +} diff --git a/src/panels/config/integrations/integration-panels/zha/show-dialog-zha-reconfigure-device.ts b/src/panels/config/integrations/integration-panels/zha/show-dialog-zha-reconfigure-device.ts new file mode 100644 index 0000000000..58a06ced05 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/zha/show-dialog-zha-reconfigure-device.ts @@ -0,0 +1,20 @@ +import { fireEvent } from "../../../../../common/dom/fire_event"; +import { ZHADevice } from "../../../../../data/zha"; + +export interface ZHAReconfigureDeviceDialogParams { + device: ZHADevice; +} + +export const loadZHAReconfigureDeviceDialog = () => + import("./dialog-zha-reconfigure-device"); + +export const showZHAReconfigureDeviceDialog = ( + element: HTMLElement, + zhaReconfigureDeviceParams: ZHAReconfigureDeviceDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-zha-reconfigure-device", + dialogImport: loadZHAReconfigureDeviceDialog, + dialogParams: zhaReconfigureDeviceParams, + }); +}; diff --git a/src/translations/en.json b/src/translations/en.json index 1828dbf15f..99d640f144 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -753,6 +753,9 @@ "enable_new_entities_description": "If disabled, newly discovered entities for {integration} will not be automatically added to Home Assistant.", "update": "Update" }, + "zha_reconfigure_device": { + "heading": "Reconfiguring device" + }, "zha_device_info": { "manuf": "by {manufacturer}", "no_area": "No Area",