mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 19:56:42 +00:00
Add Zigbee group viewing to ZHA config panel (#4365)
* add ability to view zigbee groups * review comments * remove selectable until used
This commit is contained in:
parent
bb41170765
commit
de653e1f7b
@ -51,6 +51,12 @@ export interface ReadAttributeServiceData {
|
|||||||
manufacturer?: number;
|
manufacturer?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ZHAGroup {
|
||||||
|
name: string;
|
||||||
|
group_id: number;
|
||||||
|
members: ZHADevice[];
|
||||||
|
}
|
||||||
|
|
||||||
export const reconfigureNode = (
|
export const reconfigureNode = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
ieeeAddress: string
|
ieeeAddress: string
|
||||||
@ -153,3 +159,8 @@ export const fetchClustersForZhaNode = (
|
|||||||
type: "zha/devices/clusters",
|
type: "zha/devices/clusters",
|
||||||
ieee: ieeeAddress,
|
ieee: ieeeAddress,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchGroups = (hass: HomeAssistant): Promise<ZHAGroup[]> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/groups",
|
||||||
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ZHADevice } from "../../../data/zha";
|
import { ZHADevice, ZHAGroup } from "../../../data/zha";
|
||||||
|
|
||||||
export const formatAsPaddedHex = (value: string | number): string => {
|
export const formatAsPaddedHex = (value: string | number): string => {
|
||||||
let hex = value;
|
let hex = value;
|
||||||
@ -13,3 +13,9 @@ export const sortZHADevices = (a: ZHADevice, b: ZHADevice): number => {
|
|||||||
const nameb = b.user_given_name ? b.user_given_name : b.name;
|
const nameb = b.user_given_name ? b.user_given_name : b.name;
|
||||||
return nameA.localeCompare(nameb);
|
return nameA.localeCompare(nameb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const sortZHAGroups = (a: ZHAGroup, b: ZHAGroup): number => {
|
||||||
|
const nameA = a.name;
|
||||||
|
const nameb = b.name;
|
||||||
|
return nameA.localeCompare(nameb);
|
||||||
|
};
|
||||||
|
@ -5,6 +5,7 @@ import "./zha-cluster-attributes";
|
|||||||
import "./zha-cluster-commands";
|
import "./zha-cluster-commands";
|
||||||
import "./zha-network";
|
import "./zha-network";
|
||||||
import "./zha-node";
|
import "./zha-node";
|
||||||
|
import "./zha-groups-tile";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -45,6 +46,11 @@ export class HaConfigZha extends LitElement {
|
|||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
></zha-network>
|
></zha-network>
|
||||||
|
|
||||||
|
<zha-groups-tile
|
||||||
|
.isWide="${this.isWide}"
|
||||||
|
.hass="${this.hass}"
|
||||||
|
></zha-groups-tile>
|
||||||
|
|
||||||
<zha-node
|
<zha-node
|
||||||
.isWide="${this.isWide}"
|
.isWide="${this.isWide}"
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
|
@ -12,6 +12,7 @@ import { HomeAssistant } from "../../../types";
|
|||||||
class ZHAConfigPanel extends HassRouterPage {
|
class ZHAConfigPanel extends HassRouterPage {
|
||||||
@property() public hass!: HomeAssistant;
|
@property() public hass!: HomeAssistant;
|
||||||
@property() public isWide!: boolean;
|
@property() public isWide!: boolean;
|
||||||
|
@property() public narrow!: boolean;
|
||||||
|
|
||||||
protected routerOptions: RouterOptions = {
|
protected routerOptions: RouterOptions = {
|
||||||
defaultPage: "configuration",
|
defaultPage: "configuration",
|
||||||
@ -32,6 +33,13 @@ class ZHAConfigPanel extends HassRouterPage {
|
|||||||
/* webpackChunkName: "zha-add-devices-page" */ "./zha-add-devices-page"
|
/* webpackChunkName: "zha-add-devices-page" */ "./zha-add-devices-page"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
groups: {
|
||||||
|
tag: "zha-groups-dashboard",
|
||||||
|
load: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "zha-groups-dashboard" */ "./zha-groups-dashboard"
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -39,6 +47,7 @@ class ZHAConfigPanel extends HassRouterPage {
|
|||||||
el.route = this.routeTail;
|
el.route = this.routeTail;
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
el.isWide = this.isWide;
|
el.isWide = this.isWide;
|
||||||
|
el.narrow = this.narrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
src/panels/config/zha/zha-groups-dashboard.ts
Normal file
77
src/panels/config/zha/zha-groups-dashboard.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import "../../../layouts/hass-subpage";
|
||||||
|
import "./zha-groups-data-table";
|
||||||
|
|
||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
html,
|
||||||
|
TemplateResult,
|
||||||
|
property,
|
||||||
|
customElement,
|
||||||
|
CSSResult,
|
||||||
|
css,
|
||||||
|
} from "lit-element";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { ZHAGroup, fetchGroups } from "../../../data/zha";
|
||||||
|
import { sortZHAGroups } from "./functions";
|
||||||
|
|
||||||
|
@customElement("zha-groups-dashboard")
|
||||||
|
export class ZHAGroupsDashboard extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
@property() public narrow = false;
|
||||||
|
@property() public _groups!: ZHAGroup[];
|
||||||
|
|
||||||
|
public connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this._fetchGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<hass-subpage
|
||||||
|
header=${this.hass.localize(
|
||||||
|
"ui.panel.config.zha.groups.zha_zigbee_groups"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div class="content">
|
||||||
|
<zha-groups-data-table
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.groups=${this._groups}
|
||||||
|
class="table"
|
||||||
|
></zha-groups-data-table>
|
||||||
|
</div>
|
||||||
|
</hass-subpage>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchGroups() {
|
||||||
|
this._groups = (await fetchGroups(this.hass!)).sort(sortZHAGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
css`
|
||||||
|
.content {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
zha-groups-data-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
height: 200px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-groups-dashboard": ZHAGroupsDashboard;
|
||||||
|
}
|
||||||
|
}
|
85
src/panels/config/zha/zha-groups-data-table.ts
Normal file
85
src/panels/config/zha/zha-groups-data-table.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import "../../../components/data-table/ha-data-table";
|
||||||
|
import "../../../components/entity/ha-state-icon";
|
||||||
|
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
|
||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
html,
|
||||||
|
TemplateResult,
|
||||||
|
property,
|
||||||
|
customElement,
|
||||||
|
} from "lit-element";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table";
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { ZHAGroup, ZHADevice } from "../../../data/zha";
|
||||||
|
import { formatAsPaddedHex } from "./functions";
|
||||||
|
|
||||||
|
export interface GroupRowData extends ZHAGroup {
|
||||||
|
group?: GroupRowData;
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("zha-groups-data-table")
|
||||||
|
export class ZHAGroupsDataTable extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
@property() public narrow = false;
|
||||||
|
@property() public groups: ZHAGroup[] = [];
|
||||||
|
|
||||||
|
private _columns = memoizeOne(
|
||||||
|
(narrow: boolean): DataTableColumnContainer =>
|
||||||
|
narrow
|
||||||
|
? {
|
||||||
|
name: {
|
||||||
|
title: "Group",
|
||||||
|
sortable: true,
|
||||||
|
filterable: true,
|
||||||
|
direction: "asc",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
name: {
|
||||||
|
title: this.hass.localize("ui.panel.config.zha.groups.groups"),
|
||||||
|
sortable: true,
|
||||||
|
filterable: true,
|
||||||
|
direction: "asc",
|
||||||
|
},
|
||||||
|
group_id: {
|
||||||
|
title: this.hass.localize("ui.panel.config.zha.groups.group_id"),
|
||||||
|
template: (groupId: number) => {
|
||||||
|
return html`
|
||||||
|
${formatAsPaddedHex(groupId)}
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
members: {
|
||||||
|
title: this.hass.localize("ui.panel.config.zha.groups.members"),
|
||||||
|
template: (members: ZHADevice[]) => {
|
||||||
|
return html`
|
||||||
|
${members.length}
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<ha-data-table
|
||||||
|
.columns=${this._columns(this.narrow)}
|
||||||
|
.data=${this.groups}
|
||||||
|
.id=${"group_id"}
|
||||||
|
></ha-data-table>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-groups-data-table": ZHAGroupsDataTable;
|
||||||
|
}
|
||||||
|
}
|
108
src/panels/config/zha/zha-groups-tile.ts
Normal file
108
src/panels/config/zha/zha-groups-tile.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import "../../../components/ha-card";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
property,
|
||||||
|
customElement,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
|
import { navigate } from "../../../common/navigate";
|
||||||
|
import { haStyle } from "../../../resources/styles";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
@customElement("zha-groups-tile")
|
||||||
|
export class ZHAGroupsTile extends LitElement {
|
||||||
|
@property() public hass?: HomeAssistant;
|
||||||
|
@property() public isWide?: boolean;
|
||||||
|
@property() private _showHelp = false;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
|
<div style="position: relative" slot="header">
|
||||||
|
<span>
|
||||||
|
${this.hass!.localize("ui.panel.config.zha.groups.header")}
|
||||||
|
</span>
|
||||||
|
<paper-icon-button
|
||||||
|
class="toggle-help-icon"
|
||||||
|
@click="${this._onHelpTap}"
|
||||||
|
icon="hass:help-circle"
|
||||||
|
></paper-icon-button>
|
||||||
|
</div>
|
||||||
|
<span slot="introduction">
|
||||||
|
${this.hass!.localize("ui.panel.config.zha.groups.introduction")}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<ha-card class="content">
|
||||||
|
<div class="card-actions">
|
||||||
|
<mwc-button @click=${this._onManageGroupsClick}>
|
||||||
|
${this.hass!.localize("ui.panel.config.zha.groups.manage_groups")}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
</ha-config-section>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onHelpTap(): void {
|
||||||
|
this._showHelp = !this._showHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onManageGroupsClick() {
|
||||||
|
navigate(this, "groups");
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
css`
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-card {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions.warning ha-call-service-button {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-help-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-service-description {
|
||||||
|
display: block;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text2 {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-groups-tile": ZHAGroupsTile;
|
||||||
|
}
|
||||||
|
}
|
@ -1437,6 +1437,15 @@
|
|||||||
"commands_of_cluster": "Commands of the selected cluster",
|
"commands_of_cluster": "Commands of the selected cluster",
|
||||||
"issue_zigbee_command": "Issue Zigbee Command",
|
"issue_zigbee_command": "Issue Zigbee Command",
|
||||||
"help_command_dropdown": "Select a command to interact with."
|
"help_command_dropdown": "Select a command to interact with."
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"zha_zigbee_groups": "ZHA Zigbee Groups",
|
||||||
|
"manage_groups": "Manage Zigbee Groups",
|
||||||
|
"groups": "Groups",
|
||||||
|
"group_id": "Group ID",
|
||||||
|
"members": "Members",
|
||||||
|
"header": "Zigbee Group Management",
|
||||||
|
"introduction": "Create and modify zigbee groups"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zwave": {
|
"zwave": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user