diff --git a/src/data/zwave_js.ts b/src/data/zwave_js.ts new file mode 100644 index 0000000000..68e4374b92 --- /dev/null +++ b/src/data/zwave_js.ts @@ -0,0 +1,27 @@ +import { HomeAssistant } from "../types"; + +export interface ZWaveJSNetwork { + client: ZWaveJSClient; + controller: ZWaveJSController; +} + +export interface ZWaveJSClient { + state: string; + ws_server_url: string; + server_version: string; + driver_version: string; +} + +export interface ZWaveJSController { + home_id: string; + node_count: number; +} + +export const fetchNetworkStatus = ( + hass: HomeAssistant, + entry_id: string +): Promise => + hass.callWS({ + type: "zwave_js/network_status", + entry_id, + }); diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index 3d9a829c6a..9fc0b65543 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -307,6 +307,13 @@ class HaPanelConfig extends HassRouterPage { load: () => import("./integrations/integration-panels/ozw/ozw-config-router"), }, + zwave_js: { + tag: "zwave_js-config-router", + load: () => + import( + "./integrations/integration-panels/zwave_js/zwave_js-config-router" + ), + }, }, }; diff --git a/src/panels/config/integrations/ha-integration-card.ts b/src/panels/config/integrations/ha-integration-card.ts index 9d9a101538..178869c026 100644 --- a/src/panels/config/integrations/ha-integration-card.ts +++ b/src/panels/config/integrations/ha-integration-card.ts @@ -66,6 +66,10 @@ const integrationsWithPanel = { buttonLocalizeKey: "ui.panel.config.zwave.button", path: "/config/zwave", }, + zwave_js: { + buttonLocalizeKey: "ui.panel.config.zwave_js.button", + path: "/config/zwave_js/dashboard", + }, }; @customElement("ha-integration-card") diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-dashboard.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-dashboard.ts new file mode 100644 index 0000000000..17297a0402 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-dashboard.ts @@ -0,0 +1,229 @@ +import "@material/mwc-button/mwc-button"; +import { mdiCheckCircle, mdiCircle } from "@mdi/js"; +import { + css, + CSSResultArray, + customElement, + html, + internalProperty, + LitElement, + property, + TemplateResult, +} from "lit-element"; +import { classMap } from "lit-html/directives/class-map"; +import "../../../../../components/ha-card"; +import "../../../../../components/ha-icon-next"; +import { + fetchNetworkStatus, + ZWaveJSNetwork, +} from "../../../../../data/zwave_js"; +import "../../../../../layouts/hass-tabs-subpage"; +import { haStyle } from "../../../../../resources/styles"; +import type { HomeAssistant, Route } from "../../../../../types"; +import "../../../ha-config-section"; +import { configTabs } from "./zwave_js-config-router"; + +@customElement("zwave_js-config-dashboard") +class ZWaveJSConfigDashboard extends LitElement { + @property({ type: Object }) public hass!: HomeAssistant; + + @property({ type: Object }) public route!: Route; + + @property({ type: Boolean }) public narrow!: boolean; + + @property({ type: Boolean }) public isWide!: boolean; + + @property() public configEntryId?: string; + + @internalProperty() private _network?: ZWaveJSNetwork; + + @internalProperty() private _status = "unknown"; + + @internalProperty() private _icon = mdiCircle; + + protected firstUpdated() { + if (this.hass) { + this._fetchData(); + } + } + + protected render(): TemplateResult { + return html` + + +
+ ${this.hass.localize("ui.panel.config.zwave_js.dashboard.header")} +
+ +
+ ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.introduction" + )} +
+ ${this._network + ? html` + +
+
+
+ ${this._status === "connecting" + ? html`` + : html` + + `} +
+ ${this._status !== "connecting" + ? html` +
+ ${this.hass.localize( + "ui.panel.config.zwave_js.common.network" + )} + ${this.hass.localize( + `ui.panel.config.zwave_js.network_status.${this._status}` + )}
+ ${this._network.client.ws_server_url} +
+ ` + : ``} +
+
+ ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.driver_version" + )}: + ${this._network.client.driver_version}
+ ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.server_version" + )}: + ${this._network.client.server_version}
+ ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.home_id" + )}: + ${this._network.controller.home_id}
+ ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.node_count" + )}: + ${this._network.controller.node_count} +
+
+ +
+ ` + : ``} +
+
+ `; + } + + private async _fetchData() { + if (!this.configEntryId) return; + this._network = await fetchNetworkStatus(this.hass!, this.configEntryId); + this._status = this._network.client.state; + if (this._status === "connected") { + this._icon = mdiCheckCircle; + } + } + + static get styles(): CSSResultArray { + return [ + haStyle, + css` + .secondary { + color: var(--secondary-text-color); + } + .connected { + color: green; + } + .starting { + color: orange; + } + .offline { + color: red; + } + + .content { + margin-top: 24px; + } + + .sectionHeader { + position: relative; + padding-right: 40px; + } + + .network-status div.heading { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 16px; + } + + .network-status { + text-align: center; + } + + .network-status div.heading .icon { + width: 48px; + height: 48px; + margin-right: 16px; + } + .network-status div.heading ha-svg-icon { + width: 48px; + height: 48px; + } + .network-status div.heading .details { + font-size: 1.5rem; + } + + .network-status small { + font-size: 1rem; + } + + ha-card { + margin: 0 auto; + max-width: 600px; + } + + [hidden] { + display: none; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "zwave_js-config-dashboard": ZWaveJSConfigDashboard; + } +} diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts new file mode 100644 index 0000000000..659a7fb964 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts @@ -0,0 +1,71 @@ +import { customElement, property } from "lit-element"; +import { + HassRouterPage, + RouterOptions, +} from "../../../../../layouts/hass-router-page"; +import { HomeAssistant } from "../../../../../types"; +import { navigate } from "../../../../../common/navigate"; +import { PageNavigation } from "../../../../../layouts/hass-tabs-subpage"; + +import { mdiServerNetwork } from "@mdi/js"; + +export const configTabs: PageNavigation[] = [ + { + translationKey: "ui.panel.config.zwave_js.navigation.network", + path: `/config/zwave_js/dashboard`, + iconPath: mdiServerNetwork, + }, +]; + +@customElement("zwave_js-config-router") +class ZWaveJSConfigRouter extends HassRouterPage { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() public isWide!: boolean; + + @property() public narrow!: boolean; + + private _configEntry = new URLSearchParams(window.location.search).get( + "config_entry" + ); + + protected routerOptions: RouterOptions = { + defaultPage: "dashboard", + showLoading: true, + routes: { + dashboard: { + tag: "zwave_js-config-dashboard", + load: () => import("./zwave_js-config-dashboard"), + }, + }, + }; + + protected updatePageEl(el): void { + el.route = this.routeTail; + el.hass = this.hass; + el.isWide = this.isWide; + el.narrow = this.narrow; + el.configEntryId = this._configEntry; + if (this._currentPage === "node") { + el.nodeId = this.routeTail.path.substr(1); + } + + const searchParams = new URLSearchParams(window.location.search); + if (this._configEntry && !searchParams.has("config_entry")) { + searchParams.append("config_entry", this._configEntry); + navigate( + this, + `${this.routeTail.prefix}${ + this.routeTail.path + }?${searchParams.toString()}`, + true + ); + } + } +} + +declare global { + interface HTMLElementTagNameMap { + "zwave_js-config-router": ZWaveJSConfigRouter; + } +} diff --git a/src/translations/en.json b/src/translations/en.json index 9c11dcf66b..6444a5d3a7 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2378,6 +2378,28 @@ "node_info": "Node Information", "refresh_entity": "Refresh Entity" } + }, + "zwave_js": { + "button": "Configure", + "navigation": { + "network": "Network" + }, + "common": { + "network": "Network" + }, + "dashboard": { + "header": "Manage your Z-Wave Network", + "introduction": "Manage your Z-Wave network and Z-Wave nodes", + "driver_version": "Driver Version", + "server_version": "Server Version", + "home_id": "Home ID", + "node_count": "Node Count" + }, + "network_status": { + "connected": "Connected", + "connecting": "Connecting", + "unknown": "Unknown" + } } }, "history": {