mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 10:16:46 +00:00
Add default code to alarm_control_panel (#20062)
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
parent
febbf34de6
commit
91e5fcacd5
@ -10,8 +10,10 @@ import {
|
|||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { HomeAssistant } from "../types";
|
|
||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
|
import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
import { getExtendedEntityRegistryEntry } from "./entity_registry";
|
||||||
|
|
||||||
export const FORMAT_TEXT = "text";
|
export const FORMAT_TEXT = "text";
|
||||||
export const FORMAT_NUMBER = "number";
|
export const FORMAT_NUMBER = "number";
|
||||||
@ -103,3 +105,50 @@ export const supportedAlarmModes = (stateObj: AlarmControlPanelEntity) =>
|
|||||||
const feature = ALARM_MODES[mode].feature;
|
const feature = ALARM_MODES[mode].feature;
|
||||||
return !feature || supportsFeature(stateObj, feature);
|
return !feature || supportsFeature(stateObj, feature);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setProtectedAlarmControlPanelMode = async (
|
||||||
|
element: HTMLElement,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
stateObj: AlarmControlPanelEntity,
|
||||||
|
mode: AlarmMode
|
||||||
|
) => {
|
||||||
|
const { service } = ALARM_MODES[mode];
|
||||||
|
|
||||||
|
let code: string | undefined;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(mode !== "disarmed" &&
|
||||||
|
stateObj.attributes.code_arm_required &&
|
||||||
|
stateObj.attributes.code_format) ||
|
||||||
|
(mode === "disarmed" && stateObj.attributes.code_format)
|
||||||
|
) {
|
||||||
|
const entry = await getExtendedEntityRegistryEntry(
|
||||||
|
hass,
|
||||||
|
stateObj.entity_id
|
||||||
|
).catch(() => undefined);
|
||||||
|
const defaultCode = entry?.options?.alarm_control_panel?.default_code;
|
||||||
|
|
||||||
|
if (!defaultCode) {
|
||||||
|
const disarm = mode === "disarmed";
|
||||||
|
|
||||||
|
const response = await showEnterCodeDialog(element, {
|
||||||
|
codeFormat: stateObj.attributes.code_format,
|
||||||
|
title: hass.localize(
|
||||||
|
`ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}`
|
||||||
|
),
|
||||||
|
submitText: hass.localize(
|
||||||
|
`ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}`
|
||||||
|
),
|
||||||
|
});
|
||||||
|
if (response == null) {
|
||||||
|
throw new Error("Code dialog closed");
|
||||||
|
}
|
||||||
|
code = response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await hass.callService("alarm_control_panel", service, {
|
||||||
|
entity_id: stateObj.entity_id,
|
||||||
|
code,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -96,6 +96,10 @@ export interface LockEntityOptions {
|
|||||||
default_code?: string | null;
|
default_code?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AlarmControlPanelEntityOptions {
|
||||||
|
default_code?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface WeatherEntityOptions {
|
export interface WeatherEntityOptions {
|
||||||
precipitation_unit?: string | null;
|
precipitation_unit?: string | null;
|
||||||
pressure_unit?: string | null;
|
pressure_unit?: string | null;
|
||||||
@ -112,6 +116,7 @@ export interface SwitchAsXEntityOptions {
|
|||||||
export interface EntityRegistryOptions {
|
export interface EntityRegistryOptions {
|
||||||
number?: NumberEntityOptions;
|
number?: NumberEntityOptions;
|
||||||
sensor?: SensorEntityOptions;
|
sensor?: SensorEntityOptions;
|
||||||
|
alarm_control_panel?: AlarmControlPanelEntityOptions;
|
||||||
lock?: LockEntityOptions;
|
lock?: LockEntityOptions;
|
||||||
weather?: WeatherEntityOptions;
|
weather?: WeatherEntityOptions;
|
||||||
light?: LightEntityOptions;
|
light?: LightEntityOptions;
|
||||||
@ -134,6 +139,7 @@ export interface EntityRegistryEntryUpdateParams {
|
|||||||
| SensorEntityOptions
|
| SensorEntityOptions
|
||||||
| NumberEntityOptions
|
| NumberEntityOptions
|
||||||
| LockEntityOptions
|
| LockEntityOptions
|
||||||
|
| AlarmControlPanelEntityOptions
|
||||||
| WeatherEntityOptions
|
| WeatherEntityOptions
|
||||||
| LightEntityOptions;
|
| LightEntityOptions;
|
||||||
aliases?: string[];
|
aliases?: string[];
|
||||||
|
@ -4,10 +4,12 @@ import { styleMap } from "lit/directives/style-map";
|
|||||||
import { stateColorCss } from "../../../common/entity/state_color";
|
import { stateColorCss } from "../../../common/entity/state_color";
|
||||||
import "../../../components/ha-control-button";
|
import "../../../components/ha-control-button";
|
||||||
import "../../../components/ha-state-icon";
|
import "../../../components/ha-state-icon";
|
||||||
import { AlarmControlPanelEntity } from "../../../data/alarm_control_panel";
|
import {
|
||||||
|
AlarmControlPanelEntity,
|
||||||
|
setProtectedAlarmControlPanelMode,
|
||||||
|
} from "../../../data/alarm_control_panel";
|
||||||
import "../../../state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes";
|
import "../../../state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { showEnterCodeDialog } from "../../enter-code/show-enter-code-dialog";
|
|
||||||
import "../components/ha-more-info-state-header";
|
import "../components/ha-more-info-state-header";
|
||||||
import { moreInfoControlStyle } from "../components/more-info-control-style";
|
import { moreInfoControlStyle } from "../components/more-info-control-style";
|
||||||
|
|
||||||
@ -18,24 +20,12 @@ class MoreInfoAlarmControlPanel extends LitElement {
|
|||||||
@property({ attribute: false }) public stateObj?: AlarmControlPanelEntity;
|
@property({ attribute: false }) public stateObj?: AlarmControlPanelEntity;
|
||||||
|
|
||||||
private async _disarm() {
|
private async _disarm() {
|
||||||
let code: string | undefined;
|
setProtectedAlarmControlPanelMode(
|
||||||
|
this,
|
||||||
if (this.stateObj!.attributes.code_format) {
|
this.hass,
|
||||||
const response = await showEnterCodeDialog(this, {
|
this.stateObj!,
|
||||||
codeFormat: this.stateObj!.attributes.code_format,
|
"disarmed"
|
||||||
title: this.hass.localize("ui.card.alarm_control_panel.disarm"),
|
);
|
||||||
submitText: this.hass.localize("ui.card.alarm_control_panel.disarm"),
|
|
||||||
});
|
|
||||||
if (response == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
code = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hass.callService("alarm_control_panel", "alarm_disarm", {
|
|
||||||
entity_id: this.stateObj!.entity_id,
|
|
||||||
code,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
@ -59,6 +59,7 @@ import {
|
|||||||
updateDeviceRegistryEntry,
|
updateDeviceRegistryEntry,
|
||||||
} from "../../../data/device_registry";
|
} from "../../../data/device_registry";
|
||||||
import {
|
import {
|
||||||
|
AlarmControlPanelEntityOptions,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
EntityRegistryEntryUpdateParams,
|
EntityRegistryEntryUpdateParams,
|
||||||
ExtEntityRegistryEntry,
|
ExtEntityRegistryEntry,
|
||||||
@ -257,6 +258,10 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
this._defaultCode = this.entry.options?.lock?.default_code;
|
this._defaultCode = this.entry.options?.lock?.default_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (domain === "alarm_control_panel") {
|
||||||
|
this._defaultCode = this.entry.options?.alarm_control_panel?.default_code;
|
||||||
|
}
|
||||||
|
|
||||||
if (domain === "weather") {
|
if (domain === "weather") {
|
||||||
const stateObj: HassEntity | undefined =
|
const stateObj: HassEntity | undefined =
|
||||||
this.hass.states[this.entry.entity_id];
|
this.hass.states[this.entry.entity_id];
|
||||||
@ -583,6 +588,19 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
|
${domain === "alarm_control_panel"
|
||||||
|
? html`
|
||||||
|
<ha-textfield
|
||||||
|
.value=${this._defaultCode == null ? "" : this._defaultCode}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.dialogs.entity_registry.editor.default_code"
|
||||||
|
)}
|
||||||
|
type="password"
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
@input=${this._defaultcodeChanged}
|
||||||
|
></ha-textfield>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
${domain === "sensor" &&
|
${domain === "sensor" &&
|
||||||
this._deviceClass &&
|
this._deviceClass &&
|
||||||
stateObj?.attributes.unit_of_measurement &&
|
stateObj?.attributes.unit_of_measurement &&
|
||||||
@ -1071,6 +1089,15 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
params.options = this.entry.options?.[domain] || {};
|
params.options = this.entry.options?.[domain] || {};
|
||||||
(params.options as LockEntityOptions).default_code = this._defaultCode;
|
(params.options as LockEntityOptions).default_code = this._defaultCode;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
domain === "alarm_control_panel" &&
|
||||||
|
this.entry.options?.[domain]?.default_code !== this._defaultCode
|
||||||
|
) {
|
||||||
|
params.options_domain = domain;
|
||||||
|
params.options = this.entry.options?.[domain] || {};
|
||||||
|
(params.options as AlarmControlPanelEntityOptions).default_code =
|
||||||
|
this._defaultCode;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
domain === "weather" &&
|
domain === "weather" &&
|
||||||
(stateObj?.attributes?.precipitation_unit !== this._precipitation_unit ||
|
(stateObj?.attributes?.precipitation_unit !== this._precipitation_unit ||
|
||||||
|
@ -16,10 +16,10 @@ import {
|
|||||||
ALARM_MODES,
|
ALARM_MODES,
|
||||||
AlarmControlPanelEntity,
|
AlarmControlPanelEntity,
|
||||||
AlarmMode,
|
AlarmMode,
|
||||||
|
setProtectedAlarmControlPanelMode,
|
||||||
supportedAlarmModes,
|
supportedAlarmModes,
|
||||||
} from "../../../data/alarm_control_panel";
|
} from "../../../data/alarm_control_panel";
|
||||||
import { UNAVAILABLE } from "../../../data/entity";
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
import { showEnterCodeDialog } from "../../../dialogs/enter-code/show-enter-code-dialog";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
|
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
|
||||||
import { filterModes } from "./common/filter-modes";
|
import { filterModes } from "./common/filter-modes";
|
||||||
@ -115,37 +115,7 @@ class HuiAlarmModeCardFeature
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _setMode(mode: AlarmMode) {
|
private async _setMode(mode: AlarmMode) {
|
||||||
const { service } = ALARM_MODES[mode];
|
setProtectedAlarmControlPanelMode(this, this.hass!, this.stateObj!, mode);
|
||||||
|
|
||||||
let code: string | undefined;
|
|
||||||
|
|
||||||
if (
|
|
||||||
(mode !== "disarmed" &&
|
|
||||||
this.stateObj!.attributes.code_arm_required &&
|
|
||||||
this.stateObj!.attributes.code_format) ||
|
|
||||||
(mode === "disarmed" && this.stateObj!.attributes.code_format)
|
|
||||||
) {
|
|
||||||
const disarm = mode === "disarmed";
|
|
||||||
|
|
||||||
const response = await showEnterCodeDialog(this, {
|
|
||||||
codeFormat: this.stateObj!.attributes.code_format,
|
|
||||||
title: this.hass!.localize(
|
|
||||||
`ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}`
|
|
||||||
),
|
|
||||||
submitText: this.hass!.localize(
|
|
||||||
`ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}`
|
|
||||||
),
|
|
||||||
});
|
|
||||||
if (response == null) {
|
|
||||||
throw new Error("cancel");
|
|
||||||
}
|
|
||||||
code = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.hass!.callService("alarm_control_panel", service, {
|
|
||||||
entity_id: this.stateObj!.entity_id,
|
|
||||||
code,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | null {
|
protected render(): TemplateResult | null {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import {
|
import {
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
LitElement,
|
LitElement,
|
||||||
@ -30,6 +30,11 @@ import type { HomeAssistant } from "../../../types";
|
|||||||
import { findEntities } from "../common/find-entities";
|
import { findEntities } from "../common/find-entities";
|
||||||
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
||||||
import type { LovelaceCard } from "../types";
|
import type { LovelaceCard } from "../types";
|
||||||
|
import {
|
||||||
|
ExtEntityRegistryEntry,
|
||||||
|
getExtendedEntityRegistryEntry,
|
||||||
|
subscribeEntityRegistry,
|
||||||
|
} from "../../../data/entity_registry";
|
||||||
import { AlarmPanelCardConfig, AlarmPanelCardConfigState } from "./types";
|
import { AlarmPanelCardConfig, AlarmPanelCardConfigState } from "./types";
|
||||||
|
|
||||||
const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"];
|
const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"];
|
||||||
@ -99,8 +104,22 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@state() private _config?: AlarmPanelCardConfig;
|
@state() private _config?: AlarmPanelCardConfig;
|
||||||
|
|
||||||
|
@state() private _entry?: ExtEntityRegistryEntry | null;
|
||||||
|
|
||||||
@query("#alarmCode") private _input?: HaTextField;
|
@query("#alarmCode") private _input?: HaTextField;
|
||||||
|
|
||||||
|
private _unsubEntityRegistry?: UnsubscribeFunc;
|
||||||
|
|
||||||
|
public connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
this._subscribeEntityEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
public disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this._unsubscribeEntityRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
public async getCardSize(): Promise<number> {
|
public async getCardSize(): Promise<number> {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return 9;
|
return 9;
|
||||||
@ -123,6 +142,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._config = { ...config };
|
this._config = { ...config };
|
||||||
|
this._subscribeEntityEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected updated(changedProps: PropertyValues): void {
|
||||||
@ -165,6 +185,36 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _unsubscribeEntityRegistry() {
|
||||||
|
if (this._unsubEntityRegistry) {
|
||||||
|
this._unsubEntityRegistry();
|
||||||
|
this._unsubEntityRegistry = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _subscribeEntityEntry() {
|
||||||
|
if (!this._config?.entity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this._unsubEntityRegistry = subscribeEntityRegistry(
|
||||||
|
this.hass!.connection,
|
||||||
|
async (entries) => {
|
||||||
|
if (
|
||||||
|
entries.some((entry) => entry.entity_id === this._config!.entity)
|
||||||
|
) {
|
||||||
|
this._entry = await getExtendedEntityRegistryEntry(
|
||||||
|
this.hass!,
|
||||||
|
this._config!.entity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
this._entry = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return nothing;
|
return nothing;
|
||||||
@ -184,6 +234,8 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
const stateLabel = this._stateDisplay(stateObj.state);
|
const stateLabel = this._stateDisplay(stateObj.state);
|
||||||
|
|
||||||
|
const defaultCode = this._entry?.options?.alarm_control_panel?.default_code;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<h1 class="card-header">
|
<h1 class="card-header">
|
||||||
@ -222,7 +274,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
${!stateObj.attributes.code_format
|
${!stateObj.attributes.code_format || defaultCode
|
||||||
? nothing
|
? nothing
|
||||||
: html`
|
: html`
|
||||||
<ha-textfield
|
<ha-textfield
|
||||||
@ -234,7 +286,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
: "text"}
|
: "text"}
|
||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
`}
|
`}
|
||||||
${stateObj.attributes.code_format !== FORMAT_NUMBER
|
${stateObj.attributes.code_format !== FORMAT_NUMBER || defaultCode
|
||||||
? nothing
|
? nothing
|
||||||
: html`
|
: html`
|
||||||
<div id="keypad">
|
<div id="keypad">
|
||||||
|
@ -11,9 +11,9 @@ import {
|
|||||||
ALARM_MODES,
|
ALARM_MODES,
|
||||||
AlarmControlPanelEntity,
|
AlarmControlPanelEntity,
|
||||||
AlarmMode,
|
AlarmMode,
|
||||||
|
setProtectedAlarmControlPanelMode,
|
||||||
} from "../../data/alarm_control_panel";
|
} from "../../data/alarm_control_panel";
|
||||||
import { UNAVAILABLE } from "../../data/entity";
|
import { UNAVAILABLE } from "../../data/entity";
|
||||||
import { showEnterCodeDialog } from "../../dialogs/enter-code/show-enter-code-dialog";
|
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
@customElement("ha-state-control-alarm_control_panel-modes")
|
@customElement("ha-state-control-alarm_control_panel-modes")
|
||||||
@ -44,37 +44,7 @@ export class HaStateControlAlarmControlPanelModes extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _setMode(mode: AlarmMode) {
|
private async _setMode(mode: AlarmMode) {
|
||||||
const { service } = ALARM_MODES[mode];
|
setProtectedAlarmControlPanelMode(this, this.hass!, this.stateObj!, mode);
|
||||||
|
|
||||||
let code: string | undefined;
|
|
||||||
|
|
||||||
if (
|
|
||||||
(mode !== "disarmed" &&
|
|
||||||
this.stateObj!.attributes.code_arm_required &&
|
|
||||||
this.stateObj!.attributes.code_format) ||
|
|
||||||
(mode === "disarmed" && this.stateObj!.attributes.code_format)
|
|
||||||
) {
|
|
||||||
const disarm = mode === "disarmed";
|
|
||||||
|
|
||||||
const response = await showEnterCodeDialog(this, {
|
|
||||||
codeFormat: this.stateObj!.attributes.code_format,
|
|
||||||
title: this.hass!.localize(
|
|
||||||
`ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}`
|
|
||||||
),
|
|
||||||
submitText: this.hass!.localize(
|
|
||||||
`ui.card.alarm_control_panel.${disarm ? "disarmn" : "arm"}`
|
|
||||||
),
|
|
||||||
});
|
|
||||||
if (response == null) {
|
|
||||||
throw new Error("cancel");
|
|
||||||
}
|
|
||||||
code = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.hass!.callService("alarm_control_panel", service, {
|
|
||||||
entity_id: this.stateObj!.entity_id,
|
|
||||||
code,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _valueChanged(ev: CustomEvent) {
|
private async _valueChanged(ev: CustomEvent) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user