Add Z-Wave JS Heal Node wizard (#9562)

This commit is contained in:
Charles Garwood 2021-07-27 18:16:19 -04:00 committed by GitHub
parent 07d7fa26fe
commit e12b194d41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 333 additions and 1 deletions

View File

@ -178,6 +178,17 @@ export const reinterviewNode = (
}
);
export const healNode = (
hass: HomeAssistant,
entry_id: string,
node_id: number
): Promise<boolean> =>
hass.callWS({
type: "zwave_js/heal_node",
entry_id: entry_id,
node_id: node_id,
});
export const healNetwork = (
hass: HomeAssistant,
entry_id: string

View File

@ -16,6 +16,7 @@ import {
import { haStyle } from "../../../../../../resources/styles";
import { HomeAssistant } from "../../../../../../types";
import { showZWaveJSReinterviewNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-reinterview-node";
import { showZWaveJSHealNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-heal-node";
@customElement("ha-device-actions-zwave_js")
export class HaDeviceActionsZWaveJS extends LitElement {
@ -56,6 +57,9 @@ export class HaDeviceActionsZWaveJS extends LitElement {
"ui.panel.config.zwave_js.device_info.reinterview_device"
)}
</mwc-button>
<mwc-button @click=${this._healNodeClicked}>
${this.hass.localize("ui.panel.config.zwave_js.device_info.heal_node")}
</mwc-button>
`;
}
@ -69,6 +73,17 @@ export class HaDeviceActionsZWaveJS extends LitElement {
});
}
private async _healNodeClicked() {
if (!this._nodeId || !this._entryId) {
return;
}
showZWaveJSHealNodeDialog(this, {
entry_id: this._entryId,
node_id: this._nodeId,
device: this.device,
});
}
static get styles(): CSSResultGroup {
return [
haStyle,

View File

@ -0,0 +1,273 @@
import "../../../../../components/ha-circular-progress";
import "@material/mwc-button/mwc-button";
import "@material/mwc-linear-progress/mwc-linear-progress";
import { mdiStethoscope, mdiCheckCircle, mdiCloseCircle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { createCloseHeading } from "../../../../../components/ha-dialog";
import {
DeviceRegistryEntry,
computeDeviceName,
} from "../../../../../data/device_registry";
import {
fetchNetworkStatus,
healNode,
ZWaveJSNetwork,
} from "../../../../../data/zwave_js";
import { haStyleDialog } from "../../../../../resources/styles";
import { HomeAssistant } from "../../../../../types";
import { ZWaveJSHealNodeDialogParams } from "./show-dialog-zwave_js-heal-node";
@customElement("dialog-zwave_js-heal-node")
class DialogZWaveJSHealNode extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private entry_id?: string;
@state() private node_id?: number;
@state() private device?: DeviceRegistryEntry;
@state() private _status?: string;
@state() private _error?: string;
public showDialog(params: ZWaveJSHealNodeDialogParams): void {
this.entry_id = params.entry_id;
this.device = params.device;
this.node_id = params.node_id;
this._fetchData();
}
public closeDialog(): void {
this.entry_id = undefined;
this._status = undefined;
this.node_id = undefined;
this.device = undefined;
this._error = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this.entry_id || !this.device) {
return html``;
}
return html`
<ha-dialog
open
@closed=${this.closeDialog}
.heading=${createCloseHeading(
this.hass,
this.hass.localize("ui.panel.config.zwave_js.heal_node.title")
)}
>
${!this._status
? html`
<div class="flex-container">
<ha-svg-icon
.path=${mdiStethoscope}
class="introduction"
></ha-svg-icon>
<div class="status">
<p>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.introduction",
{
device: html`<em
>${computeDeviceName(this.device, this.hass!)}</em
>`,
}
)}
</p>
</div>
</div>
<p>
<em>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.traffic_warning"
)}
</em>
</p>
<mwc-button slot="primaryAction" @click=${this._startHeal}>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.start_heal"
)}
</mwc-button>
`
: ``}
${this._status === "started"
? html`
<div class="flex-container">
<ha-circular-progress active></ha-circular-progress>
<div class="status">
<p>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.in_progress",
{
device: html`<em
>${computeDeviceName(this.device, this.hass!)}</em
>`,
}
)}
</p>
</div>
</div>
<mwc-button slot="primaryAction" @click=${this.closeDialog}>
${this.hass.localize("ui.common.close")}
</mwc-button>
`
: ``}
${this._status === "failed"
? html`
<div class="flex-container">
<ha-svg-icon
.path=${mdiCloseCircle}
class="failed"
></ha-svg-icon>
<div class="status">
<p>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.healing_failed",
{
device: html`<em
>${computeDeviceName(this.device, this.hass!)}</em
>`,
}
)}
</p>
<p>
${this._error
? html` <em>${this._error}</em> `
: `
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.healing_failed_check_logs"
)}
`}
</p>
</div>
</div>
<mwc-button slot="primaryAction" @click=${this.closeDialog}>
${this.hass.localize("ui.common.close")}
</mwc-button>
`
: ``}
${this._status === "finished"
? html`
<div class="flex-container">
<ha-svg-icon
.path=${mdiCheckCircle}
class="success"
></ha-svg-icon>
<div class="status">
<p>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.healing_complete",
{
device: html`<em
>${computeDeviceName(this.device, this.hass!)}</em
>`,
}
)}
</p>
</div>
</div>
<mwc-button slot="primaryAction" @click=${this.closeDialog}>
${this.hass.localize("ui.panel.config.zwave_js.common.close")}
</mwc-button>
`
: ``}
${this._status === "network-healing"
? html`
<div class="flex-container">
<ha-svg-icon
.path=${mdiCloseCircle}
class="failed"
></ha-svg-icon>
<div class="status">
<p>
${this.hass.localize(
"ui.panel.config.zwave_js.heal_node.network_heal_in_progress"
)}
</p>
</div>
</div>
<mwc-button slot="primaryAction" @click=${this.closeDialog}>
${this.hass.localize("ui.panel.config.zwave_js.common.close")}
</mwc-button>
`
: ``}
</ha-dialog>
`;
}
private async _fetchData(): Promise<void> {
if (!this.hass) {
return;
}
const network: ZWaveJSNetwork = await fetchNetworkStatus(
this.hass!,
this.entry_id!
);
if (network.controller.is_heal_network_active) {
this._status = "network-healing";
}
}
private async _startHeal(): Promise<void> {
if (!this.hass) {
return;
}
this._status = "started";
try {
this._status = (await healNode(this.hass, this.entry_id!, this.node_id!))
? "finished"
: "failed";
} catch (error) {
this._error = error.message;
this._status = "failed";
}
}
static get styles(): CSSResultGroup {
return [
haStyleDialog,
css`
.success {
color: var(--success-color);
}
.failed {
color: var(--error-color);
}
.flex-container {
display: flex;
align-items: center;
}
ha-svg-icon {
width: 68px;
height: 48px;
}
ha-svg-icon.introduction {
color: var(--primary-color);
}
.flex-container ha-svg-icon,
.flex-container ha-circular-progress {
margin-right: 20px;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"dialog-zwave_js-heal-node": DialogZWaveJSHealNode;
}
}

View File

@ -0,0 +1,21 @@
import { fireEvent } from "../../../../../common/dom/fire_event";
import { DeviceRegistryEntry } from "../../../../../data/device_registry";
export interface ZWaveJSHealNodeDialogParams {
entry_id: string;
node_id: number;
device: DeviceRegistryEntry;
}
export const loadHealNodeDialog = () => import("./dialog-zwave_js-heal-node");
export const showZWaveJSHealNodeDialog = (
element: HTMLElement,
healNodeDialogParams: ZWaveJSHealNodeDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-zwave_js-heal-node",
dialogImport: loadHealNodeDialog,
dialogParams: healNodeDialogParams,
});
};

View File

@ -2688,7 +2688,8 @@
"node_status": "Node Status",
"node_ready": "Node Ready",
"device_config": "Configure Device",
"reinterview_device": "Re-interview Device"
"reinterview_device": "Re-interview Device",
"heal_node": "Heal Node"
},
"node_config": {
"header": "Z-Wave Device Configuration",
@ -2763,6 +2764,17 @@
"healing_failed": "Healing failed. Additional information may be available in the logs.",
"healing_cancelled": "Network healing has been cancelled."
},
"heal_node": {
"title": "Heal a Z-Wave Device",
"introduction": "Tell {device} to update its routes back to the controller. This can help with communication issues if you have recently moved the device or your controller.",
"traffic_warning": "The healing process generates a large amount of traffic on the Z-Wave network. This may cause devices to respond slowly (or not at all) while the heal is in progress.",
"start_heal": "Heal Device",
"healing_failed": "{device} could not be healed.",
"healing_failed_check_logs": "Additional information may be available in the logs.",
"healing_complete": "{device} has been healed.",
"in_progress": "{device} healing is in progress.",
"network_heal_in_progress": "A Z-Wave network heal is already in progress. Please wait for it to finish before healing an individual device."
},
"logs": {
"title": "Z-Wave JS Logs",
"log_level": "Log Level",