mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 12:26:35 +00:00
Add view in visualization button to the device page for ZHA devices (#8090)
This commit is contained in:
parent
f31f10cea9
commit
1642c68493
@ -89,6 +89,11 @@ export const reconfigureNode = (
|
|||||||
ieee: ieeeAddress,
|
ieee: ieeeAddress,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const refreshTopology = (hass: HomeAssistant): Promise<void> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/topology/update",
|
||||||
|
});
|
||||||
|
|
||||||
export const fetchAttributesForCluster = (
|
export const fetchAttributesForCluster = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
ieeeAddress: string,
|
ieeeAddress: string,
|
||||||
|
@ -79,6 +79,11 @@ export class HaDeviceActionsZha extends LitElement {
|
|||||||
"ui.dialogs.zha_device_info.buttons.clusters"
|
"ui.dialogs.zha_device_info.buttons.clusters"
|
||||||
)}
|
)}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
|
<mwc-button @click=${this._onViewInVisualizationClick}>
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.dialogs.zha_device_info.buttons.view_in_visualization"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
<mwc-button class="warning" @click=${this._removeDevice}>
|
<mwc-button class="warning" @click=${this._removeDevice}>
|
||||||
${this.hass!.localize(
|
${this.hass!.localize(
|
||||||
"ui.dialogs.zha_device_info.buttons.remove"
|
"ui.dialogs.zha_device_info.buttons.remove"
|
||||||
@ -104,6 +109,13 @@ export class HaDeviceActionsZha extends LitElement {
|
|||||||
navigate(this, "/config/zha/add/" + this._zhaDevice!.ieee);
|
navigate(this, "/config/zha/add/" + this._zhaDevice!.ieee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onViewInVisualizationClick() {
|
||||||
|
navigate(
|
||||||
|
this,
|
||||||
|
"/config/zha/visualization/" + this._zhaDevice!.device_reg_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private async _handleZigbeeInfoClicked() {
|
private async _handleZigbeeInfoClicked() {
|
||||||
showZHADeviceZigbeeInfoDialog(this, { device: this._zhaDevice! });
|
showZHADeviceZigbeeInfoDialog(this, { device: this._zhaDevice! });
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,8 @@ class ZHAConfigDashboardRouter extends HassRouterPage {
|
|||||||
el.groupId = this.routeTail.path.substr(1);
|
el.groupId = this.routeTail.path.substr(1);
|
||||||
} else if (this._currentPage === "device") {
|
} else if (this._currentPage === "device") {
|
||||||
el.ieee = this.routeTail.path.substr(1);
|
el.ieee = this.routeTail.path.substr(1);
|
||||||
|
} else if (this._currentPage === "visualization") {
|
||||||
|
el.zoomedDeviceId = this.routeTail.path.substr(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
|
@ -9,23 +9,33 @@ import {
|
|||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { Edge, EdgeOptions, Network, Node } from "vis-network";
|
|
||||||
|
import "@material/mwc-button";
|
||||||
import { navigate } from "../../../../../common/navigate";
|
import { navigate } from "../../../../../common/navigate";
|
||||||
|
import {
|
||||||
|
fetchDevices,
|
||||||
|
refreshTopology,
|
||||||
|
ZHADevice,
|
||||||
|
} from "../../../../../data/zha";
|
||||||
|
import "../../../../../layouts/hass-subpage";
|
||||||
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
|
import { Network, Edge, Node, EdgeOptions } from "vis-network";
|
||||||
import "../../../../../common/search/search-input";
|
import "../../../../../common/search/search-input";
|
||||||
import "../../../../../components/device/ha-device-picker";
|
import "../../../../../components/device/ha-device-picker";
|
||||||
import "../../../../../components/ha-button-menu";
|
import "../../../../../components/ha-button-menu";
|
||||||
import "../../../../../components/ha-svg-icon";
|
import "../../../../../components/ha-svg-icon";
|
||||||
import { fetchDevices, ZHADevice } from "../../../../../data/zha";
|
|
||||||
import "../../../../../layouts/hass-subpage";
|
|
||||||
import { PolymerChangedEvent } from "../../../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../../../polymer-types";
|
||||||
import type { HomeAssistant } from "../../../../../types";
|
|
||||||
import { formatAsPaddedHex } from "./functions";
|
import { formatAsPaddedHex } from "./functions";
|
||||||
|
import { DeviceRegistryEntry } from "../../../../../data/device_registry";
|
||||||
|
|
||||||
@customElement("zha-network-visualization-page")
|
@customElement("zha-network-visualization-page")
|
||||||
export class ZHANetworkVisualizationPage extends LitElement {
|
export class ZHANetworkVisualizationPage extends LitElement {
|
||||||
@property({ type: Object }) public hass!: HomeAssistant;
|
@property({ type: Object }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean, reflect: true }) public narrow = false;
|
||||||
|
|
||||||
|
@property()
|
||||||
|
public zoomedDeviceId?: string;
|
||||||
|
|
||||||
@query("#visualization", true)
|
@query("#visualization", true)
|
||||||
private _visualization?: HTMLElement;
|
private _visualization?: HTMLElement;
|
||||||
@ -45,9 +55,6 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
@internalProperty()
|
@internalProperty()
|
||||||
private _filter?: string;
|
private _filter?: string;
|
||||||
|
|
||||||
@internalProperty()
|
|
||||||
private _zoomedDeviceId?: string;
|
|
||||||
|
|
||||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||||
super.firstUpdated(changedProperties);
|
super.firstUpdated(changedProperties);
|
||||||
if (this.hass) {
|
if (this.hass) {
|
||||||
@ -98,6 +105,12 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._network.on("stabilized", () => {
|
||||||
|
if (this.zoomedDeviceId) {
|
||||||
|
this._zoomToDevice();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
@ -121,13 +134,18 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
</search-input>
|
</search-input>
|
||||||
<ha-device-picker
|
<ha-device-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._zoomedDeviceId}
|
.value=${this.zoomedDeviceId}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.zha.visualization.zoom_label"
|
"ui.panel.config.zha.visualization.zoom_label"
|
||||||
)}
|
)}
|
||||||
.includeDomains="['zha']"
|
.deviceFilter=${(device) => this._filterDevices(device)}
|
||||||
@value-changed=${this._zoomToDevice}
|
@value-changed=${this._onZoomToDevice}
|
||||||
></ha-device-picker>
|
></ha-device-picker>
|
||||||
|
<mwc-button @click=${this._refreshTopology}
|
||||||
|
>${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.visualization.refresh_topology"
|
||||||
|
)}</mwc-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div id="visualization"></div>
|
<div id="visualization"></div>
|
||||||
</hass-subpage>
|
</hass-subpage>
|
||||||
@ -248,7 +266,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
filteredNodeIds.push(node.id!);
|
filteredNodeIds.push(node.id!);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._zoomedDeviceId = "";
|
this.zoomedDeviceId = "";
|
||||||
this._zoomOut();
|
this._zoomOut();
|
||||||
this._network.selectNodes(filteredNodeIds, true);
|
this._network.selectNodes(filteredNodeIds, true);
|
||||||
} else {
|
} else {
|
||||||
@ -256,21 +274,25 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _zoomToDevice(event: PolymerChangedEvent<string>) {
|
private _onZoomToDevice(event: PolymerChangedEvent<string>) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this._zoomedDeviceId = event.detail.value;
|
this.zoomedDeviceId = event.detail.value;
|
||||||
if (!this._network) {
|
if (!this._network) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this._zoomToDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _zoomToDevice() {
|
||||||
this._filter = "";
|
this._filter = "";
|
||||||
if (!this._zoomedDeviceId) {
|
if (!this.zoomedDeviceId) {
|
||||||
this._zoomOut();
|
this._zoomOut();
|
||||||
} else {
|
} else {
|
||||||
const device: ZHADevice | undefined = this._devicesByDeviceId.get(
|
const device: ZHADevice | undefined = this._devicesByDeviceId.get(
|
||||||
this._zoomedDeviceId
|
this.zoomedDeviceId
|
||||||
);
|
);
|
||||||
if (device) {
|
if (device) {
|
||||||
this._network.fit({
|
this._network!.fit({
|
||||||
nodes: [device.ieee],
|
nodes: [device.ieee],
|
||||||
animation: { duration: 500, easingFunction: "easeInQuad" },
|
animation: { duration: 500, easingFunction: "easeInQuad" },
|
||||||
});
|
});
|
||||||
@ -285,6 +307,24 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _refreshTopology(): Promise<void> {
|
||||||
|
await refreshTopology(this.hass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _filterDevices(device: DeviceRegistryEntry): boolean {
|
||||||
|
if (!this.hass) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const parts of device.identifiers) {
|
||||||
|
for (const part of parts) {
|
||||||
|
if (part === "zha") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
css`
|
css`
|
||||||
@ -299,30 +339,59 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
|||||||
line-height: var(--paper-font-display1_-_line-height);
|
line-height: var(--paper-font-display1_-_line-height);
|
||||||
opacity: var(--dark-primary-opacity);
|
opacity: var(--dark-primary-opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-header {
|
.table-header {
|
||||||
border-bottom: 1px solid --divider-color;
|
border-bottom: 1px solid --divider-color;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
height: var(--header-height);
|
height: var(--header-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host([narrow]) .table-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
height: var(--header-height) * 3;
|
||||||
|
}
|
||||||
|
|
||||||
.search-toolbar {
|
.search-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
search-input {
|
search-input {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host(:not([narrow])) search-input {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
search-input.header {
|
search-input.header {
|
||||||
left: -8px;
|
left: -8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-device-picker {
|
ha-device-picker {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host(:not([narrow])) ha-device-picker {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
mwc-button {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(:not([narrow])) mwc-button {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -745,7 +745,8 @@
|
|||||||
"remove": "Remove Device",
|
"remove": "Remove Device",
|
||||||
"clusters": "Manage Clusters",
|
"clusters": "Manage Clusters",
|
||||||
"reconfigure": "Reconfigure Device",
|
"reconfigure": "Reconfigure Device",
|
||||||
"zigbee_information": "Zigbee device signature"
|
"zigbee_information": "Zigbee device signature",
|
||||||
|
"view_in_visualization": "View in Visualization"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"reconfigure": "Reconfigure ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery powered device please ensure it is awake and accepting commands when you use this service.",
|
"reconfigure": "Reconfigure ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery powered device please ensure it is awake and accepting commands when you use this service.",
|
||||||
@ -2365,7 +2366,8 @@
|
|||||||
"header": "Network Visualization",
|
"header": "Network Visualization",
|
||||||
"caption": "Visualization",
|
"caption": "Visualization",
|
||||||
"highlight_label": "Highlight Devices",
|
"highlight_label": "Highlight Devices",
|
||||||
"zoom_label": "Zoom To Device"
|
"zoom_label": "Zoom To Device",
|
||||||
|
"refresh_topology": "Refresh Topology"
|
||||||
},
|
},
|
||||||
"group_binding": {
|
"group_binding": {
|
||||||
"header": "Group Binding",
|
"header": "Group Binding",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user