From 707338b1aa139d88408f7760dd8af50f15fe9746 Mon Sep 17 00:00:00 2001 From: Charles Garwood Date: Thu, 21 Jan 2021 10:16:24 -0500 Subject: [PATCH] Add Z-Wave info to device page for zwave_js devices (#8195) --- src/data/zwave_js.ts | 45 +++++++ .../zwave_js/ha-device-info-zwave_js.ts | 112 ++++++++++++++++++ .../config/devices/ha-config-device-page.ts | 11 ++ src/translations/en.json | 16 ++- 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/panels/config/devices/device-detail/integration-elements/zwave_js/ha-device-info-zwave_js.ts diff --git a/src/data/zwave_js.ts b/src/data/zwave_js.ts index 68e4374b92..6d9ac2dd89 100644 --- a/src/data/zwave_js.ts +++ b/src/data/zwave_js.ts @@ -1,5 +1,10 @@ import { HomeAssistant } from "../types"; +import { DeviceRegistryEntry } from "./device_registry"; +export interface ZWaveJSNodeIdentifiers { + home_id: string; + node_id: number; +} export interface ZWaveJSNetwork { client: ZWaveJSClient; controller: ZWaveJSController; @@ -17,6 +22,14 @@ export interface ZWaveJSController { node_count: number; } +export interface ZWaveJSNode { + node_id: number; + ready: boolean; + status: number; +} + +export const nodeStatus = ["unknown", "asleep", "awake", "dead", "alive"]; + export const fetchNetworkStatus = ( hass: HomeAssistant, entry_id: string @@ -25,3 +38,35 @@ export const fetchNetworkStatus = ( type: "zwave_js/network_status", entry_id, }); + +export const fetchNodeStatus = ( + hass: HomeAssistant, + entry_id: string, + node_id: number +): Promise => + hass.callWS({ + type: "zwave_js/node_status", + entry_id, + node_id, + }); + +export const getIdentifiersFromDevice = function ( + device: DeviceRegistryEntry +): ZWaveJSNodeIdentifiers | undefined { + if (!device) { + return undefined; + } + + const zwaveJSIdentifier = device.identifiers.find( + (identifier) => identifier[0] === "zwave_js" + ); + if (!zwaveJSIdentifier) { + return undefined; + } + + const identifiers = zwaveJSIdentifier[1].split("-"); + return { + node_id: parseInt(identifiers[1]), + home_id: identifiers[0], + }; +}; diff --git a/src/panels/config/devices/device-detail/integration-elements/zwave_js/ha-device-info-zwave_js.ts b/src/panels/config/devices/device-detail/integration-elements/zwave_js/ha-device-info-zwave_js.ts new file mode 100644 index 0000000000..ed35383b16 --- /dev/null +++ b/src/panels/config/devices/device-detail/integration-elements/zwave_js/ha-device-info-zwave_js.ts @@ -0,0 +1,112 @@ +import { + css, + CSSResult, + customElement, + html, + internalProperty, + LitElement, + property, + PropertyValues, + TemplateResult, +} from "lit-element"; +import { DeviceRegistryEntry } from "../../../../../../data/device_registry"; +import { + getIdentifiersFromDevice, + fetchNodeStatus, + ZWaveJSNode, + ZWaveJSNodeIdentifiers, + nodeStatus, +} from "../../../../../../data/zwave_js"; + +import { haStyle } from "../../../../../../resources/styles"; +import { HomeAssistant } from "../../../../../../types"; + +@customElement("ha-device-info-zwave_js") +export class HaDeviceInfoZWaveJS extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() public device!: DeviceRegistryEntry; + + @internalProperty() private _entryId?: string; + + @internalProperty() private _nodeId?: number; + + @internalProperty() private _homeId?: string; + + @internalProperty() private _node?: ZWaveJSNode; + + protected updated(changedProperties: PropertyValues) { + if (changedProperties.has("device")) { + const identifiers: + | ZWaveJSNodeIdentifiers + | undefined = getIdentifiersFromDevice(this.device); + if (!identifiers) { + return; + } + this._homeId = identifiers.home_id; + this._nodeId = identifiers.node_id; + this._entryId = this.device.config_entries[0]; + + this._fetchNodeDetails(); + } + } + + protected async _fetchNodeDetails() { + if (!this._nodeId || !this._entryId) { + return; + } + this._node = await fetchNodeStatus(this.hass, this._entryId, this._nodeId); + } + + protected render(): TemplateResult { + if (!this._node) { + return html``; + } + return html` +

+ ${this.hass.localize("ui.panel.config.zwave_js.device_info.zwave_info")} +

+
+ ${this.hass.localize("ui.panel.config.zwave_js.common.home_id")}: + ${this._homeId} +
+
+ ${this.hass.localize("ui.panel.config.zwave_js.common.node_id")}: + ${this._node.node_id} +
+
+ ${this.hass.localize( + "ui.panel.config.zwave_js.device_info.node_status" + )}: + ${this.hass.localize( + `ui.panel.config.zwave_js.node_status.${ + nodeStatus[this._node.status] + }` + )} +
+
+ ${this.hass.localize( + "ui.panel.config.zwave_js.device_info.node_ready" + )}: + ${this._node.ready + ? this.hass.localize("ui.common.yes") + : this.hass.localize("ui.common.no")} +
+ `; + } + + static get styles(): CSSResult[] { + return [ + haStyle, + css` + h4 { + margin-bottom: 4px; + } + div { + word-break: break-all; + margin-top: 2px; + } + `, + ]; + } +} diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 9f6a90748b..9aef24e530 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -605,6 +605,17 @@ export class HaConfigDevicePage extends LitElement { `); } + if (integrations.includes("zwave_js")) { + import( + "./device-detail/integration-elements/zwave_js/ha-device-info-zwave_js" + ); + templates.push(html` + + `); + } return templates; } diff --git a/src/translations/en.json b/src/translations/en.json index d4b29bdeb9..76bb2d2062 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2385,7 +2385,9 @@ "network": "Network" }, "common": { - "network": "Network" + "network": "Network", + "node_id": "Node ID", + "home_id": "Home ID" }, "dashboard": { "header": "Manage your Z-Wave Network", @@ -2395,6 +2397,18 @@ "home_id": "Home ID", "node_count": "Node Count" }, + "device_info": { + "zwave_info": "Z-Wave Info", + "node_status": "Node Status", + "node_ready": "Node Ready" + }, + "node_status": { + "unknown": "Unknown", + "asleep": "Asleep", + "awake": "Awake", + "dead": "Dead", + "alive": "Alive" + }, "network_status": { "connected": "Connected", "connecting": "Connecting",