mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add zwave expert UI / Installer settings (#21897)
* Add zwave expert UI / Installer settings * Fix zwave invoceCC api function name * Fix function calls of invokeZWaveCCApi * Add zwave node-installer translations and endpoint separation * Add zwave capability-control error handling, translations and thermostat setback * Fix zwave capability thermostat setback --------- Co-authored-by: Wendelin <w@pe8.at>
This commit is contained in:
parent
5247b74fd4
commit
64285d5155
@ -209,6 +209,17 @@ export interface ZWaveJSNodeStatus {
|
||||
has_firmware_update_cc: boolean;
|
||||
}
|
||||
|
||||
export type ZWaveJSNodeCapabilities = {
|
||||
[endpoint: number]: ZWaveJSEndpointCapability[];
|
||||
};
|
||||
|
||||
export interface ZWaveJSEndpointCapability {
|
||||
id: number;
|
||||
name: string;
|
||||
version: number;
|
||||
is_secure: boolean;
|
||||
}
|
||||
|
||||
export interface ZwaveJSNodeMetadata {
|
||||
node_id: number;
|
||||
exclusion: string;
|
||||
@ -404,6 +415,25 @@ export interface RequestedGrant {
|
||||
clientSideAuth: boolean;
|
||||
}
|
||||
|
||||
export const invokeZWaveCCApi = (
|
||||
hass: HomeAssistant,
|
||||
device_id: string,
|
||||
command_class: number,
|
||||
endpoint: number | undefined,
|
||||
method_name: string,
|
||||
parameters: any[],
|
||||
wait_for_result?: boolean
|
||||
): Promise<unknown> =>
|
||||
hass.callWS({
|
||||
type: "zwave_js/invoke_cc_api",
|
||||
device_id,
|
||||
command_class,
|
||||
endpoint,
|
||||
method_name,
|
||||
parameters,
|
||||
wait_for_result,
|
||||
});
|
||||
|
||||
export const fetchZwaveNetworkStatus = (
|
||||
hass: HomeAssistant,
|
||||
device_or_entry_id: {
|
||||
@ -579,6 +609,15 @@ export const fetchZwaveNodeStatus = (
|
||||
device_id,
|
||||
});
|
||||
|
||||
export const fetchZwaveNodeCapabilities = (
|
||||
hass: HomeAssistant,
|
||||
device_id: string
|
||||
): Promise<ZWaveJSNodeCapabilities> =>
|
||||
hass.callWS({
|
||||
type: "zwave_js/node_capabilities",
|
||||
device_id,
|
||||
});
|
||||
|
||||
export const subscribeZwaveNodeStatus = (
|
||||
hass: HomeAssistant,
|
||||
device_id: string,
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
mdiHospitalBox,
|
||||
mdiInformation,
|
||||
mdiUpload,
|
||||
mdiWrench,
|
||||
} from "@mdi/js";
|
||||
import { getConfigEntries } from "../../../../../../data/config_entries";
|
||||
import type { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
||||
@ -98,6 +99,13 @@ export const getZwaveDeviceActions = async (
|
||||
showZWaveJSNodeStatisticsDialog(el, {
|
||||
device,
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: hass.localize(
|
||||
"ui.panel.config.zwave_js.device_info.installer_settings"
|
||||
),
|
||||
icon: mdiWrench,
|
||||
href: `/config/zwave_js/node_installer/${device.id}?config_entry=${entryId}`,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,149 @@
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import "../../../../../../components/buttons/ha-progress-button";
|
||||
import { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
||||
import { HomeAssistant } from "../../../../../../types";
|
||||
import { invokeZWaveCCApi } from "../../../../../../data/zwave_js";
|
||||
import "../../../../../../components/ha-textfield";
|
||||
import "../../../../../../components/ha-select";
|
||||
import "../../../../../../components/ha-list-item";
|
||||
import type { HaProgressButton } from "../../../../../../components/buttons/ha-progress-button";
|
||||
import type { HaSelect } from "../../../../../../components/ha-select";
|
||||
import type { HaTextField } from "../../../../../../components/ha-textfield";
|
||||
import type { HaSwitch } from "../../../../../../components/ha-switch";
|
||||
import { extractApiErrorMessage } from "../../../../../../data/hassio/common";
|
||||
|
||||
@customElement("zwave_js-capability-control-multilevel_switch")
|
||||
class ZWaveJSCapabilityMultiLevelSwitch extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public device!: DeviceRegistryEntry;
|
||||
|
||||
@property({ type: Number }) public endpoint!: number;
|
||||
|
||||
@property({ type: Number }) public command_class!: number;
|
||||
|
||||
@property({ type: Number }) public version!: number;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.title"
|
||||
)}
|
||||
</h3>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||
: ""}
|
||||
<ha-select
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.direction"
|
||||
)}
|
||||
id="direction"
|
||||
>
|
||||
<ha-list-item .value=${"up"} selected
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.up"
|
||||
)}</ha-list-item
|
||||
>
|
||||
<ha-list-item .value=${"down"}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.down"
|
||||
)}</ha-list-item
|
||||
>
|
||||
</ha-select>
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.ignore_start_level"
|
||||
)}
|
||||
>
|
||||
<ha-switch id="ignore_start_level"></ha-switch>
|
||||
</ha-formfield>
|
||||
<ha-textfield
|
||||
type="number"
|
||||
id="start_level"
|
||||
value="0"
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.start_level"
|
||||
)}
|
||||
></ha-textfield>
|
||||
<div class="actions">
|
||||
<ha-progress-button
|
||||
.control=${"startLevelChange"}
|
||||
@click=${this._controlTransition}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.start_transition"
|
||||
)}
|
||||
</ha-progress-button>
|
||||
<ha-progress-button
|
||||
.control=${"stopLevelChange"}
|
||||
@click=${this._controlTransition}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.stop_transition"
|
||||
)}
|
||||
</ha-progress-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private async _controlTransition(ev: any) {
|
||||
const control = ev.currentTarget!.control;
|
||||
const button = ev.currentTarget as HaProgressButton;
|
||||
button.progress = true;
|
||||
|
||||
const direction = (this.shadowRoot!.getElementById("direction") as HaSelect)
|
||||
.value;
|
||||
|
||||
const ignoreStartLevel = (
|
||||
this.shadowRoot!.getElementById("ignore_start_level") as HaSwitch
|
||||
).checked;
|
||||
|
||||
const startLevel = Number(
|
||||
(this.shadowRoot!.getElementById("start_level") as HaTextField).value
|
||||
);
|
||||
|
||||
try {
|
||||
button.actionSuccess();
|
||||
await invokeZWaveCCApi(
|
||||
this.hass,
|
||||
this.device.id,
|
||||
this.command_class,
|
||||
this.endpoint,
|
||||
control,
|
||||
[{ direction, ignoreStartLevel, startLevel }],
|
||||
true
|
||||
);
|
||||
} catch (err) {
|
||||
button.actionError();
|
||||
this._error = this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.control_failed",
|
||||
{ error: extractApiErrorMessage(err) }
|
||||
);
|
||||
}
|
||||
|
||||
button.progress = false;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
ha-select,
|
||||
ha-formfield,
|
||||
ha-textfield {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"zwave_js-capability-control-multilevel_switch": ZWaveJSCapabilityMultiLevelSwitch;
|
||||
}
|
||||
}
|
@ -0,0 +1,240 @@
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
||||
import { HomeAssistant } from "../../../../../../types";
|
||||
import { invokeZWaveCCApi } from "../../../../../../data/zwave_js";
|
||||
import "../../../../../../components/ha-button";
|
||||
import "../../../../../../components/buttons/ha-progress-button";
|
||||
import "../../../../../../components/ha-textfield";
|
||||
import "../../../../../../components/ha-select";
|
||||
import "../../../../../../components/ha-list-item";
|
||||
import type { HaSelect } from "../../../../../../components/ha-select";
|
||||
import type { HaTextField } from "../../../../../../components/ha-textfield";
|
||||
import { extractApiErrorMessage } from "../../../../../../data/hassio/common";
|
||||
import type { HaProgressButton } from "../../../../../../components/buttons/ha-progress-button";
|
||||
|
||||
// enum with special states
|
||||
enum SpecialState {
|
||||
frost_protection = "Frost Protection",
|
||||
energy_saving = "Energy Saving",
|
||||
unused = "Unused",
|
||||
}
|
||||
|
||||
const SETBACK_TYPE_OPTIONS = ["none", "temporary", "permanent"];
|
||||
|
||||
@customElement("zwave_js-capability-control-thermostat_setback")
|
||||
class ZWaveJSCapabilityThermostatSetback extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public device!: DeviceRegistryEntry;
|
||||
|
||||
@property({ type: Number }) public endpoint!: number;
|
||||
|
||||
@property({ type: Number }) public command_class!: number;
|
||||
|
||||
@property({ type: Number }) public version!: number;
|
||||
|
||||
@state() private _disableSetbackState = false;
|
||||
|
||||
@query("#setback_type") private _setbackTypeInput!: HaSelect;
|
||||
|
||||
@query("#setback_state") private _setbackStateInput!: HaTextField;
|
||||
|
||||
@query("#setback_special_state")
|
||||
private _setbackSpecialStateSelect!: HaSelect;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
@state() private _loading = true;
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.title`
|
||||
)}
|
||||
</h3>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||
: ""}
|
||||
<ha-select
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_type.label`
|
||||
)}
|
||||
id="setback_type"
|
||||
.value=${"0"}
|
||||
.disabled=${this._loading}
|
||||
>
|
||||
${SETBACK_TYPE_OPTIONS.map(
|
||||
(translationKey, index) =>
|
||||
html`<ha-list-item .value=${String(index)}>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_type.${translationKey}`
|
||||
)}
|
||||
</ha-list-item>`
|
||||
)}
|
||||
</ha-select>
|
||||
<div class="setback-state">
|
||||
<ha-textfield
|
||||
type="number"
|
||||
id="setback_state"
|
||||
value="0"
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_state_label`
|
||||
)}
|
||||
min="-12.8"
|
||||
max="12.0"
|
||||
step=".1"
|
||||
.helper=${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_state_helper`
|
||||
)}
|
||||
.disabled=${this._disableSetbackState || this._loading}
|
||||
></ha-textfield>
|
||||
<ha-select
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_special_state.label`
|
||||
)}
|
||||
id="setback_special_state"
|
||||
@change=${this._changeSpecialState}
|
||||
.disabled=${this._loading}
|
||||
>
|
||||
<ha-list-item selected> </ha-list-item>
|
||||
${Object.entries(SpecialState).map(
|
||||
([translationKey, value]) =>
|
||||
html`<ha-list-item .value=${value}>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_special_state.${translationKey}`
|
||||
)}
|
||||
</ha-list-item>`
|
||||
)}
|
||||
</ha-select>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<ha-button
|
||||
class="clear-button"
|
||||
@click=${this._clear}
|
||||
.disabled=${this._loading}
|
||||
>${this.hass.localize("ui.common.clear")}</ha-button
|
||||
>
|
||||
<ha-progress-button
|
||||
@click=${this._saveSetback}
|
||||
.disabled=${this._loading}
|
||||
>
|
||||
${this.hass.localize("ui.common.save")}
|
||||
</ha-progress-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
this._loadSetback();
|
||||
}
|
||||
|
||||
private async _loadSetback() {
|
||||
this._loading = true;
|
||||
try {
|
||||
const { setbackType, setbackState } = (await invokeZWaveCCApi(
|
||||
this.hass,
|
||||
this.device.id,
|
||||
this.command_class,
|
||||
this.endpoint,
|
||||
"get",
|
||||
[],
|
||||
true
|
||||
)) as { setbackType: number; setbackState: number | SpecialState };
|
||||
|
||||
this._setbackTypeInput.value = String(setbackType);
|
||||
if (typeof setbackState === "number") {
|
||||
this._setbackStateInput.value = String(setbackState);
|
||||
this._setbackSpecialStateSelect.value = "";
|
||||
} else {
|
||||
this._setbackSpecialStateSelect.value = setbackState;
|
||||
}
|
||||
} catch (err) {
|
||||
this._error = this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.get_setback_failed",
|
||||
{ error: extractApiErrorMessage(err) }
|
||||
);
|
||||
}
|
||||
|
||||
this._loading = false;
|
||||
}
|
||||
|
||||
private _changeSpecialState() {
|
||||
this._disableSetbackState = !!this._setbackSpecialStateSelect.value;
|
||||
}
|
||||
|
||||
private async _saveSetback(ev: CustomEvent) {
|
||||
const button = ev.currentTarget as HaProgressButton;
|
||||
button.progress = true;
|
||||
|
||||
this._error = undefined;
|
||||
const setbackType = this._setbackTypeInput.value;
|
||||
|
||||
let setbackState: number | string = Number(this._setbackStateInput.value);
|
||||
if (this._setbackSpecialStateSelect.value) {
|
||||
setbackState = this._setbackSpecialStateSelect.value;
|
||||
}
|
||||
|
||||
try {
|
||||
await invokeZWaveCCApi(
|
||||
this.hass,
|
||||
this.device.id,
|
||||
this.command_class,
|
||||
this.endpoint,
|
||||
"set",
|
||||
[Number(setbackType), setbackState],
|
||||
true
|
||||
);
|
||||
|
||||
button.actionSuccess();
|
||||
} catch (err) {
|
||||
button.actionError();
|
||||
this._error = this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.save_setback_failed",
|
||||
{ error: extractApiErrorMessage(err) }
|
||||
);
|
||||
}
|
||||
|
||||
button.progress = false;
|
||||
}
|
||||
|
||||
private _clear() {
|
||||
this._loadSetback();
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
:host > ha-select {
|
||||
width: 100%;
|
||||
}
|
||||
.actions {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.actions .clear-button {
|
||||
--mdc-theme-primary: var(--red-color);
|
||||
}
|
||||
.setback-state {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
.setback-state ha-select,
|
||||
ha-textfield {
|
||||
flex: 1;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"zwave_js-capability-control-thermostat_setback": ZWaveJSCapabilityThermostatSetback;
|
||||
}
|
||||
}
|
@ -48,6 +48,10 @@ class ZWaveJSConfigRouter extends HassRouterPage {
|
||||
tag: "zwave_js-node-config",
|
||||
load: () => import("./zwave_js-node-config"),
|
||||
},
|
||||
node_installer: {
|
||||
tag: "zwave_js-node-installer",
|
||||
load: () => import("./zwave_js-node-installer"),
|
||||
},
|
||||
logs: {
|
||||
tag: "zwave_js-logs",
|
||||
load: () => import("./zwave_js-logs"),
|
||||
|
@ -0,0 +1,215 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import {
|
||||
CSSResultGroup,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
css,
|
||||
html,
|
||||
nothing,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { dynamicElement } from "../../../../../common/dom/dynamic-element-directive";
|
||||
import "../../../../../components/ha-card";
|
||||
import { computeDeviceName } from "../../../../../data/device_registry";
|
||||
import {
|
||||
ZWaveJSNodeCapabilities,
|
||||
ZwaveJSNodeMetadata,
|
||||
fetchZwaveNodeCapabilities,
|
||||
fetchZwaveNodeMetadata,
|
||||
} from "../../../../../data/zwave_js";
|
||||
import "../../../../../layouts/hass-error-screen";
|
||||
import "../../../../../layouts/hass-loading-screen";
|
||||
import "../../../../../layouts/hass-subpage";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../../../types";
|
||||
import "../../../ha-config-section";
|
||||
import "./capability-controls/zwave_js-capability-control-multilevel-switch";
|
||||
import "./capability-controls/zwave_js-capability-control-thermostat-setback";
|
||||
|
||||
const CAPABILITY_CONTROLS = {
|
||||
38: "multilevel_switch",
|
||||
71: "thermostat_setback",
|
||||
};
|
||||
|
||||
@customElement("zwave_js-node-installer")
|
||||
class ZWaveJSNodeInstaller extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ type: Boolean }) public isWide = false;
|
||||
|
||||
@property() public configEntryId?: string;
|
||||
|
||||
@property() public deviceId!: string;
|
||||
|
||||
@state() private _nodeMetadata?: ZwaveJSNodeMetadata;
|
||||
|
||||
@state() private _capabilities?: ZWaveJSNodeCapabilities;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.deviceId = this.route.path.substr(1);
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
if (!this._capabilities || changedProps.has("deviceId")) {
|
||||
this._fetchData();
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this._error) {
|
||||
return html`<hass-error-screen
|
||||
.hass=${this.hass}
|
||||
.error=${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_config.error_${this._error}`
|
||||
)}
|
||||
></hass-error-screen>`;
|
||||
}
|
||||
|
||||
if (!this._capabilities || !this._nodeMetadata) {
|
||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
||||
}
|
||||
|
||||
const device = this.hass.devices[this.deviceId];
|
||||
|
||||
const endpoints = Object.entries(this._capabilities).filter(
|
||||
([_endpoint, capabilities]) => {
|
||||
const filteredCapabilities = capabilities.filter(
|
||||
(capability) => capability.id in CAPABILITY_CONTROLS
|
||||
);
|
||||
return filteredCapabilities.length > 0;
|
||||
}
|
||||
);
|
||||
|
||||
return html`
|
||||
<hass-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
>
|
||||
<ha-config-section
|
||||
.narrow=${this.narrow}
|
||||
.isWide=${this.isWide}
|
||||
vertical
|
||||
>
|
||||
<div slot="header">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.header"
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div slot="introduction">
|
||||
${device
|
||||
? html`
|
||||
<div class="device-info">
|
||||
<h2>${computeDeviceName(device, this.hass)}</h2>
|
||||
<p>${device.manufacturer} ${device.model}</p>
|
||||
</div>
|
||||
`
|
||||
: ``}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.introduction"
|
||||
)}
|
||||
</div>
|
||||
${endpoints.length
|
||||
? endpoints.map(
|
||||
([endpoint, capabilities]) => html`
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.endpoint"
|
||||
)}:
|
||||
${endpoint}
|
||||
</h3>
|
||||
<ha-card>
|
||||
${capabilities.map(
|
||||
(capability) => html`
|
||||
${capability.id in CAPABILITY_CONTROLS
|
||||
? html` <div class="capability">
|
||||
<h4>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.command_class"
|
||||
)}:
|
||||
${capability.name}
|
||||
</h4>
|
||||
${dynamicElement(
|
||||
`zwave_js-capability-control-${CAPABILITY_CONTROLS[capability.id]}`,
|
||||
{
|
||||
hass: this.hass,
|
||||
device: device,
|
||||
endpoint: endpoint,
|
||||
command_class: capability.id,
|
||||
version: capability.version,
|
||||
is_secure: capability.is_secure,
|
||||
}
|
||||
)}
|
||||
</div>`
|
||||
: nothing}
|
||||
`
|
||||
)}
|
||||
</ha-card>
|
||||
`
|
||||
)
|
||||
: html`<ha-card class="empty"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_installer.no_settings"
|
||||
)}</ha-card
|
||||
>`}
|
||||
</ha-config-section>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
private async _fetchData() {
|
||||
if (!this.configEntryId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const device = this.hass.devices[this.deviceId];
|
||||
if (!device) {
|
||||
this._error = "device_not_found";
|
||||
return;
|
||||
}
|
||||
|
||||
[this._nodeMetadata, this._capabilities] = await Promise.all([
|
||||
fetchZwaveNodeMetadata(this.hass, device.id),
|
||||
fetchZwaveNodeCapabilities(this.hass, device.id),
|
||||
]);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
ha-card {
|
||||
margin-bottom: 40px;
|
||||
margin-top: 0;
|
||||
}
|
||||
.capability {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
padding: 4px 16px;
|
||||
}
|
||||
.capability:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.empty {
|
||||
margin-top: 32px;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"zwave_js-node-installer": ZWaveJSNodeInstaller;
|
||||
}
|
||||
}
|
@ -4841,6 +4841,7 @@
|
||||
"node_id": "ID",
|
||||
"node_ready": "Ready",
|
||||
"device_config": "Configure",
|
||||
"installer_settings": "Installer settings",
|
||||
"reinterview_device": "Re-interview",
|
||||
"rebuild_routes": "Rebuild routes",
|
||||
"remove_failed": "Remove failed",
|
||||
@ -5132,6 +5133,45 @@
|
||||
"subscribed_to_logs": "Subscribed to Z-Wave JS log messages…",
|
||||
"log_level_changed": "Log Level changed to: {level}",
|
||||
"download_logs": "Download logs"
|
||||
},
|
||||
"node_installer": {
|
||||
"header": "Installer Settings",
|
||||
"introduction": "Configure your device installer settings.",
|
||||
"endpoint": "Endpoint",
|
||||
"no_settings": "This device does not have any installer settings.",
|
||||
"command_class": "Command Class",
|
||||
"capability_controls": {
|
||||
"thermostat_setback": {
|
||||
"title": "Thermostat Setback",
|
||||
"setback_state_label": "Setback in 1/10 degrees (Kelvin)",
|
||||
"setback_state_helper": "Min: -12.8, max: 12.0",
|
||||
"setback_special_state": {
|
||||
"label": "Setback special state",
|
||||
"frost_protection": "Frost protection",
|
||||
"energy_saving": "Energy saving",
|
||||
"unused": "Unused"
|
||||
},
|
||||
"setback_type": {
|
||||
"label": "Setback Type",
|
||||
"none": "None",
|
||||
"temporary": "Temporary",
|
||||
"permanent": "Permanent"
|
||||
},
|
||||
"get_setback_failed": "Failed to get setback state. {error}",
|
||||
"save_setback_failed": "Failed to save setback state. {error}"
|
||||
},
|
||||
"multilevel_switch": {
|
||||
"title": "Transition",
|
||||
"direction": "Direction",
|
||||
"up": "Up",
|
||||
"down": "Down",
|
||||
"ignore_start_level": "Ignore start level",
|
||||
"start_level": "Start level",
|
||||
"start_transition": "Start transition",
|
||||
"stop_transition": "Stop transition",
|
||||
"control_failed": "Failed to control transition. {error}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"matter": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user