From ce08d9b45a0349c1dda01c7dce84312b5961ebe9 Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Tue, 13 Apr 2021 19:16:51 -0400 Subject: [PATCH 01/10] initial take --- src/data/zha.ts | 25 ++++ .../zha/dialog-zha-reconfigure-device.ts | 136 +++++++++++++----- 2 files changed, 124 insertions(+), 37 deletions(-) diff --git a/src/data/zha.ts b/src/data/zha.ts index e57df4078a74..583e5bdb876e 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -54,6 +54,21 @@ export interface Cluster { type: string; } +export interface AttributeConfigurationStatus { + id: number; + name: string; + success: boolean | undefined; + min: number; + max: number; + change: number; +} + +export interface ClusterConfigurationStatus { + cluster: Cluster; + bindSuccess: boolean | undefined; + attributes: Map; +} + export interface Command { name: string; id: number; @@ -301,3 +316,13 @@ export const DEVICE_MESSAGE_TYPES = [ DEVICE_FULLY_INITIALIZED, ]; export const LOG_OUTPUT = "log_output"; +export const ZHA_CHANNEL_MSG = "zha_channel_message"; +export const ZHA_CHANNEL_MSG_BIND = "zha_channel_bind"; +export const ZHA_CHANNEL_MSG_CFG_RPT = "zha_channel_configure_reporting"; +export const ZHA_CHANNEL_MSG_DATA = "zha_channel_msg_data"; +export const ZHA_CHANNEL_CFG_DONE = "zha_channel_cfg_done"; +export const CHANNEL_MESSAGE_TYPES = [ + ZHA_CHANNEL_MSG_BIND, + ZHA_CHANNEL_MSG_CFG_RPT, + ZHA_CHANNEL_CFG_DONE, +]; 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 index 8e29d5af94fb..003450b53f09 100644 --- 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 @@ -8,15 +8,25 @@ import { property, TemplateResult, } from "lit-element"; -import { createCloseHeading } from "../../../../../components/ha-dialog"; +import { mdiCheckCircle, mdiClose, mdiExclamationThick } from "@mdi/js"; 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 { + AttributeConfigurationStatus, + CHANNEL_MESSAGE_TYPES, + Cluster, + ClusterConfigurationStatus, + fetchClustersForZhaNode, + reconfigureNode, + ZHA_CHANNEL_CFG_DONE, + ZHA_CHANNEL_MSG_BIND, + ZHA_CHANNEL_MSG_CFG_RPT, +} from "../../../../../data/zha"; import { fireEvent } from "../../../../../common/dom/fire_event"; +import { computeRTLDirection } from "../../../../../common/util/compute_rtl"; @customElement("dialog-zha-reconfigure-device") class DialogZHAReconfigureDevice extends LitElement { @@ -24,26 +34,39 @@ class DialogZHAReconfigureDevice extends LitElement { @internalProperty() private _active = false; - @internalProperty() private _formattedEvents = ""; + @internalProperty() private _clusterConfigurationStatuses: Map< + number, + ClusterConfigurationStatus + > = new Map(); @internalProperty() private _params: ZHAReconfigureDeviceDialogParams | undefined = undefined; private _subscribed?: Promise<() => Promise>; - private _reconfigureDeviceTimeoutHandle: any = undefined; - public async showDialog( params: ZHAReconfigureDeviceDialogParams ): Promise { this._params = params; + this._clusterConfigurationStatuses = new Map( + (await fetchClustersForZhaNode(this.hass, params.device.ieee)).map( + (cluster: Cluster) => [ + cluster.id, + { + cluster: cluster, + bindSuccess: undefined, + attributes: new Map(), + }, + ] + ) + ); this._subscribe(params); } public closeDialog(): void { this._unsubscribe(); - this._formattedEvents = ""; this._params = undefined; + this._clusterConfigurationStatuses = new Map(); fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -56,53 +79,96 @@ class DialogZHAReconfigureDevice extends LitElement { open hideActions @closing="${this.closeDialog}" - .heading=${createCloseHeading( - this.hass, - this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`) - )} + .heading=${html` + ${this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`)}: + ${this._params?.device.user_given_name || + this._params?.device.name} + + + + `} >
${this._active ? html` -

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

` : ""}
- - + ${this._clusterConfigurationStatuses.size > 0 + ? html`${Array.from(this._clusterConfigurationStatuses.values()).map( + (clusterStatus) => html` + +
${clusterStatus.cluster.name}
+
+ Bind Successful: + ${clusterStatus.bindSuccess !== undefined + ? clusterStatus.bindSuccess + ? html`` + : html`` + : ""} +
+
+ Configure Reporting Successful: + ${clusterStatus.bindSuccess !== undefined + ? clusterStatus.bindSuccess + ? html`` + : html`` + : ""} +
+
+
` + )}` + : ""} `; } 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; + if (CHANNEL_MESSAGE_TYPES.includes(message.type)) { + if (message.type === ZHA_CHANNEL_CFG_DONE) { + this._unsubscribe(); + } else { + const clusterConfigurationStatus = this._clusterConfigurationStatuses.get( + message.zha_channel_msg_data.cluster_id + ); + if (message.type === ZHA_CHANNEL_MSG_BIND) { + clusterConfigurationStatus!.bindSuccess = + message.zha_channel_msg_data.success; + } + if (message.type === ZHA_CHANNEL_MSG_CFG_RPT) { + const attributes = message.zha_channel_msg_data.attributes; + Object.keys(attributes).forEach((name) => + clusterConfigurationStatus!.attributes.set( + attributes[name].id, + attributes[name] + ) + ); + } } } } private _unsubscribe(): void { this._active = false; - if (this._reconfigureDeviceTimeoutHandle) { - clearTimeout(this._reconfigureDeviceTimeoutHandle); - } if (this._subscribed) { this._subscribed.then((unsub) => unsub()); this._subscribed = undefined; @@ -119,10 +185,6 @@ class DialogZHAReconfigureDevice extends LitElement { params.device.ieee, this._handleMessage.bind(this) ); - this._reconfigureDeviceTimeoutHandle = setTimeout( - () => this._unsubscribe(), - 60000 - ); } static get styles(): CSSResult[] { From 09d98cf94f93ea0810c6a7b2c8b33b4a230e783c Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Thu, 15 Apr 2021 15:03:34 -0400 Subject: [PATCH 02/10] keep iterating --- .../zha/dialog-zha-reconfigure-device.ts | 219 ++++++++++++++---- src/translations/en.json | 13 +- 2 files changed, 180 insertions(+), 52 deletions(-) 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 index 003450b53f09..29baea674055 100644 --- 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 @@ -39,8 +39,15 @@ class DialogZHAReconfigureDevice extends LitElement { ClusterConfigurationStatus > = new Map(); - @internalProperty() - private _params: ZHAReconfigureDeviceDialogParams | undefined = undefined; + @internalProperty() private _params: + | ZHAReconfigureDeviceDialogParams + | undefined = undefined; + + @internalProperty() private _eventCount = 0; + + @internalProperty() private _allSuccessful = true; + + @internalProperty() private _showDetails = false; private _subscribed?: Promise<() => Promise>; @@ -67,6 +74,7 @@ class DialogZHAReconfigureDevice extends LitElement { this._unsubscribe(); this._params = undefined; this._clusterConfigurationStatuses = new Map(); + this._eventCount = 0; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -80,11 +88,10 @@ class DialogZHAReconfigureDevice extends LitElement { hideActions @closing="${this.closeDialog}" .heading=${html` - ${this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`)}: - ${this._params?.device.user_given_name || - this._params?.device.name} + + ${this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`)}: + ${this._params?.device.user_given_name || this._params?.device.name} + `} > -
+
${this._active ? html` +

+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.attempting` + )} +

` - : ""} + : this._allSuccessful + ? html` + +

+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.suceeded` + )} +

+ ` + : html` + +

+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.failed` + )} +

+ `} + + ${this._showDetails + ? this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_hide` + ) + : this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_show` + )} +
- ${this._clusterConfigurationStatuses.size > 0 - ? html`${Array.from(this._clusterConfigurationStatuses.values()).map( - (clusterStatus) => html` - -
${clusterStatus.cluster.name}
-
- Bind Successful: - ${clusterStatus.bindSuccess !== undefined - ? clusterStatus.bindSuccess - ? html`` - : html`` - : ""} -
-
- Configure Reporting Successful: - ${clusterStatus.bindSuccess !== undefined - ? clusterStatus.bindSuccess - ? html`` - : html`` - : ""} -
-
-
` - )}` + + ${this._showDetails + ? html` +
+

+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.cluster_header` + )} +

+

+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.bind_header` + )} +

+

+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.reporting_header` + )} +

+ + ${this._clusterConfigurationStatuses.size > 0 + ? html` + ${Array.from( + this._clusterConfigurationStatuses.values() + ).map( + (clusterStatus) => html` +
+ ${clusterStatus.cluster.name} +
+
+ ${clusterStatus.bindSuccess !== undefined + ? clusterStatus.bindSuccess + ? html` + + ` + : html` + + ` + : ""} +
+
+ ${clusterStatus.attributes.size > 0 + ? html` +
+
+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.attribute` + )} +
+
+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.configuration` + )} +
+ ${Array.from( + clusterStatus.attributes.values() + ).map( + (attribute) => html` + + ${attribute.name}: + ${attribute.success + ? html` + + ` + : html` + + `} + +
+ min:${attribute.min}/max:${attribute.max}/change:${attribute.change} +
+ ` + )} +
+ ` + : ""} +
+ ` + )} + ` + : ""} +
+ ` : ""} `; @@ -144,6 +242,9 @@ class DialogZHAReconfigureDevice extends LitElement { private _handleMessage(message: any): void { if (CHANNEL_MESSAGE_TYPES.includes(message.type)) { + // this is currently here to hack rerendering because map updates aren't triggering rendering? + this._eventCount += 1; + if (message.type === ZHA_CHANNEL_CFG_DONE) { this._unsubscribe(); } else { @@ -151,17 +252,17 @@ class DialogZHAReconfigureDevice extends LitElement { message.zha_channel_msg_data.cluster_id ); if (message.type === ZHA_CHANNEL_MSG_BIND) { - clusterConfigurationStatus!.bindSuccess = - message.zha_channel_msg_data.success; + const success = message.zha_channel_msg_data.success; + clusterConfigurationStatus!.bindSuccess = success; + this._allSuccessful = this._allSuccessful && success; } if (message.type === ZHA_CHANNEL_MSG_CFG_RPT) { const attributes = message.zha_channel_msg_data.attributes; - Object.keys(attributes).forEach((name) => - clusterConfigurationStatus!.attributes.set( - attributes[name].id, - attributes[name] - ) - ); + Object.keys(attributes).forEach((name) => { + const attribute = attributes[name]; + clusterConfigurationStatus!.attributes.set(attribute.id, attribute); + this._allSuccessful = this._allSuccessful && attribute.success; + }); } } } @@ -187,6 +288,10 @@ class DialogZHAReconfigureDevice extends LitElement { ); } + private _toggleDetails() { + this._showDetails = !this._showDetails; + } + static get styles(): CSSResult[] { return [ haStyleDialog, @@ -194,7 +299,7 @@ class DialogZHAReconfigureDevice extends LitElement { ha-circular-progress { padding: 20px; } - .searching { + .configuring { margin-top: 20px; display: flex; flex-direction: column; @@ -203,6 +308,18 @@ class DialogZHAReconfigureDevice extends LitElement { .log { padding: 16px; } + .wrapper { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + } + .attributes { + display: grid; + grid-template-columns: 1fr 1fr; + } + .grid-item { + border: 1px solid; + padding: 20px; + } `, ]; } diff --git a/src/translations/en.json b/src/translations/en.json index 6071289bc5e6..59522be0c2b8 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -756,7 +756,18 @@ "update": "Update" }, "zha_reconfigure_device": { - "heading": "Reconfiguring device" + "heading": "Reconfiguring device", + "configuring_alt": "Configuring", + "attempting": "Attempting to reconfigure the device...", + "succeeded": "Reconfiguring the device succeeded", + "failed": "Reconfiguring the device failed", + "button_show": "Show Details", + "button_hide": "Hide Details", + "cluster_header": "Cluster", + "bind_header": "Binding", + "reporting_header": "Reporting", + "attribute": "Attribute", + "configuration": "Configuration" }, "zha_device_info": { "manuf": "by {manufacturer}", From 0d6d5936664a1f1c7ef722f09a7b771cfe8243f6 Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Thu, 15 Apr 2021 15:22:33 -0400 Subject: [PATCH 03/10] cleanup --- .../zha/dialog-zha-reconfigure-device.ts | 42 +++++++++++++------ src/translations/en.json | 3 +- 2 files changed, 32 insertions(+), 13 deletions(-) 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 index 29baea674055..7926baf06c17 100644 --- 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 @@ -9,11 +9,13 @@ import { TemplateResult, } from "lit-element"; import { mdiCheckCircle, mdiClose, mdiExclamationThick } from "@mdi/js"; +import "@material/mwc-icon-button/mwc-icon-button"; +import "@material/mwc-button/mwc-button"; import { haStyleDialog } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; import { ZHAReconfigureDeviceDialogParams } from "./show-dialog-zha-reconfigure-device"; -import "@polymer/paper-input/paper-textarea"; import "../../../../../components/ha-circular-progress"; +import "../../../../../components/ha-svg-icon"; import { AttributeConfigurationStatus, CHANNEL_MESSAGE_TYPES, @@ -119,15 +121,21 @@ class DialogZHAReconfigureDevice extends LitElement { ` : this._allSuccessful ? html` - +

${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.suceeded` + `ui.dialogs.zha_reconfigure_device.succeeded` )}

` : html` - +

${this.hass.localize( `ui.dialogs.zha_reconfigure_device.failed` @@ -198,9 +206,18 @@ class DialogZHAReconfigureDevice extends LitElement { )}

- ${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.configuration` - )} + +
+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.configuration` + )} +
+
+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.min_max_change` + )} +
+
${Array.from( clusterStatus.attributes.values() @@ -221,7 +238,7 @@ class DialogZHAReconfigureDevice extends LitElement { `}
- min:${attribute.min}/max:${attribute.max}/change:${attribute.change} + ${attribute.min}/${attribute.max}/${attribute.change}
` )} @@ -305,9 +322,6 @@ class DialogZHAReconfigureDevice extends LitElement { flex-direction: column; align-items: center; } - .log { - padding: 16px; - } .wrapper { display: grid; grid-template-columns: 2fr 1fr 1fr; @@ -318,7 +332,11 @@ class DialogZHAReconfigureDevice extends LitElement { } .grid-item { border: 1px solid; - padding: 20px; + padding: 8px; + } + .success-fail { + width: 48px; + height: 48px; } `, ]; diff --git a/src/translations/en.json b/src/translations/en.json index 59522be0c2b8..32f68793992f 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -767,7 +767,8 @@ "bind_header": "Binding", "reporting_header": "Reporting", "attribute": "Attribute", - "configuration": "Configuration" + "configuration": "Configuration", + "min_max_change": "min / max / change" }, "zha_device_info": { "manuf": "by {manufacturer}", From 4736a6a085d8ce48fcdf438723ddde2a5f8f787a Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Thu, 15 Apr 2021 19:06:03 -0400 Subject: [PATCH 04/10] more cleanup --- src/data/zha.ts | 41 ++++++++--- .../zha/dialog-zha-reconfigure-device.ts | 68 ++++++++----------- src/translations/en.json | 3 +- 3 files changed, 63 insertions(+), 49 deletions(-) diff --git a/src/data/zha.ts b/src/data/zha.ts index 583e5bdb876e..e0a547d263e8 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -54,6 +54,18 @@ export interface Cluster { type: string; } +export interface ClusterConfigurationData { + cluster_name: string; + cluster_id: number; + success: boolean; +} + +export interface ClusterAttributeData { + cluster_name: string; + cluster_id: number; + attributes: AttributeConfigurationStatus[]; +} + export interface AttributeConfigurationStatus { id: number; name: string; @@ -69,6 +81,25 @@ export interface ClusterConfigurationStatus { attributes: Map; } +interface ClusterConfigurationBindEvent { + type: "zha_channel_bind"; + zha_channel_msg_data: ClusterConfigurationData; +} + +interface ClusterConfigurationReportConfigurationEvent { + type: "zha_channel_configure_reporting"; + zha_channel_msg_data: ClusterAttributeData; +} + +interface ClusterConfigurationEventFinish { + type: "zha_channel_cfg_done"; +} + +export type ClusterConfigurationEvent = + | ClusterConfigurationReportConfigurationEvent + | ClusterConfigurationBindEvent + | ClusterConfigurationEventFinish; + export interface Command { name: string; id: number; @@ -98,10 +129,10 @@ export interface ZHAGroupMember { export const reconfigureNode = ( hass: HomeAssistant, ieeeAddress: string, - callbackFunction: any + callbackFunction: (message: ClusterConfigurationEvent) => void ) => { return hass.connection.subscribeMessage( - (message) => callbackFunction(message), + (message: ClusterConfigurationEvent) => callbackFunction(message), { type: "zha/devices/reconfigure", ieee: ieeeAddress, @@ -319,10 +350,4 @@ export const LOG_OUTPUT = "log_output"; export const ZHA_CHANNEL_MSG = "zha_channel_message"; export const ZHA_CHANNEL_MSG_BIND = "zha_channel_bind"; export const ZHA_CHANNEL_MSG_CFG_RPT = "zha_channel_configure_reporting"; -export const ZHA_CHANNEL_MSG_DATA = "zha_channel_msg_data"; export const ZHA_CHANNEL_CFG_DONE = "zha_channel_cfg_done"; -export const CHANNEL_MESSAGE_TYPES = [ - ZHA_CHANNEL_MSG_BIND, - ZHA_CHANNEL_MSG_CFG_RPT, - ZHA_CHANNEL_CFG_DONE, -]; 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 index 7926baf06c17..36a9601b3f69 100644 --- 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 @@ -18,8 +18,8 @@ import "../../../../../components/ha-circular-progress"; import "../../../../../components/ha-svg-icon"; import { AttributeConfigurationStatus, - CHANNEL_MESSAGE_TYPES, Cluster, + ClusterConfigurationEvent, ClusterConfigurationStatus, fetchClustersForZhaNode, reconfigureNode, @@ -206,18 +206,11 @@ class DialogZHAReconfigureDevice extends LitElement { )}
- -
- ${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.configuration` - )} -
-
- ${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.min_max_change` - )} -
-
+
+ ${this.hass.localize( + `ui.dialogs.zha_reconfigure_device.min_max_change` + )} +
${Array.from( clusterStatus.attributes.values() @@ -257,30 +250,27 @@ class DialogZHAReconfigureDevice extends LitElement { `; } - private _handleMessage(message: any): void { - if (CHANNEL_MESSAGE_TYPES.includes(message.type)) { - // this is currently here to hack rerendering because map updates aren't triggering rendering? - this._eventCount += 1; - - if (message.type === ZHA_CHANNEL_CFG_DONE) { - this._unsubscribe(); - } else { - const clusterConfigurationStatus = this._clusterConfigurationStatuses.get( - message.zha_channel_msg_data.cluster_id - ); - if (message.type === ZHA_CHANNEL_MSG_BIND) { - const success = message.zha_channel_msg_data.success; - clusterConfigurationStatus!.bindSuccess = success; - this._allSuccessful = this._allSuccessful && success; - } - if (message.type === ZHA_CHANNEL_MSG_CFG_RPT) { - const attributes = message.zha_channel_msg_data.attributes; - Object.keys(attributes).forEach((name) => { - const attribute = attributes[name]; - clusterConfigurationStatus!.attributes.set(attribute.id, attribute); - this._allSuccessful = this._allSuccessful && attribute.success; - }); - } + private _handleMessage(message: ClusterConfigurationEvent): void { + // this is currently here to hack rerendering because map updates aren't triggering rendering? + this._eventCount += 1; + if (message.type === ZHA_CHANNEL_CFG_DONE) { + this._unsubscribe(); + } else { + const clusterConfigurationStatus = this._clusterConfigurationStatuses.get( + message.zha_channel_msg_data.cluster_id + ); + if (message.type === ZHA_CHANNEL_MSG_BIND) { + const success = message.zha_channel_msg_data.success; + clusterConfigurationStatus!.bindSuccess = success; + this._allSuccessful = this._allSuccessful && success; + } + if (message.type === ZHA_CHANNEL_MSG_CFG_RPT) { + const attributes = message.zha_channel_msg_data.attributes; + Object.keys(attributes).forEach((name) => { + const attribute = attributes[name]; + clusterConfigurationStatus!.attributes.set(attribute.id, attribute); + this._allSuccessful = this._allSuccessful && attribute.success; + }); } } } @@ -324,7 +314,7 @@ class DialogZHAReconfigureDevice extends LitElement { } .wrapper { display: grid; - grid-template-columns: 2fr 1fr 1fr; + grid-template-columns: 3fr 1fr 2fr; } .attributes { display: grid; @@ -332,7 +322,7 @@ class DialogZHAReconfigureDevice extends LitElement { } .grid-item { border: 1px solid; - padding: 8px; + padding: 7px; } .success-fail { width: 48px; diff --git a/src/translations/en.json b/src/translations/en.json index 32f68793992f..35d6b006c565 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -767,8 +767,7 @@ "bind_header": "Binding", "reporting_header": "Reporting", "attribute": "Attribute", - "configuration": "Configuration", - "min_max_change": "min / max / change" + "min_max_change": "min/max/change" }, "zha_device_info": { "manuf": "by {manufacturer}", From 2903fe8f70d5b43a6f1155c0611e901bbca9f4f5 Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Tue, 27 Apr 2021 07:52:46 -0400 Subject: [PATCH 05/10] comments --- .../zha/dialog-zha-reconfigure-device.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) 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 index 36a9601b3f69..8648cd851ebe 100644 --- 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 @@ -36,7 +36,7 @@ class DialogZHAReconfigureDevice extends LitElement { @internalProperty() private _active = false; - @internalProperty() private _clusterConfigurationStatuses: Map< + @internalProperty() private _clusterConfigurationStatuses?: Map< number, ClusterConfigurationStatus > = new Map(); @@ -45,8 +45,6 @@ class DialogZHAReconfigureDevice extends LitElement { | ZHAReconfigureDeviceDialogParams | undefined = undefined; - @internalProperty() private _eventCount = 0; - @internalProperty() private _allSuccessful = true; @internalProperty() private _showDetails = false; @@ -75,8 +73,7 @@ class DialogZHAReconfigureDevice extends LitElement { public closeDialog(): void { this._unsubscribe(); this._params = undefined; - this._clusterConfigurationStatuses = new Map(); - this._eventCount = 0; + this._clusterConfigurationStatuses = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -172,10 +169,10 @@ class DialogZHAReconfigureDevice extends LitElement { )} - ${this._clusterConfigurationStatuses.size > 0 + ${this._clusterConfigurationStatuses!.size > 0 ? html` ${Array.from( - this._clusterConfigurationStatuses.values() + this._clusterConfigurationStatuses!.values() ).map( (clusterStatus) => html`
@@ -252,11 +249,10 @@ class DialogZHAReconfigureDevice extends LitElement { private _handleMessage(message: ClusterConfigurationEvent): void { // this is currently here to hack rerendering because map updates aren't triggering rendering? - this._eventCount += 1; if (message.type === ZHA_CHANNEL_CFG_DONE) { this._unsubscribe(); } else { - const clusterConfigurationStatus = this._clusterConfigurationStatuses.get( + const clusterConfigurationStatus = this._clusterConfigurationStatuses!.get( message.zha_channel_msg_data.cluster_id ); if (message.type === ZHA_CHANNEL_MSG_BIND) { @@ -272,6 +268,7 @@ class DialogZHAReconfigureDevice extends LitElement { this._allSuccessful = this._allSuccessful && attribute.success; }); } + this.requestUpdate(); } } From 0e36f9971013ca3456aa8c2b2ec18fc6fdc46c50 Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Tue, 27 Apr 2021 09:14:17 -0400 Subject: [PATCH 06/10] pull in line with zwave --- .../zha/dialog-zha-reconfigure-device.ts | 301 +++++++++++++----- src/translations/en.json | 10 +- 2 files changed, 224 insertions(+), 87 deletions(-) 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 index 8648cd851ebe..43804e34950d 100644 --- 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 @@ -8,7 +8,7 @@ import { property, TemplateResult, } from "lit-element"; -import { mdiCheckCircle, mdiClose, mdiExclamationThick } from "@mdi/js"; +import { mdiCheckCircle, mdiClose, mdiCloseCircle } from "@mdi/js"; import "@material/mwc-icon-button/mwc-icon-button"; import "@material/mwc-button/mwc-button"; import { haStyleDialog } from "../../../../../resources/styles"; @@ -34,7 +34,9 @@ import { computeRTLDirection } from "../../../../../common/util/compute_rtl"; class DialogZHAReconfigureDevice extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @internalProperty() private _active = false; + @internalProperty() private _status?: string; + + @internalProperty() private _stages?: string[]; @internalProperty() private _clusterConfigurationStatuses?: Map< number, @@ -55,24 +57,14 @@ class DialogZHAReconfigureDevice extends LitElement { params: ZHAReconfigureDeviceDialogParams ): Promise { this._params = params; - this._clusterConfigurationStatuses = new Map( - (await fetchClustersForZhaNode(this.hass, params.device.ieee)).map( - (cluster: Cluster) => [ - cluster.id, - { - cluster: cluster, - bindSuccess: undefined, - attributes: new Map(), - }, - ] - ) - ); - this._subscribe(params); + this._stages = undefined; } public closeDialog(): void { this._unsubscribe(); this._params = undefined; + this._status = undefined; + this._stages = undefined; this._clusterConfigurationStatuses = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -81,11 +73,11 @@ class DialogZHAReconfigureDevice extends LitElement { if (!this._params) { return html``; } + return html` ${this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`)}: @@ -101,55 +93,138 @@ class DialogZHAReconfigureDevice extends LitElement { `} > -
- ${this._active - ? html` - -

+ ${!this._status + ? html` +

+ ${this.hass.localize( + "ui.dialogs.zha_reconfigure_device.introduction" + )} +

+

+ ${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.attempting` + "ui.dialogs.zha_reconfigure_device.battery_device_warning" )} -

- ` - : this._allSuccessful - ? html` + +

+ + ${this.hass.localize( + "ui.dialogs.zha_reconfigure_device.start_reconfiguration" + )} + + ` + : ``} + ${this._status === "started" + ? html` +
+ +
+

+ + ${this.hass.localize( + "ui.dialogs.zha_reconfigure_device.in_progress" + )} + +

+

+ ${this.hass.localize( + "ui.dialogs.zha_reconfigure_device.run_in_background" + )} +

+
+
+ + ${this.hass.localize("ui.dialogs.generic.close")} + + + ${this._showDetails + ? this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_hide` + ) + : this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_show` + )} + + ` + : ``} + ${this._status === "failed" + ? html` +
-

- ${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.succeeded` - )} -

- ` - : html` +
+

+ ${this.hass.localize( + "ui.dialogs.zha_reconfigure_device.configuration_failed" + )} +

+
+
+ + ${this.hass.localize("ui.dialogs.generic.close")} + + + ${this._showDetails + ? this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_hide` + ) + : this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_show` + )} + + ` + : ``} + ${this._status === "finished" + ? html` +
-

- ${this.hass.localize( - `ui.dialogs.zha_reconfigure_device.failed` - )} -

- `} - - ${this._showDetails - ? this.hass.localize( - `ui.dialogs.zha_reconfigure_device.button_hide` - ) - : this.hass.localize( - `ui.dialogs.zha_reconfigure_device.button_show` +
+

+ ${this.hass.localize( + "ui.dialogs.zha_reconfigure_device.configuration_complete" + )} +

+
+
+ + ${this.hass.localize("ui.dialogs.generic.close")} + + + ${this._showDetails + ? this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_hide` + ) + : this.hass.localize( + `ui.dialogs.zha_reconfigure_device.button_show` + )} + + ` + : ``} + ${this._stages + ? html` +
+ ${this._stages.map( + (stage) => html` + + + ${stage} + + ` )} - -
- +
+ ` + : ""} ${this._showDetails ? html`
@@ -182,14 +257,20 @@ class DialogZHAReconfigureDevice extends LitElement { ${clusterStatus.bindSuccess !== undefined ? clusterStatus.bindSuccess ? html` - + + + ` : html` - + + + ` : ""}
@@ -217,14 +298,20 @@ class DialogZHAReconfigureDevice extends LitElement { ${attribute.name}: ${attribute.success ? html` - + + + ` : html` - + + + `}
@@ -247,20 +334,47 @@ class DialogZHAReconfigureDevice extends LitElement { `; } + private async _startReconfiguration(): Promise { + if (!this.hass || !this._params) { + return; + } + this._clusterConfigurationStatuses = new Map( + (await fetchClustersForZhaNode(this.hass, this._params.device.ieee)).map( + (cluster: Cluster) => [ + cluster.id, + { + cluster: cluster, + bindSuccess: undefined, + attributes: new Map(), + }, + ] + ) + ); + this._subscribe(this._params); + this._status = "started"; + } + private _handleMessage(message: ClusterConfigurationEvent): void { // this is currently here to hack rerendering because map updates aren't triggering rendering? if (message.type === ZHA_CHANNEL_CFG_DONE) { this._unsubscribe(); + this._status = this._allSuccessful ? "finished" : "failed"; } else { const clusterConfigurationStatus = this._clusterConfigurationStatuses!.get( message.zha_channel_msg_data.cluster_id ); if (message.type === ZHA_CHANNEL_MSG_BIND) { + if (!this._stages) { + this._stages = ["binding"]; + } const success = message.zha_channel_msg_data.success; clusterConfigurationStatus!.bindSuccess = success; this._allSuccessful = this._allSuccessful && success; } if (message.type === ZHA_CHANNEL_MSG_CFG_RPT) { + if (this._stages && !this._stages.includes("reporting")) { + this._stages.push("reporting"); + } const attributes = message.zha_channel_msg_data.attributes; Object.keys(attributes).forEach((name) => { const attribute = attributes[name]; @@ -273,7 +387,6 @@ class DialogZHAReconfigureDevice extends LitElement { } private _unsubscribe(): void { - this._active = false; if (this._subscribed) { this._subscribed.then((unsub) => unsub()); this._subscribed = undefined; @@ -284,7 +397,6 @@ class DialogZHAReconfigureDevice extends LitElement { if (!this.hass) { return; } - this._active = true; this._subscribed = reconfigureNode( this.hass, params.device.ieee, @@ -300,15 +412,6 @@ class DialogZHAReconfigureDevice extends LitElement { return [ haStyleDialog, css` - ha-circular-progress { - padding: 20px; - } - .configuring { - margin-top: 20px; - display: flex; - flex-direction: column; - align-items: center; - } .wrapper { display: grid; grid-template-columns: 3fr 1fr 2fr; @@ -321,10 +424,40 @@ class DialogZHAReconfigureDevice extends LitElement { border: 1px solid; padding: 7px; } - .success-fail { - width: 48px; + .success { + color: var(--success-color); + } + + .failed { + color: var(--warning-color); + } + + .flex-container { + display: flex; + align-items: center; + } + + .stages { + margin-top: 16px; + } + + .stage ha-svg-icon { + width: 16px; + height: 16px; + } + .stage { + padding: 8px; + } + + ha-svg-icon { + width: 68px; height: 48px; } + + .flex-container ha-circular-progress, + .flex-container ha-svg-icon { + margin-right: 20px; + } `, ]; } diff --git a/src/translations/en.json b/src/translations/en.json index 35d6b006c565..370b01f85621 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -758,9 +758,13 @@ "zha_reconfigure_device": { "heading": "Reconfiguring device", "configuring_alt": "Configuring", - "attempting": "Attempting to reconfigure the device...", - "succeeded": "Reconfiguring the device succeeded", - "failed": "Reconfiguring the device failed", + "introduction": "Reconfigure a device on your Zigbee network. Use this feature if your device is not functioning correctly.", + "battery_device_warning": "You will need to wake battery powered devices before starting the reconfiguration process. Refer to your device's manual for instructions on how to wake the device.", + "run_in_background": "You can close this dialog and the reconfiguration will continue in the background.", + "start_reconfiguration": "Start Reconfiguration", + "in_progress": "The device is being reconfigured. This may take some time.", + "configuration_failed": "The device reconfiguration failed. Additional information may be available in the logs.", + "configuration_complete": "Device reconfiguration complete.", "button_show": "Show Details", "button_hide": "Hide Details", "cluster_header": "Cluster", From 8a465cce4ecc5654c32cc611113c2ad08be2f414 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Tue, 27 Apr 2021 20:05:11 -0400 Subject: [PATCH 07/10] Update src/panels/config/integrations/integration-panels/zha/dialog-zha-reconfigure-device.ts Co-authored-by: Bram Kragten --- .../integration-panels/zha/dialog-zha-reconfigure-device.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 43804e34950d..7c4d1c6cd98b 100644 --- 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 @@ -53,9 +53,9 @@ class DialogZHAReconfigureDevice extends LitElement { private _subscribed?: Promise<() => Promise>; - public async showDialog( + public showDialog( params: ZHAReconfigureDeviceDialogParams - ): Promise { + ): void { this._params = params; this._stages = undefined; } From b12ad75c17567f87e5e7440c1783a5abe0a7dfd3 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Tue, 27 Apr 2021 20:05:22 -0400 Subject: [PATCH 08/10] Update src/panels/config/integrations/integration-panels/zha/dialog-zha-reconfigure-device.ts Co-authored-by: Bram Kragten --- .../integration-panels/zha/dialog-zha-reconfigure-device.ts | 1 - 1 file changed, 1 deletion(-) 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 index 7c4d1c6cd98b..67aa7795bdef 100644 --- 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 @@ -355,7 +355,6 @@ class DialogZHAReconfigureDevice extends LitElement { } private _handleMessage(message: ClusterConfigurationEvent): void { - // this is currently here to hack rerendering because map updates aren't triggering rendering? if (message.type === ZHA_CHANNEL_CFG_DONE) { this._unsubscribe(); this._status = this._allSuccessful ? "finished" : "failed"; From 154b7bcd3dbefc957c5b138b6e25cd6a515ca11f Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Tue, 27 Apr 2021 20:05:31 -0400 Subject: [PATCH 09/10] Update src/panels/config/integrations/integration-panels/zha/dialog-zha-reconfigure-device.ts Co-authored-by: Bram Kragten --- .../integration-panels/zha/dialog-zha-reconfigure-device.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 67aa7795bdef..0dc81e419bf6 100644 --- 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 @@ -51,7 +51,7 @@ class DialogZHAReconfigureDevice extends LitElement { @internalProperty() private _showDetails = false; - private _subscribed?: Promise<() => Promise>; + private _subscribed?: Promise; public showDialog( params: ZHAReconfigureDeviceDialogParams From 0dad5f1dd6efc861390940605f63ecd25707edab Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Tue, 27 Apr 2021 20:18:14 -0400 Subject: [PATCH 10/10] review comments --- .../zha/dialog-zha-reconfigure-device.ts | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) 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 index 0dc81e419bf6..e32e984729a9 100644 --- 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 @@ -8,8 +8,7 @@ import { property, TemplateResult, } from "lit-element"; -import { mdiCheckCircle, mdiClose, mdiCloseCircle } from "@mdi/js"; -import "@material/mwc-icon-button/mwc-icon-button"; +import { mdiCheckCircle, mdiCloseCircle } from "@mdi/js"; import "@material/mwc-button/mwc-button"; import { haStyleDialog } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; @@ -28,7 +27,8 @@ import { ZHA_CHANNEL_MSG_CFG_RPT, } from "../../../../../data/zha"; import { fireEvent } from "../../../../../common/dom/fire_event"; -import { computeRTLDirection } from "../../../../../common/util/compute_rtl"; +import { UnsubscribeFunc } from "home-assistant-js-websocket"; +import { createCloseHeading } from "../../../../../components/ha-dialog"; @customElement("dialog-zha-reconfigure-device") class DialogZHAReconfigureDevice extends LitElement { @@ -53,9 +53,7 @@ class DialogZHAReconfigureDevice extends LitElement { private _subscribed?: Promise; - public showDialog( - params: ZHAReconfigureDeviceDialogParams - ): void { + public showDialog(params: ZHAReconfigureDeviceDialogParams): void { this._params = params; this._stages = undefined; } @@ -78,20 +76,12 @@ class DialogZHAReconfigureDevice extends LitElement { - ${this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`)}: - ${this._params?.device.user_given_name || this._params?.device.name} - - - - - `} + .heading=${createCloseHeading( + this.hass, + this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`) + + ": " + + (this._params?.device.user_given_name || this._params?.device.name) + )} > ${!this._status ? html`