140 lines
4.4 KiB
TypeScript
140 lines
4.4 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { useEntity as useEntityFromStore, useEntityState, useEntityAttribute } from '@/stores/haStore';
|
|
import { HassEntity } from 'home-assistant-js-websocket';
|
|
|
|
/**
|
|
* Hook for accessing a single Home Assistant entity
|
|
*/
|
|
export function useEntity(entityId: string): HassEntity | undefined {
|
|
return useEntityFromStore(entityId);
|
|
}
|
|
|
|
/**
|
|
* Hook for accessing entity state value
|
|
*/
|
|
export function useEntityStateValue(entityId: string): string | undefined {
|
|
return useEntityState(entityId);
|
|
}
|
|
|
|
/**
|
|
* Hook for accessing a specific entity attribute
|
|
*/
|
|
export function useEntityAttributeValue<T>(entityId: string, attribute: string): T | undefined {
|
|
return useEntityAttribute<T>(entityId, attribute);
|
|
}
|
|
|
|
/**
|
|
* Hook for climate/thermostat entities
|
|
*/
|
|
export function useClimate(entityId: string) {
|
|
const entity = useEntity(entityId);
|
|
|
|
return useMemo(() => {
|
|
if (!entity) return null;
|
|
|
|
return {
|
|
state: entity.state,
|
|
currentTemperature: entity.attributes.current_temperature as number | undefined,
|
|
targetTemperature: entity.attributes.temperature as number | undefined,
|
|
targetTempHigh: entity.attributes.target_temp_high as number | undefined,
|
|
targetTempLow: entity.attributes.target_temp_low as number | undefined,
|
|
hvacMode: entity.state as string,
|
|
hvacModes: entity.attributes.hvac_modes as string[] | undefined,
|
|
hvacAction: entity.attributes.hvac_action as string | undefined,
|
|
minTemp: entity.attributes.min_temp as number | undefined,
|
|
maxTemp: entity.attributes.max_temp as number | undefined,
|
|
targetTempStep: entity.attributes.target_temp_step as number | undefined,
|
|
friendlyName: entity.attributes.friendly_name as string | undefined,
|
|
};
|
|
}, [entity]);
|
|
}
|
|
|
|
/**
|
|
* Hook for light entities
|
|
*/
|
|
export function useLight(entityId: string) {
|
|
const entity = useEntity(entityId);
|
|
|
|
return useMemo(() => {
|
|
if (!entity) return null;
|
|
|
|
return {
|
|
state: entity.state,
|
|
isOn: entity.state === 'on',
|
|
brightness: entity.attributes.brightness as number | undefined,
|
|
brightnessPct: entity.attributes.brightness
|
|
? Math.round((entity.attributes.brightness as number) / 255 * 100)
|
|
: undefined,
|
|
colorMode: entity.attributes.color_mode as string | undefined,
|
|
rgbColor: entity.attributes.rgb_color as [number, number, number] | undefined,
|
|
friendlyName: entity.attributes.friendly_name as string | undefined,
|
|
};
|
|
}, [entity]);
|
|
}
|
|
|
|
/**
|
|
* Hook for lock entities
|
|
*/
|
|
export function useLock(entityId: string) {
|
|
const entity = useEntity(entityId);
|
|
|
|
return useMemo(() => {
|
|
if (!entity) return null;
|
|
|
|
return {
|
|
state: entity.state,
|
|
isLocked: entity.state === 'locked',
|
|
isUnlocked: entity.state === 'unlocked',
|
|
isJammed: entity.state === 'jammed',
|
|
isLocking: entity.state === 'locking',
|
|
isUnlocking: entity.state === 'unlocking',
|
|
friendlyName: entity.attributes.friendly_name as string | undefined,
|
|
};
|
|
}, [entity]);
|
|
}
|
|
|
|
/**
|
|
* Hook for alarm control panel entities (Alarmo)
|
|
*/
|
|
export function useAlarm(entityId: string) {
|
|
const entity = useEntity(entityId);
|
|
|
|
return useMemo(() => {
|
|
if (!entity) return null;
|
|
|
|
return {
|
|
state: entity.state,
|
|
isDisarmed: entity.state === 'disarmed',
|
|
isArmedHome: entity.state === 'armed_home',
|
|
isArmedAway: entity.state === 'armed_away',
|
|
isArmedNight: entity.state === 'armed_night',
|
|
isPending: entity.state === 'pending' || entity.state === 'arming',
|
|
isTriggered: entity.state === 'triggered',
|
|
codeRequired: entity.attributes.code_arm_required as boolean | undefined,
|
|
codeFormat: entity.attributes.code_format as string | undefined,
|
|
changedBy: entity.attributes.changed_by as string | undefined,
|
|
openSensors: entity.attributes.open_sensors as Record<string, string> | undefined,
|
|
friendlyName: entity.attributes.friendly_name as string | undefined,
|
|
};
|
|
}, [entity]);
|
|
}
|
|
|
|
/**
|
|
* Hook for binary sensor entities
|
|
*/
|
|
export function useBinarySensor(entityId: string) {
|
|
const entity = useEntity(entityId);
|
|
|
|
return useMemo(() => {
|
|
if (!entity) return null;
|
|
|
|
return {
|
|
state: entity.state,
|
|
isOn: entity.state === 'on',
|
|
isOff: entity.state === 'off',
|
|
deviceClass: entity.attributes.device_class as string | undefined,
|
|
friendlyName: entity.attributes.friendly_name as string | undefined,
|
|
};
|
|
}, [entity]);
|
|
}
|