Skip to content

Commit

Permalink
Add zwave expert UI / Installer settings (#21897)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
bramkragten and wendevlin authored Nov 7, 2024
1 parent 5247b74 commit 64285d5
Show file tree
Hide file tree
Showing 7 changed files with 695 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/data/zwave_js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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}`,
}
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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";

Check failure on line 4 in src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-multilevel-switch.ts

View workflow job for this annotation

GitHub Actions / Lint and check format

All imports in the declaration are only used as types. Use `import type`
import { HomeAssistant } from "../../../../../../types";

Check failure on line 5 in src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-multilevel-switch.ts

View workflow job for this annotation

GitHub Actions / Lint and check format

All imports in the declaration are only used as types. Use `import type`
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;
}
}
Loading

0 comments on commit 64285d5

Please sign in to comment.