422 lines
12 KiB
TypeScript
422 lines
12 KiB
TypeScript
|
|
/**
|
||
|
|
* Smart Home Device Interfaces
|
||
|
|
* Generic types for smart home features (lights, climate, sensors, etc.)
|
||
|
|
* Protocol-agnostic - can be implemented by Home Assistant, Hue, MQTT, etc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { TFeatureState, IFeatureInfo } from './feature.interfaces.js';
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Light Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TLightProtocol = 'home-assistant' | 'hue' | 'mqtt' | 'zigbee';
|
||
|
|
|
||
|
|
export interface ILightCapabilities {
|
||
|
|
supportsBrightness: boolean;
|
||
|
|
supportsColorTemp: boolean;
|
||
|
|
supportsRgb: boolean;
|
||
|
|
supportsHs: boolean; // Hue/Saturation
|
||
|
|
supportsXy: boolean; // CIE xy color
|
||
|
|
supportsEffects: boolean;
|
||
|
|
supportsTransition: boolean;
|
||
|
|
effects?: string[];
|
||
|
|
minMireds?: number;
|
||
|
|
maxMireds?: number;
|
||
|
|
minColorTempKelvin?: number;
|
||
|
|
maxColorTempKelvin?: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ILightState {
|
||
|
|
isOn: boolean;
|
||
|
|
brightness?: number; // 0-255
|
||
|
|
colorTemp?: number; // Kelvin
|
||
|
|
colorTempMireds?: number; // Mireds (1000000/Kelvin)
|
||
|
|
rgbColor?: [number, number, number];
|
||
|
|
hsColor?: [number, number]; // [hue 0-360, saturation 0-100]
|
||
|
|
xyColor?: [number, number]; // CIE xy
|
||
|
|
effect?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ILightFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'light';
|
||
|
|
protocol: TLightProtocol;
|
||
|
|
capabilities: ILightCapabilities;
|
||
|
|
currentState: ILightState;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Climate/Thermostat Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TClimateProtocol = 'home-assistant' | 'nest' | 'ecobee' | 'mqtt';
|
||
|
|
|
||
|
|
export type THvacMode =
|
||
|
|
| 'off'
|
||
|
|
| 'heat'
|
||
|
|
| 'cool'
|
||
|
|
| 'heat_cool' // Auto dual setpoint
|
||
|
|
| 'auto'
|
||
|
|
| 'dry'
|
||
|
|
| 'fan_only';
|
||
|
|
|
||
|
|
export type THvacAction =
|
||
|
|
| 'off'
|
||
|
|
| 'heating'
|
||
|
|
| 'cooling'
|
||
|
|
| 'drying'
|
||
|
|
| 'idle'
|
||
|
|
| 'fan';
|
||
|
|
|
||
|
|
export interface IClimateCapabilities {
|
||
|
|
hvacModes: THvacMode[];
|
||
|
|
presetModes?: string[]; // 'away', 'eco', 'boost', 'sleep'
|
||
|
|
fanModes?: string[]; // 'auto', 'low', 'medium', 'high'
|
||
|
|
swingModes?: string[]; // 'off', 'vertical', 'horizontal', 'both'
|
||
|
|
supportsTargetTemp: boolean;
|
||
|
|
supportsTargetTempRange: boolean; // For heat_cool mode
|
||
|
|
supportsHumidity: boolean;
|
||
|
|
supportsAuxHeat: boolean;
|
||
|
|
minTemp: number;
|
||
|
|
maxTemp: number;
|
||
|
|
tempStep: number; // Temperature increment (e.g., 0.5, 1)
|
||
|
|
minHumidity?: number;
|
||
|
|
maxHumidity?: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IClimateState {
|
||
|
|
currentTemp?: number;
|
||
|
|
targetTemp?: number;
|
||
|
|
targetTempHigh?: number; // For heat_cool mode
|
||
|
|
targetTempLow?: number; // For heat_cool mode
|
||
|
|
hvacMode: THvacMode;
|
||
|
|
hvacAction?: THvacAction;
|
||
|
|
presetMode?: string;
|
||
|
|
fanMode?: string;
|
||
|
|
swingMode?: string;
|
||
|
|
humidity?: number;
|
||
|
|
targetHumidity?: number;
|
||
|
|
auxHeat?: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IClimateFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'climate';
|
||
|
|
protocol: TClimateProtocol;
|
||
|
|
capabilities: IClimateCapabilities;
|
||
|
|
currentState: IClimateState;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Sensor Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TSensorProtocol = 'home-assistant' | 'mqtt' | 'snmp';
|
||
|
|
|
||
|
|
export type TSensorDeviceClass =
|
||
|
|
| 'temperature'
|
||
|
|
| 'humidity'
|
||
|
|
| 'pressure'
|
||
|
|
| 'illuminance'
|
||
|
|
| 'battery'
|
||
|
|
| 'power'
|
||
|
|
| 'energy'
|
||
|
|
| 'voltage'
|
||
|
|
| 'current'
|
||
|
|
| 'frequency'
|
||
|
|
| 'gas'
|
||
|
|
| 'co2'
|
||
|
|
| 'pm25'
|
||
|
|
| 'pm10'
|
||
|
|
| 'signal_strength'
|
||
|
|
| 'timestamp'
|
||
|
|
| 'duration'
|
||
|
|
| 'distance'
|
||
|
|
| 'speed'
|
||
|
|
| 'weight'
|
||
|
|
| 'monetary'
|
||
|
|
| 'data_size'
|
||
|
|
| 'data_rate'
|
||
|
|
| 'water'
|
||
|
|
| 'irradiance'
|
||
|
|
| 'precipitation'
|
||
|
|
| 'precipitation_intensity'
|
||
|
|
| 'wind_speed';
|
||
|
|
|
||
|
|
export type TSensorStateClass =
|
||
|
|
| 'measurement' // Instantaneous reading
|
||
|
|
| 'total' // Cumulative total
|
||
|
|
| 'total_increasing'; // Monotonically increasing total
|
||
|
|
|
||
|
|
export interface ISensorCapabilities {
|
||
|
|
deviceClass?: TSensorDeviceClass;
|
||
|
|
stateClass?: TSensorStateClass;
|
||
|
|
unit?: string;
|
||
|
|
nativeUnit?: string;
|
||
|
|
precision?: number; // Decimal places
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ISensorState {
|
||
|
|
value: string | number | boolean;
|
||
|
|
numericValue?: number;
|
||
|
|
unit?: string;
|
||
|
|
lastUpdated: Date;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ISensorFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'sensor';
|
||
|
|
protocol: TSensorProtocol;
|
||
|
|
capabilities: ISensorCapabilities;
|
||
|
|
currentState: ISensorState;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Camera Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TCameraProtocol = 'home-assistant' | 'onvif' | 'rtsp';
|
||
|
|
|
||
|
|
export interface ICameraCapabilities {
|
||
|
|
supportsStream: boolean;
|
||
|
|
supportsPtz: boolean; // Pan-tilt-zoom
|
||
|
|
supportsSnapshot: boolean;
|
||
|
|
supportsMotionDetection: boolean;
|
||
|
|
frontendStreamType?: 'hls' | 'web_rtc';
|
||
|
|
streamUrl?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ICameraState {
|
||
|
|
isRecording: boolean;
|
||
|
|
isStreaming: boolean;
|
||
|
|
motionDetected: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ICameraFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'camera';
|
||
|
|
protocol: TCameraProtocol;
|
||
|
|
capabilities: ICameraCapabilities;
|
||
|
|
currentState: ICameraState;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Cover/Blind Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TCoverProtocol = 'home-assistant' | 'mqtt' | 'somfy';
|
||
|
|
|
||
|
|
export type TCoverDeviceClass =
|
||
|
|
| 'awning'
|
||
|
|
| 'blind'
|
||
|
|
| 'curtain'
|
||
|
|
| 'damper'
|
||
|
|
| 'door'
|
||
|
|
| 'garage'
|
||
|
|
| 'gate'
|
||
|
|
| 'shade'
|
||
|
|
| 'shutter'
|
||
|
|
| 'window';
|
||
|
|
|
||
|
|
export type TCoverState = 'open' | 'opening' | 'closed' | 'closing' | 'stopped' | 'unknown';
|
||
|
|
|
||
|
|
export interface ICoverCapabilities {
|
||
|
|
deviceClass?: TCoverDeviceClass;
|
||
|
|
supportsOpen: boolean;
|
||
|
|
supportsClose: boolean;
|
||
|
|
supportsStop: boolean;
|
||
|
|
supportsPosition: boolean; // set_cover_position
|
||
|
|
supportsTilt: boolean; // set_cover_tilt_position
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ICoverStateInfo {
|
||
|
|
state: TCoverState;
|
||
|
|
position?: number; // 0-100, 0 = closed, 100 = fully open
|
||
|
|
tiltPosition?: number; // 0-100
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ICoverFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'cover';
|
||
|
|
protocol: TCoverProtocol;
|
||
|
|
capabilities: ICoverCapabilities;
|
||
|
|
currentState: ICoverStateInfo;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Switch Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TSwitchProtocol = 'home-assistant' | 'mqtt' | 'tasmota' | 'tuya';
|
||
|
|
|
||
|
|
export type TSwitchDeviceClass = 'outlet' | 'switch';
|
||
|
|
|
||
|
|
export interface ISwitchCapabilities {
|
||
|
|
deviceClass?: TSwitchDeviceClass;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ISwitchState {
|
||
|
|
isOn: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ISwitchFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'switch';
|
||
|
|
protocol: TSwitchProtocol;
|
||
|
|
capabilities: ISwitchCapabilities;
|
||
|
|
currentState: ISwitchState;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Lock Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TLockProtocol = 'home-assistant' | 'mqtt' | 'august' | 'yale';
|
||
|
|
|
||
|
|
export type TLockState =
|
||
|
|
| 'locked'
|
||
|
|
| 'unlocked'
|
||
|
|
| 'locking'
|
||
|
|
| 'unlocking'
|
||
|
|
| 'jammed'
|
||
|
|
| 'unknown';
|
||
|
|
|
||
|
|
export interface ILockCapabilities {
|
||
|
|
supportsOpen: boolean; // Physical open (some locks can open the door)
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ILockStateInfo {
|
||
|
|
state: TLockState;
|
||
|
|
isLocked: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ILockFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'lock';
|
||
|
|
protocol: TLockProtocol;
|
||
|
|
capabilities: ILockCapabilities;
|
||
|
|
currentState: ILockStateInfo;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Fan Feature Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type TFanProtocol = 'home-assistant' | 'mqtt' | 'bond';
|
||
|
|
|
||
|
|
export type TFanDirection = 'forward' | 'reverse';
|
||
|
|
|
||
|
|
export interface IFanCapabilities {
|
||
|
|
supportsSpeed: boolean;
|
||
|
|
supportsOscillate: boolean;
|
||
|
|
supportsDirection: boolean;
|
||
|
|
supportsPresetModes: boolean;
|
||
|
|
presetModes?: string[];
|
||
|
|
speedCount?: number; // Number of discrete speed levels
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IFanState {
|
||
|
|
isOn: boolean;
|
||
|
|
percentage?: number; // 0-100 speed
|
||
|
|
presetMode?: string;
|
||
|
|
oscillating?: boolean;
|
||
|
|
direction?: TFanDirection;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IFanFeatureInfo extends IFeatureInfo {
|
||
|
|
type: 'fan';
|
||
|
|
protocol: TFanProtocol;
|
||
|
|
capabilities: IFanCapabilities;
|
||
|
|
currentState: IFanState;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Protocol Client Interfaces (for dependency injection)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Light protocol client interface
|
||
|
|
* Implemented by HomeAssistantProtocol, HueProtocol, etc.
|
||
|
|
*/
|
||
|
|
export interface ILightProtocolClient {
|
||
|
|
turnOn(entityId: string, options?: { brightness?: number; colorTemp?: number; rgb?: [number, number, number]; transition?: number }): Promise<void>;
|
||
|
|
turnOff(entityId: string, options?: { transition?: number }): Promise<void>;
|
||
|
|
toggle(entityId: string): Promise<void>;
|
||
|
|
setBrightness(entityId: string, brightness: number, transition?: number): Promise<void>;
|
||
|
|
setColorTemp(entityId: string, kelvin: number, transition?: number): Promise<void>;
|
||
|
|
setRgbColor(entityId: string, r: number, g: number, b: number, transition?: number): Promise<void>;
|
||
|
|
setEffect(entityId: string, effect: string): Promise<void>;
|
||
|
|
getState(entityId: string): Promise<ILightState>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Climate protocol client interface
|
||
|
|
*/
|
||
|
|
export interface IClimateProtocolClient {
|
||
|
|
setHvacMode(entityId: string, mode: THvacMode): Promise<void>;
|
||
|
|
setTargetTemp(entityId: string, temp: number): Promise<void>;
|
||
|
|
setTargetTempRange(entityId: string, low: number, high: number): Promise<void>;
|
||
|
|
setPresetMode(entityId: string, preset: string): Promise<void>;
|
||
|
|
setFanMode(entityId: string, mode: string): Promise<void>;
|
||
|
|
setSwingMode(entityId: string, mode: string): Promise<void>;
|
||
|
|
setAuxHeat(entityId: string, enabled: boolean): Promise<void>;
|
||
|
|
getState(entityId: string): Promise<IClimateState>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sensor protocol client interface (read-only)
|
||
|
|
*/
|
||
|
|
export interface ISensorProtocolClient {
|
||
|
|
getState(entityId: string): Promise<ISensorState>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Camera protocol client interface
|
||
|
|
*/
|
||
|
|
export interface ICameraProtocolClient {
|
||
|
|
getSnapshot(entityId: string): Promise<Buffer>;
|
||
|
|
getSnapshotUrl(entityId: string): Promise<string>;
|
||
|
|
getStreamUrl(entityId: string): Promise<string>;
|
||
|
|
getState(entityId: string): Promise<ICameraState>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cover protocol client interface
|
||
|
|
*/
|
||
|
|
export interface ICoverProtocolClient {
|
||
|
|
open(entityId: string): Promise<void>;
|
||
|
|
close(entityId: string): Promise<void>;
|
||
|
|
stop(entityId: string): Promise<void>;
|
||
|
|
setPosition(entityId: string, position: number): Promise<void>;
|
||
|
|
setTiltPosition(entityId: string, position: number): Promise<void>;
|
||
|
|
getState(entityId: string): Promise<ICoverStateInfo>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Switch protocol client interface
|
||
|
|
*/
|
||
|
|
export interface ISwitchProtocolClient {
|
||
|
|
turnOn(entityId: string): Promise<void>;
|
||
|
|
turnOff(entityId: string): Promise<void>;
|
||
|
|
toggle(entityId: string): Promise<void>;
|
||
|
|
getState(entityId: string): Promise<ISwitchState>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Lock protocol client interface
|
||
|
|
*/
|
||
|
|
export interface ILockProtocolClient {
|
||
|
|
lock(entityId: string): Promise<void>;
|
||
|
|
unlock(entityId: string): Promise<void>;
|
||
|
|
open(entityId: string): Promise<void>; // Physical open if supported
|
||
|
|
getState(entityId: string): Promise<ILockStateInfo>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fan protocol client interface
|
||
|
|
*/
|
||
|
|
export interface IFanProtocolClient {
|
||
|
|
turnOn(entityId: string, percentage?: number): Promise<void>;
|
||
|
|
turnOff(entityId: string): Promise<void>;
|
||
|
|
toggle(entityId: string): Promise<void>;
|
||
|
|
setPercentage(entityId: string, percentage: number): Promise<void>;
|
||
|
|
setPresetMode(entityId: string, mode: string): Promise<void>;
|
||
|
|
setOscillating(entityId: string, oscillating: boolean): Promise<void>;
|
||
|
|
setDirection(entityId: string, direction: TFanDirection): Promise<void>;
|
||
|
|
getState(entityId: string): Promise<IFanState>;
|
||
|
|
}
|