Add download dump button to zwave_js panel (#8232)

Co-authored-by: Philip Allgaier <mail@spacegaier.de>
This commit is contained in:
Bram Kragten 2021-01-26 22:20:16 +01:00 committed by GitHub
parent 048de6b388
commit 9d289bfa34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 13 deletions

View File

@ -19,7 +19,7 @@ export interface ZWaveJSClient {
export interface ZWaveJSController { export interface ZWaveJSController {
home_id: string; home_id: string;
node_count: number; nodes: number[];
} }
export interface ZWaveJSNode { export interface ZWaveJSNode {
@ -28,6 +28,14 @@ export interface ZWaveJSNode {
status: number; status: number;
} }
export enum NodeStatus {
Unknown,
Asleep,
Awake,
Dead,
Alive,
}
export const nodeStatus = ["unknown", "asleep", "awake", "dead", "alive"]; export const nodeStatus = ["unknown", "asleep", "awake", "dead", "alive"];
export const fetchNetworkStatus = ( export const fetchNetworkStatus = (

View File

@ -57,7 +57,7 @@ class DialogBox extends LitElement {
open open
?scrimClickAction=${confirmPrompt} ?scrimClickAction=${confirmPrompt}
?escapeKeyAction=${confirmPrompt} ?escapeKeyAction=${confirmPrompt}
@closed=${this._dialogClosed} @closing=${this._dialogClosed}
defaultAction="ignore" defaultAction="ignore"
.heading=${this._params.title .heading=${this._params.title
? this._params.title ? this._params.title

View File

@ -1,5 +1,6 @@
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import { mdiCheckCircle, mdiCircle } from "@mdi/js"; import "@material/mwc-icon-button/mwc-icon-button";
import { mdiCheckCircle, mdiCircle, mdiRefresh } from "@mdi/js";
import { import {
css, css,
CSSResultArray, CSSResultArray,
@ -12,11 +13,20 @@ import {
} from "lit-element"; } from "lit-element";
import { classMap } from "lit-html/directives/class-map"; import { classMap } from "lit-html/directives/class-map";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-icon-next"; import "../../../../../components/ha-icon-next";
import { getSignedPath } from "../../../../../data/auth";
import { import {
fetchNetworkStatus, fetchNetworkStatus,
fetchNodeStatus,
NodeStatus,
ZWaveJSNetwork, ZWaveJSNetwork,
ZWaveJSNode,
} from "../../../../../data/zwave_js"; } from "../../../../../data/zwave_js";
import {
showAlertDialog,
showConfirmationDialog,
} from "../../../../../dialogs/generic/show-dialog-box";
import "../../../../../layouts/hass-tabs-subpage"; import "../../../../../layouts/hass-tabs-subpage";
import { haStyle } from "../../../../../resources/styles"; import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types"; import type { HomeAssistant, Route } from "../../../../../types";
@ -39,6 +49,8 @@ class ZWaveJSConfigDashboard extends LitElement {
@internalProperty() private _network?: ZWaveJSNetwork; @internalProperty() private _network?: ZWaveJSNetwork;
@internalProperty() private _nodes?: ZWaveJSNode[];
@internalProperty() private _status = "unknown"; @internalProperty() private _status = "unknown";
@internalProperty() private _icon = mdiCircle; @internalProperty() private _icon = mdiCircle;
@ -57,6 +69,9 @@ class ZWaveJSConfigDashboard extends LitElement {
.route=${this.route} .route=${this.route}
.tabs=${configTabs} .tabs=${configTabs}
> >
<mwc-icon-button slot="toolbar-icon" @click=${this._fetchData}>
<ha-svg-icon .path=${mdiRefresh}></ha-svg-icon>
</mwc-icon-button>
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}> <ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
<div slot="header"> <div slot="header">
${this.hass.localize("ui.panel.config.zwave_js.dashboard.header")} ${this.hass.localize("ui.panel.config.zwave_js.dashboard.header")}
@ -117,9 +132,10 @@ class ZWaveJSConfigDashboard extends LitElement {
)}: )}:
${this._network.controller.home_id}<br /> ${this._network.controller.home_id}<br />
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.zwave_js.dashboard.node_count" "ui.panel.config.zwave_js.dashboard.nodes_ready"
)}: )}:
${this._network.controller.node_count} ${this._nodes?.filter((node) => node.ready).length ?? 0} /
${this._network.controller.nodes.length}
</div> </div>
</div> </div>
<div class="card-actions"> <div class="card-actions">
@ -153,18 +169,36 @@ class ZWaveJSConfigDashboard extends LitElement {
</ha-card> </ha-card>
` `
: ``} : ``}
<button class="link dump" @click=${this._dumpDebugClicked}>
${this.hass.localize(
"ui.panel.config.zwave_js.dashboard.dump_debug"
)}
</button>
</ha-config-section> </ha-config-section>
</hass-tabs-subpage> </hass-tabs-subpage>
`; `;
} }
private async _fetchData() { private async _fetchData() {
if (!this.configEntryId) return; if (!this.configEntryId) {
return;
}
this._network = await fetchNetworkStatus(this.hass!, this.configEntryId); this._network = await fetchNetworkStatus(this.hass!, this.configEntryId);
this._status = this._network.client.state; this._status = this._network.client.state;
if (this._status === "connected") { if (this._status === "connected") {
this._icon = mdiCheckCircle; this._icon = mdiCheckCircle;
} }
this._fetchNodeStatus();
}
private async _fetchNodeStatus() {
if (!this._network) {
return;
}
const nodeStatePromisses = this._network.controller.nodes.map((nodeId) =>
fetchNodeStatus(this.hass, this.configEntryId!, nodeId)
);
this._nodes = await Promise.all(nodeStatePromisses);
} }
private async _addNodeClicked() { private async _addNodeClicked() {
@ -179,6 +213,65 @@ class ZWaveJSConfigDashboard extends LitElement {
}); });
} }
private async _dumpDebugClicked() {
await this._fetchNodeStatus();
const notReadyNodes = this._nodes?.filter((node) => !node.ready);
const deadNodes = this._nodes?.filter(
(node) => node.status === NodeStatus.Dead
);
if (deadNodes?.length) {
await showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.config.zwave_js.dashboard.dump_dead_nodes_title"
),
text: this.hass.localize(
"ui.panel.config.zwave_js.dashboard.dump_dead_nodes_text"
),
});
}
if (
notReadyNodes?.length &&
notReadyNodes.length !== deadNodes?.length &&
!(await showConfirmationDialog(this, {
title: this.hass.localize(
"ui.panel.config.zwave_js.dashboard.dump_not_ready_title"
),
text: this.hass.localize(
"ui.panel.config.zwave_js.dashboard.dump_not_ready_text"
),
confirmText: this.hass.localize(
"ui.panel.config.zwave_js.dashboard.dump_not_ready_confirm"
),
}))
) {
return;
}
let signedPath: { path: string };
try {
signedPath = await getSignedPath(
this.hass,
`/api/zwave_js/dump/${this.configEntryId}`
);
} catch (err) {
showAlertDialog(this, {
title: "Error",
text: err.error || err.body || err,
});
return;
}
const a = document.createElement("a");
a.href = signedPath.path;
a.download = `zwave_js_dump.jsonl`;
this.shadowRoot!.appendChild(a);
a.click();
this.shadowRoot!.removeChild(a);
}
static get styles(): CSSResultArray { static get styles(): CSSResultArray {
return [ return [
haStyle, haStyle,
@ -207,15 +300,10 @@ class ZWaveJSConfigDashboard extends LitElement {
.network-status div.heading { .network-status div.heading {
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
margin-bottom: 16px; margin-bottom: 16px;
} }
.network-status {
text-align: center;
}
.network-status div.heading .icon { .network-status div.heading .icon {
width: 48px; width: 48px;
height: 48px; height: 48px;
@ -238,6 +326,12 @@ class ZWaveJSConfigDashboard extends LitElement {
max-width: 600px; max-width: 600px;
} }
button.dump {
width: 100%;
text-align: center;
color: var(--secondary-text-color);
}
[hidden] { [hidden] {
display: none; display: none;
} }

View File

@ -2401,7 +2401,13 @@
"driver_version": "Driver Version", "driver_version": "Driver Version",
"server_version": "Server Version", "server_version": "Server Version",
"home_id": "Home ID", "home_id": "Home ID",
"node_count": "Node Count" "nodes_ready": "Nodes ready",
"dump_debug": "Download a dump of your network to help diagnose issues",
"dump_dead_nodes_title": "Some of your nodes are dead",
"dump_dead_nodes_text": "Some of your nodes didn't respond and are assumed dead. These will not be fully exported.",
"dump_not_ready_title": "Not all nodes are ready yet",
"dump_not_ready_text": "If you create an export while not all nodes are ready, you could miss needed data. Give your network some time to query all nodes. Do you want to continue with the dump?",
"dump_not_ready_confirm": "Download"
}, },
"device_info": { "device_info": {
"zwave_info": "Z-Wave Info", "zwave_info": "Z-Wave Info",
@ -3318,4 +3324,4 @@
} }
} }
} }
} }