home-assistant-frontend/src/panels/config/integrations/integration-panels/zwave/zwave-network.ts

303 lines
9.6 KiB
TypeScript

import { mdiCheckboxMarkedCircle, mdiClose, mdiHelpCircle } from "@mdi/js";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../../components/buttons/ha-call-api-button";
import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card";
import "../../../../../components/ha-circular-progress";
import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-icon-button";
import "../../../../../components/ha-service-description";
import {
fetchNetworkStatus,
ZWaveNetworkStatus,
ZWAVE_NETWORK_STATE_AWAKED,
ZWAVE_NETWORK_STATE_READY,
ZWAVE_NETWORK_STATE_STARTED,
ZWAVE_NETWORK_STATE_STOPPED,
} from "../../../../../data/zwave";
import { haStyle } from "../../../../../resources/styles";
import { HomeAssistant } from "../../../../../types";
import { documentationUrl } from "../../../../../util/documentation-url";
import "../../../ha-config-section";
@customElement("zwave-network")
export class ZwaveNetwork extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() public isWide!: boolean;
@state() private _showHelp = false;
@state() private _networkStatus?: ZWaveNetworkStatus;
@state() private _unsubs: Array<Promise<UnsubscribeFunc>> = [];
public disconnectedCallback(): void {
this._unsubscribe();
}
protected firstUpdated(changedProps): void {
super.firstUpdated(changedProps);
this._getNetworkStatus();
this._subscribe();
}
protected render(): TemplateResult {
return html`
<ha-config-section .isWide=${this.isWide}>
<div class="sectionHeader" slot="header">
<span>
${this.hass!.localize(
"ui.panel.config.zwave.network_management.header"
)}
</span>
<ha-icon-button
class="toggle-help-icon"
@click=${this._onHelpTap}
.path=${mdiHelpCircle}
.label=${this.hass!.localize("ui.common.help")}
></ha-icon-button>
</div>
<div slot="introduction">
${this.hass!.localize(
"ui.panel.config.zwave.network_management.introduction"
)}
<p>
<a
href=${documentationUrl(this.hass, "/docs/z-wave/control-panel/")}
target="_blank"
rel="noreferrer"
>
${this.hass!.localize("ui.panel.config.zwave.learn_more")}
</a>
</p>
</div>
${this._networkStatus
? html`
<ha-card class="content network-status">
<div class="details">
${this._networkStatus.state === ZWAVE_NETWORK_STATE_STOPPED
? html`
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_stopped"
)}
`
: this._networkStatus.state === ZWAVE_NETWORK_STATE_STARTED
? html`
<ha-circular-progress active></ha-circular-progress>
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_starting"
)}<br />
<small>
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_starting_note"
)}
</small>
`
: this._networkStatus.state === ZWAVE_NETWORK_STATE_AWAKED
? html`
<ha-svg-icon
.path=${mdiCheckboxMarkedCircle}
></ha-svg-icon>
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_started"
)}<br />
<small>
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_started_note_some_queried"
)}
</small>
`
: this._networkStatus.state === ZWAVE_NETWORK_STATE_READY
? html`
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_started"
)}<br />
<small>
${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_started_note_all_queried"
)}
</small>
`
: ""}
</div>
<div class="card-actions">
${this._networkStatus.state >= ZWAVE_NETWORK_STATE_AWAKED
? html`
${this._generateServiceButton("stop_network")}
${this._generateServiceButton("heal_network")}
${this._generateServiceButton("test_network")}
`
: html` ${this._generateServiceButton("start_network")} `}
</div>
${this._networkStatus.state >= ZWAVE_NETWORK_STATE_AWAKED
? html`
<div class="card-actions">
${this._generateServiceButton("soft_reset")}
<ha-call-api-button
.hass=${this.hass}
path="zwave/saveconfig"
>
${this.hass!.localize(
"ui.panel.config.zwave.services.save_config"
)}
</ha-call-api-button>
</div>
`
: ""}
</ha-card>
${this._networkStatus.state >= ZWAVE_NETWORK_STATE_AWAKED
? html`
<ha-card class="content">
<div class="card-actions">
${this._generateServiceButton("add_node_secure")}
${this._generateServiceButton("add_node")}
${this._generateServiceButton("remove_node")}
</div>
<div class="card-actions">
${this._generateServiceButton("cancel_command")}
</div>
</ha-card>
`
: ""}
`
: ""}
</ha-config-section>
`;
}
private async _getNetworkStatus(): Promise<void> {
this._networkStatus = await fetchNetworkStatus(this.hass!);
}
private _subscribe(): void {
this._unsubs = [
"zwave.network_start",
"zwave.network_stop",
"zwave.network_ready",
"zwave.network_complete",
"zwave.network_complete_some_dead",
].map((e) =>
this.hass!.connection.subscribeEvents(
(event) => this._handleEvent(event),
e
)
);
}
private _unsubscribe(): void {
while (this._unsubs.length) {
this._unsubs.pop()!.then((unsub) => unsub());
}
}
private _handleEvent(event) {
if (event.event_type === "zwave.network_start") {
// Optimistically set the state, wait 1s and poll the backend
// The backend will still report a state of 0 when the 'network_start'
// event is first fired.
if (this._networkStatus) {
this._networkStatus = { ...this._networkStatus, state: 5 };
}
setTimeout(() => this._getNetworkStatus, 1000);
} else {
this._getNetworkStatus();
}
}
private _onHelpTap(): void {
this._showHelp = !this._showHelp;
}
private _generateServiceButton(service: string) {
return html`
<ha-call-service-button
.hass=${this.hass}
domain="zwave"
service=${service}
>
${this.hass!.localize("ui.panel.config.zwave.services." + service)}
</ha-call-service-button>
<ha-service-description
.hass=${this.hass}
domain="zwave"
service=${service}
?hidden=${!this._showHelp}
>
</ha-service-description>
`;
}
static get styles(): CSSResultGroup {
return [
haStyle,
css`
.content {
margin-top: 24px;
}
.sectionHeader {
position: relative;
padding-right: 40px;
}
.network-status {
text-align: center;
}
.network-status div.details {
font-size: 1.5rem;
padding: 24px;
}
.network-status ha-svg-icon {
display: block;
margin: 0px auto 16px;
width: 48px;
height: 48px;
}
.network-status small {
font-size: 1rem;
}
ha-card {
margin: 0 auto;
max-width: 600px;
}
.card-actions.warning ha-call-service-button {
color: var(--error-color);
}
.toggle-help-icon {
position: absolute;
top: -6px;
right: 0;
color: var(--primary-color);
}
ha-service-description {
display: block;
color: grey;
padding: 0 8px 12px;
}
[hidden] {
display: none;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"zwave-network": ZwaveNetwork;
}
}