frontend/src/data/lock.ts

112 lines
3.0 KiB
TypeScript

import type {
HassEntityAttributeBase,
HassEntityBase,
} from "home-assistant-js-websocket";
import { getExtendedEntityRegistryEntry } from "./entity_registry";
import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog";
import type { HomeAssistant } from "../types";
import { UNAVAILABLE } from "./entity";
export const enum LockEntityFeature {
OPEN = 1,
}
interface LockEntityAttributes extends HassEntityAttributeBase {
code_format?: string;
changed_by?: string | null;
}
export interface LockEntity extends HassEntityBase {
attributes: LockEntityAttributes;
}
type ProtectedLockService = "lock" | "unlock" | "open";
export function isLocked(stateObj: LockEntity) {
return stateObj.state === "locked";
}
export function isUnlocked(stateObj: LockEntity) {
return stateObj.state === "unlocked";
}
export function isUnlocking(stateObj: LockEntity) {
return stateObj.state === "unlocking";
}
export function isLocking(stateObj: LockEntity) {
return stateObj.state === "locking";
}
export function isJammed(stateObj: LockEntity) {
return stateObj.state === "jammed";
}
export function isOpen(stateObj: LockEntity) {
return stateObj.state === "open";
}
export function isOpening(stateObj: LockEntity) {
return stateObj.state === "opening";
}
export function isWaiting(stateObj: LockEntity) {
return ["opening", "unlocking", "locking"].includes(stateObj.state);
}
export function canOpen(stateObj: LockEntity) {
if (stateObj.state === UNAVAILABLE) {
return false;
}
const assumedState = stateObj.attributes.assumed_state === true;
return assumedState || (!isOpen(stateObj) && !isWaiting(stateObj));
}
export function canLock(stateObj: LockEntity) {
if (stateObj.state === UNAVAILABLE) {
return false;
}
const assumedState = stateObj.attributes.assumed_state === true;
return assumedState || (!isLocked(stateObj) && !isWaiting(stateObj));
}
export function canUnlock(stateObj: LockEntity) {
if (stateObj.state === UNAVAILABLE) {
return false;
}
const assumedState = stateObj.attributes.assumed_state === true;
return assumedState || (!isUnlocked(stateObj) && !isWaiting(stateObj));
}
export const callProtectedLockService = async (
element: HTMLElement,
hass: HomeAssistant,
stateObj: LockEntity,
service: ProtectedLockService
) => {
let code: string | undefined;
const lockRegistryEntry = await getExtendedEntityRegistryEntry(
hass,
stateObj.entity_id
).catch(() => undefined);
const defaultCode = lockRegistryEntry?.options?.lock?.default_code;
if (stateObj!.attributes.code_format && !defaultCode) {
const response = await showEnterCodeDialog(element, {
codeFormat: "text",
codePattern: stateObj!.attributes.code_format,
title: hass.localize(`ui.card.lock.${service}`),
submitText: hass.localize(`ui.card.lock.${service}`),
});
if (response == null) {
throw new Error("Code dialog closed");
}
code = response;
}
await hass.callService("lock", service, {
entity_id: stateObj!.entity_id,
code,
});
};