mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-30 16:27:21 +00:00
Add zwave_js device statistics (#12794)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
f020add6be
commit
54377225ec
@ -244,6 +244,41 @@ export interface ZWaveJSControllerStatisticsUpdatedMessage {
|
|||||||
timeout_callback: number;
|
timeout_callback: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum RssiError {
|
||||||
|
NotAvailable = 127,
|
||||||
|
ReceiverSaturated = 126,
|
||||||
|
NoSignalDetected = 125,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProtocolDataRate {
|
||||||
|
ZWave_9k6 = 0x01,
|
||||||
|
ZWave_40k = 0x02,
|
||||||
|
ZWave_100k = 0x03,
|
||||||
|
LongRange_100k = 0x04,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZWaveJSNodeStatisticsUpdatedMessage {
|
||||||
|
event: "statistics updated";
|
||||||
|
source: "node";
|
||||||
|
commands_tx: number;
|
||||||
|
commands_rx: number;
|
||||||
|
commands_dropped_tx: number;
|
||||||
|
commands_dropped_rx: number;
|
||||||
|
timeout_response: number;
|
||||||
|
rtt: number | null;
|
||||||
|
rssi: RssiError | number | null;
|
||||||
|
lwr: ZWaveJSRouteStatistics | null;
|
||||||
|
nlwr: ZWaveJSRouteStatistics | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZWaveJSRouteStatistics {
|
||||||
|
protocol_data_rate: number;
|
||||||
|
repeaters: string[];
|
||||||
|
rssi: RssiError | number | null;
|
||||||
|
repeater_rssi: (RssiError | number)[];
|
||||||
|
route_failed_between: [string, string] | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ZWaveJSRemovedNode {
|
export interface ZWaveJSRemovedNode {
|
||||||
node_id: number;
|
node_id: number;
|
||||||
manufacturer: string;
|
manufacturer: string;
|
||||||
@ -597,6 +632,19 @@ export const subscribeZwaveControllerStatistics = (
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const subscribeZwaveNodeStatistics = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_id: string,
|
||||||
|
callbackFunction: (message: ZWaveJSNodeStatisticsUpdatedMessage) => void
|
||||||
|
): Promise<UnsubscribeFunc> =>
|
||||||
|
hass.connection.subscribeMessage(
|
||||||
|
(message: any) => callbackFunction(message),
|
||||||
|
{
|
||||||
|
type: "zwave_js/subscribe_node_statistics",
|
||||||
|
device_id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const getZwaveJsIdentifiersFromDevice = (
|
export const getZwaveJsIdentifiersFromDevice = (
|
||||||
device: DeviceRegistryEntry
|
device: DeviceRegistryEntry
|
||||||
): ZWaveJSNodeIdentifiers | undefined => {
|
): ZWaveJSNodeIdentifiers | undefined => {
|
||||||
|
@ -3,6 +3,7 @@ import { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
|||||||
import { fetchZwaveNodeStatus } from "../../../../../../data/zwave_js";
|
import { fetchZwaveNodeStatus } from "../../../../../../data/zwave_js";
|
||||||
import type { HomeAssistant } from "../../../../../../types";
|
import type { HomeAssistant } from "../../../../../../types";
|
||||||
import { showZWaveJSHealNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-heal-node";
|
import { showZWaveJSHealNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-heal-node";
|
||||||
|
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 { 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 { showZWaveJSRemoveFailedNodeDialog } from "../../../../integrations/integration-panels/zwave_js/show-dialog-zwave_js-remove-failed-node";
|
||||||
import type { DeviceAction } from "../../../ha-config-device-page";
|
import type { DeviceAction } from "../../../ha-config-device-page";
|
||||||
@ -64,5 +65,14 @@ export const getZwaveDeviceActions = async (
|
|||||||
device_id: device.id,
|
device_id: device.id,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.device_info.node_statistics"
|
||||||
|
),
|
||||||
|
action: () =>
|
||||||
|
showZWaveJSNodeStatisticsDialog(el, {
|
||||||
|
device: device,
|
||||||
|
}),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,477 @@
|
|||||||
|
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
|
import "../../../../../components/ha-expansion-panel";
|
||||||
|
import "../../../../../components/ha-help-tooltip";
|
||||||
|
import "../../../../../components/ha-svg-icon";
|
||||||
|
import { mdiSwapHorizontal } 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 {
|
||||||
|
DeviceRegistryEntry,
|
||||||
|
computeDeviceName,
|
||||||
|
subscribeDeviceRegistry,
|
||||||
|
} from "../../../../../data/device_registry";
|
||||||
|
import {
|
||||||
|
subscribeZwaveNodeStatistics,
|
||||||
|
ProtocolDataRate,
|
||||||
|
ZWaveJSNodeStatisticsUpdatedMessage,
|
||||||
|
ZWaveJSRouteStatistics,
|
||||||
|
RssiError,
|
||||||
|
} from "../../../../../data/zwave_js";
|
||||||
|
import { haStyleDialog } from "../../../../../resources/styles";
|
||||||
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
import { ZWaveJSNodeStatisticsDialogParams } from "./show-dialog-zwave_js-node-statistics";
|
||||||
|
import { createCloseHeading } from "../../../../../components/ha-dialog";
|
||||||
|
|
||||||
|
type WorkingRouteStatistics =
|
||||||
|
| (ZWaveJSRouteStatistics & {
|
||||||
|
repeater_rssi_table?: TemplateResult;
|
||||||
|
rssi_translated?: TemplateResult | string;
|
||||||
|
route_failed_between_translated?: [string, string];
|
||||||
|
})
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
@customElement("dialog-zwave_js-node-statistics")
|
||||||
|
class DialogZWaveJSNodeStatistics extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private device?: DeviceRegistryEntry;
|
||||||
|
|
||||||
|
@state() private _nodeStatistics?: ZWaveJSNodeStatisticsUpdatedMessage & {
|
||||||
|
rssi_translated?: TemplateResult | string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@state() private _deviceIDsToName: { [key: string]: string } = {};
|
||||||
|
|
||||||
|
@state() private _workingRoutes: {
|
||||||
|
lwr?: WorkingRouteStatistics;
|
||||||
|
nlwr?: WorkingRouteStatistics;
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
private _subscribedNodeStatistics?: Promise<UnsubscribeFunc>;
|
||||||
|
|
||||||
|
private _subscribedDeviceRegistry?: UnsubscribeFunc;
|
||||||
|
|
||||||
|
public showDialog(params: ZWaveJSNodeStatisticsDialogParams): void {
|
||||||
|
this.device = params.device;
|
||||||
|
this._subscribeDeviceRegistry();
|
||||||
|
this._subscribeNodeStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): void {
|
||||||
|
this._nodeStatistics = undefined;
|
||||||
|
this.device = undefined;
|
||||||
|
|
||||||
|
this._unsubscribe();
|
||||||
|
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (!this.device) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
.heading=${createCloseHeading(
|
||||||
|
this.hass,
|
||||||
|
this.hass.localize("ui.panel.config.zwave_js.node_statistics.title")
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<mwc-list noninteractive>
|
||||||
|
<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_tx.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_tx.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta">${this._nodeStatistics?.commands_tx}</span>
|
||||||
|
</mwc-list-item>
|
||||||
|
<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_rx.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_rx.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta">${this._nodeStatistics?.commands_rx}</span>
|
||||||
|
</mwc-list-item>
|
||||||
|
<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_dropped_tx.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_dropped_tx.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta"
|
||||||
|
>${this._nodeStatistics?.commands_dropped_tx}</span
|
||||||
|
>
|
||||||
|
</mwc-list-item>
|
||||||
|
<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_dropped_rx.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.commands_dropped_rx.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta"
|
||||||
|
>${this._nodeStatistics?.commands_dropped_rx}</span
|
||||||
|
>
|
||||||
|
</mwc-list-item>
|
||||||
|
<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.timeout_response.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.timeout_response.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta">${this._nodeStatistics?.timeout_response}</span>
|
||||||
|
</mwc-list-item>
|
||||||
|
${this._nodeStatistics?.rtt
|
||||||
|
? html`<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.rtt.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.rtt.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta">${this._nodeStatistics.rtt}</span>
|
||||||
|
</mwc-list-item>`
|
||||||
|
: ``}
|
||||||
|
${this._nodeStatistics?.rssi_translated
|
||||||
|
? html`<mwc-list-item twoline hasmeta>
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.rssi.label"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.node_statistics.rssi.tooltip"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span slot="meta">${this._nodeStatistics.rssi_translated}</span>
|
||||||
|
</mwc-list-item>`
|
||||||
|
: ``}
|
||||||
|
</mwc-list>
|
||||||
|
${Object.entries(this._workingRoutes).map(([wrKey, wrValue]) =>
|
||||||
|
wrValue
|
||||||
|
? html`
|
||||||
|
<ha-expansion-panel
|
||||||
|
.header=${this.hass.localize(
|
||||||
|
`ui.panel.config.zwave_js.node_statistics.${wrKey}`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div class="row">
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.protocol.label"
|
||||||
|
)}<ha-help-tooltip
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.protocol.tooltip"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
</ha-help-tooltip
|
||||||
|
></span>
|
||||||
|
<span
|
||||||
|
>${this.hass.localize(
|
||||||
|
`ui.panel.config.zwave_js.route_statistics.protocol.protocol_data_rate.${
|
||||||
|
ProtocolDataRate[wrValue.protocol_data_rate]
|
||||||
|
}`
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.data_rate.label"
|
||||||
|
)}<ha-help-tooltip
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.data_rate.tooltip"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
</ha-help-tooltip
|
||||||
|
></span>
|
||||||
|
<span
|
||||||
|
>${this.hass.localize(
|
||||||
|
`ui.panel.config.zwave_js.route_statistics.data_rate.protocol_data_rate.${
|
||||||
|
ProtocolDataRate[wrValue.protocol_data_rate]
|
||||||
|
}`
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
${wrValue.rssi_translated
|
||||||
|
? html`<div class="row">
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.rssi.label"
|
||||||
|
)}<ha-help-tooltip
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.rssi.tooltip"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
</ha-help-tooltip
|
||||||
|
></span>
|
||||||
|
<span>${wrValue.rssi_translated}</span>
|
||||||
|
</div>`
|
||||||
|
: ``}
|
||||||
|
<div class="row">
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.route_failed_between.label"
|
||||||
|
)}<ha-help-tooltip
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.route_failed_between.tooltip"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
</ha-help-tooltip
|
||||||
|
></span>
|
||||||
|
<span>
|
||||||
|
${wrValue.route_failed_between_translated
|
||||||
|
? html`${wrValue
|
||||||
|
.route_failed_between_translated[0]}<ha-svg-icon
|
||||||
|
.path=${mdiSwapHorizontal}
|
||||||
|
></ha-svg-icon
|
||||||
|
>${wrValue.route_failed_between_translated[1]}`
|
||||||
|
: this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.route_failed_between.not_applicable"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<span>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.repeaters.label"
|
||||||
|
)}<ha-help-tooltip
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.repeaters.tooltip"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
</ha-help-tooltip></span
|
||||||
|
><span>
|
||||||
|
${wrValue.repeater_rssi_table
|
||||||
|
? html`<div class="row">
|
||||||
|
<span class="key-cell"
|
||||||
|
><b
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.repeaters.repeaters"
|
||||||
|
)}:</b
|
||||||
|
></span
|
||||||
|
>
|
||||||
|
<span class="value-cell"
|
||||||
|
><b
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.repeaters.rssi"
|
||||||
|
)}:</b
|
||||||
|
></span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
${wrValue.repeater_rssi_table}`
|
||||||
|
: html`${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.route_statistics.repeaters.direct"
|
||||||
|
)}`}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</ha-expansion-panel>
|
||||||
|
`
|
||||||
|
: ``
|
||||||
|
)}
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeRSSI(
|
||||||
|
rssi: number,
|
||||||
|
includeUnit: boolean
|
||||||
|
): TemplateResult | string {
|
||||||
|
if (Object.values(RssiError).includes(rssi)) {
|
||||||
|
return html`<ha-help-tooltip
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
`ui.panel.config.zwave_js.rssi.rssi_error.${RssiError[rssi]}`
|
||||||
|
)}
|
||||||
|
></ha-help-tooltip>`;
|
||||||
|
}
|
||||||
|
if (includeUnit) {
|
||||||
|
return `${rssi}
|
||||||
|
${this.hass.localize("ui.panel.config.zwave_js.rssi.unit")}`;
|
||||||
|
}
|
||||||
|
return rssi.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeDeviceNameById(device_id: string): "unknown device" | string {
|
||||||
|
if (!this._deviceIDsToName) {
|
||||||
|
return "unknown device";
|
||||||
|
}
|
||||||
|
const device = this._deviceIDsToName[device_id];
|
||||||
|
if (!device) {
|
||||||
|
return "unknown device";
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._deviceIDsToName[device_id] || "unknown device";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _subscribeNodeStatistics(): void {
|
||||||
|
if (!this.hass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._subscribedNodeStatistics = subscribeZwaveNodeStatistics(
|
||||||
|
this.hass,
|
||||||
|
this.device!.id,
|
||||||
|
(message: ZWaveJSNodeStatisticsUpdatedMessage) => {
|
||||||
|
this._nodeStatistics = {
|
||||||
|
...message,
|
||||||
|
rssi_translated: message.rssi
|
||||||
|
? this._computeRSSI(message.rssi, false)
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const workingRoutesValueMap: [
|
||||||
|
string,
|
||||||
|
WorkingRouteStatistics | null | undefined
|
||||||
|
][] = [
|
||||||
|
["lwr", this._nodeStatistics?.lwr],
|
||||||
|
["nlwr", this._nodeStatistics?.nlwr],
|
||||||
|
];
|
||||||
|
|
||||||
|
const workingRoutes: {
|
||||||
|
lwr?: WorkingRouteStatistics;
|
||||||
|
nlwr?: WorkingRouteStatistics;
|
||||||
|
} = {};
|
||||||
|
workingRoutesValueMap.forEach(([wrKey, wrValue]) => {
|
||||||
|
workingRoutes[wrKey] = wrValue;
|
||||||
|
|
||||||
|
if (wrValue) {
|
||||||
|
if (wrValue.rssi) {
|
||||||
|
wrValue.rssi_translated = this._computeRSSI(wrValue.rssi, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrValue.route_failed_between) {
|
||||||
|
wrValue.route_failed_between_translated = [
|
||||||
|
this._computeDeviceNameById(wrValue.route_failed_between[0]),
|
||||||
|
this._computeDeviceNameById(wrValue.route_failed_between[1]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrValue.repeaters && wrValue.repeaters.length) {
|
||||||
|
wrValue.repeater_rssi_table = html`${wrValue.repeaters.map(
|
||||||
|
(_, idx) =>
|
||||||
|
html`<div class="row">
|
||||||
|
<span class="key-cell"
|
||||||
|
>${this._computeDeviceNameById(
|
||||||
|
wrValue.repeaters[idx]
|
||||||
|
)}:</span
|
||||||
|
>
|
||||||
|
<span class="value-cell"
|
||||||
|
>${this._computeRSSI(
|
||||||
|
wrValue.repeater_rssi[idx],
|
||||||
|
true
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
</div>`
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._workingRoutes = workingRoutes;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _subscribeDeviceRegistry(): void {
|
||||||
|
if (!this.hass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._subscribedDeviceRegistry = subscribeDeviceRegistry(
|
||||||
|
this.hass.connection,
|
||||||
|
(devices: DeviceRegistryEntry[]) => {
|
||||||
|
const devicesIdToName = {};
|
||||||
|
devices.forEach((device) => {
|
||||||
|
devicesIdToName[device.id] = computeDeviceName(device, this.hass);
|
||||||
|
});
|
||||||
|
this._deviceIDsToName = devicesIdToName;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _unsubscribe(): void {
|
||||||
|
if (this._subscribedNodeStatistics) {
|
||||||
|
this._subscribedNodeStatistics.then((unsub) => unsub());
|
||||||
|
this._subscribedNodeStatistics = undefined;
|
||||||
|
}
|
||||||
|
if (this._subscribedDeviceRegistry) {
|
||||||
|
this._subscribedDeviceRegistry();
|
||||||
|
this._subscribedDeviceRegistry = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return [
|
||||||
|
haStyleDialog,
|
||||||
|
css`
|
||||||
|
mwc-list-item {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-cell {
|
||||||
|
display: table-cell;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-cell {
|
||||||
|
display: table-cell;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span[slot="meta"] {
|
||||||
|
font-size: 0.95em;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-zwave_js-node-statistics": DialogZWaveJSNodeStatistics;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import { DeviceRegistryEntry } from "../../../../../data/device_registry";
|
||||||
|
|
||||||
|
export interface ZWaveJSNodeStatisticsDialogParams {
|
||||||
|
device: DeviceRegistryEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loadNodeStatisticsDialog = () =>
|
||||||
|
import("./dialog-zwave_js-node-statistics");
|
||||||
|
|
||||||
|
export const showZWaveJSNodeStatisticsDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
nodeStatisticsDialogParams: ZWaveJSNodeStatisticsDialogParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "dialog-zwave_js-node-statistics",
|
||||||
|
dialogImport: loadNodeStatisticsDialog,
|
||||||
|
dialogParams: nodeStatisticsDialogParams,
|
||||||
|
});
|
||||||
|
};
|
@ -3103,7 +3103,87 @@
|
|||||||
"highest_security": "Highest Security",
|
"highest_security": "Highest Security",
|
||||||
"unknown": "Unknown",
|
"unknown": "Unknown",
|
||||||
"zwave_plus": "Z-Wave Plus",
|
"zwave_plus": "Z-Wave Plus",
|
||||||
"zwave_plus_version": "Version {version}"
|
"zwave_plus_version": "Version {version}",
|
||||||
|
"node_statistics": "Show Device Statistics"
|
||||||
|
},
|
||||||
|
"node_statistics": {
|
||||||
|
"title": "Device Statistics",
|
||||||
|
"commands_tx": {
|
||||||
|
"label": "Commands TX",
|
||||||
|
"tooltip": "# of commands successfully sent to the node"
|
||||||
|
},
|
||||||
|
"commands_rx": {
|
||||||
|
"label": "Commands RX",
|
||||||
|
"tooltip": "# of commands received from the node, including responses to sent commands"
|
||||||
|
},
|
||||||
|
"commands_dropped_tx": {
|
||||||
|
"label": "Commands Dropped TX",
|
||||||
|
"tooltip": "# of outgoing commands that were dropped because they could not be sent"
|
||||||
|
},
|
||||||
|
"commands_dropped_rx": {
|
||||||
|
"label": "Commands Dropped RX",
|
||||||
|
"tooltip": "# of commands from the node that were dropped by the host"
|
||||||
|
},
|
||||||
|
"timeout_response": {
|
||||||
|
"label": "Timeout Response",
|
||||||
|
"tooltip": "# of Get-type commands where the node's response did not come in time"
|
||||||
|
},
|
||||||
|
"rtt": {
|
||||||
|
"label": "RTT",
|
||||||
|
"tooltip": "Average round-trip-time in ms of commands to this node"
|
||||||
|
},
|
||||||
|
"rssi": {
|
||||||
|
"label": "RSSI",
|
||||||
|
"tooltip": "Average RSSI in dBm of frames received by this node"
|
||||||
|
},
|
||||||
|
"lwr": "Last Working Route",
|
||||||
|
"nlwr": "Next to Last Working Route"
|
||||||
|
},
|
||||||
|
"route_statistics": {
|
||||||
|
"protocol": {
|
||||||
|
"label": "Protocol",
|
||||||
|
"tooltip": "The protocol for this route",
|
||||||
|
"protocol_data_rate": {
|
||||||
|
"ZWave_9k6": "Z-Wave",
|
||||||
|
"ZWave_40k": "Z-Wave",
|
||||||
|
"ZWave_100k": "Z-Wave",
|
||||||
|
"LongRange_100k": "Z-Wave Long Range"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data_rate": {
|
||||||
|
"label": "Data Rate",
|
||||||
|
"tooltip": "The used data rate for this route",
|
||||||
|
"protocol_data_rate": {
|
||||||
|
"ZWave_9k6": "9.6 kbps",
|
||||||
|
"ZWave_40k": "40 kbps",
|
||||||
|
"ZWave_100k": "100 kbps",
|
||||||
|
"LongRange_100k": "100 kbps"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"repeaters": {
|
||||||
|
"label": "Repeaters + RSSI",
|
||||||
|
"tooltip": "Which nodes are repeaters for this route and their RSSI",
|
||||||
|
"repeaters": "Repeater Device",
|
||||||
|
"rssi": "RSSI",
|
||||||
|
"direct": "None, direct connection"
|
||||||
|
},
|
||||||
|
"rssi": {
|
||||||
|
"label": "RSSI",
|
||||||
|
"tooltip": "The RSSI of the ACK frame received by the controller"
|
||||||
|
},
|
||||||
|
"route_failed_between": {
|
||||||
|
"label": "Route Failed Between",
|
||||||
|
"tooltip": "The nodes between which the transmission failed most recently",
|
||||||
|
"not_applicable": "N/A"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rssi": {
|
||||||
|
"unit": "dBm",
|
||||||
|
"rssi_error": {
|
||||||
|
"NotAvailable": "Not available",
|
||||||
|
"ReceiverSaturated": "Receiver saturated",
|
||||||
|
"NoSignalDetected": "No signal detected"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_config": {
|
"node_config": {
|
||||||
"header": "Z-Wave Device Configuration",
|
"header": "Z-Wave Device Configuration",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user