/** * Base Device Class for Dyson Devices * * Abstract class that provides common functionality for all Dyson device types. * Manages MQTT connection, state, and event emission. */ import { EventEmitter } from 'events'; import { DysonMqttClient } from '../protocol/mqttClient.js'; import type { ConnectVariant, MqttMessage, MqttConnectFn } from '../protocol/mqttClient.js'; import type { DeviceInfo, DeviceState, DeviceFeatures, DeviceEvents } from './types.js'; import { createDefaultState, DEFAULT_FEATURES } from './types.js'; /** * MQTT client factory type for dependency injection */ export type MqttClientFactory = (host: string, serial: string, credentials: string, productType: string, mqttConnect?: MqttConnectFn) => DysonMqttClient; /** * Abstract base class for all Dyson devices * * Provides: * - MQTT client management * - Device state management * - Event emission for state changes * - Abstract methods for device-specific behavior * * @example * ```typescript * class PureCoolDevice extends DysonDevice { * readonly productType = '438'; * readonly supportedFeatures = { ...DEFAULT_FEATURES, airQualitySensor: true }; * * protected handleStateMessage(data: unknown): void { * // Parse device-specific state * } * } * ``` */ export declare abstract class DysonDevice extends EventEmitter { /** Dyson product type code (e.g., '438' for TP04) */ abstract readonly productType: string; /** Features supported by this device type */ abstract readonly supportedFeatures: DeviceFeatures; /** Device information */ protected readonly deviceInfo: DeviceInfo; /** MQTT client for device communication */ protected mqttClient: DysonMqttClient | null; /** Current device state */ protected state: DeviceState; /** MQTT client factory for dependency injection */ private readonly mqttClientFactory; /** Optional MQTT connect function for testing */ private readonly mqttConnectFn?; /** Polling interval handle for periodic state requests */ private pollingIntervalHandle?; /** Polling interval in milliseconds */ private pollingIntervalMs; /** * Create a new DysonDevice * * @param deviceInfo - Device information from discovery * @param mqttClientFactory - Optional factory for creating MQTT client (for testing) * @param mqttConnectFn - Optional MQTT connect function (for testing) */ constructor(deviceInfo: DeviceInfo, mqttClientFactory?: MqttClientFactory, mqttConnectFn?: MqttConnectFn); /** * Set the polling interval for state updates * * @param seconds - Interval in seconds (MIN_SECONDS-MAX_SECONDS, default DEFAULT_SECONDS) */ setPollingInterval(seconds: number): void; /** * Start periodic polling for state updates */ private startPolling; /** * Stop periodic polling */ private stopPolling; /** * Connect to the device * * Establishes MQTT connection, subscribes to status topic, * and requests current state. * * @throws {Error} If connection fails or device IP is not set */ connect(): Promise; /** * Disconnect from the device */ disconnect(): Promise; /** * Check if device is connected */ isConnected(): boolean; /** * Get current device state */ getState(): Readonly; /** * Get device serial number */ getSerial(): string; /** * Get the MQTT CONNECT variant that produced the active connection, or * `null` if not connected. Useful for diagnostics when a device required a * fallback variant (e.g., Big+Quiet firmware that rejects the default * clientId). */ getActiveVariant(): ConnectVariant | null; /** * Get device name */ getName(): string; /** * Get device IP address */ getIpAddress(): string | undefined; /** * Send a command to the device * * @param data - Command data to send * @throws {Error} If not connected */ protected sendCommand(data: Record): Promise; /** * Update device state and emit stateChange event * * @param partial - Partial state to merge */ protected updateState(partial: Partial): void; /** * Handle incoming MQTT message * * Routes messages to appropriate handlers based on message type. * * @param message - MQTT message received */ protected handleMessage(message: MqttMessage): void; /** * Handle state message from device * * Must be implemented by subclasses to parse device-specific state. * * @param data - Parsed message data */ protected abstract handleStateMessage(data: Record): void; /** * Handle environmental sensor data * * Delegates to MessageCodec.parseEnvironmentalData for consistent parsing. * * @param data - Parsed sensor data */ protected handleEnvironmentalMessage(data: Record): void; /** * Set up MQTT client event handlers */ private setupMqttHandlers; } export type { DeviceInfo, DeviceState, DeviceFeatures, DeviceEvents }; export { createDefaultState, DEFAULT_FEATURES }; //# sourceMappingURL=dysonDevice.d.ts.map